MultiApkGenerator_test.cpp revision 8780eb6e4918ae24fb1ae74d631042c32e41dc3d
1/*
2 * Copyright (C) 2017 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 "optimize/MultiApkGenerator.h"
18
19#include <string>
20
21#include "gmock/gmock.h"
22#include "gtest/gtest.h"
23
24#include "LoadedApk.h"
25#include "ResourceTable.h"
26#include "configuration/ConfigurationParser.h"
27#include "filter/Filter.h"
28#include "format/Archive.h"
29#include "format/binary/TableFlattener.h"
30#include "process/IResourceTableConsumer.h"
31#include "test/Context.h"
32#include "test/Test.h"
33
34namespace aapt {
35namespace {
36
37using ::aapt::configuration::Abi;
38using ::aapt::configuration::AndroidSdk;
39using ::aapt::configuration::Artifact;
40using ::aapt::configuration::PostProcessingConfiguration;
41using ::aapt::test::GetValue;
42using ::aapt::test::GetValueForConfig;
43using ::aapt::test::ParseConfigOrDie;
44using ::testing::Eq;
45using ::testing::IsNull;
46using ::testing::Not;
47using ::testing::NotNull;
48using ::testing::PrintToString;
49using ::testing::Return;
50using ::testing::Test;
51using ::testing::_;
52
53/**
54 * Subclass the MultiApkGenerator class so that we can access the protected FilterTable method to
55 * directly test table filter.
56 */
57class MultiApkGeneratorWrapper : public MultiApkGenerator {
58 public:
59  MultiApkGeneratorWrapper(LoadedApk* apk, IAaptContext* context)
60      : MultiApkGenerator(apk, context) {
61  }
62
63  std::unique_ptr<ResourceTable> FilterTable(
64      const configuration::Artifact& artifact,
65      const configuration::PostProcessingConfiguration& config, const ResourceTable& old_table,
66      FilterChain* pChain) override {
67    return MultiApkGenerator::FilterTable(artifact, config, old_table, pChain);
68  }
69};
70
71/** MultiApkGenerator test fixture. */
72class MultiApkGeneratorTest : public ::testing::Test {
73 public:
74  std::unique_ptr<ResourceTable> BuildTable() {
75    return test::ResourceTableBuilder()
76        .AddFileReference(kResourceName, "res/drawable-mdpi/icon.png", mdpi_)
77        .AddFileReference(kResourceName, "res/drawable-hdpi/icon.png", hdpi_)
78        .AddFileReference(kResourceName, "res/drawable-xhdpi/icon.png", xhdpi_)
79        .AddFileReference(kResourceName, "res/drawable-xxhdpi/icon.png", xxhdpi_)
80        .AddFileReference(kResourceName, "res/drawable-v19/icon.xml", v19_)
81        .AddFileReference(kResourceName, "res/drawable-v21/icon.xml", v21_)
82        .AddSimple("android:string/one")
83        .Build();
84  }
85
86  inline FileReference* ValueForConfig(ResourceTable* table, const ConfigDescription& config) {
87    return GetValueForConfig<FileReference>(table, kResourceName, config);
88  };
89
90  void SetUp() override {
91  }
92
93 protected:
94  static constexpr const char* kResourceName = "android:drawable/icon";
95
96  ConfigDescription default_ = ParseConfigOrDie("").CopyWithoutSdkVersion();
97  ConfigDescription mdpi_ = ParseConfigOrDie("mdpi").CopyWithoutSdkVersion();
98  ConfigDescription hdpi_ = ParseConfigOrDie("hdpi").CopyWithoutSdkVersion();
99  ConfigDescription xhdpi_ = ParseConfigOrDie("xhdpi").CopyWithoutSdkVersion();
100  ConfigDescription xxhdpi_ = ParseConfigOrDie("xxhdpi").CopyWithoutSdkVersion();
101  ConfigDescription xxxhdpi_ = ParseConfigOrDie("xxxhdpi").CopyWithoutSdkVersion();
102  ConfigDescription v19_ = ParseConfigOrDie("v19");
103  ConfigDescription v21_ = ParseConfigOrDie("v21");
104};
105
106TEST_F(MultiApkGeneratorTest, VersionFilterNewerVersion) {
107  std::unique_ptr<ResourceTable> table = BuildTable();
108
109  LoadedApk apk = {{"test.apk"}, {}, std::move(table), {}};
110  std::unique_ptr<IAaptContext> ctx = test::ContextBuilder().SetMinSdkVersion(19).Build();
111  PostProcessingConfiguration empty_config;
112  TableFlattenerOptions table_flattener_options;
113  FilterChain chain;
114
115  Artifact x64 = test::ArtifactBuilder()
116                     .SetName("${basename}.${sdk}.apk")
117                     .SetDensityGroup("xhdpi")
118                     .SetAndroidSdk("v23")
119                     .Build();
120
121  auto config = test::PostProcessingConfigurationBuilder()
122                    .SetLocaleGroup("en", {"en"})
123                    .SetAbiGroup("x64", {Abi::kX86_64})
124                    .SetDensityGroup("xhdpi", {"xhdpi"})
125                    .SetAndroidSdk("v23", AndroidSdk::ForMinSdk(23))
126                    .AddArtifact(x64)
127                    .Build();
128
129  MultiApkGeneratorWrapper generator{&apk, ctx.get()};
130  std::unique_ptr<ResourceTable> split =
131      generator.FilterTable(x64, config, *apk.GetResourceTable(), &chain);
132
133  ResourceTable* new_table = split.get();
134  EXPECT_THAT(ValueForConfig(new_table, mdpi_), IsNull());
135  EXPECT_THAT(ValueForConfig(new_table, hdpi_), IsNull());
136  EXPECT_THAT(ValueForConfig(new_table, xxhdpi_), IsNull());
137  EXPECT_THAT(ValueForConfig(new_table, xxxhdpi_), IsNull());
138  EXPECT_THAT(ValueForConfig(new_table, v19_), IsNull());
139
140  // xhdpi directly matches one of the required dimensions.
141  EXPECT_THAT(ValueForConfig(new_table, xhdpi_), NotNull());
142  // drawable-v21 was converted to drawable.
143  EXPECT_THAT(ValueForConfig(new_table, default_), NotNull());
144  EXPECT_THAT(GetValue<Id>(new_table, "android:string/one"), NotNull());
145}
146
147TEST_F(MultiApkGeneratorTest, VersionFilterOlderVersion) {
148  std::unique_ptr<ResourceTable> table = BuildTable();
149
150  LoadedApk apk = {{"test.apk"}, {}, std::move(table), {}};
151  std::unique_ptr<IAaptContext> ctx = test::ContextBuilder().SetMinSdkVersion(1).Build();
152  PostProcessingConfiguration empty_config;
153  TableFlattenerOptions table_flattener_options;
154  FilterChain chain;
155
156  Artifact x64 = test::ArtifactBuilder()
157                     .SetName("${basename}.${sdk}.apk")
158                     .SetDensityGroup("xhdpi")
159                     .SetAndroidSdk("v4")
160                     .Build();
161
162  auto config = test::PostProcessingConfigurationBuilder()
163                    .SetLocaleGroup("en", {"en"})
164                    .SetAbiGroup("x64", {Abi::kX86_64})
165                    .SetDensityGroup("xhdpi", {"xhdpi"})
166                    .SetAndroidSdk("v4", AndroidSdk::ForMinSdk(4))
167                    .AddArtifact(x64)
168                    .Build();
169
170  MultiApkGeneratorWrapper generator{&apk, ctx.get()};;
171  std::unique_ptr<ResourceTable> split =
172      generator.FilterTable(x64, config, *apk.GetResourceTable(), &chain);
173
174  ResourceTable* new_table = split.get();
175  EXPECT_THAT(ValueForConfig(new_table, mdpi_), IsNull());
176  EXPECT_THAT(ValueForConfig(new_table, hdpi_), IsNull());
177  EXPECT_THAT(ValueForConfig(new_table, xxhdpi_), IsNull());
178  EXPECT_THAT(ValueForConfig(new_table, xxxhdpi_), IsNull());
179
180  EXPECT_THAT(ValueForConfig(new_table, xhdpi_), NotNull());
181  EXPECT_THAT(ValueForConfig(new_table, v19_), NotNull());
182  EXPECT_THAT(ValueForConfig(new_table, v21_), NotNull());
183  EXPECT_THAT(GetValue<Id>(new_table, "android:string/one"), NotNull());
184}
185
186TEST_F(MultiApkGeneratorTest, VersionFilterNoVersion) {
187  std::unique_ptr<ResourceTable> table = BuildTable();
188
189  LoadedApk apk = {{"test.apk"}, {}, std::move(table), {}};
190  std::unique_ptr<IAaptContext> ctx = test::ContextBuilder().SetMinSdkVersion(1).Build();
191  PostProcessingConfiguration empty_config;
192  TableFlattenerOptions table_flattener_options;
193  FilterChain chain;
194
195  Artifact x64 =
196      test::ArtifactBuilder().SetName("${basename}.${sdk}.apk").SetDensityGroup("xhdpi").Build();
197
198  auto config = test::PostProcessingConfigurationBuilder()
199                    .SetLocaleGroup("en", {"en"})
200                    .SetAbiGroup("x64", {Abi::kX86_64})
201                    .SetDensityGroup("xhdpi", {"xhdpi"})
202                    .AddArtifact(x64)
203                    .Build();
204
205  MultiApkGeneratorWrapper generator{&apk, ctx.get()};
206  std::unique_ptr<ResourceTable> split =
207      generator.FilterTable(x64, config, *apk.GetResourceTable(), &chain);
208
209  ResourceTable* new_table = split.get();
210  EXPECT_THAT(ValueForConfig(new_table, mdpi_), IsNull());
211  EXPECT_THAT(ValueForConfig(new_table, hdpi_), IsNull());
212  EXPECT_THAT(ValueForConfig(new_table, xxhdpi_), IsNull());
213  EXPECT_THAT(ValueForConfig(new_table, xxxhdpi_), IsNull());
214
215  EXPECT_THAT(ValueForConfig(new_table, xhdpi_), NotNull());
216  EXPECT_THAT(ValueForConfig(new_table, v19_), NotNull());
217  EXPECT_THAT(ValueForConfig(new_table, v21_), NotNull());
218  EXPECT_THAT(GetValue<Id>(new_table, "android:string/one"), NotNull());
219}
220
221}  // namespace
222}  // namespace aapt
223