blob: e5980d59fd658bd52f1a8cc186bf569fada954a7 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2001-2002 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23
24/**
25 * @test
26 * @bug 4287595
27 * @bug 4462989
28 * @bug 4531511
29 * @summary Test class redefinition
30 *
31 * @author Robert Field
32 *
33 * @library ..
34 * @run build TestScaffold VMConnection TargetListener TargetAdapter
35 * @run compile -g RedefineTest.java
36 * @run shell RedefineSetUp.sh
37 * @run main RedefineTest
38 */
39import com.sun.jdi.*;
40import com.sun.jdi.event.*;
41import com.sun.jdi.request.*;
42import java.util.*;
43import java.io.*;
44
45 /********** target program **********/
46
47class RedefineTarg {
48 public static void show(String where){
49 System.out.println("Returned: " + where);
50 }
51
52 public static void lastly(String where){
53 }
54
55 public static void main(String[] args){
56 RedefineSubTarg sub = new RedefineSubTarg();
57 String where = "";
58 for (int i = 0; i < 5; ++i) {
59 where = sub.foo(where);
60 show(where);
61 }
62 lastly(where);
63 }
64}
65
66 /********** test program **********/
67
68public class RedefineTest extends TestScaffold {
69 ReferenceType targetClass;
70 static final String expected ="Boring Boring Different Boring Different ";
71 int repetitionCount = 0;
72 boolean beforeRedefine = true;
73
74 RedefineTest (String args[]) {
75 super(args);
76 }
77
78 public static void main(String[] args) throws Exception {
79 new RedefineTest(args).startTests();
80 }
81
82 /********** event handlers **********/
83
84 public void methodEntered(MethodEntryEvent event) {
85 Method meth = event.location().method();
86 ThreadReference thread = event.thread();
87
88 if (meth.name().equals("foo")) {
89 ++repetitionCount;
90 beforeRedefine = true;
91 try {
92 expectNonObsolete(thread);
93 inspectLineNumber(event, thread.frame(0));
94
95 doRedefine(thread);
96 beforeRedefine = false;
97
98 switch (repetitionCount) {
99 case 1:
100 case 5:
101 expectNonObsolete(thread);
102 inspectLineNumber(event, thread.frame(0));
103 break;
104 case 2:
105 case 3:
106 case 4:
107 expectObsolete(thread);
108 inspectLineNumber(event, thread.frame(0));
109 break;
110 }
111
112
113 } catch (Exception exc) {
114 failure("Test Failure: unexpected exception - " + exc);
115 exc.printStackTrace();
116 }
117 }
118 }
119
120 public void breakpointReached(BreakpointEvent event) {
121 ThreadReference thread = event.thread();
122 try {
123 StackFrame frame = thread.frame(0);
124 LocalVariable lv = frame.visibleVariableByName("where");
125 Value vWhere = frame.getValue(lv);
126 String remoteWhere = ((StringReference)vWhere).value();
127 println("Value of where: " + remoteWhere);
128 if (!remoteWhere.equals(expected)) {
129 failure("FAIL: expected result string: '" + expected +
130 "' got: '" + remoteWhere + "'");
131 }
132 } catch (Exception thr) {
133 failure("Test Failure: unexpected exception: " + thr);
134 }
135 }
136
137 /********** test assists **********/
138
139 void expectNonObsolete(ThreadReference thread) throws Exception {
140 if (isObsolete(thread)) {
141 failure("FAIL: Method should NOT be obsolete");
142 } else {
143 println("as it should be, not obsolete");
144 }
145 }
146
147 void expectObsolete(ThreadReference thread) throws Exception {
148 if (isObsolete(thread)) {
149 println("obsolete like it should be");
150 } else {
151 failure("FAIL: Method should be obsolete");
152 }
153 }
154
155 void inspectLineNumber(LocatableEvent event, StackFrame frame) throws Exception {
156 /*
157 * For each value of repetitionCount, use the beforeRedefine
158 * boolean to distinguish the time before and after the actual
159 * redefinition takes place. Line numbers are inspected both
160 * before and after each redefine.
161 */
162 int n = -1;
163 int expectedLine = -1;
164 switch (repetitionCount) {
165 case 1:
166 expectedLine = 4;
167 break;
168 case 2:
169 expectedLine = beforeRedefine ? 4:21;
170 break;
171 case 3:
172 expectedLine = beforeRedefine ? 21:4;
173 break;
174 case 4:
175 expectedLine = beforeRedefine ? 4:21;
176 break;
177 case 5:
178 /* The class won't be redefined on this iteration (look
179 * for a java.lang.UnsupportedOperationException instead)
180 * so expected line stays the same as last successful
181 * redefine.
182 */
183 expectedLine = 21;
184 break;
185 }
186 Method method = event.location().method();
187 if (frame.location().method().isObsolete()) {
188 /*
189 * Then skip. Obsolete methods are not interesting to
190 * inspect.
191 */
192 println("inspectLineNumber skipping obsolete method " + method.name());
193 } else {
194 n = method.location().lineNumber();
195 int m = frame.location().lineNumber();
196 if ((n != expectedLine) || (n != m)) {
197 failure("Test Failure: line number disagreement: " +
198 n + " (event) versus " + m + " (frame) versus " + expectedLine +
199 " (expected)");
200 } else {
201 println("inspectLineNumber in method " + method.name() + " at line " + n);
202 }
203 }
204 }
205
206 boolean isObsolete(ThreadReference thread) throws Exception {
207 StackFrame frame = thread.frame(0);
208 Method meth = frame.location().method();
209 return meth.isObsolete();
210 }
211
212 void doRedefine(ThreadReference thread) throws Exception {
213 Exception receivedException = null;
214 String fileName = "notThis";
215
216 switch (repetitionCount) {
217 case 1:
218 fileName = "RedefineSubTarg.class";
219 break;
220 case 2:
221 fileName = "Different_RedefineSubTarg.class";
222 break;
223 case 3:
224 fileName = "RedefineSubTarg.class";
225 break;
226 case 4:
227 fileName = "Different_RedefineSubTarg.class";
228 break;
229 case 5:
230 fileName = "SchemaChange_RedefineSubTarg.class";
231 break;
232 }
233 File phyl = new File(fileName);
234 byte[] bytes = new byte[(int)phyl.length()];
235 InputStream in = new FileInputStream(phyl);
236 in.read(bytes);
237 in.close();
238
239 Map map = new HashMap();
240 map.put(findReferenceType("RedefineSubTarg"), bytes);
241
242 println(System.getProperty("line.separator") + "Iteration # " + repetitionCount +
243 " ------ Redefine as: " + fileName);
244 try {
245 vm().redefineClasses(map);
246 } catch (Exception thr) {
247 receivedException = thr;
248 }
249 switch (repetitionCount) {
250 case 5:
251 if (receivedException == null) {
252 failure("FAIL: no exception; expected: UnsupportedOperationException");
253 } else if (receivedException instanceof UnsupportedOperationException) {
254 println("Received expected exception: " + receivedException);
255 } else {
256 failure("FAIL: got exception: " + receivedException +
257 ", expected: UnsupportedOperationException");
258 }
259 break;
260 default:
261 if (receivedException != null) {
262 failure("FAIL: unexpected exception: " +
263 receivedException);
264 }
265 break;
266 }
267 return;
268 }
269
270 /********** test core **********/
271
272 protected void runTests() throws Exception {
273
274 BreakpointEvent bpe = startToMain("RedefineTarg");
275 targetClass = bpe.location().declaringType();
276 EventRequestManager erm = vm().eventRequestManager();
277
278 /*
279 * Method entry in sub targ
280 */
281 MethodEntryRequest mee = erm.createMethodEntryRequest();
282 mee.addClassFilter("RedefineSubTarg");
283 mee.enable();
284
285 /*
286 * BP at end to get value
287 */
288 List lastlys = targetClass.methodsByName("lastly");
289 if (lastlys.size() != 1) {
290 throw new Exception ("TestFailure: Expected one 'lastly' method, found: " +
291 lastlys);
292 }
293 Location loc = ((Method)(lastlys.get(0))).location();
294 EventRequest req = erm.createBreakpointRequest(loc);
295 req.enable();
296
297 // Allow application to complete and shut down
298 listenUntilVMDisconnect();
299
300 /*
301 * deal with results of test
302 * if anything has called failure("foo") testFailed will be true
303 */
304 if (!testFailed) {
305 println("RedefineTest: passed");
306 } else {
307 throw new Exception("RedefineTest: failed");
308 }
309 }
310}