From 05039e9dd77c58b46901c5c9496f95606084cd15 Mon Sep 17 00:00:00 2001
From: Max Loh <mloh@google.com>
Date: Thu, 28 Mar 2024 18:22:19 +0000
Subject: [PATCH] Revert^2 "Aslgen tests"

9d5ad5cfd2e0c0801115b67c6195389b6d8de668

Bug: 329902686
Test: Unit tests.
Change-Id: Ie2027d77ac109a3b2bcd3d13a44df824e24d5aff
---
 tools/app_metadata_bundles/Android.bp         |  13 +++
 .../android/asllib/AndroidSafetyLabel.java    |  18 +++
 .../lib/java/com/android/asllib/XmlUtils.java |   2 +-
 .../java/com/android/aslgen/AllTests.java     |  26 +++++
 .../java/com/android/aslgen/AslgenTests.java  | 105 ++++++++++++++++++
 .../aslgen/validmappings/contacts/hr.xml      |  11 ++
 .../aslgen/validmappings/contacts/od.xml      |  17 +++
 .../aslgen/validmappings/location/hr.xml      |  16 +++
 .../aslgen/validmappings/location/od.xml      |  25 +++++
 .../src/test/resources/test.xml               |  16 +++
 10 files changed, 248 insertions(+), 1 deletion(-)
 create mode 100644 tools/app_metadata_bundles/src/test/java/com/android/aslgen/AllTests.java
 create mode 100644 tools/app_metadata_bundles/src/test/java/com/android/aslgen/AslgenTests.java
 create mode 100644 tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/contacts/hr.xml
 create mode 100644 tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/contacts/od.xml
 create mode 100644 tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/location/hr.xml
 create mode 100644 tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/location/od.xml
 create mode 100644 tools/app_metadata_bundles/src/test/resources/test.xml

diff --git a/tools/app_metadata_bundles/Android.bp b/tools/app_metadata_bundles/Android.bp
index be6bea6b7fea..a012dca19904 100644
--- a/tools/app_metadata_bundles/Android.bp
+++ b/tools/app_metadata_bundles/Android.bp
@@ -5,6 +5,7 @@ package {
     // to get the below license kinds:
     //   SPDX-license-identifier-Apache-2.0
     default_applicable_licenses: ["frameworks_base_license"],
+    default_team: "trendy_team_preload_safety",
 }
 
 java_library_host {
@@ -24,3 +25,15 @@ java_binary_host {
         "asllib",
     ],
 }
+
+java_test_host {
+    name: "aslgen-test",
+    srcs: ["src/test/java/**/*.java"],
+    exclude_srcs: [
+    ],
+    java_resource_dirs: ["src/test/resources"],
+    static_libs: [
+        "aslgen",
+        "junit",
+    ],
+}
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AndroidSafetyLabel.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AndroidSafetyLabel.java
index bc8063ef7b5f..ed9f1ac70a2b 100644
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AndroidSafetyLabel.java
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/AndroidSafetyLabel.java
@@ -22,9 +22,12 @@ import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.xml.sax.SAXException;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.List;
 
 import javax.xml.parsers.DocumentBuilderFactory;
@@ -78,6 +81,13 @@ public class AndroidSafetyLabel implements AslMarshallable {
         }
     }
 
+    /** Reads a {@link AndroidSafetyLabel} from a String. */
+    public static AndroidSafetyLabel readFromString(String in, Format format)
+            throws IOException, ParserConfigurationException, SAXException, MalformedXmlException {
+        InputStream stream = new ByteArrayInputStream(in.getBytes(StandardCharsets.UTF_8));
+        return readFromStream(stream, format);
+    }
+
     /** Write the content of the {@link AndroidSafetyLabel} to a {@link OutputStream}. */
     // TODO(b/329902686): Support outputting human-readable format.
     public void writeToStream(OutputStream out, Format format)
@@ -108,6 +118,14 @@ public class AndroidSafetyLabel implements AslMarshallable {
         transformer.transform(domSource, streamResult);
     }
 
