blob: 97e0c5c9556ccef0ae084dd062373786d2cfccb4 [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.cts.releaseparser;
import com.android.cts.releaseparser.ReleaseProto.*;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
import java.io.File;
import java.io.FileReader;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.NoSuchAlgorithmException;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class ReleaseParser {
// configuration option
private static final String NOT_SHARDABLE_TAG = "not-shardable";
// test class option
private static final String RUNTIME_HIT_TAG = "runtime-hint";
// com.android.tradefed.testtype.AndroidJUnitTest option
private static final String PACKAGE_TAG = "package";
// com.android.compatibility.common.tradefed.testtype.JarHostTest option
private static final String JAR_NAME_TAG = "jar";
// com.android.tradefed.testtype.GTest option
private static final String NATIVE_TEST_DEVICE_PATH_TAG = "native-test-device-path";
private static final String MODULE_TAG = "module-name";
private static final String SUITE_API_INSTALLER_TAG =
"com.android.tradefed.targetprep.suite.SuiteApkInstaller";
private static final String JAR_HOST_TEST_TAG =
"com.android.compatibility.common.tradefed.testtype.JarHostTest";
// com.android.tradefed.targetprep.suite.SuiteApkInstaller option
private static final String TEST_FILE_NAME_TAG = "test-file-name";
// com.android.compatibility.common.tradefed.targetprep.FilePusher option
private static final String PUSH_TAG = "push";
// test class
private static final String ANDROID_JUNIT_TEST_TAG =
"com.android.tradefed.testtype.AndroidJUnitTest";
// Target File Extensions
private static final String CONFIG_EXT_TAG = ".config";
private static final String JAR_EXT_TAG = ".jar";
private static final String APK_EXT_TAG = ".apk";
private static final String SO_EXT_TAG = ".so";
private static final String TEST_SUITE_TRADEFED_TAG = "-tradefed.jar";
private static final String TESTCASES_FOLDER_FORMAT = "testcases/%s";
private final String mFolderPath;
private Path mRootPath;
private ReleaseContent.Builder mRelContentBuilder;
private Map<String, Entry> mEntries;
ReleaseParser(String folder) {
mFolderPath = folder;
File fFile = new File(mFolderPath);
mRootPath = Paths.get(fFile.getAbsolutePath());
mEntries = new HashMap<String, Entry>();
}
public String getRelNameVer() {
ReleaseContent relContent = getReleaseContent();
return String.format(
"%s-%s-%s",
relContent.getName(), relContent.getVersion(), relContent.getBuildNumber());
}
public ReleaseContent getReleaseContent() {
if (mRelContentBuilder == null) {
mRelContentBuilder = ReleaseContent.newBuilder();
// also add the root folder entry
Entry.Builder fBuilder = parseFolder(mFolderPath);
fBuilder.setName(
String.format(
"%s-%s-%s",
mRelContentBuilder.getName(),
mRelContentBuilder.getVersion(),
mRelContentBuilder.getBuildNumber()));
fBuilder.setParentFolder(mFolderPath);
Entry fEntry = fBuilder.build();
mEntries.put(fEntry.getRelativePath(), fEntry);
mRelContentBuilder.putAllEntries(mEntries);
}
return mRelContentBuilder.build();
}
// Parse all files in a folder and return the foler entry builder
private Entry.Builder parseFolder(String fPath) {
Entry.Builder folderEntry = Entry.newBuilder();
File folder = new File(fPath);
Path folderPath = Paths.get(folder.getAbsolutePath());
String folderRelativePath = mRootPath.relativize(folderPath).toString();
File[] fileList = folder.listFiles();
Long folderSize = 0L;
List<Entry> entryList = new ArrayList<Entry>();
// walks through all files
for (File file : fileList) {
if (file.isFile()) {
String fileRelativePath =
mRootPath.relativize(Paths.get(file.getAbsolutePath())).toString();
Entry.Builder fileEntry = Entry.newBuilder();
fileEntry.setName(file.getName());
fileEntry.setSize(file.length());
fileEntry.setContentId(getFileContentId(file));
fileEntry.setRelativePath(fileRelativePath);
fileEntry.setParentFolder(folderRelativePath);
try {
TestModuleConfig tmConfig = parseTestModuleConfig(fileEntry, file);
if (null != tmConfig) {
fileEntry.setTestModuleConfig(tmConfig);
}
// get [cts]-known-failures.xml
if (file.getName().endsWith(TEST_SUITE_TRADEFED_TAG)) {
mRelContentBuilder.setTestSuiteTradefed(fileRelativePath);
TestSuiteTradefedParser tstParser = new TestSuiteTradefedParser(file);
mRelContentBuilder.addAllKnownFailures(tstParser.getKnownFailureList());
mRelContentBuilder.setName(tstParser.getName());
mRelContentBuilder.setFullname(tstParser.getFullname());
mRelContentBuilder.setBuildNumber(tstParser.getBuildNumber());
mRelContentBuilder.setTargetArch(tstParser.getTargetArch());
mRelContentBuilder.setVersion(tstParser.getVersion());
}
} catch (Exception ex) {
System.err.println(String.format("Cannot parse %s", file.getAbsolutePath()));
ex.printStackTrace();
}
Entry fEntry = fileEntry.build();
entryList.add(fEntry);
mEntries.put(fEntry.getRelativePath(), fEntry);
folderSize += file.length();
} else if (file.isDirectory()) {
// Checks subfolders
Entry.Builder subFolderEntry = parseFolder(file.getAbsolutePath());
subFolderEntry.setParentFolder(folderRelativePath);
Entry sfEntry = subFolderEntry.build();
entryList.add(sfEntry);
mEntries.put(sfEntry.getRelativePath(), sfEntry);
folderSize += sfEntry.getSize();
}
}
folderEntry.setName(folderRelativePath);
folderEntry.setSize(folderSize);
folderEntry.setType(Entry.EntryType.FOLDER);
folderEntry.setContentId(getFolderContentId(folderEntry, entryList));
folderEntry.setRelativePath(folderRelativePath);
return folderEntry;
}
// Parse a file
private static TestModuleConfig parseTestModuleConfig(Entry.Builder fEntry, File file)
throws Exception {
if (file.getName().endsWith(CONFIG_EXT_TAG)) {
fEntry.setType(Entry.EntryType.CONFIG);
return parseConfigFile(file);
} else if (file.getName().endsWith(APK_EXT_TAG)) {
fEntry.setType(Entry.EntryType.APK);
} else if (file.getName().endsWith(JAR_EXT_TAG)) {
fEntry.setType(Entry.EntryType.JAR);
} else if (file.getName().endsWith(SO_EXT_TAG)) {
fEntry.setType(Entry.EntryType.SO);
} else {
// Just file in general
fEntry.setType(Entry.EntryType.FILE);
}
return null;
}
private static TestModuleConfig parseConfigFile(File file) throws Exception {
XMLReader xmlReader = XMLReaderFactory.createXMLReader();
TestModuleConfigHandler testModuleXmlHandler = new TestModuleConfigHandler(file.getName());
xmlReader.setContentHandler(testModuleXmlHandler);
FileReader fileReader = null;
try {
fileReader = new FileReader(file);
xmlReader.parse(new InputSource(fileReader));
return testModuleXmlHandler.getTestModuleConfig();
} finally {
if (null != fileReader) {
fileReader.close();
}
}
}
private static String getFileContentId(File file) {
String id = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
FileInputStream fis = new FileInputStream(file);
byte[] dataBytes = new byte[10240];
int nread = 0;
while ((nread = fis.read(dataBytes)) != -1) {
md.update(dataBytes, 0, nread);
}
// Converts to Base64 String
id = Base64.getEncoder().encodeToString(md.digest());
} catch (IOException e) {
System.err.println("IOException:" + e.getMessage());
} catch (NoSuchAlgorithmException e) {
System.err.println("NoSuchAlgorithmException:" + e.getMessage());
}
return id;
}
private static String getFolderContentId(Entry.Builder folderEntry, List<Entry> entryList) {
String id = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
for (Entry entry : entryList) {
md.update(entry.getContentId().getBytes(StandardCharsets.UTF_8));
}
// Converts to Base64 String
id = Base64.getEncoder().encodeToString(md.digest());
} catch (NoSuchAlgorithmException e) {
System.err.println("NoSuchAlgorithmException:" + e.getMessage());
}
return id;
}
// writes releaes content to a CSV file
public void writeRelesaeContentCsvFile(String relNameVer, String csvFile) {
try {
FileWriter fWriter = new FileWriter(csvFile);
PrintWriter pWriter = new PrintWriter(fWriter);
//Header
pWriter.printf("release,type,name,size,relative_path,content_id,parent_folder\n");
for (Entry entry : getFileEntriesList()) {
pWriter.printf(
"%s,%s,%s,%d,%s,%s,%s\n",
relNameVer,
entry.getType(),
entry.getName(),
entry.getSize(),
entry.getRelativePath(),
entry.getContentId(),
entry.getParentFolder());
}
pWriter.flush();
pWriter.close();
} catch (IOException e) {
System.err.println("IOException:" + e.getMessage());
}
}
// writes known failures to a CSV file
public void writeKnownFailureCsvFile(String relNameVer, String csvFile) {
ReleaseContent relContent = getReleaseContent();
try {
FileWriter fWriter = new FileWriter(csvFile);
PrintWriter pWriter = new PrintWriter(fWriter);
//Header
pWriter.printf("release,compatibility:exclude-filter\n");
for (String kf : relContent.getKnownFailuresList()) {
pWriter.printf("%s,%s\n", relNameVer, kf);
}
pWriter.flush();
pWriter.close();
} catch (IOException e) {
System.err.println("IOException:" + e.getMessage());
}
}
public Collection<Entry> getFileEntriesList() {
return getReleaseContent().getEntries().values();
}
}