blob: 20429f022dbce3e0b0c78e361ff9b752111bb624 [file] [log] [blame]
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package util.build;
18
19import com.android.dx.util.FileUtils;
20
21import dot.junit.AllTests;
22
23import junit.framework.TestCase;
24import junit.framework.TestResult;
25import junit.framework.TestSuite;
26import junit.textui.TestRunner;
27
28import java.io.BufferedWriter;
29import java.io.File;
30import java.io.FileNotFoundException;
31import java.io.FileOutputStream;
32import java.io.FileReader;
33import java.io.IOException;
34import java.io.OutputStreamWriter;
35import java.util.ArrayList;
36import java.util.Collections;
37import java.util.Comparator;
38import java.util.HashSet;
39import java.util.Iterator;
40import java.util.LinkedHashMap;
41import java.util.List;
42import java.util.Scanner;
43import java.util.Set;
44import java.util.TreeSet;
45import java.util.Map.Entry;
46import java.util.regex.MatchResult;
47import java.util.regex.Matcher;
48import java.util.regex.Pattern;
49
50/**
51 * Main class to generate data from the test suite to later run from a shell
52 * script. the project's home folder.<br>
53 * <project-home>/src must contain the java sources<br>
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -070054 * <project-home>/src/<for-each-package>/Main_testN1.java will be generated<br>
55 * (one Main class for each test method in the Test_... class
56 */
57public class BuildDalvikSuite {
58
59 public static boolean DEBUG = true;
60
61 private static String JAVASRC_FOLDER = "";
62 private static String MAIN_SRC_OUTPUT_FOLDER = "";
63
64 // the folder for the generated junit-files for the cts host (which in turn
65 // execute the real vm tests using adb push/shell etc)
66 private static String HOSTJUNIT_SRC_OUTPUT_FOLDER = "";
67 private static String OUTPUT_FOLDER = "";
68 private static String COMPILED_CLASSES_FOLDER = "";
69
70 private static String CLASSES_OUTPUT_FOLDER = "";
71 private static String HOSTJUNIT_CLASSES_OUTPUT_FOLDER = "";
72
73 private static String CLASS_PATH = "";
74
Tsu Chiang Chuange6e045d2011-05-15 14:30:35 -070075 private static String restrictTo = null; // e.g. restrict to "opcodes.add_double"
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -070076
77 private static final String TARGET_JAR_ROOT_PATH = "/data/local/tmp/vm-tests";
78
79 private int testClassCnt = 0;
80 private int testMethodsCnt = 0;
81
82 /*
83 * using a linked hashmap to keep the insertion order for iterators.
84 * the junit suite/tests adding order is used to generate the order of the
85 * report.
86 * a map. key: fully qualified class name, value: a list of test methods for
87 * the given class
88 */
89 private LinkedHashMap<String, List<String>> map = new LinkedHashMap<String,
90 List<String>>();
91
92 private class MethodData {
93 String methodBody, constraint, title;
94 }
95
96 /**
97 * @param args
98 * args 0 must be the project root folder (where src, lib etc.
99 * resides)
100 * @throws IOException
101 */
102 public static void main(String[] args) throws IOException {
103
104 if (args.length > 5) {
105 JAVASRC_FOLDER = args[0];
106 OUTPUT_FOLDER = args[1];
107 CLASS_PATH = args[2];
108 MAIN_SRC_OUTPUT_FOLDER = args[3];
109 CLASSES_OUTPUT_FOLDER = MAIN_SRC_OUTPUT_FOLDER + "/classes";
110
111 COMPILED_CLASSES_FOLDER = args[4];
112
113 HOSTJUNIT_SRC_OUTPUT_FOLDER = args[5];
114 HOSTJUNIT_CLASSES_OUTPUT_FOLDER = HOSTJUNIT_SRC_OUTPUT_FOLDER + "/classes";
115
116 if (args.length > 6) {
117 // optional: restrict to e.g. "opcodes.add_double"
118 restrictTo = args[6];
119 System.out.println("restricting build to: " + restrictTo);
120 }
121
122 } else {
123 System.out.println("usage: java-src-folder output-folder classpath " +
124 "generated-main-files compiled_output generated-main-files " +
125 "[restrict-to-opcode]");
126 System.exit(-1);
127 }
128
129 long start = System.currentTimeMillis();
130 BuildDalvikSuite cat = new BuildDalvikSuite();
131 cat.compose();
132 long end = System.currentTimeMillis();
133
134 System.out.println("elapsed seconds: " + (end - start) / 1000);
135 }
136
137 public void compose() throws IOException {
138 System.out.println("Collecting all junit tests...");
139 new TestRunner() {
140 @Override
141 protected TestResult createTestResult() {
142 return new TestResult() {
143 @Override
144 protected void run(TestCase test) {
145 addToTests(test);
146 }
147
148 };
149 }
150 }.doRun(AllTests.suite());
151
152 // for each combination of TestClass and method, generate a Main_testN1
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700153 // class in the respective package.
154 // for the report make sure all N... tests are called first, then B,
Tsu Chiang Chuange6e045d2011-05-15 14:30:35 -0700155 // then E, then VFE test methods.
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700156 // e.g. dxc.junit.opcodes.aaload.Test_aaload - testN1() ->
Tsu Chiang Chuange6e045d2011-05-15 14:30:35 -0700157 // File Main_testN1.java in package dxc.junit.opcodes.aaload.
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700158 //
159 handleTests();
160 }
161
162 private void addToTests(TestCase test) {
163
164 String packageName = test.getClass().getPackage().getName();
165 packageName = packageName.substring(packageName.lastIndexOf('.'));
166
167
168 String method = test.getName(); // e.g. testVFE2
169 String fqcn = test.getClass().getName(); // e.g.
170 // dxc.junit.opcodes.iload_3.Test_iload_3
171
172 // ignore all tests not belonging to the given restriction
173 if (restrictTo != null && !fqcn.contains(restrictTo)) return;
174
175 testMethodsCnt++;
176 List<String> li = map.get(fqcn);
177 if (li == null) {
178 testClassCnt++;
179 li = new ArrayList<String>();
180 map.put(fqcn, li);
181 }
182 li.add(method);
183 }
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700184 private String curJunitFileName = null;
185 private String curJunitFileData = "";
186
187 private JavacBuildStep javacHostJunitBuildStep;
188
189 private void flushHostJunitFile() {
190 if (curJunitFileName != null) {
191 File toWrite = new File(curJunitFileName);
192 String absPath = toWrite.getAbsolutePath();
193 // add to java source files for later compilation
194 javacHostJunitBuildStep.addSourceFile(absPath);
195 // write file
196 curJunitFileData += "\n}\n";
197 writeToFileMkdir(toWrite, curJunitFileData);
198 curJunitFileName = null;
199 curJunitFileData = "";
200 }
201 }
202
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700203 private void openCTSHostFileFor(String pName, String classOnlyName) {
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700204 // flush previous JunitFile
205 flushHostJunitFile();
Tsu Chiang Chuange6e045d2011-05-15 14:30:35 -0700206 String sourceName = "JUnit_" + classOnlyName;
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700207
208 // prepare current testcase-file
209 curJunitFileName = HOSTJUNIT_SRC_OUTPUT_FOLDER + "/" + pName.replaceAll("\\.","/") + "/" +
210 sourceName + ".java";
211 curJunitFileData = getWarningMessage() +
212 "package " + pName + ";\n" +
213 "import java.io.IOException;\n" +
Tsu Chiang Chuange6e045d2011-05-15 14:30:35 -0700214 "import com.android.tradefed.testtype.DeviceTestCase;\n" +
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700215 "\n" +
216 "public class " + sourceName + " extends DeviceTestCase {\n";
217 }
218
Tsu Chiang Chuange6e045d2011-05-15 14:30:35 -0700219 private String getShellExecJavaLine(String classpath, String mainclass) {
Brett Chabot44650b12011-10-25 18:09:39 -0700220 String cmd = String.format("ANDROID_DATA=%s dalvikvm -Xint:portable -Xmx512M -Xss32K " +
Brian Muramatsu24e14672011-10-25 18:36:55 -0700221 "-Djava.io.tmpdir=%s -classpath %s %s", TARGET_JAR_ROOT_PATH, TARGET_JAR_ROOT_PATH,
Brett Chabot44650b12011-10-25 18:09:39 -0700222 classpath, mainclass);
Tsu Chiang Chuange6e045d2011-05-15 14:30:35 -0700223 return "String res = getDevice().executeShellCommand(\""+ cmd + "\");\n" +
224 "// A sucessful adb shell command returns an empty string.\n" +
Brian Carlstrom79f22222011-10-01 16:04:26 -0700225 "assertEquals(\"" + cmd + "\", \"\", res);";
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700226 }
227
228 private String getWarningMessage() {
229 return "//Autogenerated code by " + this.getClass().getName() + "; do not edit.\n";
230 }
231
232 private void addCTSHostMethod(String pName, String method, MethodData md,
233 Set<String> dependentTestClassNames) {
234 curJunitFileData += "public void " + method + "() throws Exception {\n";
235 final String targetCoreJarPath = String.format("%s/dot/junit/dexcore.jar",
236 TARGET_JAR_ROOT_PATH);
237
238 // push class with Main jar.
239 String mjar = "Main_" + method + ".jar";
240 String pPath = pName.replaceAll("\\.","/");
241 String mainJar = String.format("%s/%s/%s", TARGET_JAR_ROOT_PATH, pPath, mjar);
242
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700243 String cp = String.format("%s:%s", targetCoreJarPath, mainJar);
244 for (String depFqcn : dependentTestClassNames) {
245 int lastDotPos = depFqcn.lastIndexOf('.');
246 String sourceName = depFqcn.replaceAll("\\.", "/") + ".jar";
247 String targetName= String.format("%s/%s", TARGET_JAR_ROOT_PATH,
248 sourceName);
249 cp += ":" + targetName;
250 // dot.junit.opcodes.invoke_interface_range.ITest
251 // -> dot/junit/opcodes/invoke_interface_range/ITest.jar
252 }
253
254 //"dot.junit.opcodes.add_double_2addr.Main_testN2";
255 String mainclass = pName + ".Main_" + method;
Tsu Chiang Chuange6e045d2011-05-15 14:30:35 -0700256 curJunitFileData += " " + getShellExecJavaLine(cp, mainclass);
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700257 curJunitFileData += "}\n\n";
258 }
259
260 private void handleTests() throws IOException {
261 System.out.println("collected " + testMethodsCnt + " test methods in " +
262 testClassCnt + " junit test classes");
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700263 Set<BuildStep> targets = new TreeSet<BuildStep>();
264
265 javacHostJunitBuildStep = new JavacBuildStep(HOSTJUNIT_CLASSES_OUTPUT_FOLDER, CLASS_PATH);
266
267
268 JavacBuildStep javacBuildStep = new JavacBuildStep(
269 CLASSES_OUTPUT_FOLDER, CLASS_PATH);
270
271 for (Entry<String, List<String>> entry : map.entrySet()) {
272
273 String fqcn = entry.getKey();
274 int lastDotPos = fqcn.lastIndexOf('.');
275 String pName = fqcn.substring(0, lastDotPos);
276 String classOnlyName = fqcn.substring(lastDotPos + 1);
277 String instPrefix = "new " + classOnlyName + "()";
278
279 openCTSHostFileFor(pName, classOnlyName);
280
281 List<String> methods = entry.getValue();
282 Collections.sort(methods, new Comparator<String>() {
283 public int compare(String s1, String s2) {
284 // TODO sort according: test ... N, B, E, VFE
285 return s1.compareTo(s2);
286 }
287 });
288 for (String method : methods) {
289 // e.g. testN1
290 if (!method.startsWith("test")) {
291 throw new RuntimeException("no test method: " + method);
292 }
293
294 // generate the Main_xx java class
295
296 // a Main_testXXX.java contains:
297 // package <packagenamehere>;
298 // public class Main_testxxx {
299 // public static void main(String[] args) {
300 // new dxc.junit.opcodes.aaload.Test_aaload().testN1();
301 // }
302 // }
303 MethodData md = parseTestMethod(pName, classOnlyName, method);
304 String methodContent = md.methodBody;
305
306 Set<String> dependentTestClassNames = parseTestClassName(pName,
307 classOnlyName, methodContent);
308
309 addCTSHostMethod(pName, method, md, dependentTestClassNames);
310
311
312 if (dependentTestClassNames.isEmpty()) {
313 continue;
314 }
315
316
317 String content = getWarningMessage() +
318 "package " + pName + ";\n" +
319 "import " + pName + ".d.*;\n" +
320 "import dot.junit.*;\n" +
321 "public class Main_" + method + " extends DxAbstractMain {\n" +
322 " public static void main(String[] args) throws Exception {" +
323 methodContent + "\n}\n";
324
325 String fileName = getFileName(pName, method, ".java");
326 File sourceFile = getFileFromPackage(pName, method);
327
328 File classFile = new File(CLASSES_OUTPUT_FOLDER + "/" +
329 getFileName(pName, method, ".class"));
330 // if (sourceFile.lastModified() > classFile.lastModified()) {
331 writeToFile(sourceFile, content);
332 javacBuildStep.addSourceFile(sourceFile.getAbsolutePath());
333
334 BuildStep dexBuildStep = generateDexBuildStep(
335 CLASSES_OUTPUT_FOLDER, getFileName(pName, method, ""));
336 targets.add(dexBuildStep);
337 // }
338
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700339 generateBuildStepFor(pName, method, dependentTestClassNames,
340 targets);
341 }
342
343
344 }
345
Tsu Chiang Chuange6e045d2011-05-15 14:30:35 -0700346 // write latest HOSTJUNIT generated file.
347 flushHostJunitFile();
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700348
349 if (!javacHostJunitBuildStep.build()) {
350 System.out.println("main javac cts-host-hostjunit-classes build step failed");
351 System.exit(1);
352 }
353
354 if (javacBuildStep.build()) {
355 for (BuildStep buildStep : targets) {
356 if (!buildStep.build()) {
357 System.out.println("building failed. buildStep: " +
358 buildStep.getClass().getName() + ", " + buildStep);
359 System.exit(1);
360 }
361 }
362 } else {
363 System.out.println("main javac dalvik-cts-buildutil build step failed");
364 System.exit(1);
365 }
366 }
367
368 private void generateBuildStepFor(String pName, String method,
369 Set<String> dependentTestClassNames, Set<BuildStep> targets) {
370
371
372 for (String dependentTestClassName : dependentTestClassNames) {
373 generateBuildStepForDependant(dependentTestClassName, targets);
374 }
375 }
376
377 private void generateBuildStepForDependant(String dependentTestClassName,
378 Set<BuildStep> targets) {
379
380 File sourceFolder = new File(JAVASRC_FOLDER);
381 String fileName = dependentTestClassName.replace('.', '/').trim();
382
383 if (new File(sourceFolder, fileName + ".dfh").exists()) {
384
385 BuildStep.BuildFile inputFile = new BuildStep.BuildFile(
386 JAVASRC_FOLDER, fileName + ".dfh");
387 BuildStep.BuildFile dexFile = new BuildStep.BuildFile(
388 OUTPUT_FOLDER, fileName + ".dex");
389
390 DFHBuildStep buildStep = new DFHBuildStep(inputFile, dexFile);
391
392 BuildStep.BuildFile jarFile = new BuildStep.BuildFile(
393 OUTPUT_FOLDER, fileName + ".jar");
394 JarBuildStep jarBuildStep = new JarBuildStep(dexFile,
395 "classes.dex", jarFile, true);
396 jarBuildStep.addChild(buildStep);
397
398 targets.add(jarBuildStep);
399 return;
400 }
401
402 if (new File(sourceFolder, fileName + ".d").exists()) {
403
404 BuildStep.BuildFile inputFile = new BuildStep.BuildFile(
405 JAVASRC_FOLDER, fileName + ".d");
406 BuildStep.BuildFile dexFile = new BuildStep.BuildFile(
407 OUTPUT_FOLDER, fileName + ".dex");
408
409 DasmBuildStep buildStep = new DasmBuildStep(inputFile, dexFile);
410
411 BuildStep.BuildFile jarFile = new BuildStep.BuildFile(
412 OUTPUT_FOLDER, fileName + ".jar");
413
414 JarBuildStep jarBuildStep = new JarBuildStep(dexFile,
415 "classes.dex", jarFile, true);
416 jarBuildStep.addChild(buildStep);
417 targets.add(jarBuildStep);
418 return;
419 }
420
421 if (new File(sourceFolder, fileName + ".java").exists()) {
422
423 BuildStep dexBuildStep = generateDexBuildStep(
424 COMPILED_CLASSES_FOLDER, fileName);
425 targets.add(dexBuildStep);
426 return;
427 }
428
429 try {
430 if (Class.forName(dependentTestClassName) != null) {
431
432 BuildStep dexBuildStep = generateDexBuildStep(
433 COMPILED_CLASSES_FOLDER, fileName);
434 targets.add(dexBuildStep);
435 return;
436 }
437 } catch (ClassNotFoundException e) {
438 // do nothing
439 }
440
441 throw new RuntimeException("neither .dfh,.d,.java file of dependant test class found : " +
442 dependentTestClassName + ";" + fileName);
443 }
444
445 private BuildStep generateDexBuildStep(String classFileFolder,
446 String classFileName) {
447 BuildStep.BuildFile classFile = new BuildStep.BuildFile(
448 classFileFolder, classFileName + ".class");
449
450 BuildStep.BuildFile tmpJarFile = new BuildStep.BuildFile(OUTPUT_FOLDER,
451 classFileName + "_tmp.jar");
452
453 JarBuildStep jarBuildStep = new JarBuildStep(classFile, classFileName +
454 ".class", tmpJarFile, false);
455
456 BuildStep.BuildFile outputFile = new BuildStep.BuildFile(OUTPUT_FOLDER,
457 classFileName + ".jar");
458
459 DexBuildStep dexBuildStep = new DexBuildStep(tmpJarFile, outputFile,
460 true);
461
462 dexBuildStep.addChild(jarBuildStep);
463 return dexBuildStep;
464
465 }
466
467 /**
468 * @param pName
469 * @param classOnlyName
470 * @param methodSource
471 * @return testclass names
472 */
473 private Set<String> parseTestClassName(String pName, String classOnlyName,
474 String methodSource) {
475 Set<String> entries = new HashSet<String>();
476 String opcodeName = classOnlyName.substring(5);
477
478 Scanner scanner = new Scanner(methodSource);
479
480 String[] patterns = new String[] {"new\\s(T_" + opcodeName + "\\w*)",
481 "(T_" + opcodeName + "\\w*)", "new\\s(T\\w*)"};
482
483 String token = null;
484 for (String pattern : patterns) {
485 token = scanner.findWithinHorizon(pattern, methodSource.length());
486 if (token != null) {
487 break;
488 }
489 }
490
491 if (token == null) {
492 System.err.println("warning: failed to find dependent test class name: " + pName +
493 ", " + classOnlyName + " in methodSource:\n" + methodSource);
494 return entries;
495 }
496
497 MatchResult result = scanner.match();
498
499 entries.add((pName + ".d." + result.group(1)).trim());
500
501 // search additional @uses directives
502 Pattern p = Pattern.compile("@uses\\s+(.*)\\s+", Pattern.MULTILINE);
503 Matcher m = p.matcher(methodSource);
504 while (m.find()) {
505 String res = m.group(1);
506 entries.add(res.trim());
507 }
508
509 // lines with the form @uses
510 // dot.junit.opcodes.add_double.jm.T_add_double_2
511 // one dependency per one @uses
512 // TODO
513
514 return entries;
515 }
516
517 private MethodData parseTestMethod(String pname, String classOnlyName,
518 String method) {
519
520 String path = pname.replaceAll("\\.", "/");
521 String absPath = JAVASRC_FOLDER + "/" + path + "/" + classOnlyName + ".java";
522 File f = new File(absPath);
523
524 Scanner scanner;
525 try {
526 scanner = new Scanner(f);
527 } catch (FileNotFoundException e) {
528 throw new RuntimeException("error while reading to file: " + e.getClass().getName() +
529 ", msg:" + e.getMessage());
530 }
Tsu Chiang Chuange6e045d2011-05-15 14:30:35 -0700531
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700532 String methodPattern = "public\\s+void\\s+" + method + "[^\\{]+\\{";
Tsu Chiang Chuange6e045d2011-05-15 14:30:35 -0700533
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700534 String token = scanner.findWithinHorizon(methodPattern, (int) f.length());
535 if (token == null) {
536 throw new RuntimeException("cannot find method source of 'public void " + method +
537 "' in file '" + absPath + "'");
538 }
539
540 MatchResult result = scanner.match();
541 result.start();
542 result.end();
543
544 StringBuilder builder = new StringBuilder();
545 //builder.append(token);
546
547 try {
548 FileReader reader = new FileReader(f);
549 reader.skip(result.end());
550
551 char currentChar;
552 int blocks = 1;
553 while ((currentChar = (char) reader.read()) != -1 && blocks > 0) {
554 switch (currentChar) {
555 case '}': {
556 blocks--;
557 builder.append(currentChar);
558 break;
559 }
560 case '{': {
561 blocks++;
562 builder.append(currentChar);
563 break;
564 }
565 default: {
566 builder.append(currentChar);
567 break;
568 }
569 }
570 }
571 if (reader != null) {
572 reader.close();
573 }
574 } catch (Exception e) {
575 throw new RuntimeException("failed to parse", e);
576 }
577
578 // find the @title/@constraint in javadoc comment for this method
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700579 // using platform's default charset
580 String all = new String(FileUtils.readFile(f));
581 // System.out.println("grepping javadoc found for method " + method +
582 // " in " + pname + "," + classOnlyName);
583 String commentPattern = "/\\*\\*([^{]*)\\*/\\s*" + methodPattern;
584 Pattern p = Pattern.compile(commentPattern, Pattern.DOTALL);
585 Matcher m = p.matcher(all);
586 String title = null, constraint = null;
587 if (m.find()) {
588 String res = m.group(1);
589 // System.out.println("res: " + res);
590 // now grep @title and @constraint
591 Matcher titleM = Pattern.compile("@title (.*)", Pattern.DOTALL)
592 .matcher(res);
593 if (titleM.find()) {
594 title = titleM.group(1).replaceAll("\\n \\*", "");
595 title = title.replaceAll("\\n", " ");
596 title = title.trim();
597 // System.out.println("title: " + title);
598 } else {
599 System.err.println("warning: no @title found for method " + method + " in " + pname +
600 "," + classOnlyName);
601 }
602 // constraint can be one line only
603 Matcher constraintM = Pattern.compile("@constraint (.*)").matcher(
604 res);
605 if (constraintM.find()) {
606 constraint = constraintM.group(1);
607 constraint = constraint.trim();
608 // System.out.println("constraint: " + constraint);
609 } else if (method.contains("VFE")) {
610 System.err
611 .println("warning: no @constraint for for a VFE method:" + method + " in " +
612 pname + "," + classOnlyName);
613 }
614 } else {
615 System.err.println("warning: no javadoc found for method " + method + " in " + pname +
616 "," + classOnlyName);
617 }
618 MethodData md = new MethodData();
619 md.methodBody = builder.toString();
620 md.constraint = constraint;
621 md.title = title;
622 if (scanner != null) {
623 scanner.close();
624 }
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700625 return md;
626 }
627
628 private void writeToFileMkdir(File file, String content) {
629 File parent = file.getParentFile();
630 if (!parent.exists() && !parent.mkdirs()) {
631 throw new RuntimeException("failed to create directory: " + parent.getAbsolutePath());
632 }
633 writeToFile(file, content);
634 }
635
636 private void writeToFile(File file, String content) {
637 try {
638 if (file.length() == content.length()) {
639 FileReader reader = new FileReader(file);
640 char[] charContents = new char[(int) file.length()];
641 reader.read(charContents);
Chris Dearman7c9f67a2011-12-15 21:24:16 -0800642 reader.close();
Tsu Chiang Chuang9a223d72011-04-27 17:19:46 -0700643 String contents = new String(charContents);
644 if (contents.equals(content)) {
645 // System.out.println("skipping identical: "
646 // + file.getAbsolutePath());
647 return;
648 }
649 }
650
651 //System.out.println("writing file " + file.getAbsolutePath());
652
653 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(
654 new FileOutputStream(file), "utf-8"));
655 bw.write(content);
656 bw.close();
657 } catch (Exception e) {
658 throw new RuntimeException("error while writing to file: " + e.getClass().getName() +
659 ", msg:" + e.getMessage());
660 }
661 }
662
663 private File getFileFromPackage(String pname, String methodName)
664 throws IOException {
665 // e.g. dxc.junit.argsreturns.pargsreturn
666 String path = getFileName(pname, methodName, ".java");
667 String absPath = MAIN_SRC_OUTPUT_FOLDER + "/" + path;
668 File dirPath = new File(absPath);
669 File parent = dirPath.getParentFile();
670 if (!parent.exists() && !parent.mkdirs()) {
671 throw new IOException("failed to create directory: " + absPath);
672 }
673 return dirPath;
674 }
675
676 private String getFileName(String pname, String methodName,
677 String extension) {
678 String path = pname.replaceAll("\\.", "/");
679 return new File(path, "Main_" + methodName + extension).getPath();
680 }
681}