1 /*
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 
17 package util.build;
18 
19 import java.io.File;
20 import java.io.IOException;
21 import java.util.Collections;
22 import java.util.Comparator;
23 import java.util.List;
24 
25 /**
26  * Main class to generate data from the test suite to later run from a shell
27  * script. the project's home folder.<br>
28  * <project-home>/src must contain the java sources<br>
29  * <project-home>/src/<for-each-package>/Main_testN1.java will be generated<br>
30  * (one Main class for each test method in the Test_... class
31  */
32 public class BuildCTSMainsSources extends BuildUtilBase {
33 
34     private String MAIN_SRC_OUTPUT_FOLDER = "";
35 
36     /**
37      * @param args
38      *            args 0 must be the project root folder (where src, lib etc.
39      *            resides)
40      * @throws IOException
41      */
main(String[] args)42     public static void main(String[] args) throws IOException {
43         BuildCTSMainsSources cat = new BuildCTSMainsSources();
44         if (!cat.parseArgs(args)) {
45           printUsage();
46           System.exit(-1);
47         }
48 
49         long start = System.currentTimeMillis();
50         cat.run(cat::handleTest);
51         long end = System.currentTimeMillis();
52 
53         System.out.println("elapsed seconds: " + (end - start) / 1000);
54     }
55 
parseArgs(String[] args)56     private boolean parseArgs(String[] args) {
57       if (args.length == 1) {
58           MAIN_SRC_OUTPUT_FOLDER = args[0];
59           return true;
60       } else {
61           return false;
62       }
63     }
64 
printUsage()65     private static void printUsage() {
66         System.out.println("usage: java-src-folder output-folder classpath " +
67                            "generated-main-files compiled_output");
68     }
69 
getWarningMessage()70     private String getWarningMessage() {
71         return "//Autogenerated code by " + this.getClass().getName() + "; do not edit.\n";
72     }
73 
handleTest(String fqcn, List<String> methods)74     private void handleTest(String fqcn, List<String> methods) {
75         int lastDotPos = fqcn.lastIndexOf('.');
76         String pName = fqcn.substring(0, lastDotPos);
77         String classOnlyName = fqcn.substring(lastDotPos + 1);
78 
79         Collections.sort(methods, new Comparator<String>() {
80             @Override
81             public int compare(String s1, String s2) {
82                 // TODO sort according: test ... N, B, E, VFE
83                 return s1.compareTo(s2);
84             }
85         });
86         for (String method : methods) {
87             // e.g. testN1
88             if (!method.startsWith("test")) {
89                 throw new RuntimeException("no test method: " + method);
90             }
91 
92             // generate the Main_xx java class
93 
94             // a Main_testXXX.java contains:
95             // package <packagenamehere>;
96             // public class Main_testxxx {
97             // public static void main(String[] args) {
98             // new dxc.junit.opcodes.aaload.Test_aaload().testN1();
99             // }
100             // }
101             MethodData md = parseTestMethod(pName, classOnlyName, method);
102             String methodContent = md.methodBody;
103 
104             List<String> dependentTestClassNames = parseTestClassName(pName,
105                     classOnlyName, methodContent);
106 
107             if (dependentTestClassNames.isEmpty()) {
108                 continue;
109             }
110 
111             String content = getWarningMessage() +
112                     "package " + pName + ";\n" +
113                     "import " + pName + ".d.*;\n" +
114                     "import dot.junit.*;\n" +
115                     "public class Main_" + method + " extends DxAbstractMain {\n" +
116                     "    public static void main(String[] args) throws Exception {" +
117                     methodContent + "\n}\n";
118 
119             File sourceFile;
120             try {
121                 sourceFile = getFileFromPackage(pName, method);
122             } catch (IOException e) {
123                 throw new RuntimeException(e);
124             }
125 
126             writeToFile(sourceFile, content);
127         }
128     }
129 
getFileFromPackage(String pname, String methodName)130     private File getFileFromPackage(String pname, String methodName) throws IOException {
131         // e.g. dxc.junit.argsreturns.pargsreturn
132         String path = getFileName(pname, methodName, ".java");
133         String absPath = MAIN_SRC_OUTPUT_FOLDER + "/" + path;
134         File dirPath = new File(absPath);
135         File parent = dirPath.getParentFile();
136         if (!parent.exists() && !parent.mkdirs()) {
137             throw new IOException("failed to create directory: " + absPath);
138         }
139         return dirPath;
140     }
141 
getFileName(String pname, String methodName, String extension)142     private String getFileName(String pname, String methodName, String extension) {
143         String path = pname.replaceAll("\\.", "/");
144         return new File(path, "Main_" + methodName + extension).getPath();
145     }
146 }
147