1 /* 2 * Copyright (C) 2019 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 "link/ResourceExcluder.h" 18 19 #include "ResourceTable.h" 20 #include "test/Test.h" 21 22 using ::aapt::test::HasValue; 23 using ::android::ConfigDescription; 24 using ::testing::Not; 25 26 namespace { 27 28 ConfigDescription BuildArg(const std::string arg) { 29 ConfigDescription config_description; 30 ConfigDescription::Parse(arg, &config_description); 31 return config_description; 32 } 33 34 std::vector<ConfigDescription> BuildArgList(const std::string arg) { 35 ConfigDescription config_description; 36 ConfigDescription::Parse(arg, &config_description); 37 return { config_description }; 38 } 39 40 } // namespace 41 42 namespace aapt { 43 44 TEST(ResourceExcluderTest, NonMatchConfigNotExcluded) { 45 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); 46 ConfigDescription default_config; 47 auto fr_config = test::ParseConfigOrDie("fr"); 48 49 std::unique_ptr<ResourceTable> table = 50 test::ResourceTableBuilder() 51 .AddString("android:string/test", ResourceId{}, default_config, "default") 52 .AddString("android:string/test", ResourceId{}, fr_config, "fr") 53 .Build(); 54 55 auto args = BuildArgList("en"); 56 57 ASSERT_TRUE(ResourceExcluder(args).Consume(context.get(), table.get())); 58 EXPECT_THAT(table, HasValue("android:string/test", default_config)); 59 EXPECT_THAT(table, HasValue("android:string/test", fr_config)); 60 } 61 62 TEST(ResourceExcluderTest, ExactConfigExcluded) { 63 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); 64 ConfigDescription default_config; 65 auto fr_config = test::ParseConfigOrDie("fr"); 66 67 std::unique_ptr<ResourceTable> table = 68 test::ResourceTableBuilder() 69 .AddString("android:string/test", ResourceId{}, default_config, "default") 70 .AddString("android:string/test", ResourceId{}, fr_config, "fr") 71 .Build(); 72 73 auto args = BuildArgList("fr"); 74 75 ASSERT_TRUE(ResourceExcluder(args).Consume(context.get(), table.get())); 76 EXPECT_THAT(table, HasValue("android:string/test", default_config)); 77 EXPECT_THAT(table, Not(HasValue("android:string/test", fr_config))); 78 } 79 80 TEST(ResourceExcluderTest, MoreSpecificConfigExcluded) { 81 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); 82 ConfigDescription default_config; 83 auto fr_land_config = test::ParseConfigOrDie("fr-land"); 84 85 std::unique_ptr<ResourceTable> table = 86 test::ResourceTableBuilder() 87 .AddString("android:string/test", ResourceId{}, default_config, "default") 88 .AddString("android:string/test", ResourceId{}, fr_land_config, "fr-land") 89 .Build(); 90 91 auto args = BuildArgList("fr"); 92 93 ASSERT_TRUE(ResourceExcluder(args).Consume(context.get(), table.get())); 94 EXPECT_THAT(table, HasValue("android:string/test", default_config)); 95 EXPECT_THAT(table, Not(HasValue("android:string/test", fr_land_config))); 96 } 97 98 TEST(ResourceExcluderTest, MultipleMoreSpecificConfigExcluded) { 99 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); 100 ConfigDescription default_config; 101 auto night_config = test::ParseConfigOrDie("night"); 102 auto fr_config = test::ParseConfigOrDie("fr"); 103 auto fr_land_config = test::ParseConfigOrDie("fr-land"); 104 auto fr_night_config = test::ParseConfigOrDie("fr-night"); 105 106 std::unique_ptr<ResourceTable> table = 107 test::ResourceTableBuilder() 108 .AddString("android:string/test", ResourceId{}, default_config, "default") 109 .AddString("android:string/test", ResourceId{}, night_config, "night") 110 .AddString("android:string/test", ResourceId{}, fr_config, "fr") 111 .AddString("android:string/test", ResourceId{}, fr_land_config, "fr-land") 112 .AddString("android:string/test", ResourceId{}, fr_night_config, "fr-night") 113 .Build(); 114 115 auto args = BuildArgList("fr"); 116 117 ASSERT_TRUE(ResourceExcluder(args).Consume(context.get(), table.get())); 118 EXPECT_THAT(table, HasValue("android:string/test", default_config)); 119 EXPECT_THAT(table, HasValue("android:string/test", night_config)); 120 EXPECT_THAT(table, Not(HasValue("android:string/test", fr_config))); 121 EXPECT_THAT(table, Not(HasValue("android:string/test", fr_land_config))); 122 EXPECT_THAT(table, Not(HasValue("android:string/test", fr_night_config))); 123 } 124 125 TEST(ResourceExcluderTest, MultipleConfigsExcluded) { 126 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); 127 ConfigDescription default_config; 128 auto night_config = test::ParseConfigOrDie("night"); 129 auto fr_config = test::ParseConfigOrDie("fr"); 130 auto fr_land_config = test::ParseConfigOrDie("fr-land"); 131 auto fr_night_config = test::ParseConfigOrDie("fr-night"); 132 133 std::unique_ptr<ResourceTable> table = 134 test::ResourceTableBuilder() 135 .AddString("android:string/test", ResourceId{}, default_config, "default") 136 .AddString("android:string/test", ResourceId{}, night_config, "night") 137 .AddString("android:string/test", ResourceId{}, fr_config, "fr") 138 .AddString("android:string/test", ResourceId{}, fr_land_config, "fr-land") 139 .AddString("android:string/test", ResourceId{}, fr_night_config, "fr-night") 140 .Build(); 141 142 std::vector<ConfigDescription> args; 143 args.push_back(BuildArg("land")); 144 args.push_back(BuildArg("night")); 145 146 ASSERT_TRUE(ResourceExcluder(args).Consume(context.get(), table.get())); 147 EXPECT_THAT(table, HasValue("android:string/test", default_config)); 148 EXPECT_THAT(table, Not(HasValue("android:string/test", night_config))); 149 EXPECT_THAT(table, HasValue("android:string/test", fr_config)); 150 EXPECT_THAT(table, Not(HasValue("android:string/test", fr_land_config))); 151 EXPECT_THAT(table, Not(HasValue("android:string/test", fr_night_config))); 152 } 153 154 TEST(ResourceExcluderTest, LessSpecificConfigNotExcluded) { 155 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); 156 ConfigDescription default_config; 157 auto fr_config = test::ParseConfigOrDie("fr"); 158 auto fr_land_config = test::ParseConfigOrDie("fr-land"); 159 160 std::unique_ptr<ResourceTable> table = 161 test::ResourceTableBuilder() 162 .AddString("android:string/test", ResourceId{}, default_config, "default") 163 .AddString("android:string/test", ResourceId{}, fr_config, "fr") 164 .AddString("android:string/test", ResourceId{}, fr_land_config, "fr-land") 165 .Build(); 166 167 auto args = BuildArgList("fr-land"); 168 169 ASSERT_TRUE(ResourceExcluder(args).Consume(context.get(), table.get())); 170 EXPECT_THAT(table, HasValue("android:string/test", default_config)); 171 EXPECT_THAT(table, HasValue("android:string/test", fr_config)); 172 EXPECT_THAT(table, Not(HasValue("android:string/test", fr_land_config))); 173 } 174 175 TEST(ResourceExcluderTest, LowerPrecedenceStillExcludes) { 176 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); 177 ConfigDescription default_config; 178 auto fr_config = test::ParseConfigOrDie("fr"); 179 auto fr_night_config = test::ParseConfigOrDie("fr-night"); 180 181 std::unique_ptr<ResourceTable> table = 182 test::ResourceTableBuilder() 183 .AddString("android:string/test", ResourceId{}, default_config, "default") 184 .AddString("android:string/test", ResourceId{}, fr_config, "fr") 185 .AddString("android:string/test", ResourceId{}, fr_night_config, "fr-night") 186 .Build(); 187 188 // "night" is lower precedence than "fr" 189 auto args = BuildArgList("night"); 190 191 ASSERT_TRUE(ResourceExcluder(args).Consume(context.get(), table.get())); 192 EXPECT_THAT(table, HasValue("android:string/test", default_config)); 193 EXPECT_THAT(table, HasValue("android:string/test", fr_config)); 194 EXPECT_THAT(table, Not(HasValue("android:string/test", fr_night_config))); 195 } 196 197 TEST(ResourceExcluderTest, OnlyExcludesSpecificTier) { 198 std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); 199 ConfigDescription default_config; 200 auto mdpi_config = test::ParseConfigOrDie("mdpi"); 201 auto hdpi_config = test::ParseConfigOrDie("hdpi"); 202 auto xhdpi_config = test::ParseConfigOrDie("xhdpi"); 203 204 std::unique_ptr<ResourceTable> table = 205 test::ResourceTableBuilder() 206 .AddString("android:string/test", ResourceId{}, default_config, "default") 207 .AddString("android:string/test", ResourceId{}, mdpi_config, "mdpi") 208 .AddString("android:string/test", ResourceId{}, hdpi_config, "hdpi") 209 .AddString("android:string/test", ResourceId{}, xhdpi_config, "xhdpi") 210 .Build(); 211 212 auto args = BuildArgList("hdpi"); 213 214 ASSERT_TRUE(ResourceExcluder(args).Consume(context.get(), table.get())); 215 EXPECT_THAT(table, HasValue("android:string/test", default_config)); 216 EXPECT_THAT(table, HasValue("android:string/test", mdpi_config)); 217 EXPECT_THAT(table, Not(HasValue("android:string/test", hdpi_config))); 218 EXPECT_THAT(table, HasValue("android:string/test", xhdpi_config)); 219 } 220 221 } // namespace aapt 222