1 /* 2 * Copyright (c) 2003, 2005, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 25 import java.io.*; 26 import java.lang.instrument.*; 27 28 import java.security.ProtectionDomain; 29 import java.util.*; 30 31 32 /** 33 * Simple tests for the TransformerManager 34 * 35 */ 36 public abstract class 37 ATransformerManagementTestCase 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 }