Tests for 'aapt2 dump badging' command.

Bug: b/228949376
Test: Dump_test.cpp
Change-Id: If07e77b9281bdfd456df7c84f4a912bdf0851490
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index 0849600..3dc550e 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -191,6 +191,7 @@
         "integration-tests/CompileTest/**/*",
         "integration-tests/CommandTests/**/*",
         "integration-tests/ConvertTest/**/*",
+        "integration-tests/DumpTest/**/*",
     ],
 }
 
diff --git a/tools/aapt2/cmd/Dump.h b/tools/aapt2/cmd/Dump.h
index ec320ec..c7a3567 100644
--- a/tools/aapt2/cmd/Dump.h
+++ b/tools/aapt2/cmd/Dump.h
@@ -131,6 +131,14 @@
                       &options_.include_meta_data);
   }
 
+  void SetIncludeMetaData(bool value) {
+    options_.include_meta_data = value;
+  }
+
+  void SetOnlyPermissions(bool value) {
+    options_.only_permissions = value;
+  }
+
   int Dump(LoadedApk* apk) override {
     return DumpManifest(apk, options_, GetPrinter(), GetDiagnostics());
   }
diff --git a/tools/aapt2/cmd/Dump_test.cpp b/tools/aapt2/cmd/Dump_test.cpp
new file mode 100644
index 0000000..d018882
--- /dev/null
+++ b/tools/aapt2/cmd/Dump_test.cpp
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+#include "Dump.h"
+
+#include "LoadedApk.h"
+#include "io/StringStream.h"
+#include "test/Test.h"
+#include "text/Printer.h"
+
+using ::aapt::io::StringOutputStream;
+using ::aapt::text::Printer;
+using testing::Eq;
+using testing::Ne;
+
+namespace aapt {
+
+using DumpTest = CommandTestFixture;
+
+class NoopDiagnostics : public IDiagnostics {
+ public:
+  void Log(Level level, DiagMessageActual& actualMsg) override {
+  }
+};
+static NoopDiagnostics noop_diag;
+
+void DumpBadgingToString(LoadedApk* loaded_apk, std::string* output, bool include_meta_data = false,
+                         bool only_permissions = false) {
+  StringOutputStream output_stream(output);
+  Printer printer(&output_stream);
+
+  DumpBadgingCommand command(&printer, &noop_diag);
+  command.SetIncludeMetaData(include_meta_data);
+  command.SetOnlyPermissions(only_permissions);
+  ASSERT_EQ(command.Dump(loaded_apk), 0);
+  output_stream.Flush();
+}
+
+TEST_F(DumpTest, DumpBadging) {
+  auto apk_path = file::BuildPath(
+      {android::base::GetExecutableDirectory(), "integration-tests", "DumpTest", "minimal.apk"});
+  auto loaded_apk = LoadedApk::LoadApkFromPath(apk_path, &noop_diag);
+
+  std::string output;
+  DumpBadgingToString(loaded_apk.get(), &output);
+
+  std::string expected;
+  auto expected_path = file::BuildPath({android::base::GetExecutableDirectory(),
+                                        "integration-tests", "DumpTest", "minimal_expected.txt"});
+  ::android::base::ReadFileToString(expected_path, &expected);
+  ASSERT_EQ(output, expected);
+}
+
+TEST_F(DumpTest, DumpBadgingAllComponents) {
+  auto apk_path = file::BuildPath(
+      {android::base::GetExecutableDirectory(), "integration-tests", "DumpTest", "components.apk"});
+  auto loaded_apk = LoadedApk::LoadApkFromPath(apk_path, &noop_diag);
+
+  std::string output;
+  DumpBadgingToString(loaded_apk.get(), &output, /* include_meta_data= */ true);
+
+  std::string expected;
+  auto expected_path =
+      file::BuildPath({android::base::GetExecutableDirectory(), "integration-tests", "DumpTest",
+                       "components_expected.txt"});
+  ::android::base::ReadFileToString(expected_path, &expected);
+  ASSERT_EQ(output, expected);
+}
+
+TEST_F(DumpTest, DumpBadgingPermissionsOnly) {
+  auto apk_path = file::BuildPath(
+      {android::base::GetExecutableDirectory(), "integration-tests", "DumpTest", "components.apk"});
+  auto loaded_apk = LoadedApk::LoadApkFromPath(apk_path, &noop_diag);
+
+  std::string output;
+  DumpBadgingToString(loaded_apk.get(), &output, /* include_meta_data= */ false,
+                      /* only_permissions= */ true);
+
+  std::string expected;
+  auto expected_path =
+      file::BuildPath({android::base::GetExecutableDirectory(), "integration-tests", "DumpTest",
+                       "components_permissions_expected.txt"});
+  ::android::base::ReadFileToString(expected_path, &expected);
+  ASSERT_EQ(output, expected);
+}
+
+}  // namespace aapt
\ No newline at end of file
diff --git a/tools/aapt2/dump/DumpManifest.cpp b/tools/aapt2/dump/DumpManifest.cpp
index 9828b97..2c833e7 100644
--- a/tools/aapt2/dump/DumpManifest.cpp
+++ b/tools/aapt2/dump/DumpManifest.cpp
@@ -1565,16 +1565,16 @@
 
   void Print(text::Printer* printer) override {
     if (extractor()->options_.include_meta_data && !name.empty()) {
-      printer->Print(StringPrintf("meta-data: name='%s' ", name.data()));
+      printer->Print(StringPrintf("meta-data: name='%s'", name.data()));
       if (!value.empty()) {
-        printer->Print(StringPrintf("value='%s' ", value.data()));
+        printer->Print(StringPrintf(" value='%s'", value.data()));
       } else if (value_int) {
-        printer->Print(StringPrintf("value='%d' ", *value_int));
+        printer->Print(StringPrintf(" value='%d'", *value_int));
       } else {
         if (!resource.empty()) {
-          printer->Print(StringPrintf("resource='%s' ", resource.data()));
+          printer->Print(StringPrintf(" resource='%s'", resource.data()));
         } else if (resource_int) {
-          printer->Print(StringPrintf("resource='%d' ", *resource_int));
+          printer->Print(StringPrintf(" resource='%d'", *resource_int));
         }
       }
       printer->Print("\n");
diff --git a/tools/aapt2/integration-tests/DumpTest/components.apk b/tools/aapt2/integration-tests/DumpTest/components.apk
new file mode 100644
index 0000000..deb55ea
--- /dev/null
+++ b/tools/aapt2/integration-tests/DumpTest/components.apk
Binary files differ
diff --git a/tools/aapt2/integration-tests/DumpTest/components_expected.txt b/tools/aapt2/integration-tests/DumpTest/components_expected.txt
new file mode 100644
index 0000000..79b6706
--- /dev/null
+++ b/tools/aapt2/integration-tests/DumpTest/components_expected.txt
@@ -0,0 +1,56 @@
+package: name='com.example.bundletool.minimal' versionCode='1' versionName='1.0' platformBuildVersionName='12' platformBuildVersionCode='31' compileSdkVersion='31' compileSdkVersionCodename='12'
+sdkVersion:'21'
+targetSdkVersion:'31'
+uses-configuration: reqTouchScreen='3' reqKeyboardType='2' reqHardKeyboard='-1' reqNavigation='3' reqFiveWayNav='-1'
+supports-gl-texture:'GL_OES_compressed_paletted_texture'
+uses-permission: name='android.permission.BIND_ACCESSIBILITY_SERVICE' maxSdkVersion='24'
+uses-permission-sdk-23: name='android.permission.RECEIVE_SMS'
+uses-permission: name='android.permission.WRITE_EXTERNAL_STORAGE'
+compatible-screens:'500/240','400/160'
+application-label:'minimal'
+application-icon-160:'res/uF.xml'
+application-icon-240:'res/uF.xml'
+application-icon-320:'res/uF.xml'
+application-icon-480:'res/uF.xml'
+application-icon-640:'res/uF.xml'
+application-icon-65534:'res/uF.xml'
+application: label='minimal' icon='res/uF.xml'
+uses-library:'mylib1'
+uses-library-not-required:'my_optional_lib'
+uses-native-library:'native1'
+uses-native-library-not-required:'optional'
+launchable-activity: name='com.example.bundletool.minimal.MainActivity'  label='minimal' icon=''
+meta-data: name='android.nfc.cardemulation.host_apdu_service' resource='res/dU.xml'
+uses-permission: name='android.permission.READ_EXTERNAL_STORAGE'
+uses-implied-permission: name='android.permission.READ_EXTERNAL_STORAGE' reason='requested WRITE_EXTERNAL_STORAGE'
+feature-group: label=''
+  uses-feature: name='android.hardware.bluetooth'
+  uses-feature: name='android.hardware.camera'
+  uses-feature: name='android.hardware.faketouch'
+  uses-implied-feature: name='android.hardware.faketouch' reason='default feature for all apps'
+  uses-feature-sdk-23: name='android.hardware.telephony'
+  uses-implied-feature-sdk-23: name='android.hardware.telephony' reason='requested a telephony permission'
+provides-component:'app-widget'
+provides-component:'device-admin'
+provides-component:'ime'
+provides-component:'wallpaper'
+provides-component:'accessibility'
+provides-component:'print-service'
+provides-component:'search'
+provides-component:'document-provider'
+provides-component:'notification-listener'
+provides-component:'dream'
+provides-component:'camera'
+provides-component:'camera-secure'
+main
+other-receivers
+other-services
+supports-screens: 'normal' 'large' 'xlarge'
+supports-any-density: 'true'
+requires-smallest-width:'240'
+compatible-width-limit:'360'
+largest-width-limit:'480'
+locales: '--_--'
+densities: '160' '240' '320' '480' '640' '65534'
+native-code: 'x86_64'
+alt-native-code: 'x86'
diff --git a/tools/aapt2/integration-tests/DumpTest/components_permissions_expected.txt b/tools/aapt2/integration-tests/DumpTest/components_permissions_expected.txt
new file mode 100644
index 0000000..f79de5c
--- /dev/null
+++ b/tools/aapt2/integration-tests/DumpTest/components_permissions_expected.txt
@@ -0,0 +1,5 @@
+package: com.example.bundletool.minimal
+permission: minimal.FIRST_PERMISSION
+uses-permission: name='android.permission.BIND_ACCESSIBILITY_SERVICE' maxSdkVersion='24'
+uses-permission-sdk-23: name='android.permission.RECEIVE_SMS'
+uses-permission: name='android.permission.WRITE_EXTERNAL_STORAGE'
diff --git a/tools/aapt2/integration-tests/DumpTest/minimal.apk b/tools/aapt2/integration-tests/DumpTest/minimal.apk
new file mode 100644
index 0000000..a8415fa
--- /dev/null
+++ b/tools/aapt2/integration-tests/DumpTest/minimal.apk
Binary files differ
diff --git a/tools/aapt2/integration-tests/DumpTest/minimal_expected.txt b/tools/aapt2/integration-tests/DumpTest/minimal_expected.txt
new file mode 100644
index 0000000..85ab5d8
--- /dev/null
+++ b/tools/aapt2/integration-tests/DumpTest/minimal_expected.txt
@@ -0,0 +1,92 @@
+package: name='com.lato.bubblegirl' versionCode='33' versionName='1.0.0' platformBuildVersionName='8.1.0' platformBuildVersionCode='27'
+sdkVersion:'19'
+targetSdkVersion:'26'
+application-label:'Bubble Girl'
+application-label-ar:'Bubble Girl'
+application-label-az:'Bubble Girl'
+application-label-be:'Bubble Girl'
+application-label-bg:'Bubble Girl'
+application-label-bn:'Bubble Girl'
+application-label-bs:'Bubble Girl'
+application-label-ca:'Bubble Girl'
+application-label-cs:'Bubble Girl'
+application-label-da:'Bubble Girl'
+application-label-de:'Bubble Girl'
+application-label-el:'Bubble Girl'
+application-label-es:'Bubble Girl'
+application-label-es-ES:'Bubble Girl'
+application-label-et:'Bubble Girl'
+application-label-eu:'Bubble Girl'
+application-label-fa:'Bubble Girl'
+application-label-fi:'Bubble Girl'
+application-label-fr:'Bubble Girl'
+application-label-fr-CA:'Bubble Girl'
+application-label-gl:'Bubble Girl'
+application-label-hi:'Bubble Girl'
+application-label-hr:'Bubble Girl'
+application-label-hu:'Bubble Girl'
+application-label-hy:'Bubble Girl'
+application-label-in:'Bubble Girl'
+application-label-is:'Bubble Girl'
+application-label-it:'Bubble Girl'
+application-label-iw:'Bubble Girl'
+application-label-ja:'Bubble Girl'
+application-label-jv:'Bubble Girl'
+application-label-ka:'Bubble Girl'
+application-label-kk:'Bubble Girl'
+application-label-kn:'Bubble Girl'
+application-label-ko:'Bubble Girl'
+application-label-lt:'Bubble Girl'
+application-label-lv:'Bubble Girl'
+application-label-mk:'Bubble Girl'
+application-label-ml:'Bubble Girl'
+application-label-mr:'Bubble Girl'
+application-label-ms:'Bubble Girl'
+application-label-nb:'Bubble Girl'
+application-label-nl:'Bubble Girl'
+application-label-pa:'Bubble Girl'
+application-label-pl:'Bubble Girl'
+application-label-pt-BR:'Bubble Girl'
+application-label-pt-PT:'Bubble Girl'
+application-label-ro:'Bubble Girl'
+application-label-ru:'Bubble Girl'
+application-label-sk:'Bubble Girl'
+application-label-sl:'Bubble Girl'
+application-label-sq:'Bubble Girl'
+application-label-sr:'Bubble Girl'
+application-label-su:'Bubble Girl'
+application-label-sv:'Bubble Girl'
+application-label-ta:'Bubble Girl'
+application-label-te:'Bubble Girl'
+application-label-th:'Bubble Girl'
+application-label-tl:'Bubble Girl'
+application-label-tr:'Bubble Girl'
+application-label-tt:'Bubble Girl'
+application-label-uk:'Bubble Girl'
+application-label-vi:'Bubble Girl'
+application-label-zh-CN:'Bubble Girl'
+application-label-zh-HK:'Bubble Girl'
+application-label-zh-TW:'Bubble Girl'
+application-icon-160:'res/theme/1f.png'
+application-icon-240:'res/theme/1f.png'
+application-icon-320:'res/theme/1f.png'
+application-icon-480:'res/theme/1f.png'
+application-icon-640:'res/theme/1f.png'
+application: label='Bubble Girl' icon='res/theme/1f.png'
+launchable-activity: name='com.sonymobile.runtimeskinning.livewallpaperlib.configactivity.LauncherActivity'  label='' icon=''
+uses-library:'com.sony.device'
+uses-permission: name='com.sonymobile.permission.RUNTIME_SKIN'
+feature-group: label=''
+  uses-gl-es: '0x30000'
+  uses-feature: name='android.software.live_wallpaper'
+  uses-feature: name='android.hardware.faketouch'
+  uses-implied-feature: name='android.hardware.faketouch' reason='default feature for all apps'
+  uses-feature: name='android.hardware.screen.portrait'
+  uses-implied-feature: name='android.hardware.screen.portrait' reason='one or more activities have specified a portrait orientation'
+provides-component:'wallpaper'
+main
+other-activities
+supports-screens: 'small' 'normal' 'large' 'xlarge'
+supports-any-density: 'true'
+locales: '--_--' 'ar' 'az' 'be' 'bg' 'bn' 'bs' 'ca' 'cs' 'da' 'de' 'el' 'es' 'es-ES' 'et' 'eu' 'fa' 'fi' 'fr' 'fr-CA' 'gl' 'hi' 'hr' 'hu' 'hy' 'in' 'is' 'it' 'iw' 'ja' 'jv' 'ka' 'kk' 'kn' 'ko' 'lt' 'lv' 'mk' 'ml' 'mr' 'ms' 'nb' 'nl' 'pa' 'pl' 'pt-BR' 'pt-PT' 'ro' 'ru' 'sk' 'sl' 'sq' 'sr' 'su' 'sv' 'ta' 'te' 'th' 'tl' 'tr' 'tt' 'uk' 'vi' 'zh-CN' 'zh-HK' 'zh-TW'
+densities: '160' '240' '320' '480' '640'