Remove raw values from proto APK
Raw attribute values are not included in xml files when building binary
APKs but they are when building proto APKs. Remove raw attribute values
and create a new convert flag that (--keep-raw-values) that allows raw
value to be kept.
Also added flag to link to keep raw attribute values.
Bug: 115915884
Bug: 116700688
Test: aapt2_tests
Change-Id: Id50136b775b3f43d159ca06181282f6a7b8eaf40
diff --git a/tools/aapt2/test/Fixture.cpp b/tools/aapt2/test/Fixture.cpp
new file mode 100644
index 0000000..aae79fa
--- /dev/null
+++ b/tools/aapt2/test/Fixture.cpp
@@ -0,0 +1,154 @@
+/*
+ * 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.
+ */
+
+#include "test/Fixture.h"
+
+#include <dirent.h>
+
+#include "android-base/errors.h"
+#include "android-base/file.h"
+#include "android-base/stringprintf.h"
+#include "android-base/utf8.h"
+#include "androidfw/StringPiece.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "cmd/Compile.h"
+#include "cmd/Link.h"
+#include "io/FileStream.h"
+#include "io/Util.h"
+#include "util/Files.h"
+
+using testing::Eq;
+using testing::Ne;
+
+namespace aapt {
+
+void ClearDirectory(const android::StringPiece& path) {
+ const std::string root_dir = path.to_string();
+ std::unique_ptr<DIR, decltype(closedir)*> dir(opendir(root_dir.data()), closedir);
+ if (!dir) {
+ StdErrDiagnostics().Error(DiagMessage() << android::base::SystemErrorCodeToString(errno));
+ return;
+ }
+
+ while (struct dirent* entry = readdir(dir.get())) {
+ // Do not delete hidden files and do not recurse to the parent of this directory
+ if (util::StartsWith(entry->d_name, ".")) {
+ continue;
+ }
+
+ std::string full_path = file::BuildPath({root_dir, entry->d_name});
+ if (file::GetFileType(full_path) == file::FileType::kDirectory) {
+ ClearDirectory(full_path);
+#ifdef _WIN32
+ _rmdir(full_path.c_str());
+#else
+ rmdir(full_path.c_str());
+#endif
+ } else {
+ android::base::utf8::unlink(full_path.c_str());
+ }
+ }
+}
+
+void TestDirectoryFixture::SetUp() {
+ temp_dir_ = file::BuildPath({android::base::GetExecutableDirectory(),
+ "_temp",
+ testing::UnitTest::GetInstance()->current_test_case()->name(),
+ testing::UnitTest::GetInstance()->current_test_info()->name()});
+ ASSERT_TRUE(file::mkdirs(temp_dir_));
+ ClearDirectory(temp_dir_);
+}
+
+void TestDirectoryFixture::TearDown() {
+ ClearDirectory(temp_dir_);
+}
+
+bool TestDirectoryFixture::WriteFile(const std::string& path, const std::string& contents) {
+ CHECK(util::StartsWith(path, temp_dir_))
+ << "Attempting to create a file outside of test temporary directory.";
+
+ // Create any intermediate directories specified in the path
+ auto pos = std::find(path.rbegin(), path.rend(), file::sDirSep);
+ if (pos != path.rend()) {
+ std::string dirs = path.substr(0, (&*pos - path.data()));
+ file::mkdirs(dirs);
+ }
+
+ return android::base::WriteStringToFile(contents, path);
+}
+
+bool CommandTestFixture::CompileFile(const std::string& path, const std::string& contents,
+ const android::StringPiece& out_dir, IDiagnostics* diag) {
+ CHECK(WriteFile(path, contents));
+ CHECK(file::mkdirs(out_dir.data()));
+ return CompileCommand(diag).Execute({path, "-o", out_dir, "-v"}, &std::cerr) == 0;
+}
+
+bool CommandTestFixture::Link(const std::vector<std::string>& args,
+ const android::StringPiece& flat_dir, IDiagnostics* diag) {
+ std::vector<android::StringPiece> link_args;
+ for(const std::string& arg : args) {
+ link_args.emplace_back(arg);
+ }
+
+ // Link against the android SDK
+ std::string android_sdk = file::BuildPath({android::base::GetExecutableDirectory(),
+ "integration-tests", "CommandTests",
+ "android-28.jar"});
+ link_args.insert(link_args.end(), {"-I", android_sdk});
+
+ // Add the files from the compiled resources directory to the link file arguments
+ Maybe<std::vector<std::string>> compiled_files = file::FindFiles(flat_dir, diag);
+ if (compiled_files) {
+ for (std::string& compile_file : compiled_files.value()) {
+ compile_file = file::BuildPath({flat_dir, compile_file});
+ link_args.emplace_back(std::move(compile_file));
+ }
+ }
+
+ return LinkCommand(diag).Execute(link_args, &std::cerr) == 0;
+}
+
+std::string CommandTestFixture::GetDefaultManifest() {
+ const std::string manifest_file = GetTestPath("AndroidManifest.xml");
+ CHECK(WriteFile(manifest_file, R"(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.aapt.command.test">
+ </manifest>)"));
+ return manifest_file;
+}
+
+void CommandTestFixture::AssertLoadXml(LoadedApk *apk, const android::StringPiece &xml_path,
+ android::ResXMLTree *out_tree) {
+ ASSERT_THAT(apk, Ne(nullptr));
+
+ io::IFile* file = apk->GetFileCollection()->FindFile(xml_path);
+ ASSERT_THAT(file, Ne(nullptr));
+
+ std::unique_ptr<io::IData> data = file->OpenAsData();
+ ASSERT_THAT(data, Ne(nullptr));
+
+ out_tree->setTo(data->data(), data->size());
+ ASSERT_THAT(out_tree->getError(), Eq(android::OK));
+ while (out_tree->next() != android::ResXMLTree::START_TAG) {
+ ASSERT_THAT(out_tree->getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
+ ASSERT_THAT(out_tree->getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
+ }
+}
+
+} // namespace aapt
\ No newline at end of file
diff --git a/tools/aapt2/test/Fixture.h b/tools/aapt2/test/Fixture.h
new file mode 100644
index 0000000..89d3b7b
--- /dev/null
+++ b/tools/aapt2/test/Fixture.h
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+#ifndef AAPT_TEST_FIXTURE_H
+#define AAPT_TEST_FIXTURE_H
+
+#include "android-base/file.h"
+#include "android-base/macros.h"
+#include "androidfw/StringPiece.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+#include "io/Util.h"
+#include "util/Files.h"
+#include "LoadedApk.h"
+
+namespace aapt {
+
+class TestDirectoryFixture : public ::testing::Test {
+ public:
+ TestDirectoryFixture() = default;
+ virtual ~TestDirectoryFixture() = default;
+
+ // Creates the test directory or clears its contents if it contains previously created files.
+ void SetUp() override;
+
+ // Clears the contents of the test directory.
+ void TearDown() override;
+
+ // Retrieve the test directory of the fixture.
+ const android::StringPiece GetTestDirectory() {
+ return temp_dir_;
+ }
+
+ // Retrieves the absolute path of the specified relative path in the test directory. Directories
+ // should be separated using forward slashes ('/'), and these slashes will be translated to
+ // backslashes when running Windows tests.
+ const std::string GetTestPath(const android::StringPiece& path) {
+ std::string base = temp_dir_;
+ for (android::StringPiece part : util::Split(path, '/')) {
+ file::AppendPath(&base, part);
+ }
+ return base;
+ }
+
+ // Creates a file with the specified contents, creates any intermediate directories in the
+ // process. The file path must be an absolute path within the test directory.
+ bool WriteFile(const std::string& path, const std::string& contents);
+
+ private:
+ std::string temp_dir_;
+ DISALLOW_COPY_AND_ASSIGN(TestDirectoryFixture);
+};
+
+class CommandTestFixture : public TestDirectoryFixture {
+ public:
+ CommandTestFixture() = default;
+ virtual ~CommandTestFixture() = default;
+
+ // Wries the contents of the file to the specified path. The file is compiled and the flattened
+ // file is written to the out directory.
+ bool CompileFile(const std::string& path, const std::string& contents,
+ const android::StringPiece& flat_out_dir, IDiagnostics* diag);
+
+ // Executes the link command with the specified arguments. The flattened files residing in the
+ // flat directory will be added to the link command as file arguments.
+ bool Link(const std::vector<std::string>& args, const android::StringPiece& flat_dir,
+ IDiagnostics* diag);
+
+ // Creates a minimal android manifest within the test directory and returns the file path.
+ std::string GetDefaultManifest();
+
+ // Asserts that loading the tree from the specified file in the apk succeeds.
+ void AssertLoadXml(LoadedApk* apk, const android::StringPiece& xml_path,
+ android::ResXMLTree* out_tree);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CommandTestFixture);
+};
+
+} // namespace aapt
+
+#endif // AAPT_TEST_FIXTURE_H
\ No newline at end of file
diff --git a/tools/aapt2/test/Test.h b/tools/aapt2/test/Test.h
index a24c01c..7d96d1f 100644
--- a/tools/aapt2/test/Test.h
+++ b/tools/aapt2/test/Test.h
@@ -23,5 +23,6 @@
#include "test/Builders.h"
#include "test/Common.h"
#include "test/Context.h"
+#include "test/Fixture.h"
#endif // AAPT_TEST_TEST_H