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 51 @Override getDebuggeeClassName()52 protected String getDebuggeeClassName() { 53 return "org.apache.harmony.jpda.tests.jdwp.VirtualMachine.RedefineClassesDebuggee"; 54 } 55 findNewClassByteCode()56 File findNewClassByteCode() { 57 File foundFile = null; 58 String nameSeparator = File.separator; 59 String pathSeparator = File.pathSeparator; 60 String byteCodeFileNameSuffix = "org" + nameSeparator + "apache" + nameSeparator 61 + "harmony" + nameSeparator + "jpda" + nameSeparator + "tests" + nameSeparator 62 + "jdwp" + nameSeparator + "VirtualMachine" 63 + nameSeparator + byteCodeToRedefineFile; 64 String byteCodeFileName = null; 65 String classPaths = System.getProperty("java.class.path"); 66 int begPos = 0; 67 int classPathsLength = classPaths.length(); 68 69 for (int i = 0; i <= classPathsLength; i++) { 70 if ( i == classPathsLength ) { 71 if ( begPos == i ) { 72 break; 73 } 74 } else { 75 if ( ! pathSeparator.equals(classPaths.substring(i,i+1))) { 76 continue; 77 } 78 if ( begPos == i ) { 79 begPos++; 80 continue; 81 } 82 } 83 byteCodeFileName = classPaths.substring(begPos,i); 84 if ( ! nameSeparator.equals(classPaths.substring(i-1,i)) ) { 85 byteCodeFileName = byteCodeFileName + nameSeparator; 86 } 87 byteCodeFileName = byteCodeFileName + byteCodeFileNameSuffix; 88 foundFile = new File(byteCodeFileName); 89 if ( foundFile.exists() ) { 90 break; 91 } 92 foundFile = null; 93 begPos = i+1; 94 } 95 return foundFile; 96 } 97 98 /** 99 * This testcase exercises VirtualMachine.RedefineClasses command. 100 * <BR>At first the test starts RedefineClassesDebuggee which invokes 101 * the 'testMethod()' of RedefineClass_Debuggee class and prints the string 102 * returned by this method before redefining. 103 * <BR> Then the test performs VirtualMachine.RedefineClasses command 104 * for RedefineClass_Debuggee class - the 'testMethod()' is redefined. 105 * Next, the debuggee invokes the 'testMethod()' again and it is expected 106 * that the method returns another resulting string. 107 * The test checks that this resulting string is expected string. 108 */ testRedefineClasses001()109 public void testRedefineClasses001() { 110 String thisTestName = "testClassObject001"; 111 112 //check capability, relevant for this test 113 logWriter.println("=> Check capability: canRedefineClasses"); 114 if (!debuggeeWrapper.vmMirror.canRedefineClasses()) { 115 logWriter.println("##WARNING: this VM doesn't possess capability: canRedefineClasses"); 116 return; 117 } 118 119 logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": START..."); 120 synchronizer.receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY); 121 File newClassByteCodeFile = findNewClassByteCode(); 122 if ( newClassByteCodeFile == null ) { 123 logWriter.println 124 ("===> Can NOT find out byte code file for redefine:"); 125 logWriter.println 126 ("===> File name = " + byteCodeToRedefineFile); 127 logWriter.println 128 ("===> Test can NOT be run!"); 129 logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": FINISH"); 130 return; 131 } 132 133 logWriter.println 134 ("\n=> Send VirtualMachine::ClassesBySignature command and and get checked class referenceTypeID..."); 135 logWriter.println("=> checkedClassSignature = " + checkedClassSignature); 136 CommandPacket classesBySignatureCommand = new CommandPacket( 137 JDWPCommands.VirtualMachineCommandSet.CommandSetID, 138 JDWPCommands.VirtualMachineCommandSet.ClassesBySignatureCommand); 139 classesBySignatureCommand.setNextValueAsString(checkedClassSignature); 140 141 ReplyPacket classesBySignatureReply = debuggeeWrapper.vmMirror.performCommand(classesBySignatureCommand); 142 classesBySignatureCommand = null; 143 144 checkReplyPacket(classesBySignatureReply, "VirtualMachine::ClassesBySignature command"); 145 146 int returnedClassesNumber = classesBySignatureReply.getNextValueAsInt(); 147 logWriter.println("=> ReturnedClassesNumber = " + returnedClassesNumber); 148 if ( returnedClassesNumber != 1 ) { 149 // Number of returned reference types - is NOt used here 150 printErrorAndFail("Unexpected number of classes is returned: " + 151 returnedClassesNumber + 152 ", Expected number = 1"); 153 } 154 155 classesBySignatureReply.getNextValueAsByte(); 156 // refTypeTag of class - is NOt used here 157 158 long refTypeID = classesBySignatureReply.getNextValueAsReferenceTypeID(); 159 classesBySignatureReply = null; 160 161 logWriter.println("=> Checked class referenceTypeID = " + refTypeID); 162 163 logWriter.println("\n=> Preparing info for " + thisCommandName); 164 logWriter.println 165 ("=> File name with new class byte code to redefine = " + byteCodeToRedefineFile); 166 FileInputStream newClassByteCodeFileInputStream = null; 167 try { 168 newClassByteCodeFileInputStream = new FileInputStream(newClassByteCodeFile); 169 } catch (Throwable thrown) { 170 logWriter.println 171 ("===> Can NOT create FileInputStream for byte code file:"); 172 logWriter.println("===> File name = " + byteCodeToRedefineFile); 173 logWriter.println("===> Exception is thrown: " + thrown); 174 logWriter.println("===> Test can NOT be run!"); 175 logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": FINISH"); 176 return; 177 } 178 int newClassByteCodeSize = 0; 179 try { 180 newClassByteCodeSize = (int)newClassByteCodeFileInputStream.skip(Long.MAX_VALUE); 181 } catch (Throwable thrown) { 182 logWriter.println 183 ("===> Can NOT do FileInputStream.skip() to the end of file:"); 184 logWriter.println("===> File name = " + byteCodeToRedefineFile); 185 logWriter.println("===> Exception is thrown: " + thrown); 186 logWriter.println("===> Test can NOT be run!"); 187 logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": FINISH"); 188 return; 189 } 190 logWriter.println("=> newClassByteCodeSize = " + newClassByteCodeSize); 191 try { 192 newClassByteCodeFileInputStream.close(); 193 } catch (Throwable thrown) { 194 logWriter.println 195 ("===> WARNING: Can NOT close FileInputStream for byte code file:"); 196 logWriter.println("===> File name = " + byteCodeToRedefineFile); 197 logWriter.println("===> Exception is thrown: " + thrown); 198 } 199 newClassByteCodeFileInputStream = null; 200 201 try { 202 newClassByteCodeFileInputStream = new FileInputStream(newClassByteCodeFile); 203 } catch (Throwable thrown) { 204 logWriter.println 205 ("===> Can NOT re-create FileInputStream for byte code file:"); 206 logWriter.println("===> File name = " + byteCodeToRedefineFile); 207 logWriter.println("===> Exception is thrown: " + thrown); 208 logWriter.println("===> Test can NOT be run!"); 209 logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": FINISH"); 210 return; 211 } 212 213 CommandPacket checkedCommand = new CommandPacket( 214 JDWPCommands.VirtualMachineCommandSet.CommandSetID, 215 JDWPCommands.VirtualMachineCommandSet.RedefineClassesCommand); 216 checkedCommand.setNextValueAsInt(1); // number of classes to redefine 217 checkedCommand.setNextValueAsReferenceTypeID(refTypeID); 218 checkedCommand.setNextValueAsInt(newClassByteCodeSize); 219 int writtenBytes = 0; 220 int currentByte = 0; 221 while ( true ) { 222 try { 223 currentByte = newClassByteCodeFileInputStream.read(); 224 } catch (Throwable thrown) { 225 logWriter.println 226 ("===> Can NOT read current byte from byte code file:"); 227 logWriter.println("===> File name = " + byteCodeToRedefineFile); 228 logWriter.println("===> Byte number = " + writtenBytes); 229 logWriter.println("===> Exception is thrown: " + thrown); 230 logWriter.println("===> Test can NOT be run!"); 231 logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": FINISH"); 232 return; 233 } 234 if ( currentByte == -1 ) { // EOF is reached 235 break; 236 } 237 checkedCommand.setNextValueAsByte((byte)currentByte); 238 writtenBytes++; 239 } 240 logWriter.println("=> Number of written bytes as new class file = " + writtenBytes); 241 if ( newClassByteCodeSize != writtenBytes ) { 242 logWriter.println("===> WARNING: Number of written bytes != newClassByteCodeSize"); 243 logWriter.println("===> Test can NOT be run!"); 244 logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": FINISH"); 245 return; 246 } 247 248 logWriter.println("\n=> Send " + thisCommandName + " and check reply..."); 249 250 ReplyPacket checkedReply = debuggeeWrapper.vmMirror.performCommand(checkedCommand); 251 checkedCommand = null; 252 int[] expectedErrors = { 253 JDWPConstants.Error.NOT_IMPLEMENTED, 254 }; 255 short errorCode = checkedReply.getErrorCode(); 256 if ( errorCode != JDWPConstants.Error.NONE ) { 257 if ( errorCode != JDWPConstants.Error.UNSUPPORTED_VERSION ) { 258 finalSyncMessage = JPDADebuggeeSynchronizer.SGNL_CONTINUE; 259 printErrorAndFail( 260 "## WARNING: A class file for redefine has a version number not supported by this VM" + 261 "\n## File name with byte code = " + byteCodeToRedefineFile + 262 "\n## It should be re-created"); 263 } 264 boolean expectedErr = false; 265 for (int i=0; i < expectedErrors.length; i++) { 266 if ( errorCode == expectedErrors[i] ) { 267 expectedErr = true; 268 break; 269 } 270 } 271 if ( expectedErr ) { 272 logWriter.println("=> " + thisCommandName 273 + " returns expected ERROR = " + errorCode 274 + "(" + JDWPConstants.Error.getName(errorCode) + ")"); 275 logWriter.println 276 ("==> " + thisTestName + " for " + thisCommandName + ": FINISH"); 277 return; 278 } else { 279 finalSyncMessage = JPDADebuggeeSynchronizer.SGNL_CONTINUE; 280 printErrorAndFail(thisCommandName 281 + " returns unexpected ERROR = " + errorCode 282 + "(" + JDWPConstants.Error.getName(errorCode) + ")"); 283 } 284 } 285 logWriter.println("=> " + thisCommandName + " returns reply without any error"); 286 287 assertAllDataRead(checkedReply); 288 289 logWriter.println("\n=> Send Debuggee signal to continue and execute redefined testMethod"); 290 synchronizer.sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE); 291 292 String testMethodResult = synchronizer.receiveMessage(); 293 logWriter.println("=> Redefined testMethod result = \"" + testMethodResult + "\""); 294 if ( testMethodResult.equals("testMethod_Result_After_Redefine") ) { 295 logWriter.println("=> OK - it is expected result"); 296 } else { 297 printErrorAndFail("it is NOT expected result" + 298 "\n Expected result = \"testMethod_Result_After_Redefine\""); 299 } 300 301 logWriter.println("==> " + thisTestName + " for " + thisCommandName + ": FINISH"); 302 } 303 } 304