+    /** Get the content of the {@link AndroidSafetyLabel} as String. */
+    public String getXmlAsString(Format format)
+            throws IOException, ParserConfigurationException, TransformerException {
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        this.writeToStream(out, format);
+        return out.toString(StandardCharsets.UTF_8);
+    }
+
     /** Creates an on-device DOM element from an {@link AndroidSafetyLabel} */
     @Override
     public List<Element> toOdDomElements(Document doc) {
diff --git a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/XmlUtils.java b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/XmlUtils.java
index 3bc9ccc2138b..cedaf9374cd4 100644
--- a/tools/app_metadata_bundles/src/lib/java/com/android/asllib/XmlUtils.java
+++ b/tools/app_metadata_bundles/src/lib/java/com/android/asllib/XmlUtils.java
@@ -108,7 +108,7 @@ public class XmlUtils {
     public static List<Element> asElementList(NodeList nodeList) {
         List<Element> elementList = new ArrayList<Element>();
         for (int i = 0; i < nodeList.getLength(); i++) {
-            var elementAsNode = nodeList.item(0);
+            var elementAsNode = nodeList.item(i);
             if (elementAsNode instanceof Element) {
                 elementList.add(((Element) elementAsNode));
             }
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/aslgen/AllTests.java b/tools/app_metadata_bundles/src/test/java/com/android/aslgen/AllTests.java
new file mode 100644
index 000000000000..7ebb7a1c44bf
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/java/com/android/aslgen/AllTests.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2017 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.aslgen;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    AslgenTests.class,
+})
+public class AllTests {}
diff --git a/tools/app_metadata_bundles/src/test/java/com/android/aslgen/AslgenTests.java b/tools/app_metadata_bundles/src/test/java/com/android/aslgen/AslgenTests.java
new file mode 100644
index 000000000000..cea22a2178b7
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/java/com/android/aslgen/AslgenTests.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2017 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.aslgen;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.asllib.AndroidSafetyLabel;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+@RunWith(JUnit4.class)
+public class AslgenTests {
+    private static final String VALID_MAPPINGS_PATH = "com/android/aslgen/validmappings";
+    private static final List<String> VALID_MAPPINGS_SUBDIRS = List.of("location", "contacts");
+    private static final String HR_XML_FILENAME = "hr.xml";
+    private static final String OD_XML_FILENAME = "od.xml";
+
+    /** Logic for setting up tests (empty if not yet needed). */
+    public static void main(String[] params) throws Exception {}
+
+    /** Tests valid mappings between HR and OD. */
+    @Test
+    public void testValidMappings() throws Exception {
+        System.out.println("start testing valid mappings.");
+
+        for (String subdir : VALID_MAPPINGS_SUBDIRS) {
+            Path hrPath = Paths.get(VALID_MAPPINGS_PATH, subdir, HR_XML_FILENAME);
+            Path odPath = Paths.get(VALID_MAPPINGS_PATH, subdir, OD_XML_FILENAME);
+
+            System.out.println("hr path: " + hrPath.toString());
+            System.out.println("od path: " + odPath.toString());
+
+            InputStream hrStream =
+                    getClass().getClassLoader().getResourceAsStream(hrPath.toString());
+            String hrContents = new String(hrStream.readAllBytes(), StandardCharsets.UTF_8);
+            InputStream odStream =
+                    getClass().getClassLoader().getResourceAsStream(odPath.toString());
+            String odContents = new String(odStream.readAllBytes(), StandardCharsets.UTF_8);
+            AndroidSafetyLabel asl =
+                    AndroidSafetyLabel.readFromString(
+                            hrContents, AndroidSafetyLabel.Format.HUMAN_READABLE);
+            String out = asl.getXmlAsString(AndroidSafetyLabel.Format.ON_DEVICE);
+            System.out.println("out: " + out);
+
+            assertEquals(getFormattedXml(out), getFormattedXml(odContents));
+        }
+    }
+
+    private static String getFormattedXml(String xmlStr)
+            throws ParserConfigurationException, IOException, SAXException, TransformerException {
+        InputStream stream = new ByteArrayInputStream(xmlStr.getBytes(StandardCharsets.UTF_8));
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware(true);
+        Document document = factory.newDocumentBuilder().parse(stream);
+
+        TransformerFactory transformerFactory = TransformerFactory.newInstance();
+        Transformer transformer = transformerFactory.newTransformer();
+        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
+
+        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+        StreamResult streamResult = new StreamResult(outStream); // out
+        DOMSource domSource = new DOMSource(document);
+        transformer.transform(domSource, streamResult);
+
+        return outStream.toString(StandardCharsets.UTF_8);
+    }
+}
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/contacts/hr.xml b/tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/contacts/hr.xml
new file mode 100644
index 000000000000..fe020558074d
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/contacts/hr.xml
@@ -0,0 +1,11 @@
+<app-metadata-bundles>
+    <safety-labels version="12345">
+        <data-labels>
+            <data-shared dataCategory="contacts"
+                dataType="contacts"
+                isSharingOptional="false"
+                ephemeral="true"
+                purposes="analytics" />
+        </data-labels>
+    </safety-labels>
+</app-metadata-bundles>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/contacts/od.xml b/tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/contacts/od.xml
new file mode 100644
index 000000000000..ba6327e9b200
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/contacts/od.xml
@@ -0,0 +1,17 @@
+<bundle>
+    <pbundle_as_map name="safety_labels">
+        <pbundle_as_map name="data_labels">
+            <pbundle_as_map name="data_shared">
+                <pbundle_as_map name="contacts">
+                    <pbundle_as_map name="contacts">
+                        <int-array name="purposes" num="1">
+                            <item value="2"/>
+                        </int-array>
+                        <boolean name="is_sharing_optional" value="false"/>
+                        <boolean name="ephemeral" value="true"/>
+                    </pbundle_as_map>
+                </pbundle_as_map>
+            </pbundle_as_map>
+        </pbundle_as_map>
+    </pbundle_as_map>
+</bundle>
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/location/hr.xml b/tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/location/hr.xml
new file mode 100644
index 000000000000..202cc1e1c526
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/location/hr.xml
@@ -0,0 +1,16 @@
+<app-metadata-bundles>
+    <safety-labels version="12345">
+        <data-labels>
+            <data-shared dataCategory="location"
+                dataType="precise_location"
+                isSharingOptional="true"
+                ephemeral="true"
+                purposes="app_functionality|analytics" />
+            <data-shared dataCategory="location"
+                dataType="approx_location"
+                isSharingOptional="false"
+                ephemeral="false"
+                purposes="app_functionality" />
+        </data-labels>
+    </safety-labels>
+</app-metadata-bundles>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/location/od.xml b/tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/location/od.xml
new file mode 100644
index 000000000000..fbcb4fb2f1a4
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/com/android/aslgen/validmappings/location/od.xml
@@ -0,0 +1,25 @@
+<bundle>
+    <pbundle_as_map name="safety_labels">
+        <pbundle_as_map name="data_labels">
+            <pbundle_as_map name="data_shared">
+                <pbundle_as_map name="location">
+                    <pbundle_as_map name="precise_location">
+                        <int-array name="purposes" num="2">
+                            <item value="2"/>
+                            <item value="1"/>
+                        </int-array>
+                        <boolean name="is_sharing_optional" value="true"/>
+                        <boolean name="ephemeral" value="true"/>
+                    </pbundle_as_map>
+                    <pbundle_as_map name="approx_location">
+                        <int-array name="purposes" num="1">
+                            <item value="1"/>
+                        </int-array>
+                        <boolean name="is_sharing_optional" value="false"/>
+                        <boolean name="ephemeral" value="false"/>
+                    </pbundle_as_map>
+                </pbundle_as_map>
+            </pbundle_as_map>
+        </pbundle_as_map>
+    </pbundle_as_map>
+</bundle>
\ No newline at end of file
diff --git a/tools/app_metadata_bundles/src/test/resources/test.xml b/tools/app_metadata_bundles/src/test/resources/test.xml
new file mode 100644
index 000000000000..202cc1e1c526
--- /dev/null
+++ b/tools/app_metadata_bundles/src/test/resources/test.xml
@@ -0,0 +1,16 @@
+<app-metadata-bundles>
+    <safety-labels version="12345">
+        <data-labels>
+            <data-shared dataCategory="location"
+                dataType="precise_location"
+                isSharingOptional="true"
+                ephemeral="true"
+                purposes="app_functionality|analytics" />
+            <data-shared dataCategory="location"
+                dataType="approx_location"
+                isSharingOptional="false"
+                ephemeral="false"
+                purposes="app_functionality" />
+        </data-labels>
+    </safety-labels>
+</app-metadata-bundles>
\ No newline at end of file
-- 
GitLab