• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 com.android.cts.releaseparser;
18 
19 import com.android.cts.releaseparser.ReleaseProto.*;
20 
21 import java.io.File;
22 import java.io.FileWriter;
23 import java.io.IOException;
24 import java.io.PrintWriter;
25 import java.nio.charset.StandardCharsets;
26 import java.nio.file.Path;
27 import java.nio.file.Paths;
28 import java.security.MessageDigest;
29 import java.security.NoSuchAlgorithmException;
30 import java.util.ArrayList;
31 import java.util.Base64;
32 import java.util.Collection;
33 import java.util.HashMap;
34 import java.util.List;
35 import java.util.Map;
36 
37 class ReleaseParser {
38     private static final String ROOT_FOLDER_TAG = "/";
39     // configuration option
40     private static final String NOT_SHARDABLE_TAG = "not-shardable";
41     // test class option
42     private static final String RUNTIME_HIT_TAG = "runtime-hint";
43     // com.android.tradefed.testtype.AndroidJUnitTest option
44     private static final String PACKAGE_TAG = "package";
45     // com.android.compatibility.common.tradefed.testtype.JarHostTest option
46     private static final String JAR_NAME_TAG = "jar";
47     // com.android.tradefed.testtype.GTest option
48     private static final String NATIVE_TEST_DEVICE_PATH_TAG = "native-test-device-path";
49     private static final String MODULE_TAG = "module-name";
50 
51     private static final String SUITE_API_INSTALLER_TAG =
52             "com.android.tradefed.targetprep.suite.SuiteApkInstaller";
53     private static final String JAR_HOST_TEST_TAG =
54             "com.android.compatibility.common.tradefed.testtype.JarHostTest";
55     // com.android.tradefed.targetprep.suite.SuiteApkInstaller option
56     private static final String TEST_FILE_NAME_TAG = "test-file-name";
57     // com.android.compatibility.common.tradefed.targetprep.FilePusher option
58     private static final String PUSH_TAG = "push";
59 
60     // test class
61     private static final String ANDROID_JUNIT_TEST_TAG =
62             "com.android.tradefed.testtype.AndroidJUnitTest";
63 
64     private static final String TESTCASES_FOLDER_FORMAT = "testcases/%s";
65 
66     private final String mFolderPath;
67     private Path mRootPath;
68     private ReleaseContent.Builder mRelContentBuilder;
69     private Map<String, Entry> mEntries;
70 
ReleaseParser(String folder)71     ReleaseParser(String folder) {
72         mFolderPath = folder;
73         File fFile = new File(mFolderPath);
74         mRootPath = Paths.get(fFile.getAbsolutePath());
75         mEntries = new HashMap<String, Entry>();
76     }
77 
getReleaseId()78     public String getReleaseId() {
79         ReleaseContent relContent = getReleaseContent();
80         return getReleaseId(relContent);
81     }
82 
getReleaseId(ReleaseContent relContent)83     public static String getReleaseId(ReleaseContent relContent) {
84         return String.format(
85                 "%s-%s-%s",
86                 relContent.getFullname(), relContent.getVersion(), relContent.getBuildNumber());
87     }
88 
getReleaseContent()89     public ReleaseContent getReleaseContent() {
90         if (mRelContentBuilder == null) {
91             mRelContentBuilder = ReleaseContent.newBuilder();
92             // default APP_DISTRIBUTION_PACKAGE if no BUILD_PROP nor TEST_SUITE_TRADEFED is found
93             mRelContentBuilder.setReleaseType(ReleaseType.APP_DISTRIBUTION_PACKAGE);
94             // also add the root folder entry
95             Entry.Builder fBuilder = parseFolder(mFolderPath);
96             if (mRelContentBuilder.getName().equals("")) {
97                 System.err.println("Release Name unknown!");
98                 mRelContentBuilder.setName(mFolderPath);
99                 mRelContentBuilder.setFullname(mFolderPath);
100             }
101             fBuilder.setRelativePath(ROOT_FOLDER_TAG);
102             String relId = getReleaseId(mRelContentBuilder.build());
103             fBuilder.setName(relId);
104             mRelContentBuilder.setReleaseId(relId);
105             mRelContentBuilder.setContentId(fBuilder.getContentId());
106             mRelContentBuilder.setSize(fBuilder.getSize());
107             Entry fEntry = fBuilder.build();
108             mEntries.put(fEntry.getRelativePath(), fEntry);
109             mRelContentBuilder.putAllEntries(mEntries);
110         }
111         return mRelContentBuilder.build();
112     }
113 
114     // Parse all files in a folder and return the foler entry builder
parseFolder(String fPath)115     private Entry.Builder parseFolder(String fPath) {
116         Entry.Builder folderEntry = Entry.newBuilder();
117         File folder = new File(fPath);
118         Path folderPath = Paths.get(folder.getAbsolutePath());
119         String folderRelativePath = mRootPath.relativize(folderPath).toString();
120         File[] fileList = folder.listFiles();
121         Long folderSize = 0L;
122         List<Entry> entryList = new ArrayList<Entry>();
123 
124         // walks through all files
125         System.out.println("Parsing: " + folderRelativePath);
126         // skip if it's a symbolic link to a folder
127         if (fileList != null) {
128             for (File file : fileList) {
129                 if (file.isFile()) {
130                     String fileRelativePath =
131                             mRootPath.relativize(Paths.get(file.getAbsolutePath())).toString();
132                     FileParser fParser = FileParser.getParser(file);
133                     Entry.Builder fileEntryBuilder = fParser.getFileEntryBuilder();
134                     fileEntryBuilder.setRelativePath(fileRelativePath);
135 
136                     if (folderRelativePath.isEmpty()) {
137                         fileEntryBuilder.setParentFolder(ROOT_FOLDER_TAG);
138                     } else {
139                         fileEntryBuilder.setParentFolder(folderRelativePath);
140                     }
141 
142                     Entry.EntryType eType = fParser.getType();
143                     switch (eType) {
144                         case TEST_SUITE_TRADEFED:
145                             mRelContentBuilder.setTestSuiteTradefed(fileRelativePath);
146                             TestSuiteTradefedParser tstParser = (TestSuiteTradefedParser) fParser;
147                             // get [cts]-known-failures.xml
148                             mRelContentBuilder.addAllKnownFailures(tstParser.getKnownFailureList());
149                             mRelContentBuilder.setName(tstParser.getName());
150                             mRelContentBuilder.setFullname(tstParser.getFullName());
151                             mRelContentBuilder.setBuildNumber(tstParser.getBuildNumber());
152                             mRelContentBuilder.setTargetArch(tstParser.getTargetArch());
153                             mRelContentBuilder.setVersion(tstParser.getVersion());
154                             mRelContentBuilder.setReleaseType(ReleaseType.TEST_SUITE);
155                             break;
156                         case BUILD_PROP:
157                             BuildPropParser bpParser = (BuildPropParser) fParser;
158                             try {
159                                 mRelContentBuilder.setReleaseType(ReleaseType.DEVICE_BUILD);
160                                 mRelContentBuilder.setName(bpParser.getName());
161                                 mRelContentBuilder.setFullname(bpParser.getFullName());
162                                 mRelContentBuilder.setBuildNumber(bpParser.getBuildNumber());
163                                 mRelContentBuilder.setVersion(bpParser.getVersion());
164                                 mRelContentBuilder.putAllProperties(bpParser.getProperties());
165                             } catch (Exception e) {
166                                 System.err.println(
167                                         "No product name, version & etc. in "
168                                                 + file.getAbsoluteFile()
169                                                 + ", err:"
170                                                 + e.getMessage());
171                             }
172                             break;
173                         default:
174                     }
175                     // System.err.println("File:" + file.getAbsoluteFile());
176                     if (fParser.getDependencies() != null) {
177                         fileEntryBuilder.addAllDependencies(fParser.getDependencies());
178                     }
179                     if (fParser.getDynamicLoadingDependencies() != null) {
180                         fileEntryBuilder.addAllDynamicLoadingDependencies(
181                                 fParser.getDynamicLoadingDependencies());
182                     }
183                     fileEntryBuilder.setAbiBits(fParser.getAbiBits());
184                     fileEntryBuilder.setAbiArchitecture(fParser.getAbiArchitecture());
185 
186                     Entry fEntry = fileEntryBuilder.build();
187                     entryList.add(fEntry);
188                     mEntries.put(fEntry.getRelativePath(), fEntry);
189                     folderSize += file.length();
190                 } else if (file.isDirectory()) {
191                     // Checks subfolders
192                     Entry.Builder subFolderEntry = parseFolder(file.getAbsolutePath());
193                     if (folderRelativePath.isEmpty()) {
194                         subFolderEntry.setParentFolder(ROOT_FOLDER_TAG);
195                     } else {
196                         subFolderEntry.setParentFolder(folderRelativePath);
197                     }
198                     Entry sfEntry = subFolderEntry.build();
199                     entryList.add(sfEntry);
200                     mEntries.put(sfEntry.getRelativePath(), sfEntry);
201                     folderSize += sfEntry.getSize();
202                 }
203             }
204         }
205         folderEntry.setName(folderRelativePath);
206         folderEntry.setSize(folderSize);
207         folderEntry.setType(Entry.EntryType.FOLDER);
208         folderEntry.setContentId(getFolderContentId(folderEntry, entryList));
209         folderEntry.setRelativePath(folderRelativePath);
210         return folderEntry;
211     }
212 
getFolderContentId(Entry.Builder folderEntry, List<Entry> entryList)213     private static String getFolderContentId(Entry.Builder folderEntry, List<Entry> entryList) {
214         String id = null;
215         try {
216             MessageDigest md = MessageDigest.getInstance("SHA-256");
217             for (Entry entry : entryList) {
218                 md.update(entry.getContentId().getBytes(StandardCharsets.UTF_8));
219             }
220             // Converts to Base64 String
221             id = Base64.getEncoder().encodeToString(md.digest());
222         } catch (NoSuchAlgorithmException e) {
223             System.err.println("NoSuchAlgorithmException:" + e.getMessage());
224         }
225         return id;
226     }
227 
228     // writes releaes content to a CSV file
writeRelesaeContentCsvFile(String relNameVer, String csvFile)229     public void writeRelesaeContentCsvFile(String relNameVer, String csvFile) {
230         try {
231             FileWriter fWriter = new FileWriter(csvFile);
232             PrintWriter pWriter = new PrintWriter(fWriter);
233             // Header
234             pWriter.printf(
235                     "release,type,name,size,relative_path,content_id,parent_folder,code_id,architecture,bits,dependencies,dynamic_loading_dependencies,services\n");
236             for (Entry entry : getFileEntries()) {
237                 pWriter.printf(
238                         "%s,%s,%s,%d,%s,%s,%s,%s,%s,%d,%s,%s,%s\n",
239                         relNameVer,
240                         entry.getType(),
241                         entry.getName(),
242                         entry.getSize(),
243                         entry.getRelativePath(),
244                         entry.getContentId(),
245                         entry.getParentFolder(),
246                         entry.getCodeId(),
247                         entry.getAbiArchitecture(),
248                         entry.getAbiBits(),
249                         String.join(" ", entry.getDependenciesList()),
250                         String.join(" ", entry.getDynamicLoadingDependenciesList()),
251                         RcParser.toString(entry.getServicesList()));
252             }
253             pWriter.flush();
254             pWriter.close();
255         } catch (IOException e) {
256             System.err.println("IOException:" + e.getMessage());
257         }
258     }
259 
260     // writes known failures to a CSV file
writeKnownFailureCsvFile(String relNameVer, String csvFile)261     public void writeKnownFailureCsvFile(String relNameVer, String csvFile) {
262         ReleaseContent relContent = getReleaseContent();
263         if (relContent.getKnownFailuresList().size() == 0) {
264             // Skip if no Known Failures
265             return;
266         }
267 
268         try {
269             FileWriter fWriter = new FileWriter(csvFile);
270             PrintWriter pWriter = new PrintWriter(fWriter);
271             //Header
272             pWriter.printf("release,compatibility:exclude-filter\n");
273             for (String kf : relContent.getKnownFailuresList()) {
274                 pWriter.printf("%s,%s\n", relNameVer, kf);
275             }
276             pWriter.flush();
277             pWriter.close();
278         } catch (IOException e) {
279             System.err.println("IOException:" + e.getMessage());
280         }
281     }
282 
getFileEntries()283     public Collection<Entry> getFileEntries() {
284         return getReleaseContent().getEntries().values();
285     }
286 }
287