001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: *
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: /**
020: * @author Anatoly F. Bondarenko
021: * @version $Revision: 1.8 $
022: */
023:
024: /**
025: * Created on 30.03.2005
026: */package org.apache.harmony.jpda.tests.jdwp.VirtualMachine;
027:
028: import java.io.*;
029:
030: import org.apache.harmony.jpda.tests.framework.jdwp.CommandPacket;
031: import org.apache.harmony.jpda.tests.framework.jdwp.JDWPCommands;
032: import org.apache.harmony.jpda.tests.framework.jdwp.JDWPConstants;
033: import org.apache.harmony.jpda.tests.framework.jdwp.ReplyPacket;
034: import org.apache.harmony.jpda.tests.jdwp.share.JDWPSyncTestCase;
035: import org.apache.harmony.jpda.tests.share.JPDADebuggeeSynchronizer;
036:
037: /**
038: * JDWP Unit test for VirtualMachine.RedefineClasses command.
039: */
040: public class RedefineClassesTest extends JDWPSyncTestCase {
041:
042: static final int testStatusPassed = 0;
043: static final int testStatusFailed = -1;
044: static final String this CommandName = "VirtualMachine::RedefineClasses command";
045: static final String checkedClassSignature = "Lorg/apache/harmony/jpda/tests/jdwp/VirtualMachine/RedefineClass_Debuggee;";
046: static final String byteCodeToRedefineFile = "RedefineByteCode_Debuggee001";
047:
048: protected String getDebuggeeClassName() {
049: return "org.apache.harmony.jpda.tests.jdwp.VirtualMachine.RedefineClassesDebuggee";
050: }
051:
052: File findNewClassByteCode() {
053: File foundFile = null;
054: String nameSeparator = File.separator;
055: String pathSeparator = File.pathSeparator;
056: String byteCodeFileNameSuffix = "org" + nameSeparator
057: + "apache" + nameSeparator + "harmony" + nameSeparator
058: + "jpda" + nameSeparator + "tests" + nameSeparator
059: + "jdwp" + nameSeparator + "VirtualMachine"
060: + nameSeparator + byteCodeToRedefineFile;
061: String byteCodeFileName = null;
062: String classPaths = System.getProperty("java.class.path");
063: int begPos = 0;
064: int classPathsLength = classPaths.length();
065: ;
066:
067: for (int i = 0; i <= classPathsLength; i++) {
068: if (i == classPathsLength) {
069: if (begPos == i) {
070: break;
071: }
072: } else {
073: if (!pathSeparator.equals(classPaths
074: .substring(i, i + 1))) {
075: continue;
076: }
077: if (begPos == i) {
078: begPos++;
079: continue;
080: }
081: }
082: byteCodeFileName = classPaths.substring(begPos, i);
083: if (!nameSeparator.equals(classPaths.substring(i - 1, i))) {
084: byteCodeFileName = byteCodeFileName + nameSeparator;
085: }
086: byteCodeFileName = byteCodeFileName
087: + byteCodeFileNameSuffix;
088: foundFile = new File(byteCodeFileName);
089: if (foundFile.exists()) {
090: break;
091: }
092: foundFile = null;
093: begPos = i + 1;
094: }
095: return foundFile;
096: }
097:
098: /**
099: * 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: */
109: public void testRedefineClasses001() {
110: String this TestName = "testClassObject001";
111:
112: //check capability, relevant for this test
113: logWriter.println("=> Check capability: canRedefineClasses");
114: debuggeeWrapper.vmMirror.capabilities();
115: boolean isCapability = debuggeeWrapper.vmMirror.targetVMCapabilities.canRedefineClasses;
116: if (!isCapability) {
117: logWriter
118: .println("##WARNING: this VM doesn't possess capability: canRedefineClasses");
119: return;
120: }
121:
122: logWriter.println("==> " + this TestName + " for "
123: + this CommandName + ": START...");
124: synchronizer
125: .receiveMessage(JPDADebuggeeSynchronizer.SGNL_READY);
126: File newClassByteCodeFile = findNewClassByteCode();
127: if (newClassByteCodeFile == null) {
128: logWriter
129: .println("===> Can NOT find out byte code file for redefine:");
130: logWriter.println("===> File name = "
131: + byteCodeToRedefineFile);
132: logWriter.println("===> Test can NOT be run!");
133: logWriter.println("==> " + this TestName + " for "
134: + this CommandName + ": FINISH");
135: return;
136: }
137:
138: logWriter
139: .println("\n=> Send VirtualMachine::ClassesBySignature command and and get checked class referenceTypeID...");
140: logWriter.println("=> checkedClassSignature = "
141: + checkedClassSignature);
142: CommandPacket classesBySignatureCommand = new CommandPacket(
143: JDWPCommands.VirtualMachineCommandSet.CommandSetID,
144: JDWPCommands.VirtualMachineCommandSet.ClassesBySignatureCommand);
145: classesBySignatureCommand
146: .setNextValueAsString(checkedClassSignature);
147:
148: ReplyPacket classesBySignatureReply = debuggeeWrapper.vmMirror
149: .performCommand(classesBySignatureCommand);
150: classesBySignatureCommand = null;
151:
152: checkReplyPacket(classesBySignatureReply,
153: "VirtualMachine::ClassesBySignature command");
154:
155: int returnedClassesNumber = classesBySignatureReply
156: .getNextValueAsInt();
157: logWriter.println("=> ReturnedClassesNumber = "
158: + returnedClassesNumber);
159: if (returnedClassesNumber != 1) {
160: // Number of returned reference types - is NOt used here
161: printErrorAndFail("Unexpected number of classes is returned: "
162: + returnedClassesNumber + ", Expected number = 1");
163: }
164:
165: classesBySignatureReply.getNextValueAsByte();
166: // refTypeTag of class - is NOt used here
167:
168: long refTypeID = classesBySignatureReply
169: .getNextValueAsReferenceTypeID();
170: classesBySignatureReply = null;
171:
172: logWriter.println("=> Checked class referenceTypeID = "
173: + refTypeID);
174:
175: logWriter.println("\n=> Preparing info for " + this CommandName);
176: logWriter
177: .println("=> File name with new class byte code to redefine = "
178: + byteCodeToRedefineFile);
179: FileInputStream newClassByteCodeFileInputStream = null;
180: try {
181: newClassByteCodeFileInputStream = new FileInputStream(
182: newClassByteCodeFile);
183: } catch (Throwable thrown) {
184: logWriter
185: .println("===> Can NOT create FileInputStream for byte code file:");
186: logWriter.println("===> File name = "
187: + byteCodeToRedefineFile);
188: logWriter.println("===> Exception is thrown: " + thrown);
189: logWriter.println("===> Test can NOT be run!");
190: logWriter.println("==> " + this TestName + " for "
191: + this CommandName + ": FINISH");
192: return;
193: }
194: int newClassByteCodeSize = 0;
195: try {
196: newClassByteCodeSize = (int) newClassByteCodeFileInputStream
197: .skip(Long.MAX_VALUE);
198: } catch (Throwable thrown) {
199: logWriter
200: .println("===> Can NOT do FileInputStream.skip() to the end of file:");
201: logWriter.println("===> File name = "
202: + byteCodeToRedefineFile);
203: logWriter.println("===> Exception is thrown: " + thrown);
204: logWriter.println("===> Test can NOT be run!");
205: logWriter.println("==> " + this TestName + " for "
206: + this CommandName + ": FINISH");
207: return;
208: }
209: logWriter.println("=> newClassByteCodeSize = "
210: + newClassByteCodeSize);
211: try {
212: newClassByteCodeFileInputStream.close();
213: } catch (Throwable thrown) {
214: logWriter
215: .println("===> WARNING: Can NOT close FileInputStream for byte code file:");
216: logWriter.println("===> File name = "
217: + byteCodeToRedefineFile);
218: logWriter.println("===> Exception is thrown: " + thrown);
219: }
220: newClassByteCodeFileInputStream = null;
221:
222: try {
223: newClassByteCodeFileInputStream = new FileInputStream(
224: newClassByteCodeFile);
225: } catch (Throwable thrown) {
226: logWriter
227: .println("===> Can NOT re-create FileInputStream for byte code file:");
228: logWriter.println("===> File name = "
229: + byteCodeToRedefineFile);
230: logWriter.println("===> Exception is thrown: " + thrown);
231: logWriter.println("===> Test can NOT be run!");
232: logWriter.println("==> " + this TestName + " for "
233: + this CommandName + ": FINISH");
234: return;
235: }
236:
237: CommandPacket checkedCommand = new CommandPacket(
238: JDWPCommands.VirtualMachineCommandSet.CommandSetID,
239: JDWPCommands.VirtualMachineCommandSet.RedefineClassesCommand);
240: checkedCommand.setNextValueAsInt(1); // number of classes to redefine
241: checkedCommand.setNextValueAsReferenceTypeID(refTypeID);
242: checkedCommand.setNextValueAsInt(newClassByteCodeSize);
243: int writtenBytes = 0;
244: int currentByte = 0;
245: while (true) {
246: try {
247: currentByte = newClassByteCodeFileInputStream.read();
248: } catch (Throwable thrown) {
249: logWriter
250: .println("===> Can NOT read current byte from byte code file:");
251: logWriter.println("===> File name = "
252: + byteCodeToRedefineFile);
253: logWriter.println("===> Byte number = " + writtenBytes);
254: logWriter
255: .println("===> Exception is thrown: " + thrown);
256: logWriter.println("===> Test can NOT be run!");
257: logWriter.println("==> " + this TestName + " for "
258: + this CommandName + ": FINISH");
259: return;
260: }
261: if (currentByte == -1) { // EOF is reached
262: break;
263: }
264: checkedCommand.setNextValueAsByte((byte) currentByte);
265: writtenBytes++;
266: }
267: logWriter
268: .println("=> Number of written bytes as new class file = "
269: + writtenBytes);
270: if (newClassByteCodeSize != writtenBytes) {
271: logWriter
272: .println("===> WARNING: Number of written bytes != newClassByteCodeSize");
273: logWriter.println("===> Test can NOT be run!");
274: logWriter.println("==> " + this TestName + " for "
275: + this CommandName + ": FINISH");
276: return;
277: }
278:
279: logWriter.println("\n=> Send " + this CommandName
280: + " and check reply...");
281:
282: ReplyPacket checkedReply = debuggeeWrapper.vmMirror
283: .performCommand(checkedCommand);
284: checkedCommand = null;
285: int[] expectedErrors = { JDWPConstants.Error.NOT_IMPLEMENTED, };
286: short errorCode = checkedReply.getErrorCode();
287: if (errorCode != JDWPConstants.Error.NONE) {
288: if (errorCode != JDWPConstants.Error.UNSUPPORTED_VERSION) {
289: finalSyncMessage = JPDADebuggeeSynchronizer.SGNL_CONTINUE;
290: printErrorAndFail("## WARNING: A class file for redefine has a version number not supported by this VM"
291: + "\n## File name with byte code = "
292: + byteCodeToRedefineFile
293: + "\n## It should be re-created");
294: }
295: boolean expectedErr = false;
296: for (int i = 0; i < expectedErrors.length; i++) {
297: if (errorCode == expectedErrors[i]) {
298: expectedErr = true;
299: break;
300: }
301: }
302: if (expectedErr) {
303: logWriter.println("=> " + this CommandName
304: + " returns expected ERROR = " + errorCode
305: + "(" + JDWPConstants.Error.getName(errorCode)
306: + ")");
307: logWriter.println("==> " + this TestName + " for "
308: + this CommandName + ": FINISH");
309: return;
310: } else {
311: finalSyncMessage = JPDADebuggeeSynchronizer.SGNL_CONTINUE;
312: printErrorAndFail(this CommandName
313: + " returns unexpected ERROR = " + errorCode
314: + "(" + JDWPConstants.Error.getName(errorCode)
315: + ")");
316: }
317: }
318: logWriter.println("=> " + this CommandName
319: + " returns reply without any error");
320:
321: assertAllDataRead(checkedReply);
322:
323: logWriter
324: .println("\n=> Send Debuggee signal to continue and execute redefined testMethod");
325: synchronizer
326: .sendMessage(JPDADebuggeeSynchronizer.SGNL_CONTINUE);
327:
328: String testMethodResult = synchronizer.receiveMessage();
329: logWriter.println("=> Redefined testMethod result = \""
330: + testMethodResult + "\"");
331: if (testMethodResult.equals("testMethod_Result_After_Redefine")) {
332: logWriter.println("=> OK - it is expected result");
333: } else {
334: printErrorAndFail("it is NOT expected result"
335: + "\n Expected result = \"testMethod_Result_After_Redefine\"");
336: }
337:
338: logWriter.println("==> " + this TestName + " for "
339: + this CommandName + ": FINISH");
340: }
341:
342: public static void main(String[] args) {
343: junit.textui.TestRunner.run(RedefineClassesTest.class);
344: }
345: }
|