1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 /** 20 * @author Anatoly F. Bondarenko 21 */ 22 23 /** 24 * Created on 30.03.2005 25 */ 26 package org.apache.harmony.jpda.tests.jdwp.VirtualMachine; 27 28 29 30 import java.io.*; 31 32 import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket; 33 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands; 34 import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants; 35 import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket; 36 import org.apache.harmony.jpda.tests.jdwp.share.JDWPSyncTestCase; 37 import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer; 38 39 /** 40 * JDWP Unit test for VirtualMachine.RedefineClasses command. 41 */ 42 public class RedefineClassesTest extends JDWPSyncTestCase { 43 44 static final int testStatusPassed = 0; 45 static final int testStatusFailed = -1; 46 static final String thisCommandName = "VirtualMachine::RedefineClasses command"; 47 static final String checkedClassSignature 48 = "Lorg/apache/harmony/jpda/tests/jdwp/VirtualMachine/RedefineClass_Debuggee;"; 49 static final String byteCodeToRedefineFile = "RedefineByteCode_Debuggee001"; 50 getDebuggeeClassName()51 protected String getDebuggeeClassName() { 52 return "org.apache.harmony.jpda.tests.jdwp.VirtualMachine.RedefineClassesDebuggee"; 53 } 54 findNewClassByteCode()55 File findNewClassByteCode() { 56 File foundFile = null; 57 String nameSeparator = File.separator; 58 String pathSeparator = File.pathSeparator; 59 String byteCodeFileNameSuffix = "org" + nameSeparator + "apache" + nameSeparator 60 + "harmony" + nameSeparator + "jpda" + nameSeparator + "tests" + nameSeparator 61 + "jdwp" + nameSeparator + "VirtualMachine" 62 + nameSeparator + byteCodeToRedefineFile; 63 String byteCodeFileName = null; 64 String classPaths = System.getProperty("java.class.path"); 65 int begPos = 0; 66 int classPathsLength = classPaths.length();; 67 68 for (int i = 0; i <= classPathsLength; i++) { 69 if ( i == classPathsLength ) { 70 if ( begPos == i ) { 71 break; 72 } 73 } else { 74 if ( ! pathSeparator.equals(classPaths.substring(i,i+1))) { 75 continue; 76 } 77 if ( begPos == i ) { 78 begPos++; 79 continue; 80 } 81 } 82 byteCodeFileName = classPaths.substring(begPos,i); 83 if ( ! nameSeparator.equals(classPaths.substring(i-1,i)) ) { 84 byteCodeFileName = byteCodeFileName + nameSeparator; 85 } 86 byteCodeFileName = byteCodeFileName + byteCodeFileNameSuffix; 87 foundFile = new File(byteCodeFileName); 88 if ( foundFile.exists() ) { 89 break; 90 } 91 foundFile = null; 92 begPos = i+1; 93 } 94 return foundFile; 95 } 96 97 /** 98 * This testcase exercises VirtualMachine.RedefineClasses command. 99 * <BR>At first the test starts RedefineClassesDebuggee which invokes 100 * the 'testMethod()' of RedefineClass_Debuggee class and prints the string 101 * returned by this method before redefining. 102 * <BR> Then the test performs VirtualMachine.RedefineClasses command 103 * for RedefineClass_Debuggee class - the 'testMethod()' is redefined. 104 * Next, the debuggee invokes the 'testMethod()' again and it is expected 105 * that the method returns another resulting string. 106 * The test checks that this resulting string is expected string. 107 */ testRedefineClasses001()108 public void testRedefineClasses001() { 109 String thisTestName = "testClassObject001"; 110 111 //check capability, relevant for this test 112 logWriter.println("=> Check capability: canRedefineClasses"); 113 if (!debuggeeWrapper.vmMirror.canRedefineClasses()) { 114 logWriter.println("##WARNING: this VM doesn't possess capability: canRedefineClasses"); 115 return; 116 } 117 118 logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": START..."); 119 synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY); 120 File newClassByteCodeFile = findNewClassByteCode(); 121 if ( newClassByteCodeFile == null ) { 122 logWriter.println 123 ("===> Can NOT find out byte code file for redefine:"); 124 logWriter.println 125 ("===> File name = " + byteCodeToRedefineFile); 126 logWriter.println 127 ("===> Test can NOT be run!"); 128 logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": FINISH"); 129 return; 130 } 131 132 logWriter.println 133 ("\n=> Send VirtualMachine::ClassesBySignature command and and get checked class referenceTypeID..."); 134 logWriter.println("=> checkedClassSignature = " + checkedClassSignature); 135 CommandPacket classesBySignatureCommand = new CommandPacket( 136 JDWPCommands.VirtualMachineCommandSet.CommandSetID, 137 JDWPCommands.VirtualMachineCommandSet.ClassesBySignatureCommand); 138 classesBySignatureCommand.setNextValueAsString(checkedClassSignature); 139 140 ReplyPacket classesBySignatureReply = debuggeeWrapper.vmMirror.performCommand(classesBySignatureCommand); 141 classesBySignatureCommand = null; 142 143 checkReplyPacket(classesBySignatureReply, "VirtualMachine::ClassesBySignature command"); 144 145 int returnedClassesNumber = classesBySignatureReply.getNextValueAsInt(); 146 logWriter.println("=> ReturnedClassesNumber = " + returnedClassesNumber); 147 if ( returnedClassesNumber != 1 ) { 148 // Number of returned reference types - is NOt used here 149 printErrorAndFail("Unexpected number of classes is returned: " + 150 returnedClassesNumber + 151 ", Expected number = 1"); 152 } 153 154 classesBySignatureReply.getNextValueAsByte(); 155 // refTypeTag of class - is NOt used here 156 157 long refTypeID = classesBySignatureReply.getNextValueAsReferenceTypeID(); 158 classesBySignatureReply = null; 159 160 logWriter.println("=> Checked class referenceTypeID = " + refTypeID); 161 162 logWriter.println("\n=> Preparing info for " + thisCommandName); 163 logWriter.println 164 ("=> File name with new class byte code to redefine = " + byteCodeToRedefineFile); 165 FileInputStream newClassByteCodeFileInputStream = null; 166 try { 167 newClassByteCodeFileInputStream = new FileInputStream(newClassByteCodeFile); 168 } catch (Throwable thrown) { 169 logWriter.println 170 ("===> Can NOT create FileInputStream for byte code file:"); 171 logWriter.println("===> File name = " + byteCodeToRedefineFile); 172 logWriter.println("===> Exception is thrown: " + thrown); 173 logWriter.println("===> Test can NOT be run!"); 174 logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": FINISH"); 175 return; 176 } 177 int newClassByteCodeSize = 0; 178 try { 179 newClassByteCodeSize = (int)newClassByteCodeFileInputStream.skip(Long.MAX_VALUE); 180 } catch (Throwable thrown) { 181 logWriter.println 182 ("===> Can NOT do FileInputStream.skip() to the end of file:"); 183 logWriter.println("===> File name = " + byteCodeToRedefineFile); 184 logWriter.println("===> Exception is thrown: " + thrown); 185 logWriter.println("===> Test can NOT be run!"); 186 logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": FINISH"); 187 return; 188 } 189 logWriter.println("=> newClassByteCodeSize = " + newClassByteCodeSize); 190 try { 191 newClassByteCodeFileInputStream.close(); 192 } catch (Throwable thrown) { 193 logWriter.println 194 ("===> WARNING: Can NOT close FileInputStream for byte code file:"); 195 logWriter.println("===> File name = " + byteCodeToRedefineFile); 196 logWriter.println("===> Exception is thrown: " + thrown); 197 } 198 newClassByteCodeFileInputStream = null; 199 200 try { 201 newClassByteCodeFileInputStream = new FileInputStream(newClassByteCodeFile); 202 } catch (Throwable thrown) { 203 logWriter.println 204 ("===> Can NOT re-create FileInputStream for byte code file:"); 205 logWriter.println("===> File name = " + byteCodeToRedefineFile); 206 logWriter.println("===> Exception is thrown: " + thrown); 207 logWriter.println("===> Test can NOT be run!"); 208 logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": FINISH"); 209 return; 210 } 211 212 CommandPacket checkedCommand = new CommandPacket( 213 JDWPCommands.VirtualMachineCommandSet.CommandSetID, 214 JDWPCommands.VirtualMachineCommandSet.RedefineClassesCommand); 215 checkedCommand.setNextValueAsInt(1); // number of classes to redefine 216 checkedCommand.setNextValueAsReferenceTypeID(refTypeID); 217 checkedCommand.setNextValueAsInt(newClassByteCodeSize); 218 int writtenBytes = 0; 219 int currentByte = 0; 220 while ( true ) { 221 try { 222 currentByte = newClassByteCodeFileInputStream.read(); 223 } catch (Throwable thrown) { 224 logWriter.println 225 ("===> Can NOT read current byte from byte code file:"); 226 logWriter.println("===> File name = " + byteCodeToRedefineFile); 227 logWriter.println("===> Byte number = " + writtenBytes); 228 logWriter.println("===> Exception is thrown: " + thrown); 229 logWriter.println("===> Test can NOT be run!"); 230 logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": FINISH"); 231 return; 232 } 233 if ( currentByte == -1 ) { // EOF is reached 234 break; 235 } 236 checkedCommand.setNextValueAsByte((byte)currentByte); 237 writtenBytes++; 238 } 239 logWriter.println("=> Number of written bytes as new class file = " + writtenBytes); 240 if ( newClassByteCodeSize != writtenBytes ) { 241 logWriter.println("===> WARNING: Number of written bytes != newClassByteCodeSize"); 242 logWriter.println("===> Test can NOT be run!"); 243 logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": FINISH"); 244 return; 245 } 246 247 logWriter.println("\n=> Send " + thisCommandName + " and check reply..."); 248 249 ReplyPacket checkedReply = debuggeeWrapper.vmMirror.performCommand(checkedCommand); 250 checkedCommand = null; 251 int[] expectedErrors = { 252 JDWPConstants.Error.NOT_IMPLEMENTED, 253 }; 254 short errorCode = checkedReply.getErrorCode(); 255 if ( errorCode != JDWPConstants.Error.NONE ) { 256 if ( errorCode != JDWPConstants.Error.UNSUPPORTED_VERSION ) { 257 finalSyncMessage = JPDADebuggeeSynchronizer.SGNL_CONTINUE; 258 printErrorAndFail( 259 "## WARNING: A class file for redefine has a version number not supported by this VM" + 260 "\n## File name with byte code = " + byteCodeToRedefineFile + 261 "\n## It should be re-created"); 262 } 263 boolean expectedErr = false; 264 for (int i=0; i < expectedErrors.length; i++) { 265 if ( errorCode == expectedErrors[i] ) { 266 expectedErr = true; 267 break; 268 } 269 } 270 if ( expectedErr ) { 271 logWriter.println("=> " + thisCommandName 272 + " returns expected ERROR = " + errorCode 273 + "(" + JDWPConstants.Error.getName(errorCode) + ")"); 274 logWriter.println 275 ("==> " + thisTestName + " for " + thisCommandName + ": FINISH"); 276 return; 277 } else { 278 finalSyncMessage = JPDADebuggeeSynchronizer.SGNL_CONTINUE; 279 printErrorAndFail(thisCommandName 280 + " returns unexpected ERROR = " + errorCode 281 + "(" + JDWPConstants.Error.getName(errorCode) + ")"); 282 } 283 } 284 logWriter.println("=> " + thisCommandName + " returns reply without any error"); 285 286 assertAllDataRead(checkedReply); 287 288 logWriter.println("\n=> Send Debuggee signal to continue and execute redefined testMethod"); 289 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 290 291 String testMethodResult = synchronizer.receiveMessage(); 292 logWriter.println("=> Redefined testMethod result = \"" + testMethodResult + "\""); 293 if ( testMethodResult.equals("testMethod_Result_After_Redefine") ) { 294 logWriter.println("=> OK - it is expected result"); 295 } else { 296 printErrorAndFail("it is NOT expected result" + 297 "\n Expected result = \"testMethod_Result_After_Redefine\""); 298 } 299 300 logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": FINISH"); 301 } 302 } 303