blob: 0a8f709b831891e834e600d5426cdbe1d3edd25d [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2005 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
25import java.io.*;
26import java.lang.instrument.*;
27
28import java.security.ProtectionDomain;
29import java.util.*;
30
31
32/**
33 * Simple tests for the TransformerManager
34 *
35 */
36public abstract class
37ATransformerManagementTestCase
38 extends AInstrumentationTestCase
39{
40 private static final String redefinedClassName = "DummyClass";
41
42 protected int kModSamples = 2;
43 public final ClassFileTransformer[] kTransformerSamples = new ClassFileTransformer[]
44 {
45 new MyClassFileTransformer( Integer.toString(0)),
46 new MyClassFileTransformer( Integer.toString(1)),
47 new MyClassFileTransformer( Integer.toString(2)),
48 new MyClassFileTransformer( Integer.toString(3)),
49 new MyClassFileTransformer( Integer.toString(4)),
50 new MyClassFileTransformer( Integer.toString(5)),
51 new MyClassFileTransformer( Integer.toString(6)),
52 new MyClassFileTransformer( Integer.toString(7)),
53 new MyClassFileTransformer( Integer.toString(8)),
54 new MyClassFileTransformer( Integer.toString(9)),
55 new MyClassFileTransformer( Integer.toString(10)),
56 new MyClassFileTransformer( Integer.toString(11)),
57 new MyClassFileTransformer( Integer.toString(12)),
58 new MyClassFileTransformer( Integer.toString(13)),
59 new MyClassFileTransformer( Integer.toString(14)),
60 new MyClassFileTransformer( Integer.toString(15)),
61 new MyClassFileTransformer( Integer.toString(16)),
62 new MyClassFileTransformer( Integer.toString(17)),
63 new MyClassFileTransformer( Integer.toString(18)),
64 };
65
66 private ArrayList fTransformers; // The list of transformers
67 private int fTransformerIndex; // The number of transformers encountered
68 private String fDelayedFailure; // Set non-null if failed in transformer
69
70
71 /**
72 * Constructor for ATransformerManagementTestCase.
73 */
74 public ATransformerManagementTestCase(String name)
75 {
76 super(name);
77 }
78
79
80 /**
81 * Returns one of the sample transformers
82 * @return a random transformer
83 */
84 protected ClassFileTransformer
85 getRandomTransformer()
86 {
87 int randIndex = (int)Math.floor(Math.random() * kTransformerSamples.length);
88 verbosePrint("Choosing random transformer #" + randIndex);
89 return kTransformerSamples[randIndex];
90 }
91
92 /**
93 * Method addTransformerToManager.
94 * @param manager
95 * @param transformer
96 */
97 protected void
98 addTransformerToManager(
99 Instrumentation manager,
100 ClassFileTransformer transformer)
101 {
102 if (transformer != null)
103 {
104 fTransformers.add(transformer);
105 }
106 manager.addTransformer(transformer);
107 verbosePrint("Added transformer " + transformer);
108 }
109
110 /**
111 * Remove transformer from manager and list
112 * @param manager
113 * @param transformer
114 */
115 protected void
116 removeTransformerFromManager(
117 Instrumentation manager,
118 ClassFileTransformer transformer)
119 {
120 assertTrue("Transformer not found in manager ("+transformer+")", manager.removeTransformer(transformer));
121
122 if (transformer != null)
123 {
124 fTransformers.remove(transformer);
125 }
126 verbosePrint("Removed transformer " + transformer);
127 }
128
129 /**
130 * Decrements the transformer index as well as removes transformer
131 * @param fInst manager
132 * @param transformer transformer to remove
133 * @param decrementIndex the tranformer index gets out of sync with transformers
134 * that are removed from the manager
135 */
136 protected void
137 removeTransformerFromManager( Instrumentation manager,
138 ClassFileTransformer transformer,
139 boolean decrementIndex)
140 {
141 removeTransformerFromManager(manager, transformer);
142 if (decrementIndex)
143 {
144 fTransformerIndex--;
145 verbosePrint("removeTransformerFromManager fTransformerIndex decremented to: " +
146 fTransformerIndex);
147 }
148 }
149
150 /**
151 * verify transformer by asserting that the number of transforms that occured
152 * is the same as the number of valid transformers added to the list.
153 * @param manager
154 */
155 protected void
156 verifyTransformers(Instrumentation manager)
157 {
158 File f = new File(System.getProperty("test.classes", "."), redefinedClassName + ".class");
159 System.out.println("Reading test class from " + f);
160 try
161 {
162 InputStream redefineStream = new FileInputStream(f);
163 byte[] bytes = NamedBuffer.loadBufferFromStream(redefineStream);
164 ClassDefinition cd = new ClassDefinition(DummyClass.class, bytes);
165 fInst.redefineClasses(new ClassDefinition[]{ cd });
166 verbosePrint("verifyTransformers redefined " + redefinedClassName);
167 }
168 catch (IOException e)
169 {
170 fail("Could not load the class: " + redefinedClassName);
171 }
172 catch (ClassNotFoundException e)
173 {
174 fail("Could not find the class: " + redefinedClassName);
175 }
176 catch (UnmodifiableClassException e)
177 {
178 fail("Could not modify the class: " + redefinedClassName);
179 }
180
181 // Report any delayed failures
182 assertTrue(fDelayedFailure, fDelayedFailure == null);
183
184 assertEquals("The number of transformers that were run does not match the expected number added to manager",
185 fTransformers.size(), fTransformerIndex);
186 }
187
188
189 /**
190 * Asserts that the transformer being checked by the manager is the correct
191 * one (as far as order goes) and updates the number of transformers that have
192 * been called. Note that since this is being called inside of a transformer,
193 * a standard assert (which throws an exception) cannot be used since it would
194 * simply cancel the transformation and otherwise be ignored. Instead, note
195 * the failure for delayed processing.
196 * @param ClassFileTransformer
197 */
198 private void
199 checkInTransformer(ClassFileTransformer transformer)
200 {
201 verbosePrint("checkInTransformer: " + transformer);
202 if (fDelayedFailure == null)
203 {
204 if (fTransformers.size() <= fTransformerIndex)
205 {
206 String msg = "The number of transformers that have checked in (" +(fTransformerIndex+1) +
207 ") is greater number of tranformers created ("+fTransformers.size()+")";
208 fDelayedFailure = msg;
209 System.err.println("Delayed failure: " + msg);
210 verbosePrint("Delayed failure: " + msg);
211 }
212 if (!fTransformers.get(fTransformerIndex).equals(transformer))
213 {
214 String msg = "Transformer " + fTransformers.get(fTransformerIndex) +
215 " should be the same as " + transformer;
216 fDelayedFailure = msg;
217 System.err.println("Delayed failure: " + msg);
218 verbosePrint("Delayed failure: " + msg);
219 }
220 fTransformerIndex++;
221 verbosePrint("fTransformerIndex incremented to: " + fTransformerIndex);
222 }
223 }
224
225 /**
226 * Create a new manager, a new transformer list, and initializes the number of transformers
227 * indexed to zero.
228 */
229 protected void
230 setUp()
231 throws Exception
232 {
233 super.setUp();
234 fTransformers = new ArrayList();
235 fTransformerIndex = 0;
236 fDelayedFailure = null;
237 verbosePrint("setUp completed");
238 }
239
240 /**
241 * Sets the manager and transformers to null so that setUp needs to update.
242 */
243 protected void
244 tearDown()
245 throws Exception
246 {
247 verbosePrint("tearDown beginning");
248 fTransformers = null;
249 super.tearDown();
250 }
251
252 /*
253 * Simple transformer that registers when it transforms
254 */
255 public class MyClassFileTransformer extends SimpleIdentityTransformer {
256 private final String fID;
257
258 public MyClassFileTransformer(String id) {
259 super();
260 fID = id;
261 }
262
263 public String toString() {
264 return MyClassFileTransformer.this.getClass().getName() + fID;
265 }
266
267 public byte[]
268 transform(
269 ClassLoader loader,
270 String className,
271 Class<?> classBeingRedefined,
272 ProtectionDomain protectionDomain,
273 byte[] classfileBuffer) {
274
275 // The transform testing is triggered by redefine, ignore others
276 if (classBeingRedefined != null) checkInTransformer(MyClassFileTransformer.this);
277
278 return super.transform( loader,
279 className,
280 classBeingRedefined,
281 protectionDomain,
282 classfileBuffer);
283 }
284 }
285
286
287 /**
288 * Class loader that does nothing
289 */
290 public class MyClassLoader extends ClassLoader
291 {
292 /**
293 * Constructor for MyClassLoader.
294 */
295 public MyClassLoader()
296 {
297 super();
298 }
299
300 }
301
302 public String debug_byteArrayToString(byte[] b) {
303 if (b == null) return "null";
304
305 StringBuffer buf = new StringBuffer();
306 buf.append("byte[");
307 buf.append(b.length);
308 buf.append("] (");
309 for (int i = 0; i < b.length; i++)
310 {
311 buf.append(b[i]);
312 buf.append(",");
313 }
314 buf.deleteCharAt(buf.length()-1);
315 buf.append(")");
316
317 return buf.toString();
318 }
319}