1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "Convert.h"
18
19 #include "LoadedApk.h"
20 #include "test/Test.h"
21 #include "ziparchive/zip_archive.h"
22
23 using testing::Eq;
24 using testing::Ne;
25
26 namespace aapt {
27
28 using ConvertTest = CommandTestFixture;
29
TEST_F(ConvertTest,RemoveRawXmlStrings)30 TEST_F(ConvertTest, RemoveRawXmlStrings) {
31 StdErrDiagnostics diag;
32 const std::string compiled_files_dir = GetTestPath("compiled");
33 ASSERT_TRUE(CompileFile(GetTestPath("res/xml/test.xml"), R"(<Item AgentCode="007"/>)",
34 compiled_files_dir, &diag));
35
36 const std::string out_apk = GetTestPath("out.apk");
37 std::vector<std::string> link_args = {
38 "--manifest", GetDefaultManifest(),
39 "-o", out_apk,
40 "--keep-raw-values",
41 "--proto-format"
42 };
43
44 ASSERT_TRUE(Link(link_args, compiled_files_dir, &diag));
45
46 const std::string out_convert_apk = GetTestPath("out_convert.apk");
47 std::vector<android::StringPiece> convert_args = {
48 "-o", out_convert_apk,
49 "--output-format", "binary",
50 out_apk,
51 };
52 ASSERT_THAT(ConvertCommand().Execute(convert_args, &std::cerr), Eq(0));
53
54 // Load the binary xml tree
55 android::ResXMLTree tree;
56 std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(out_convert_apk, &diag);
57
58 std::unique_ptr<io::IData> data = OpenFileAsData(apk.get(), "res/xml/test.xml");
59 ASSERT_THAT(data, Ne(nullptr));
60
61 AssertLoadXml(apk.get(), data.get(), &tree);
62
63 // Check that the raw string index has not been assigned
64 EXPECT_THAT(tree.getAttributeValueStringID(0), Eq(-1));
65 }
66
TEST_F(ConvertTest,KeepRawXmlStrings)67 TEST_F(ConvertTest, KeepRawXmlStrings) {
68 StdErrDiagnostics diag;
69 const std::string compiled_files_dir = GetTestPath("compiled");
70 ASSERT_TRUE(CompileFile(GetTestPath("res/xml/test.xml"), R"(<Item AgentCode="007"/>)",
71 compiled_files_dir, &diag));
72
73 const std::string out_apk = GetTestPath("out.apk");
74 std::vector<std::string> link_args = {
75 "--manifest", GetDefaultManifest(),
76 "-o", out_apk,
77 "--keep-raw-values",
78 "--proto-format"
79 };
80
81 ASSERT_TRUE(Link(link_args, compiled_files_dir, &diag));
82
83 const std::string out_convert_apk = GetTestPath("out_convert.apk");
84 std::vector<android::StringPiece> convert_args = {
85 "-o", out_convert_apk,
86 "--output-format", "binary",
87 "--keep-raw-values",
88 out_apk,
89 };
90 ASSERT_THAT(ConvertCommand().Execute(convert_args, &std::cerr), Eq(0));
91
92 // Load the binary xml tree
93 android::ResXMLTree tree;
94 std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(out_convert_apk, &diag);
95
96 std::unique_ptr<io::IData> data = OpenFileAsData(apk.get(), "res/xml/test.xml");
97 ASSERT_THAT(data, Ne(nullptr));
98
99 AssertLoadXml(apk.get(), data.get(), &tree);
100
101 // Check that the raw string index has been set to the correct string pool entry
102 int32_t raw_index = tree.getAttributeValueStringID(0);
103 ASSERT_THAT(raw_index, Ne(-1));
104 EXPECT_THAT(util::GetString(tree.getStrings(), static_cast<size_t>(raw_index)), Eq("007"));
105 }
106
TEST_F(ConvertTest,DuplicateEntriesWrittenOnce)107 TEST_F(ConvertTest, DuplicateEntriesWrittenOnce) {
108 StdErrDiagnostics diag;
109 const std::string apk_path =
110 file::BuildPath({android::base::GetExecutableDirectory(),
111 "integration-tests", "ConvertTest", "duplicate_entries.apk"});
112
113 const std::string out_convert_apk = GetTestPath("out_convert.apk");
114 std::vector<android::StringPiece> convert_args = {
115 "-o", out_convert_apk,
116 "--output-format", "proto",
117 apk_path
118 };
119 ASSERT_THAT(ConvertCommand().Execute(convert_args, &std::cerr), Eq(0));
120
121 ZipArchiveHandle handle;
122 ASSERT_THAT(OpenArchive(out_convert_apk.c_str(), &handle), Eq(0));
123
124 void* cookie = nullptr;
125
126 int32_t result = StartIteration(handle, &cookie, "res/theme/10", "");
127
128 // If this is -5, that means we've found a duplicate entry and this test has failed
129 EXPECT_THAT(result, Eq(0));
130
131 // But if read succeeds, verify only one res/theme/10 entry
132 int count = 0;
133
134 // Can't pass nullptrs into Next()
135 std::string zip_name;
136 ZipEntry zip_data;
137
138 while ((result = Next(cookie, &zip_data, &zip_name)) == 0) {
139 count++;
140 }
141
142 EndIteration(cookie);
143
144 EXPECT_THAT(count, Eq(1));
145 }
146
147 } // namespace aapt
148