1 5 package org.h2.test.coverage; 6 7 import java.io.BufferedReader ; 8 import java.io.BufferedWriter ; 9 import java.io.File ; 10 import java.io.FileReader ; 11 import java.io.FileWriter ; 12 import java.io.Reader ; 13 import java.io.Writer ; 14 import java.util.ArrayList ; 15 16 21 public class Coverage { 22 static final String IMPORT = "import " + Coverage.class.getPackage().getName() + ".Profile"; 23 ArrayList files = new ArrayList (); 24 ArrayList exclude = new ArrayList (); 25 Tokenizer tokenizer; 26 Writer writer; 27 Writer data; 28 String token = ""; 29 String add = ""; 30 String file; 31 int index; 32 int indent; 33 int line; 34 String last; 35 String word, function; 36 boolean perClass; 37 boolean perFunction = true; 38 39 void printUsage() { 40 System.out 41 .println("Usage:\n" 42 + "- copy all your source files to another directory\n" 43 + " (be carefull, they will be modified - don't take originals!)\n" 44 + "- java " + getClass().getName() + " <directory>\n" 45 + " this will modified the source code and create 'profile.txt'\n" 46 + "- compile the modified source files\n" 47 + "- run your main application\n" 48 + "- after the application exits, a file 'notcovered.txt' is created,\n" 49 + " which contains the class names, function names and line numbers\n" 50 + " of code that has not been covered\n\n" 51 + "Options:\n" 52 + "-r recurse all subdirectories\n" 53 + "-e exclude files\n" 54 + "-c coverage on a per-class basis\n" 55 + "-f coverage on a per-function basis\n" 56 + "<dir> directory name (. for current directory)"); 57 } 58 59 public static void main(String [] arg) { 60 (new Coverage()).run(arg); 61 } 62 63 void run(String [] arg) { 64 if (arg.length == 0 || arg[0].equals("-?")) { 65 printUsage(); 66 return; 67 } 68 Coverage c = new Coverage(); 69 int recurse = 1; 70 for (int i = 0; i < arg.length; i++) { 71 String s = arg[i]; 72 if (s.equals("-r")) { 73 recurse = 100; 75 } else if (s.equals("-c")) { 76 c.perClass = true; 77 } else if (s.equals("-f")) { 78 c.perFunction = true; 79 } else if (s.equals("-e")) { 80 c.addExclude(arg[++i]); 81 } else { 82 c.addDir(s, recurse); 83 } 84 } 85 try { 86 c.data = new BufferedWriter (new FileWriter ("profile.txt")); 87 c.processAll(); 88 c.data.close(); 89 } catch (Exception e) { 90 e.printStackTrace(); 91 } 92 } 93 94 void addExclude(String file) { 95 exclude.add(file); 96 } 97 98 boolean isExcluded(String s) { 99 for(int i=0; i<exclude.size(); i++) { 100 if(s.startsWith(exclude.get(i).toString())) { 101 return true; 102 } 103 } 104 return false; 105 } 106 107 void addDir(String path, int recurse) { 108 File f = new File (path); 109 if (f.isFile() && path.endsWith(".java")) { 110 if(!isExcluded(path)) { 111 files.add(path); 112 } 113 } else if (f.isDirectory() && recurse > 0) { 114 String [] list = f.list(); 115 for (int i = 0; i < list.length; i++) { 116 addDir(path + "/" + list[i], recurse - 1); 117 } 118 } 119 } 120 121 void processAll() { 122 int len = files.size(); 123 long time = System.currentTimeMillis(); 124 for (int i = 0; i < len; i++) { 125 long t2 = System.currentTimeMillis(); 126 if (t2 - time > 1000 || i >= len - 1) { 127 System.out.println((i + 1) + " of " + len + " " + (100 * i / len) + "%"); 128 time = t2; 129 } 130 String fileName = (String ) files.get(i); 131 processFile(fileName); 132 } 133 } 134 135 void processFile(String name) { 136 file = name; 137 int i; 138 i = file.lastIndexOf('.'); 139 if (i != -1) { 140 file = file.substring(0, i); 141 } 142 while(true) { 143 i = file.indexOf('/'); 144 if(i < 0) { 145 i = file.indexOf('\\'); 146 } 147 if(i<0) { 148 break; 149 } 150 file = file.substring(0, i) + "." +file.substring(i+1); 151 } 152 if (name.endsWith("Coverage.java") || name.endsWith("Tokenizer.java") 153 || name.endsWith("Profile.java")) { 154 return; 155 } 156 File f = new File (name); 157 File fnew = new File (name + ".new"); 158 try { 159 writer = new BufferedWriter (new FileWriter (fnew)); 160 Reader r = new BufferedReader (new FileReader (f)); 161 tokenizer = new Tokenizer(r); 162 indent = 0; 163 try { 164 process(); 165 } catch (Exception e) { 166 r.close(); 167 writer.close(); 168 e.printStackTrace(); 169 printError(e.getMessage()); 170 throw e; 171 } 172 r.close(); 173 writer.close(); 174 File fbak = new File (name + ".bak"); 175 fbak.delete(); 176 f.renameTo(fbak); 177 File fcopy = new File (name); 178 fnew.renameTo(fcopy); 179 if (perClass) { 180 nextDebug(); 181 } 182 } catch (Exception e) { 183 e.printStackTrace(); 184 printError(e.getMessage()); 185 } 186 } 187 188 void read() throws Exception { 189 last = token; 190 String write = token; 191 token = null; 192 tokenizer.initToken(); 193 int i = tokenizer.nextToken(); 194 if (i != Tokenizer.TYPE_EOF) { 195 token = tokenizer.getString(); 196 if (token == null) { 197 token = "" + ((char) i); 198 } else if (i == '\'') { 199 token = tokenizer.getToken(); 201 } else if (i == '\"') { 202 token = tokenizer.getToken(); 204 } else { 205 if (write == null) { 206 write = ""; 207 } else { 208 write = write + " "; 209 } 210 } 211 } 212 if (write == null 213 || (!write.equals("else ") && !write.equals("else") 214 && !write.equals("super ") && !write.equals("super") 215 && !write.equals("this ") && !write.equals("this") 216 && !write.equals("} ") && !write.equals("}"))) { 217 if (add != null && !add.equals("")) { 218 writeLine(); 219 write(add); 220 if (!perClass) { 221 nextDebug(); 222 } 223 } 224 } 225 add = ""; 226 if (write != null) { 227 write(write); 228 } 229 } 230 231 void readThis(String s) throws Exception { 232 if (!token.equals(s)) { 233 throw new Exception ("Expected: " + s + " got:" + token); 234 } 235 read(); 236 } 237 238 void process() throws Exception { 239 boolean imp = false; 240 read(); 241 do { 242 while (true) { 243 if (token == null || token.equals("{")) { 244 break; 245 } else if (token.equals(";")) { 246 if (!imp) { 247 write(";" + IMPORT); 248 imp = true; 249 } 250 } 251 read(); 252 } 253 processClass(); 254 } while (token != null); 255 } 256 257 void processInit() throws Exception { 258 do { 259 if (token.equals("{")) { 260 read(); 261 processInit(); 262 } else if (token.equals("}")) { 263 read(); 264 return; 265 } else { 266 read(); 267 } 268 } while (true); 269 } 270 271 void processClass() throws Exception { 272 int type = 0; 273 while (true) { 274 if (token == null) { 275 break; 276 } else if (token.equals("class")) { 277 read(); 278 type = 1; 279 } else if (token.equals("=")) { 280 read(); 281 type = 2; 282 } else if (token.equals("static")) { 283 word = "static"; 284 read(); 285 type = 3; 286 } else if (token.equals("(")) { 287 word = last + "("; 288 read(); 289 if (!token.equals(")")) { 290 word = word + token; 291 } 292 type = 3; 293 } else if (token.equals(",")) { 294 read(); 295 word = word + "," + token; 296 } else if (token.equals(")")) { 297 word = word + ")"; 298 read(); 299 } else if (token.equals(";")) { 300 read(); 301 type = 0; 302 } else if (token.equals("{")) { 303 read(); 304 if (type == 1) { 305 processClass(); 306 } else if (type == 2) { 307 processInit(); 308 } else if (type == 3) { 309 writeLine(); 310 setLine(); 311 processFunction(); 312 writeLine(); 313 } 314 } else if (token.equals("}")) { 315 read(); 316 break; 317 } else { 318 read(); 319 } 320 } 321 } 322 323 void processBraket() throws Exception { 324 do { 325 if (token.equals("(")) { 326 read(); 327 processBraket(); 328 } else if (token.equals(")")) { 329 read(); 330 return; 331 } else { 332 read(); 333 } 334 } while (true); 335 } 336 337 void processFunction() throws Exception { 338 function = word; 339 writeLine(); 340 do { 341 processStatement(); 342 } while (!token.equals("}")); 343 read(); 344 writeLine(); 345 } 346 347 void processBlockOrStatement() throws Exception { 348 if (!token.equals("{")) { 349 write("{ //++"); 350 writeLine(); 351 setLine(); 352 processStatement(); 353 write("} //++"); 354 writeLine(); 355 } else { 356 read(); 357 setLine(); 358 processFunction(); 359 } 360 } 361 362 void processStatement() throws Exception { 363 while (true) { 364 if (token.equals("while") || token.equals("for") 365 || token.equals("synchronized")) { 366 read(); 367 readThis("("); 368 processBraket(); 369 indent++; 370 processBlockOrStatement(); 371 indent--; 372 return; 373 } else if (token.equals("if")) { 374 read(); 375 readThis("("); 376 processBraket(); 377 indent++; 378 processBlockOrStatement(); 379 indent--; 380 if (token.equals("else")) { 381 read(); 382 indent++; 383 processBlockOrStatement(); 384 indent--; 385 } 386 return; 387 } else if (token.equals("try")) { 388 read(); 389 indent++; 390 processBlockOrStatement(); 391 indent--; 392 while (true) { 393 if (token.equals("catch")) { 394 read(); 395 readThis("("); 396 processBraket(); 397 indent++; 398 processBlockOrStatement(); 399 indent--; 400 } else if (token.equals("finally")) { 401 read(); 402 indent++; 403 processBlockOrStatement(); 404 indent--; 405 } else { 406 break; 407 } 408 } 409 return; 410 } else if (token.equals("{")) { 411 if (last.equals(")")) { 412 read(); 414 processClass(); 415 return; 416 } else if (last.equals("]")) { 417 while (!token.equals("}")) { 419 read(); 420 } 421 read(); 422 return; 423 } 424 indent++; 425 processBlockOrStatement(); 426 indent--; 427 return; 428 } else if (token.equals("do")) { 429 read(); 430 indent++; 431 processBlockOrStatement(); 432 readThis("while"); 433 readThis("("); 434 processBraket(); 435 readThis(";"); 436 setLine(); 437 indent--; 438 return; 439 } else if (token.equals("case")) { 440 add = ""; 441 read(); 442 while (!token.equals(":")) { 443 read(); 444 } 445 read(); 446 setLine(); 447 } else if (token.equals("default")) { 448 add = ""; 449 read(); 450 readThis(":"); 451 setLine(); 452 } else if (token.equals("switch")) { 453 read(); 454 readThis("("); 455 processBraket(); 456 indent++; 457 processBlockOrStatement(); 458 indent--; 459 return; 460 } else if (token.equals("class")) { 461 read(); 462 processClass(); 463 return; 464 } else if (token.equals("(")) { 465 read(); 466 processBraket(); 467 } else if (token.equals("=")) { 468 read(); 469 if (token.equals("{")) { 470 read(); 471 processInit(); 472 } 473 } else if (token.equals(";")) { 474 read(); 475 setLine(); 476 return; 477 } else if (token.equals("}")) { 478 return; 479 } else { 480 read(); 481 } 482 } 483 } 484 485 void setLine() throws Exception { 486 add += "Profile.visit(" + index + ");"; 487 line = tokenizer.getLine(); 488 } 489 490 void nextDebug() throws Exception { 491 if (perFunction) { 492 int i = function.indexOf("("); 493 String func = i<0 ? function : function.substring(0, i); 494 String fileLine = file + "." + func +"("; 495 i = file.lastIndexOf('.'); 496 String fil = i<0 ? file : file.substring(i+1); 497 fileLine += fil + ".java:" + line + ")"; 498 data.write(fileLine + " " + last + "\r\n"); 499 } else { 500 data.write(file + " " + line + "\r\n"); 501 } 502 index++; 503 } 504 505 void writeLine() throws Exception { 506 write("\r\n"); 507 for (int i = 0; i < indent; i++) { 508 writer.write(' '); 509 } 510 } 511 512 void write(String s) throws Exception { 513 writer.write(s); 514 } 516 517 void printError(String error) { 518 System.out.println(""); 519 System.out.println("File:" + file); 520 System.out.println("ERROR: " + error); 521 } 522 } 523 524 | Popular Tags |