[CTS V] Adding Handler for Screenshots Metadata
Include logic to generate the new screenshots metadata xml file.
Adding it to this common compatibility folder since CTS Verifier is not
yet migrated to the "production" pipes. Will pilot the change with
Verifiers first and add will migrate the logic to the main xTS production flow later on.
Bug: 224814107
Test: m CtsVerifier && manual test
Change-Id: I1fd7650bbad56104b6b08d8ccc83fdcab7f8f9a2
(cherry picked from commit 16a6036e5e70e56a38387e6f7dba683a38802ecf)
diff --git a/libraries/compatibility-common-util/src/com/android/compatibility/common/util/ITestResult.java b/libraries/compatibility-common-util/src/com/android/compatibility/common/util/ITestResult.java
index 33340e6..45811d2 100644
--- a/libraries/compatibility-common-util/src/com/android/compatibility/common/util/ITestResult.java
+++ b/libraries/compatibility-common-util/src/com/android/compatibility/common/util/ITestResult.java
@@ -170,4 +170,13 @@
* @param resultHistories The test result histories.
*/
void setTestResultHistories(List<TestResultHistory> resultHistories);
+
+ /**
+ * Set test screenshots metadata of test item. This method is for per-case screenshots in CTS
+ * Verifier. If this field is used for large test suites like CTS, it may cause performance
+ * issues in APFE. Thus please do not use this field in other test suites.
+ */
+ void setTestScreenshotsMetadata(TestScreenshotsMetadata screenshotsMetadata);
+
+ TestScreenshotsMetadata getTestScreenshotsMetadata();
}
diff --git a/libraries/compatibility-common-util/src/com/android/compatibility/common/util/ScreenshotsMetadataHandler.java b/libraries/compatibility-common-util/src/com/android/compatibility/common/util/ScreenshotsMetadataHandler.java
new file mode 100644
index 0000000..a5b0a4e
--- /dev/null
+++ b/libraries/compatibility-common-util/src/com/android/compatibility/common/util/ScreenshotsMetadataHandler.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2015 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.compatibility.common.util;
+
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * Handles conversion of results to/from files.
+ */
+public class ScreenshotsMetadataHandler {
+
+ private static final String ENCODING = "UTF-8";
+ private static final String TYPE = "org.kxml2.io.KXmlParser,org.kxml2.io.KXmlSerializer";
+ private static final String NS = null;
+ public static final String SCREENSHOTS_METADATA_FILE_NAME = "screenshots_metadata.xml";
+
+ // XML constants
+ private static final String CASE_TAG = "TestCase";
+ private static final String MODULE_TAG = "Module";
+ private static final String NAME_ATTR = "name";
+ private static final String RESULT_TAG = "Result";
+ private static final String TEST_TAG = "Test";
+
+ /**
+ * @param result - result of a single Compatibility invocation
+ * @param resultDir - directory where to write the screenshots metadata file
+ * @return The screenshots metadata file created.
+ */
+ public static File writeResults(IInvocationResult result, File resultDir)
+ throws IOException, XmlPullParserException {
+ File screenshotsMetadataFile = new File(resultDir, SCREENSHOTS_METADATA_FILE_NAME);
+ OutputStream stream = new FileOutputStream(screenshotsMetadataFile);
+ XmlSerializer serializer = XmlPullParserFactory.newInstance(TYPE, null).newSerializer();
+ serializer.setOutput(stream, ENCODING);
+ serializer.startDocument(ENCODING, false);
+ serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
+ serializer.processingInstruction(
+ "xml-stylesheet type=\"text/xsl\" href=\"compatibility_result.xsl\"");
+ serializer.startTag(NS, RESULT_TAG);
+ // Results
+ for (IModuleResult module : result.getModules()) {
+ serializer.startTag(NS, MODULE_TAG);
+ serializer.attribute(NS, NAME_ATTR, module.getName());
+ for (ICaseResult cr : module.getResults()) {
+ serializer.startTag(NS, CASE_TAG);
+ serializer.attribute(NS, NAME_ATTR, cr.getName());
+ for (ITestResult r : cr.getResults()) {
+ TestStatus status = r.getResultStatus();
+ if (status == null) {
+ continue; // test was not executed, don't report
+ }
+ serializer.startTag(NS, TEST_TAG);
+ serializer.attribute(NS, NAME_ATTR, r.getName());
+
+ TestScreenshotsMetadata screenshotsMetadata = r.getTestScreenshotsMetadata();
+ if (screenshotsMetadata != null) {
+ TestScreenshotsMetadata.serialize(serializer, screenshotsMetadata);
+ }
+ serializer.endTag(NS, TEST_TAG);
+ }
+ serializer.endTag(NS, CASE_TAG);
+ }
+ serializer.endTag(NS, MODULE_TAG);
+ }
+ serializer.endDocument();
+ return screenshotsMetadataFile;
+ }
+}
diff --git a/libraries/compatibility-common-util/src/com/android/compatibility/common/util/TestResult.java b/libraries/compatibility-common-util/src/com/android/compatibility/common/util/TestResult.java
index d2a9ca9..13db332 100644
--- a/libraries/compatibility-common-util/src/com/android/compatibility/common/util/TestResult.java
+++ b/libraries/compatibility-common-util/src/com/android/compatibility/common/util/TestResult.java
@@ -34,6 +34,7 @@
private boolean mIsRetry;
private boolean mSkipped;
private List<TestResultHistory> mTestResultHistories;
+ private TestScreenshotsMetadata mTestScreenshotsMetadata;
/**
* Create a {@link TestResult} for the given test name.
@@ -237,6 +238,7 @@
mIsRetry = false;
mSkipped = false;
mTestResultHistories = null;
+ mTestScreenshotsMetadata = null;
}
/**
@@ -299,4 +301,14 @@
public void setTestResultHistories(List<TestResultHistory> resultHistories) {
mTestResultHistories = resultHistories;
}
+
+ @Override
+ public void setTestScreenshotsMetadata(TestScreenshotsMetadata screenshotsMetadata) {
+ mTestScreenshotsMetadata = screenshotsMetadata;
+ }
+
+ @Override
+ public TestScreenshotsMetadata getTestScreenshotsMetadata() {
+ return mTestScreenshotsMetadata;
+ }
}
diff --git a/libraries/compatibility-common-util/src/com/android/compatibility/common/util/TestScreenshotsMetadata.java b/libraries/compatibility-common-util/src/com/android/compatibility/common/util/TestScreenshotsMetadata.java
new file mode 100644
index 0000000..423e7ed
--- /dev/null
+++ b/libraries/compatibility-common-util/src/com/android/compatibility/common/util/TestScreenshotsMetadata.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2022 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.compatibility.common.util;
+
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Utility class to add test case screenshot metadata to the report. This class records per-case
+ * screenshot metadata for CTS Verifier. If this field is used for large test suites like CTS, it
+ * may cause performance issues in APFE. Thus please do not use this class in other test suites.
+ */
+public class TestScreenshotsMetadata implements Serializable {
+
+ // XML constants
+ private static final String SCREENSHOTS_TAG = "Screenshots";
+ private static final String SCREENSHOT_TAG = "Screenshot";
+ private static final String NAME_ATTR = "name";
+ private static final String DESCRIPTION_ATTR = "description";
+
+ private final String mTestName;
+ private final Set<TestScreenshotsMetadata.ScreenshotMetadata> mScreenshotMetadataSet;
+
+ /**
+ * Constructor of test screenshots metadata.
+ *
+ * @param screenshots a Set of ScreenshotMetadata.
+ */
+ public TestScreenshotsMetadata(String testName,
+ Set<TestScreenshotsMetadata.ScreenshotMetadata> screenshots) {
+ mTestName = testName;
+ mScreenshotMetadataSet = screenshots;
+ }
+
+ /** Get test name */
+ public String getTestName() {
+ return mTestName;
+ }
+
+ /** Get a set of ScreenshotMetadata. */
+ public Set<TestScreenshotsMetadata.ScreenshotMetadata> getScreenshotMetadataSet() {
+ return mScreenshotMetadataSet;
+ }
+
+ @Override
+ public String toString() {
+ ArrayList<String> arr = new ArrayList<>();
+ for (TestScreenshotsMetadata.ScreenshotMetadata e : mScreenshotMetadataSet) {
+ arr.add(e.toString());
+ }
+ return String.join(", ", arr);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof TestScreenshotsMetadata)) {
+ return false;
+ }
+ TestScreenshotsMetadata that = (TestScreenshotsMetadata) o;
+ return Objects.equals(mTestName, that.mTestName)
+ && Objects.equals(mScreenshotMetadataSet, that.mScreenshotMetadataSet);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int hashCode() {
+ return Objects.hash(mTestName, mScreenshotMetadataSet);
+ }
+
+ /**
+ * Serializes a given {@link TestScreenshotsMetadata} to XML.
+ *
+ * @param serializer given serializer.
+ * @param screenshotsMetadata test screenshots metadata.
+ */
+ public static void serialize(
+ XmlSerializer serializer, TestScreenshotsMetadata screenshotsMetadata)
+ throws IOException {
+ if (screenshotsMetadata == null) {
+ throw new IllegalArgumentException("Test screenshots metadata was null");
+ }
+
+ serializer.startTag(null, SCREENSHOTS_TAG);
+
+ for (TestScreenshotsMetadata.ScreenshotMetadata screenshotMetadata :
+ screenshotsMetadata.getScreenshotMetadataSet()) {
+ serializer.startTag(null, SCREENSHOT_TAG);
+ serializer.attribute(null,
+ NAME_ATTR, String.valueOf(screenshotMetadata.getScreenshotName()));
+ serializer.attribute(
+ null, DESCRIPTION_ATTR, String.valueOf(screenshotMetadata.getDescription()));
+ serializer.endTag(null, SCREENSHOT_TAG);
+ }
+ serializer.endTag(null, SCREENSHOTS_TAG);
+ }
+
+ /** Single screenshot information */
+ public static class ScreenshotMetadata implements Serializable {
+ String mScreenshotName;
+ String mDescription;
+
+ public void setDescription(String description) {
+ mDescription = description;
+ }
+
+ public String getDescription() {
+ return mDescription;
+ }
+
+ public void setScreenshotName(String screenshotName) {
+ mScreenshotName = screenshotName;
+ }
+
+ public String getScreenshotName() {
+ return mScreenshotName;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof ScreenshotMetadata)) {
+ return false;
+ }
+ TestScreenshotsMetadata.ScreenshotMetadata that =
+ (TestScreenshotsMetadata.ScreenshotMetadata) o;
+ return mScreenshotName.equals(that.mScreenshotName)
+ && mDescription.equals(that.mDescription);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mScreenshotName, mDescription);
+ }
+
+ @Override
+ public String toString() {
+ return "[" + mScreenshotName + ", " + mDescription + "]";
+ }
+ }
+}