• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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