1 /* TestStmtCoverage.java */ 2 package org.quilt.cover.stmt; 3 4 import java.io.*; 5 import java.lang.Class; 6 import java.lang.reflect.*; 7 import java.net.*; 8 9 // DEBUG 10 import java.lang.reflect.Field; 11 import java.lang.reflect.Method; 12 // END 13 14 import junit.framework.*; 15 import org.apache.bcel.generic.*; 16 import org.quilt.cl.*; 17 import org.quilt.cover.stmt.*; 18 19 /*** 20 * This is derived from org.quilt.cl.TestTransformer; it instruments 21 * the test-data classes and the classes synthesized by ClassFactory. 22 * All of the instrumented classes are run and checked to see that 23 * they produce normal output, despite the instrumentation ;-) 24 * 25 * @author <a href="jddixon@users.sourceforge.net">Jim Dixon</a> 26 */ 27 public class TestStmtCoverage extends TestCase { 28 29 private ControlFlowGraph cfg; 30 31 /*** Classpath. */ 32 private URL [] cp = null; // this is built up below 33 34 private String[] delegating = { 35 // NOTHING beyond standard defaults 36 }; 37 // we want everything to be instrumented 38 private String[] include = { 39 "test.data.", 40 "AnonymousClass", "AnonymousClass2Catches", 41 "BasicLoad", "ComplicatedConstructor", 42 "ExceptionLoad", "ExceptionThrow", 43 "Finally", "Finally2Classes", 44 "InnerClass", "Looper", 45 "NestedTryBlocks", "OddSwitches", 46 "PrivateClass", "StaticInit", 47 "SuperClass", "SwitchLoad", 48 "Wimple" 49 }; 50 private String[] exclude = { 51 // NOTHING 52 }; 53 54 private GraphXformer spy; 55 private GraphXformer talker, talker2; 56 57 private StmtRegistry stmtReg; 58 59 private QuiltClassLoader qLoader = null; 60 61 public TestStmtCoverage (String name) { 62 super(name); 63 } 64 65 public void setUp () { 66 File sam1 = new File ("target/test-data-classes/"); 67 String fullPath1 = sam1.getAbsolutePath() + "/"; 68 File sam2 = new File ("target/classes"); 69 String fullPath2 = sam2.getAbsolutePath() + "/"; 70 File sam3 = new File ("target/test-classes"); 71 String fullPath3 = sam3.getAbsolutePath() + "/"; 72 try { 73 // Terminating slash is required. Relative paths don't 74 // work. 75 URL [] samples = { 76 new URL ( "file://" + fullPath1), 77 new URL ( "file://" + fullPath2), 78 new URL ( "file://" + fullPath3) 79 }; 80 cp = samples; 81 } catch (MalformedURLException e) { 82 e.printStackTrace(); 83 fail ("problem creating class path"); 84 } 85 ClassLoader parent = ClassLoader.getSystemClassLoader(); 86 qLoader = new QuiltClassLoader( 87 cp, 88 parent, // parent 89 delegating, // delegated classes 90 include, // being instrumented 91 exclude); // do NOT instrument 92 93 // Graph Xformers ///////////////////////////////// 94 spy = new GraphSpy(); 95 qLoader.addGraphXformer(spy); 96 97 // dumps graph BEFORE transformation 98 talker = new GraphTalker(); 99 qLoader.addGraphXformer(talker); 100 101 // adds xformers for statement coverage to qLoader 102 // EXPERIMENT 103 stmtReg = (StmtRegistry) qLoader.addQuiltRegistry( 104 "org.quilt.cover.stmt.StmtRegistry"); 105 // old way 106 //stmtReg = new StmtRegistry(qLoader); 107 //qLoader.addQuiltRegistry(stmtReg); 108 109 // dumps graph AFTER transformation 110 talker2 = new GraphTalker(); 111 qLoader.addGraphXformer(talker2); 112 } 113 114 // SUPPORT METHODS ////////////////////////////////////////////// 115 private RunTest loadAsRunTest (String name) { 116 Class clazz = null; 117 try { 118 clazz = qLoader.loadClass(name); 119 // // DEBUG -- trying to get fields causes an error 120 // Field[] fields = clazz.getFields(); 121 // StringBuffer fieldData = new StringBuffer(); 122 // for (int k = 0; k < fields.length; k++) 123 // fieldData.append(" ").append(fields[k].toString()) 124 // .append("\n"); 125 126 // Method[] methods = clazz.getMethods(); 127 // StringBuffer methodData = new StringBuffer(); 128 // for (int k = 0; k < methods.length; k++) 129 // methodData.append(" ").append(methods[k].toString()) 130 // .append("\n"); 131 // 132 // System.out.println("TestStmtRegistry: loading class " + name 133 // + "\nFIELDS (" + fields.length + ") :\n" 134 // + fieldData.toString() 135 // + "\nMETHODS (" + methods.length + ") :\n" 136 // + methodData.toString() ); 137 // // END 138 } catch (ClassNotFoundException e) { 139 e.printStackTrace(); 140 fail ("exception loading " + name + " using loadClass"); 141 } 142 RunTest rt = null; 143 try { 144 rt = (RunTest) clazz.newInstance(); 145 } catch ( InstantiationException e ) { 146 fail ("InstantiationException instantiating loaded class " + name); 147 } catch ( IllegalAccessException e ) { 148 fail ("IllegalAccessException instantiating loaded class " + name); 149 } catch (ClassCastException e) { 150 fail ("ClassCastException instantiating loaded class " + name); 151 } 152 return rt; 153 } 154 /*** 155 * Check that the class has been properly instrumented by 156 * org.quilt.cover.stmt. At the moment this means only that the 157 * hitcount array, public static int[] q$$q is one of the class's 158 * fields. We also check that it has NOT been initialized, 159 * although we will eventually make sure that it has been. 160 */ 161 private void checkInstrumentation(Object rt) { 162 String name = rt.getClass().getName(); 163 System.out.println("checkInstrumentation for class " + name); 164 try { 165 Field qField = rt.getClass().getField("q$$q"); 166 if (qField == null) { 167 System.out.println(name + " has no hit count array"); 168 fail(name + " has NO hit count array"); 169 } else try { 170 int [] hitCounts = (int[]) qField.get(null); 171 assertNotNull("q$$q has not been initialized", hitCounts); 172 } catch (IllegalAccessException e) { 173 e.printStackTrace(); 174 } 175 // check version 176 qField = rt.getClass().getField("q$$qVer"); 177 if (qField == null) { 178 System.out.println(name + " has no version field"); 179 fail(name + " has NO version field"); 180 } else try { 181 int version = qField.getInt(qField); 182 assertEquals("q$$q has wrong version number", 0, version); 183 } catch (IllegalAccessException e) { 184 e.printStackTrace(); 185 } 186 // check StmtRegistry 187 188 } catch (NoSuchFieldException e) { 189 fail (name + " has no q$$q field"); 190 } 191 } 192 193 // ACTUAL TESTS ///////////////////////////////////////////////// 194 public void testGetReg() { 195 StmtRegistry regInLoader = (StmtRegistry)qLoader.getRegistry( 196 "org.quilt.cover.stmt.StmtRegistry"); 197 assertNotNull("qLoader StmtRegistry is null", regInLoader); 198 assertSame ("qLoader has different StmtRegistry", 199 stmtReg, regInLoader); 200 } 201 public void testLoader() { 202 Class a1 = null; 203 try { 204 a1 = qLoader.loadClass("AnonymousClass"); 205 } catch (ClassNotFoundException e) { 206 e.printStackTrace(); 207 fail ("Error loading AnonymousClass using loadClass"); 208 } 209 assertNotNull("qLoader returned null", a1); 210 } // END 211 212 // /*** 213 // * Test classes from src/test-data. All of these (should) have a 214 // * RunTest interface. They are loaded and then run to see that 215 // * they produce expected values. 216 // * 217 // * By and large the test inputs are primes greater than 2; in earlier 218 // * tests some failed, returned 0, and were judged successful because 219 // * 0 was the expected result. 220 // * 221 // * At the moment these are split into three groups, so that if they 222 // * fail we will see more results. 223 // */ 224 public void testInvokeTestData() { 225 RunTest 226 rt = loadAsRunTest("AnonymousClass"); 227 checkInstrumentation(rt); 228 // AnonymousClass.runTest(x) returns x 229 assertEquals ("AnonymousClass isn't working", 47, rt.runTest(47)); 230 231 rt = loadAsRunTest("BasicLoad"); 232 checkInstrumentation(rt); 233 // BasicLoad.runTest(x) returns x*x 234 assertEquals ("BasicLoad isn't working", 49, rt.runTest(7)); 235 236 rt = loadAsRunTest("ComplicatedConstructor"); 237 checkInstrumentation(rt); 238 assertEquals("ComplicatedConstructor isn't working", 239 61, rt.runTest(3)); 240 rt = loadAsRunTest("ExceptionLoad"); 241 checkInstrumentation(rt); 242 // ExceptionLoad.runTest(x) also returns x*x 243 assertEquals ("ExceptionLoad isn't working", 121, rt.runTest(11)); 244 245 rt = loadAsRunTest("InnerClass"); 246 checkInstrumentation(rt); 247 // InnerClass.runTest(x) also returns x*x 248 assertEquals ("InnerClass isn't working", 9, rt.runTest(3)); 249 250 rt = loadAsRunTest("Looper"); 251 assertEquals("Looper isn't working", 127008000, rt.runTest(5)); 252 253 // rt = loadAsRunTest("OddSwitches"); 254 // // we like to play 255 // assertEquals( 91, rt.runTest(1001)); 256 // assertEquals( 31, rt.runTest(3)); 257 // assertEquals( 9, rt.runTest(9)); 258 // assertEquals(101, rt.runTest(1005)); 259 // assertEquals(-41, rt.runTest(-1)); 260 // assertEquals( -3, rt.runTest(-51)); 261 // assertEquals( 7, rt.runTest(-2)); 262 263 rt = loadAsRunTest("PrivateClass"); 264 checkInstrumentation(rt); 265 // returns 4 266 assertEquals ("PrivateClass isn't working", 4, rt.runTest(7)); 267 268 rt = loadAsRunTest("SuperClass"); 269 checkInstrumentation(rt); 270 // returns 3*x 271 assertEquals ("SuperClass isn't working", 21, rt.runTest(7)); 272 273 // This would normally not be here, it would be at a higher 274 // level in the testing process. But we are testing the 275 // registry itself. XXX Collect the string and extract 276 // run results from it. 277 String runResults = stmtReg.getReport(); 278 System.out.println("\nQuilt coverage report:\n" + runResults); 279 } // END TESTDATA 280 281 // SYNTHESIZED CLASSES ////////////////////////////////////////// 282 // public void testSynth () { 283 // assertEquals ("synthesizing isn't disabled in loader", 284 // false, qLoader.getSynthEnabled() ); 285 // qLoader.setSynthEnabled(true); 286 // assertEquals ("enabling synthesizing failed", 287 // true, qLoader.getSynthEnabled() ); 288 289 // RunTest 290 // rt = loadAsRunTest("test.data.TestDefault"); 291 // checkInstrumentation(rt); 292 // // testDefault.runTest(x) returns 2 whatever the input is 293 // assertEquals ("testDefault isn't working", 2, rt.runTest(47)); 294 // assertEquals ("testDefault isn't working", 2, rt.runTest(-7)); 295 // String 296 // runResults = stmtReg.getReport(); /// <----------- 297 // System.out.println("\nQuilt coverage report:\n" + runResults); 298 299 // rt = loadAsRunTest("test.data.TestIfThen"); 300 // checkInstrumentation(rt); 301 // // testIfThen.runTest(x) returns 3 if x > 0, 5 otherwise 302 // assertEquals ("testIfThen isn't working", 3, rt.runTest(47)); 303 // assertEquals ("testIfThen isn't working", 5, rt.runTest(-7)); 304 305 // runResults = stmtReg.getReport(); /// <----------- 306 // System.out.println("\nQuilt coverage report:\n" + runResults); 307 308 // rt = loadAsRunTest("test.data.TestNPEWithCatch"); 309 // checkInstrumentation(rt); 310 // // testNPEWithCatch.runTest(x) always returns 3 311 // assertEquals ("testNPEWithCatch isn't working", 3, rt.runTest(47)); 312 // assertEquals ("testNPEWithCatch isn't working", 3, rt.runTest(-7)); 313 314 // rt = loadAsRunTest("test.data.TestNPENoCatch"); 315 // checkInstrumentation(rt); 316 // // testNPENoCatch.runTest(x) always throws a NullPointerException 317 // int x; 318 // try { 319 // x = rt.runTest(47); 320 // fail ("testNPENoCatch didn't throw exception"); 321 // } catch (NullPointerException e) { 322 // ; // ignore it 323 // } 324 // try { 325 // x = rt.runTest(-7); 326 // fail ("testNPENoCatch didn't throw exception"); 327 // } catch (NullPointerException e) { 328 // ; // ignore it 329 // } 330 331 // rt = loadAsRunTest("test.data.TestSelect"); 332 // checkInstrumentation(rt); 333 // // testSelect.runTest(x) returns 334 // // 1 if x == 1; 3 if x == 2; 5 if x == 3; 2 otherwise 335 // assertEquals ("testSelect isn't working", 2, rt.runTest(47)); 336 // assertEquals ("testSelect isn't working", 2, rt.runTest(-7)); 337 // assertEquals ("testSelect isn't working", 1, rt.runTest(1)); 338 // assertEquals ("testSelect isn't working", 3, rt.runTest(2)); 339 // assertEquals ("testSelect isn't working", 5, rt.runTest(3)); 340 341 // rt = loadAsRunTest("test.data.TestWhile"); 342 // checkInstrumentation(rt); 343 // // testWhile.runTest(x) returns 344 // // 0 if x >= 0, x otherwise 345 // assertEquals ("testWhile isn't working", 0, rt.runTest(47)); 346 // assertEquals ("testWhile isn't working",-7, rt.runTest(-7)); 347 // } // END999 348 349 // ///////////////////////////////////////////////////////////////// 350 // // BUGS BUGS BUGS BUGS ////////////////////////////////////////// 351 // ///////////////////////////////////////////////////////////////// 352 // 353 // ///////////////////////////////////////////////////////////////// 354 // // LESSER BUGS ////////////////////////////////////////////////// 355 // // "edge not in this graph" -- FIXED (a bit crudely) 356 // public void testNestedTryBlocks() { 357 // RunTest 358 // rt = loadAsRunTest("NestedTryBlocks"); 359 // checkInstrumentation(rt); 360 // assertEquals ("NestedTryBlocks isn't working", 22, rt.runTest(7)); 361 // } // END NESTED 362 363 ///////////////////////////////////////////////////////////////// 364 // SERIOUS BUGS ///////////////////////////////////////////////// 365 366 // // STATICINIT /////////////////////////////////////////////////// 367 // // XXX BUG java.lang.NullPointerException 368 // // at org.apache.bcel.generic.LineNumberGen 369 // // .getLineNumber(LineNumberGen.java:109) 370 // // at org.apache.bcel.generic.MethodGen 371 // // .getLineNumberTable(MethodGen.java:420) 372 // // at org.apache.bcel.generic.MethodGen.getMethod(MethodGen.java:599) 373 // public void testStaticInit() { 374 // RunTest 375 // rt = loadAsRunTest("StaticInit"); 376 // checkInstrumentation(rt); 377 // assertEquals("StaticInit isn't working", 10, rt.runTest(7)); 378 // } // END STATIC 379 380 // // TESTFINALLY ////////////////////////////////////////////////// 381 // // XXX BUG Invalid start_pc/length in local var table BUG XXX 382 // public void testFinally() { 383 // RunTest 384 // rt = loadAsRunTest("Finally"); 385 // checkInstrumentation(rt); 386 387 // // Finally.runTest(x) returns -1 388 // assertEquals ("Finally isn't working", -1, rt.runTest(11)); 389 // assertEquals ("Finally isn't working", -1, rt.runTest(1)); 390 // } // END FINALLY 391 392 // // TESTFINALLY2CATCHES ////////////////////////////////////////// 393 // // XXX BUG Mismatched stack types BUG XXX 394 // public void testFinally2Catches() { 395 // RunTest 396 // rt = loadAsRunTest("Finally2Catches"); 397 // checkInstrumentation(rt); 398 399 // // what Finally.runTest(x) returns is a bit complicated ... 400 // assertEquals ("Finally2Catches isn't working", 3600, rt.runTest(11)); 401 // } // END 402 403 // // SWITCHLOAD 404 // // XXX BUG Falling off the end of the code BUG XXX 405 // public void testFinally2Catches() { 406 // RunTest 407 // rt = loadAsRunTest("SwitchLoad"); 408 // checkInstrumentation(rt); 409 // // returns 42 410 // assertEquals ("SwitchLoad isn't working", 42, rt.runTest(7)); 411 // } // END 412 413 // // WIMPLE /////////////////////////////////////////////////////// 414 // // XXX BUG java.lang.NullPointerException 415 // // at org.apache.bcel.generic.LineNumberGen 416 // // .getLineNumber(LineNumberGen.java:109) 417 // // at org.apache.bcel.generic.MethodGen 418 // // .getLineNumberTable(MethodGen.java:420) 419 // // at org.apache.bcel.generic.MethodGen.getMethod(MethodGen.java:599) 420 // public void testWimple() { 421 // RunTest 422 // rt = loadAsRunTest("Wimple"); 423 // checkInstrumentation(rt); 424 // // returns ?? 425 // assertEquals ("Wimple isn't working", 92, rt.runTest(7)); 426 // } // END WIMPLE 427 428 }

This page was automatically generated by Maven