From d397f64580d9029b714dc08bbf9715cbb3906036 Mon Sep 17 00:00:00 2001 From: Orion Hodson Date: Tue, 9 May 2017 09:56:13 +0100 Subject: Additional test for SourceDebugExtension Adds test for an array type which by definition cannot have JSR45 metadata. This was triggering a null dereference in ART. Test: art/tools/run-jdwp-tests.sh --mode=host Bug: 38126955 Change-Id: Ie69d9bbc1c672d9c8b2ae8e8ca6d18e39e7eb387 --- .../SourceDebugExtensionDebuggee.java | 7 ++ .../ReferenceType/SourceDebugExtensionTest.java | 116 +++++++++++++++++---- 2 files changed, 103 insertions(+), 20 deletions(-) diff --git a/jdwp/src/test/java/org/apache/harmony/jpda/tests/jdwp/ReferenceType/SourceDebugExtensionDebuggee.java b/jdwp/src/test/java/org/apache/harmony/jpda/tests/jdwp/ReferenceType/SourceDebugExtensionDebuggee.java index 5a04599..ea90778 100644 --- a/jdwp/src/test/java/org/apache/harmony/jpda/tests/jdwp/ReferenceType/SourceDebugExtensionDebuggee.java +++ b/jdwp/src/test/java/org/apache/harmony/jpda/tests/jdwp/ReferenceType/SourceDebugExtensionDebuggee.java @@ -26,6 +26,7 @@ package org.apache.harmony.jpda.tests.jdwp.ReferenceType; import java.lang.reflect.Constructor; +import java.lang.reflect.Proxy; import java.net.URLClassLoader; import java.net.URL; import java.nio.ByteBuffer; @@ -173,11 +174,17 @@ public class SourceDebugExtensionDebuggee extends SyncDebuggee { } } + // Instantiate a proxy whose name should contain "$Proxy". + Class proxy = Proxy.getProxyClass(SomeInterface.class.getClassLoader(), + new Class[] { SomeInterface.class }); + synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_READY); logWriter.println("--> Debuggee: SourceDebugExtensionDebuggee..."); synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); } + interface SomeInterface {} + public static void main(String [] args) { runDebuggee(SourceDebugExtensionDebuggee.class); } diff --git a/jdwp/src/test/java/org/apache/harmony/jpda/tests/jdwp/ReferenceType/SourceDebugExtensionTest.java b/jdwp/src/test/java/org/apache/harmony/jpda/tests/jdwp/ReferenceType/SourceDebugExtensionTest.java index 93dbfa9..7f40430 100644 --- a/jdwp/src/test/java/org/apache/harmony/jpda/tests/jdwp/ReferenceType/SourceDebugExtensionTest.java +++ b/jdwp/src/test/java/org/apache/harmony/jpda/tests/jdwp/ReferenceType/SourceDebugExtensionTest.java @@ -43,8 +43,6 @@ public class SourceDebugExtensionTest extends JDWPSyncTestCase { static final String thisCommandName = "ReferenceType.SourceDebugExtension command"; static final String debuggeeSignature = "Lorg/apache/harmony/jpda/tests/jdwp/ReferenceType/SourceDebugExtensionDebuggee;"; - static final String classWithSourceDebugExtension = - "Lorg/apache/harmony/jpda/tests/jdwp/Events/SourceDebugExtensionMockClass;"; static final String expectedSourceDebugExtension = "SMAP\nhelloworld_jsp.java\nJSP\n*S JSP\n" + "*F\n+ 0 helloworld.jsp\nhelloworld.jsp\n*L\n1,5:53\n6:58,3\n7,4:61\n*E\n"; @@ -53,20 +51,8 @@ public class SourceDebugExtensionTest extends JDWPSyncTestCase { return "org.apache.harmony.jpda.tests.jdwp.ReferenceType.SourceDebugExtensionDebuggee"; } - /** - * This testcase exercises ReferenceType.SourceDebugExtension command. - * - *
The test starts a SourceDebugExtensionDebuggee instance, which instantiates a - * SourceDebugExtensionMockClass instance. The SourceDebugExtensionMockClass comes from a - * class file generated by a JSP to Java bytecode compiler. The testcase requests - * referenceTypeId for this class by VirtualMachine.ClassesBySignature command, then - * performs ReferenceType.SourceDebugExtension to get the JSR45 metadata for the - * class. The testcase checks that no any unexpected ERROR is returned and that - * the JSR45 metadata matches the expected value. - */ - public void testSourceDebugExtension001() { - String thisTestName = "testSourceDebugExtension001"; + private void doTest(String testName, String classSignature, int expectedErrorCode) { //check capability, relevant for this test logWriter.println("=> Check capability: canGetSourceDebugExtension"); if (!debuggeeWrapper.vmMirror.canGetSourceDebugExtension()) { @@ -74,10 +60,10 @@ public class SourceDebugExtensionTest extends JDWPSyncTestCase { return; } - logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": START..."); + logWriter.println("==> " + testName + " for " + thisCommandName + ": START..."); synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY); - long refTypeID = getClassIDBySignature(classWithSourceDebugExtension); - logWriter.println("=> Class with SourceDebugExtension = " + classWithSourceDebugExtension); + long refTypeID = getClassIDBySignature(classSignature); + logWriter.println("=> Class with SourceDebugExtension = " + classSignature); logWriter.println("=> referenceTypeID for class with SourceDebugExtension = " + refTypeID); logWriter.println("=> CHECK: send " + thisCommandName + " and check reply..."); @@ -90,6 +76,7 @@ public class SourceDebugExtensionTest extends JDWPSyncTestCase { checkedCommand = null; short errorCode = checkedReply.getErrorCode(); + assertEquals(expectedErrorCode, errorCode); switch ( errorCode ) { case JDWPConstants.Error.NONE: @@ -98,6 +85,9 @@ public class SourceDebugExtensionTest extends JDWPSyncTestCase { logWriter.println("=> Returned SourceDebugExtension = " + sourceDebugExtension); assertEquals(expectedSourceDebugExtension, sourceDebugExtension); break; + case JDWPConstants.Error.ABSENT_INFORMATION: + logWriter.println("=> ABSENT_INFORMATION is returned"); + break; default: logWriter.println("\n## FAILURE: " + thisCommandName + " returns unexpected ERROR = " + errorCode + "(" + JDWPConstants.Error.getName(errorCode) + ")"); @@ -107,9 +97,95 @@ public class SourceDebugExtensionTest extends JDWPSyncTestCase { assertAllDataRead(checkedReply); - logWriter.println("=> CHECK PASSED: No any unexpected ERROR is returned"); + logWriter.println("=> CHECK PASSED: Received expected result"); synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); - logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": FINISH"); + logWriter.println("==> " + testName + " for " + thisCommandName + ": FINISH"); + } + + /** + * This testcase exercises ReferenceType.SourceDebugExtension command. + * + *
The test starts a SourceDebugExtensionDebuggee instance, which instantiates a + * SourceDebugExtensionMockClass instance. The SourceDebugExtensionMockClass comes from a + * class file generated by a JSP to Java bytecode compiler. The testcase requests + * referenceTypeId for this class by VirtualMachine.ClassesBySignature command, then + * performs ReferenceType.SourceDebugExtension to get the JSR45 metadata for the + * class. The testcase checks that no any unexpected ERROR is returned and that + * the JSR45 metadata matches the expected value. + */ + public void testSourceDebugExtension001() { + doTest("testSourceDebugExtension001", + "Lorg/apache/harmony/jpda/tests/jdwp/Events/SourceDebugExtensionMockClass;", + JDWPConstants.Error.NONE); + } + + /** + * This testcase exercises ReferenceType.SourceDebugExtension command. + * + * The class queried is a primitive type which on ART does not + * have an associated DEX cache. + */ + public void testSourceDebugExtension002() { + doTest("testSourceDebugExtension001", "I", JDWPConstants.Error.ABSENT_INFORMATION); + } + + /** + * This testcase exercises ReferenceType.SourceDebugExtension command. + * + * The class queried is a primitive array which on ART does not + * have an associated DEX cache. + */ + public void testSourceDebugExtension003() { + doTest("testSourceDebugExtension003", "[I", JDWPConstants.Error.ABSENT_INFORMATION); + } + + /** + * This testcase exercises ReferenceType.SourceDebugExtension command. + * + * The class queried is an array which on ART does not have an + * associated DEX cache. + */ + public void testSourceDebugExtension004() { + doTest("testSourceDebugExtension004", "[Ljava/lang/String;", + JDWPConstants.Error.ABSENT_INFORMATION); + } + + /** + * This testcase exercises ReferenceType.SourceDebugExtension command. + * + * The test queries all classes to find a proxy class and then + * tries he SourceDebugExtension command on the proxy class. The + * debuggee instantiates a proxy so we know there is at least one. + */ + public void testSourceDebugExtension005() { + // Identifying the name of a proxy class is tricky so get all class names and walk them: + + logWriter.println("==> Send VirtualMachine::AllClasses command..."); + CommandPacket packet = new CommandPacket( + JDWPCommands.VirtualMachineCommandSet.CommandSetID, + JDWPCommands.VirtualMachineCommandSet.AllClassesCommand); + ReplyPacket reply = debuggeeWrapper.vmMirror.performCommand(packet); + checkReplyPacket(reply, "VirtualMachine::AllClasses command"); + + long typeID; + String signature; + int status; + int classes = reply.getNextValueAsInt(); + int count = 0; + for (int i = 0; i < classes; i++) { + reply.getNextValueAsByte(); + typeID = reply.getNextValueAsReferenceTypeID(); + signature = reply.getNextValueAsString(); + status = reply.getNextValueAsInt(); + if (signature.contains("$Proxy")) { + doTest("testSourceDebugExtension005", signature, + JDWPConstants.Error.ABSENT_INFORMATION); + return; + } + } + + logWriter.println("\n## FAILURE: testSourceDebugExtension005 did not find a proxy class"); + fail("testSourceDebugExtension005 did not find a proxy class"); } } -- cgit v1.2.3