You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
415 lines
17 KiB
415 lines
17 KiB
/*
|
|
* Copyright (C) 2017 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 "Util.h"
|
|
|
|
#include "android-base/stringprintf.h"
|
|
|
|
#include "AppInfo.h"
|
|
#include "split/TableSplitter.h"
|
|
#include "test/Builders.h"
|
|
#include "test/Test.h"
|
|
#include "util/Files.h"
|
|
|
|
using ::android::ConfigDescription;
|
|
|
|
namespace aapt {
|
|
|
|
#ifdef _WIN32
|
|
#define CREATE_PATH(path) android::base::StringPrintf(";%s", path)
|
|
#else
|
|
#define CREATE_PATH(path) android::base::StringPrintf(":%s", path)
|
|
#endif
|
|
|
|
#define EXPECT_CONFIG_EQ(constraints, config) \
|
|
EXPECT_EQ(constraints.configs.size(), 1); \
|
|
EXPECT_EQ(*constraints.configs.begin(), config); \
|
|
constraints.configs.clear();
|
|
|
|
TEST(UtilTest, SplitNamesAreSanitized) {
|
|
AppInfo app_info{"com.pkg"};
|
|
SplitConstraints split_constraints{
|
|
{test::ParseConfigOrDie("en-rUS-land"), test::ParseConfigOrDie("b+sr+Latn")}};
|
|
|
|
const auto doc = GenerateSplitManifest(app_info, split_constraints);
|
|
const auto &root = doc->root;
|
|
EXPECT_EQ(root->name, "manifest");
|
|
// split names cannot contain hyphens or plus signs.
|
|
EXPECT_EQ(root->FindAttribute("", "split")->value, "config.b_sr_Latn_en_rUS_land");
|
|
// but we should use resource qualifiers verbatim in 'targetConfig'.
|
|
EXPECT_EQ(root->FindAttribute("", "targetConfig")->value, "b+sr+Latn,en-rUS-land");
|
|
}
|
|
|
|
TEST (UtilTest, LongVersionCodeDefined) {
|
|
auto doc = test::BuildXmlDom(R"(
|
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
package="com.android.aapt.test" android:versionCode="0x1" android:versionCodeMajor="0x1">
|
|
</manifest>)");
|
|
SetLongVersionCode(doc->root.get(), 42);
|
|
|
|
auto version_code = doc->root->FindAttribute(xml::kSchemaAndroid, "versionCode");
|
|
ASSERT_NE(version_code, nullptr);
|
|
EXPECT_EQ(version_code->value, "0x0000002a");
|
|
|
|
ASSERT_NE(version_code->compiled_value, nullptr);
|
|
auto compiled_version_code = ValueCast<BinaryPrimitive>(version_code->compiled_value.get());
|
|
ASSERT_NE(compiled_version_code, nullptr);
|
|
EXPECT_EQ(compiled_version_code->value.data, 42U);
|
|
|
|
auto version_code_major = doc->root->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
|
|
EXPECT_EQ(version_code_major, nullptr);
|
|
}
|
|
|
|
TEST (UtilTest, LongVersionCodeUndefined) {
|
|
auto doc = test::BuildXmlDom(R"(
|
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
package="com.android.aapt.test">
|
|
</manifest>)");
|
|
SetLongVersionCode(doc->root.get(), 420000000000);
|
|
|
|
auto version_code = doc->root->FindAttribute(xml::kSchemaAndroid, "versionCode");
|
|
ASSERT_NE(version_code, nullptr);
|
|
EXPECT_EQ(version_code->value, "0xc9f36800");
|
|
|
|
ASSERT_NE(version_code->compiled_value, nullptr);
|
|
auto compiled_version_code = ValueCast<BinaryPrimitive>(version_code->compiled_value.get());
|
|
ASSERT_NE(compiled_version_code, nullptr);
|
|
EXPECT_EQ(compiled_version_code->value.data, 0xc9f36800);
|
|
|
|
auto version_code_major = doc->root->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor");
|
|
ASSERT_NE(version_code_major, nullptr);
|
|
EXPECT_EQ(version_code_major->value, "0x00000061");
|
|
|
|
ASSERT_NE(version_code_major->compiled_value, nullptr);
|
|
auto compiled_version_code_major = ValueCast<BinaryPrimitive>(
|
|
version_code_major->compiled_value.get());
|
|
ASSERT_NE(compiled_version_code_major, nullptr);
|
|
EXPECT_EQ(compiled_version_code_major->value.data, 0x61);
|
|
}
|
|
|
|
|
|
TEST (UtilTest, ParseSplitParameters) {
|
|
IDiagnostics* diagnostics = test::ContextBuilder().Build().get()->GetDiagnostics();
|
|
std::string path;
|
|
SplitConstraints constraints;
|
|
ConfigDescription expected_configuration;
|
|
|
|
// ========== Test IMSI ==========
|
|
// mcc: 'mcc[0-9]{3}'
|
|
// mnc: 'mnc[0-9]{1,3}'
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("mcc310"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setMcc(0x0136)
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("mcc310-mnc004"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setMcc(0x0136)
|
|
.setMnc(0x0004)
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("mcc310-mnc000"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setMcc(0x0136)
|
|
.setMnc(0xFFFF)
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
// ========== Test LOCALE ==========
|
|
// locale: '[a-z]{2,3}(-r[a-z]{2})?'
|
|
// locale: 'b+[a-z]{2,3}(+[a-z[0-9]]{2})?'
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("es"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setLanguage(0x6573)
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("fr-rCA"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setLanguage(0x6672)
|
|
.setCountry(0x4341)
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("b+es+419"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setLanguage(0x6573)
|
|
.setCountry(0xA424)
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
// ========== Test SCREEN_TYPE ==========
|
|
// orientation: '(port|land|square)'
|
|
// touchscreen: '(notouch|stylus|finger)'
|
|
// density" '(anydpi|nodpi|ldpi|mdpi|tvdpi|hdpi|xhdpi|xxhdpi|xxxhdpi|[0-9]*dpi)'
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("square"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setOrientation(0x03)
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("stylus"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setTouchscreen(0x02)
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("xxxhdpi"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setDensity(0x0280)
|
|
.setSdkVersion(0x0004) // version [any density requires donut]
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("land-xhdpi-finger"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setOrientation(0x02)
|
|
.setTouchscreen(0x03)
|
|
.setDensity(0x0140)
|
|
.setSdkVersion(0x0004) // version [any density requires donut]
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
// ========== Test INPUT ==========
|
|
// keyboard: '(nokeys|qwerty|12key)'
|
|
// navigation: '(nonav|dpad|trackball|wheel)'
|
|
// inputFlags: '(keysexposed|keyshidden|keyssoft)'
|
|
// inputFlags: '(navexposed|navhidden)'
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("qwerty"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setKeyboard(0x02)
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("dpad"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setNavigation(0x02)
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("keyssoft-navhidden"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setInputFlags(0x0B)
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("keyshidden-nokeys-navexposed-trackball"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setKeyboard(0x01)
|
|
.setNavigation(0x03)
|
|
.setInputFlags(0x06)
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
// ========== Test SCREEN_SIZE ==========
|
|
// screenWidth/screenHeight: '[0-9]+x[0-9]+'
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("1920x1080"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setScreenWidth(0x0780)
|
|
.setScreenHeight(0x0438)
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
// ========== Test VERSION ==========
|
|
// version 'v[0-9]+'
|
|
|
|
// ========== Test SCREEN_CONFIG ==========
|
|
// screenLayout [direction]: '(ldltr|ldrtl)'
|
|
// screenLayout [size]: '(small|normal|large|xlarge)'
|
|
// screenLayout [long]: '(long|notlong)'
|
|
// uiMode [type]: '(desk|car|television|appliance|watch|vrheadset)'
|
|
// uiMode [night]: '(night|notnight)'
|
|
// smallestScreenWidthDp: 'sw[0-9]dp'
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("ldrtl"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setScreenLayout(0x80)
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("small"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setScreenLayout(0x01)
|
|
.setSdkVersion(0x0004) // screenLayout (size) requires donut
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("notlong"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setScreenLayout(0x10)
|
|
.setSdkVersion(0x0004) // screenLayout (long) requires donut
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("ldltr-normal-long"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setScreenLayout(0x62)
|
|
.setSdkVersion(0x0004) // screenLayout (size|long) requires donut
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("car"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setUiMode(0x03)
|
|
.setSdkVersion(0x0008) // uiMode requires froyo
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("vrheadset"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setUiMode(0x07)
|
|
.setSdkVersion(0x001A) // uiMode 'vrheadset' requires oreo
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("television-night"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setUiMode(0x24)
|
|
.setSdkVersion(0x0008) // uiMode requires froyo
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("sw1920dp"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setSmallestScreenWidthDp(0x0780)
|
|
.setSdkVersion(0x000D) // smallestScreenWidthDp requires honeycomb mr2
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
// ========== Test SCREEN_SIZE_DP ==========
|
|
// screenWidthDp: 'w[0-9]dp'
|
|
// screenHeightDp: 'h[0-9]dp'
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("w1920dp"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setScreenWidthDp(0x0780)
|
|
.setSdkVersion(0x000D) // screenWidthDp requires honeycomb mr2
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("h1080dp"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setScreenHeightDp(0x0438)
|
|
.setSdkVersion(0x000D) // screenHeightDp requires honeycomb mr2
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
// ========== Test SCREEN_CONFIG_2 ==========
|
|
// screenLayout2: '(round|notround)'
|
|
// colorMode: '(widecg|nowidecg)'
|
|
// colorMode: '(highhdr|lowdr)'
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("round"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setScreenLayout2(0x02)
|
|
.setSdkVersion(0x0017) // screenLayout2 (round) requires marshmallow
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("widecg-highdr"),
|
|
diagnostics, &path, &constraints));
|
|
expected_configuration = test::ConfigDescriptionBuilder()
|
|
.setColorMode(0x0A)
|
|
.setSdkVersion(0x001A) // colorMode (hdr|colour gamut) requires oreo
|
|
.Build();
|
|
EXPECT_CONFIG_EQ(constraints, expected_configuration);
|
|
}
|
|
|
|
TEST (UtilTest, AdjustSplitConstraintsForMinSdk) {
|
|
std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
|
|
|
|
IDiagnostics* diagnostics = context.get()->GetDiagnostics();
|
|
std::vector<SplitConstraints> test_constraints;
|
|
std::string path;
|
|
|
|
test_constraints.push_back({});
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("v7"),
|
|
diagnostics, &path, &test_constraints.back()));
|
|
test_constraints.push_back({});
|
|
ASSERT_TRUE(ParseSplitParameter(CREATE_PATH("xhdpi"),
|
|
diagnostics, &path, &test_constraints.back()));
|
|
EXPECT_EQ(test_constraints.size(), 2);
|
|
EXPECT_EQ(test_constraints[0].name, "v7");
|
|
EXPECT_EQ(test_constraints[0].configs.size(), 1);
|
|
EXPECT_NE(*test_constraints[0].configs.begin(), ConfigDescription::DefaultConfig());
|
|
EXPECT_EQ(test_constraints[1].name, "xhdpi");
|
|
EXPECT_EQ(test_constraints[1].configs.size(), 1);
|
|
EXPECT_NE(*test_constraints[0].configs.begin(), ConfigDescription::DefaultConfig());
|
|
|
|
auto adjusted_contraints = AdjustSplitConstraintsForMinSdk(26, test_constraints);
|
|
EXPECT_EQ(adjusted_contraints.size(), 2);
|
|
EXPECT_EQ(adjusted_contraints[0].name, "v7");
|
|
EXPECT_EQ(adjusted_contraints[0].configs.size(), 0);
|
|
EXPECT_EQ(adjusted_contraints[1].name, "xhdpi");
|
|
EXPECT_EQ(adjusted_contraints[1].configs.size(), 1);
|
|
EXPECT_NE(*adjusted_contraints[1].configs.begin(), ConfigDescription::DefaultConfig());
|
|
}
|
|
|
|
TEST (UtilTest, RegularExperssionsSimple) {
|
|
std::string valid(".bc$");
|
|
std::regex expression = GetRegularExpression(valid);
|
|
EXPECT_TRUE(std::regex_search("file.abc", expression));
|
|
EXPECT_TRUE(std::regex_search("file.123bc", expression));
|
|
EXPECT_FALSE(std::regex_search("abc.zip", expression));
|
|
}
|
|
|
|
TEST (UtilTest, RegularExpressionComplex) {
|
|
std::string valid("\\.(d|D)(e|E)(x|X)$");
|
|
std::regex expression = GetRegularExpression(valid);
|
|
EXPECT_TRUE(std::regex_search("file.dex", expression));
|
|
EXPECT_TRUE(std::regex_search("file.DEX", expression));
|
|
EXPECT_TRUE(std::regex_search("file.dEx", expression));
|
|
EXPECT_FALSE(std::regex_search("file.dexx", expression));
|
|
EXPECT_FALSE(std::regex_search("dex.file", expression));
|
|
EXPECT_FALSE(std::regex_search("file.adex", expression));
|
|
}
|
|
|
|
TEST (UtilTest, RegularExpressionNonEnglish) {
|
|
std::string valid("\\.(k|K)(o|O)(ń|Ń)(c|C)(ó|Ó)(w|W)(k|K)(a|A)$");
|
|
std::regex expression = GetRegularExpression(valid);
|
|
EXPECT_TRUE(std::regex_search("file.końcówka", expression));
|
|
EXPECT_TRUE(std::regex_search("file.KOŃCÓWKA", expression));
|
|
EXPECT_TRUE(std::regex_search("file.kOńcÓwkA", expression));
|
|
EXPECT_FALSE(std::regex_search("file.koncowka", expression));
|
|
}
|
|
|
|
} // namespace aapt
|