Merge "Fix tests affected by sparse.apk"
This commit is contained in:
@@ -211,6 +211,8 @@ cc_test {
|
||||
"tests/data/**/*.apk",
|
||||
"tests/data/**/*.arsc",
|
||||
"tests/data/**/*.idmap",
|
||||
":FrameworkResourcesSparseTestApp",
|
||||
":FrameworkResourcesNotSparseTestApp",
|
||||
],
|
||||
test_suites: ["device-tests"],
|
||||
}
|
||||
|
||||
@@ -71,62 +71,6 @@ TEST(LoadedArscTest, LoadSinglePackageArsc) {
|
||||
ASSERT_TRUE(LoadedPackage::GetEntry(type.type, entry_index).has_value());
|
||||
}
|
||||
|
||||
TEST(LoadedArscTest, LoadSparseEntryApp) {
|
||||
std::string contents;
|
||||
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/sparse/sparse.apk", "resources.arsc",
|
||||
&contents));
|
||||
|
||||
std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(contents.data(),
|
||||
contents.length());
|
||||
ASSERT_THAT(loaded_arsc, NotNull());
|
||||
|
||||
const LoadedPackage* package =
|
||||
loaded_arsc->GetPackageById(get_package_id(sparse::R::integer::foo_9));
|
||||
ASSERT_THAT(package, NotNull());
|
||||
|
||||
const uint8_t type_index = get_type_id(sparse::R::integer::foo_9) - 1;
|
||||
const uint16_t entry_index = get_entry_id(sparse::R::integer::foo_9);
|
||||
|
||||
const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
|
||||
ASSERT_THAT(type_spec, NotNull());
|
||||
ASSERT_THAT(type_spec->type_entries.size(), Ge(1u));
|
||||
|
||||
auto type = type_spec->type_entries[0];
|
||||
ASSERT_TRUE(LoadedPackage::GetEntry(type.type, entry_index).has_value());
|
||||
}
|
||||
|
||||
TEST(LoadedArscTest, FindSparseEntryApp) {
|
||||
std::string contents;
|
||||
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/sparse/sparse.apk", "resources.arsc",
|
||||
&contents));
|
||||
|
||||
std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(contents.data(),
|
||||
contents.length());
|
||||
ASSERT_THAT(loaded_arsc, NotNull());
|
||||
|
||||
const LoadedPackage* package =
|
||||
loaded_arsc->GetPackageById(get_package_id(sparse::R::string::only_v26));
|
||||
ASSERT_THAT(package, NotNull());
|
||||
|
||||
const uint8_t type_index = get_type_id(sparse::R::string::only_v26) - 1;
|
||||
const uint16_t entry_index = get_entry_id(sparse::R::string::only_v26);
|
||||
|
||||
const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
|
||||
ASSERT_THAT(type_spec, NotNull());
|
||||
ASSERT_THAT(type_spec->type_entries.size(), Ge(1u));
|
||||
|
||||
// Ensure that AAPT2 sparsely encoded the v26 config as expected.
|
||||
auto type_entry = std::find_if(
|
||||
type_spec->type_entries.begin(), type_spec->type_entries.end(),
|
||||
[](const TypeSpec::TypeEntry& x) { return x.config.sdkVersion == 26; });
|
||||
ASSERT_NE(type_entry, type_spec->type_entries.end());
|
||||
ASSERT_NE(type_entry->type->flags & ResTable_type::FLAG_SPARSE, 0);
|
||||
|
||||
// Test fetching a resource with only sparsely encoded configs by name.
|
||||
auto id = package->FindEntryByName(u"string", u"only_v26");
|
||||
ASSERT_EQ(id.value(), fix_package_id(sparse::R::string::only_v26, 0));
|
||||
}
|
||||
|
||||
TEST(LoadedArscTest, LoadSharedLibrary) {
|
||||
std::string contents;
|
||||
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/lib_one/lib_one.apk", "resources.arsc",
|
||||
@@ -404,4 +348,84 @@ TEST(LoadedArscTest, LoadCustomLoader) {
|
||||
// sizeof(Res_value) might not be backwards compatible.
|
||||
// TEST(LoadedArscTest, LoadingShouldBeForwardsAndBackwardsCompatible) { ASSERT_TRUE(false); }
|
||||
|
||||
class LoadedArscParameterizedTest :
|
||||
public testing::TestWithParam<std::string> {
|
||||
};
|
||||
|
||||
TEST_P(LoadedArscParameterizedTest, LoadSparseEntryApp) {
|
||||
std::string contents;
|
||||
ASSERT_TRUE(ReadFileFromZipToString(GetParam(), "resources.arsc", &contents));
|
||||
|
||||
std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(contents.data(),
|
||||
contents.length());
|
||||
ASSERT_THAT(loaded_arsc, NotNull());
|
||||
|
||||
const LoadedPackage* package =
|
||||
loaded_arsc->GetPackageById(get_package_id(sparse::R::integer::foo_9));
|
||||
ASSERT_THAT(package, NotNull());
|
||||
|
||||
const uint8_t type_index = get_type_id(sparse::R::integer::foo_9) - 1;
|
||||
const uint16_t entry_index = get_entry_id(sparse::R::integer::foo_9);
|
||||
|
||||
const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
|
||||
ASSERT_THAT(type_spec, NotNull());
|
||||
ASSERT_THAT(type_spec->type_entries.size(), Ge(1u));
|
||||
|
||||
auto type = type_spec->type_entries[0];
|
||||
ASSERT_TRUE(LoadedPackage::GetEntry(type.type, entry_index).has_value());
|
||||
}
|
||||
|
||||
TEST_P(LoadedArscParameterizedTest, FindSparseEntryApp) {
|
||||
std::string contents;
|
||||
ASSERT_TRUE(ReadFileFromZipToString(GetParam(), "resources.arsc", &contents));
|
||||
|
||||
std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(contents.data(),
|
||||
contents.length());
|
||||
ASSERT_THAT(loaded_arsc, NotNull());
|
||||
|
||||
const LoadedPackage* package =
|
||||
loaded_arsc->GetPackageById(get_package_id(sparse::R::string::only_land));
|
||||
ASSERT_THAT(package, NotNull());
|
||||
|
||||
const uint8_t type_index = get_type_id(sparse::R::string::only_land) - 1;
|
||||
|
||||
const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
|
||||
ASSERT_THAT(type_spec, NotNull());
|
||||
ASSERT_THAT(type_spec->type_entries.size(), Ge(1u));
|
||||
|
||||
// Type Entry with default orientation is not sparse encoded because the ratio of
|
||||
// populated entries to total entries is above threshold.
|
||||
// Only find out default locale because Soong build system will introduce pseudo
|
||||
// locales for the apk generated at runtime.
|
||||
auto type_entry_default = std::find_if(
|
||||
type_spec->type_entries.begin(), type_spec->type_entries.end(),
|
||||
[] (const TypeSpec::TypeEntry& x) { return x.config.orientation == 0 &&
|
||||
x.config.locale == 0; });
|
||||
ASSERT_NE(type_entry_default, type_spec->type_entries.end());
|
||||
ASSERT_EQ(type_entry_default->type->flags & ResTable_type::FLAG_SPARSE, 0);
|
||||
|
||||
// Type Entry with land orientation is sparse encoded as expected.
|
||||
// Only find out default locale because Soong build system will introduce pseudo
|
||||
// locales for the apk generated at runtime.
|
||||
auto type_entry_land = std::find_if(
|
||||
type_spec->type_entries.begin(), type_spec->type_entries.end(),
|
||||
[](const TypeSpec::TypeEntry& x) { return x.config.orientation ==
|
||||
ResTable_config::ORIENTATION_LAND &&
|
||||
x.config.locale == 0; });
|
||||
ASSERT_NE(type_entry_land, type_spec->type_entries.end());
|
||||
ASSERT_NE(type_entry_land->type->flags & ResTable_type::FLAG_SPARSE, 0);
|
||||
|
||||
// Test fetching a resource with only sparsely encoded configs by name.
|
||||
auto id = package->FindEntryByName(u"string", u"only_land");
|
||||
ASSERT_EQ(id.value(), fix_package_id(sparse::R::string::only_land, 0));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
FrameWorkResourcesLoadedArscTests,
|
||||
LoadedArscParameterizedTest,
|
||||
::testing::Values(
|
||||
base::GetExecutableDirectory() + "/tests/data/sparse/sparse.apk",
|
||||
base::GetExecutableDirectory() + "/FrameworkResourcesSparseTestApp.apk"
|
||||
));
|
||||
|
||||
} // namespace android
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "androidfw/ResourceTypes.h"
|
||||
#include "android-base/file.h"
|
||||
|
||||
#include <codecvt>
|
||||
#include <locale>
|
||||
@@ -41,34 +42,6 @@ TEST(ResTableTest, ShouldLoadSuccessfully) {
|
||||
ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
|
||||
}
|
||||
|
||||
TEST(ResTableTest, ShouldLoadSparseEntriesSuccessfully) {
|
||||
std::string contents;
|
||||
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/sparse/sparse.apk", "resources.arsc",
|
||||
&contents));
|
||||
|
||||
ResTable table;
|
||||
ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
|
||||
|
||||
ResTable_config config;
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.sdkVersion = 26;
|
||||
table.setParameters(&config);
|
||||
|
||||
String16 name(u"com.android.sparse:integer/foo_9");
|
||||
uint32_t flags;
|
||||
uint32_t resid =
|
||||
table.identifierForName(name.string(), name.size(), nullptr, 0, nullptr, 0, &flags);
|
||||
ASSERT_NE(0u, resid);
|
||||
|
||||
Res_value val;
|
||||
ResTable_config selected_config;
|
||||
ASSERT_GE(
|
||||
table.getResource(resid, &val, false /*mayBeBag*/, 0u /*density*/, &flags, &selected_config),
|
||||
0);
|
||||
EXPECT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
|
||||
EXPECT_EQ(900u, val.data);
|
||||
}
|
||||
|
||||
TEST(ResTableTest, SimpleTypeIsRetrievedCorrectly) {
|
||||
std::string contents;
|
||||
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk",
|
||||
@@ -476,4 +449,43 @@ TEST(ResTableTest, TruncatedEncodeLength) {
|
||||
ASSERT_FALSE(invalid_pool->stringAt(invalid_val.data).has_value());
|
||||
}
|
||||
|
||||
class ResTableParameterizedTest :
|
||||
public testing::TestWithParam<std::string> {
|
||||
};
|
||||
|
||||
TEST_P(ResTableParameterizedTest, ShouldLoadSparseEntriesSuccessfully) {
|
||||
std::string contents;
|
||||
ASSERT_TRUE(ReadFileFromZipToString(GetParam(), "resources.arsc", &contents));
|
||||
|
||||
ResTable table;
|
||||
ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size()));
|
||||
|
||||
ResTable_config config;
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.orientation = ResTable_config::ORIENTATION_LAND;
|
||||
table.setParameters(&config);
|
||||
|
||||
String16 name(u"com.android.sparse:integer/foo_9");
|
||||
uint32_t flags;
|
||||
uint32_t resid =
|
||||
table.identifierForName(name.string(), name.size(), nullptr, 0, nullptr, 0, &flags);
|
||||
ASSERT_NE(0u, resid);
|
||||
|
||||
Res_value val;
|
||||
ResTable_config selected_config;
|
||||
ASSERT_GE(
|
||||
table.getResource(resid, &val, false /*mayBeBag*/, 0u /*density*/, &flags, &selected_config),
|
||||
0);
|
||||
EXPECT_EQ(Res_value::TYPE_INT_DEC, val.dataType);
|
||||
EXPECT_EQ(900u, val.data);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
FrameWorkResourcesResTableTests,
|
||||
ResTableParameterizedTest,
|
||||
::testing::Values(
|
||||
base::GetExecutableDirectory() + "/tests/data/sparse/sparse.apk",
|
||||
base::GetExecutableDirectory() + "/FrameworkResourcesSparseTestApp.apk"
|
||||
));
|
||||
|
||||
} // namespace android
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "androidfw/AssetManager.h"
|
||||
#include "androidfw/ResourceTypes.h"
|
||||
#include "android-base/file.h"
|
||||
|
||||
#include "BenchmarkHelpers.h"
|
||||
#include "data/sparse/R.h"
|
||||
@@ -24,40 +25,74 @@ namespace sparse = com::android::sparse;
|
||||
|
||||
namespace android {
|
||||
|
||||
static void BM_SparseEntryGetResourceHelper(const std::vector<std::string>& paths,
|
||||
uint32_t resid, benchmark::State& state, void (*GetResourceBenchmarkFunc)(
|
||||
const std::vector<std::string>&, const ResTable_config*,
|
||||
uint32_t, benchmark::State&)){
|
||||
ResTable_config config;
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.orientation = ResTable_config::ORIENTATION_LAND;
|
||||
GetResourceBenchmarkFunc(paths, &config, resid, state);
|
||||
}
|
||||
|
||||
static void BM_SparseEntryGetResourceOldSparse(benchmark::State& state, uint32_t resid) {
|
||||
ResTable_config config;
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.sdkVersion = 26;
|
||||
GetResourceBenchmarkOld({GetTestDataPath() + "/sparse/sparse.apk"}, &config, resid, state);
|
||||
BM_SparseEntryGetResourceHelper({GetTestDataPath() + "/sparse/sparse.apk"}, resid,
|
||||
state, &GetResourceBenchmarkOld);
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldSparse, Small, sparse::R::integer::foo_9);
|
||||
BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldSparse, Large, sparse::R::string::foo_999);
|
||||
|
||||
static void BM_SparseEntryGetResourceOldNotSparse(benchmark::State& state, uint32_t resid) {
|
||||
ResTable_config config;
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.sdkVersion = 26;
|
||||
GetResourceBenchmarkOld({GetTestDataPath() + "/sparse/not_sparse.apk"}, &config, resid, state);
|
||||
BM_SparseEntryGetResourceHelper({GetTestDataPath() + "/sparse/not_sparse.apk"}, resid,
|
||||
state, &GetResourceBenchmarkOld);
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldNotSparse, Small, sparse::R::integer::foo_9);
|
||||
BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldNotSparse, Large, sparse::R::string::foo_999);
|
||||
|
||||
static void BM_SparseEntryGetResourceSparse(benchmark::State& state, uint32_t resid) {
|
||||
ResTable_config config;
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.sdkVersion = 26;
|
||||
GetResourceBenchmark({GetTestDataPath() + "/sparse/sparse.apk"}, &config, resid, state);
|
||||
BM_SparseEntryGetResourceHelper({GetTestDataPath() + "/sparse/sparse.apk"}, resid,
|
||||
state, &GetResourceBenchmark);
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_SparseEntryGetResourceSparse, Small, sparse::R::integer::foo_9);
|
||||
BENCHMARK_CAPTURE(BM_SparseEntryGetResourceSparse, Large, sparse::R::string::foo_999);
|
||||
|
||||
static void BM_SparseEntryGetResourceNotSparse(benchmark::State& state, uint32_t resid) {
|
||||
ResTable_config config;
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.sdkVersion = 26;
|
||||
GetResourceBenchmark({GetTestDataPath() + "/sparse/not_sparse.apk"}, &config, resid, state);
|
||||
BM_SparseEntryGetResourceHelper({GetTestDataPath() + "/sparse/not_sparse.apk"}, resid,
|
||||
state, &GetResourceBenchmark);
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_SparseEntryGetResourceNotSparse, Small, sparse::R::integer::foo_9);
|
||||
BENCHMARK_CAPTURE(BM_SparseEntryGetResourceNotSparse, Large, sparse::R::string::foo_999);
|
||||
|
||||
static void BM_SparseEntryGetResourceOldSparseRuntime(benchmark::State& state, uint32_t resid) {
|
||||
BM_SparseEntryGetResourceHelper({base::GetExecutableDirectory() +
|
||||
"/FrameworkResourcesSparseTestApp.apk"}, resid, state,
|
||||
&GetResourceBenchmarkOld);
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldSparseRuntime, Small, sparse::R::integer::foo_9);
|
||||
BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldSparseRuntime, Large, sparse::R::string::foo_999);
|
||||
|
||||
static void BM_SparseEntryGetResourceOldNotSparseRuntime(benchmark::State& state, uint32_t resid) {
|
||||
BM_SparseEntryGetResourceHelper({base::GetExecutableDirectory() +
|
||||
"/FrameworkResourcesNotSparseTestApp.apk"}, resid, state,
|
||||
&GetResourceBenchmarkOld);
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldNotSparseRuntime, Small, sparse::R::integer::foo_9);
|
||||
BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldNotSparseRuntime, Large, sparse::R::string::foo_999);
|
||||
|
||||
static void BM_SparseEntryGetResourceSparseRuntime(benchmark::State& state, uint32_t resid) {
|
||||
BM_SparseEntryGetResourceHelper({base::GetExecutableDirectory() +
|
||||
"/FrameworkResourcesSparseTestApp.apk"}, resid, state,
|
||||
&GetResourceBenchmark);
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_SparseEntryGetResourceSparseRuntime, Small, sparse::R::integer::foo_9);
|
||||
BENCHMARK_CAPTURE(BM_SparseEntryGetResourceSparseRuntime, Large, sparse::R::string::foo_999);
|
||||
|
||||
static void BM_SparseEntryGetResourceNotSparseRuntime(benchmark::State& state, uint32_t resid) {
|
||||
BM_SparseEntryGetResourceHelper({base::GetExecutableDirectory() +
|
||||
"/FrameworkResourcesNotSparseTestApp.apk"}, resid, state,
|
||||
&GetResourceBenchmark);
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_SparseEntryGetResourceNotSparseRuntime, Small, sparse::R::integer::foo_9);
|
||||
BENCHMARK_CAPTURE(BM_SparseEntryGetResourceNotSparseRuntime, Large, sparse::R::string::foo_999);
|
||||
|
||||
} // namespace android
|
||||
|
||||
14
libs/androidfw/tests/data/sparse/Android.bp
Normal file
14
libs/androidfw/tests/data/sparse/Android.bp
Normal file
@@ -0,0 +1,14 @@
|
||||
android_test_helper_app {
|
||||
name: "FrameworkResourcesSparseTestApp",
|
||||
sdk_version: "current",
|
||||
min_sdk_version: "32",
|
||||
aaptflags: [
|
||||
"--enable-sparse-encoding",
|
||||
],
|
||||
}
|
||||
|
||||
android_test_helper_app {
|
||||
name: "FrameworkResourcesNotSparseTestApp",
|
||||
sdk_version: "current",
|
||||
min_sdk_version: "32",
|
||||
}
|
||||
@@ -17,4 +17,5 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.sparse">
|
||||
<application />
|
||||
<uses-sdk android:minSdkVersion="32" />
|
||||
</manifest>
|
||||
|
||||
@@ -42,7 +42,7 @@ struct R {
|
||||
struct string {
|
||||
enum : uint32_t {
|
||||
foo_999 = 0x7f0203e7,
|
||||
only_v26 = 0x7f0203e8
|
||||
only_land = 0x7f0203e8
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
#!/bin/bash
|
||||
|
||||
OUTPUT_default=res/values/strings.xml
|
||||
OUTPUT_v26=res/values-v26/strings.xml
|
||||
OUTPUT_land=res/values-land/strings.xml
|
||||
|
||||
echo "<resources>" > $OUTPUT_default
|
||||
echo "<resources>" > $OUTPUT_v26
|
||||
echo "<resources>" > $OUTPUT_land
|
||||
for i in {0..999}
|
||||
do
|
||||
echo " <string name=\"foo_$i\">$i</string>" >> $OUTPUT_default
|
||||
if [ "$(($i % 3))" -eq "0" ]
|
||||
then
|
||||
echo " <string name=\"foo_$i\">$(($i * 10))</string>" >> $OUTPUT_v26
|
||||
echo " <string name=\"foo_$i\">$(($i * 10))</string>" >> $OUTPUT_land
|
||||
fi
|
||||
done
|
||||
echo "</resources>" >> $OUTPUT_default
|
||||
|
||||
echo " <string name=\"only_v26\">only v26</string>" >> $OUTPUT_v26
|
||||
echo "</resources>" >> $OUTPUT_v26
|
||||
echo " <string name=\"only_land\">only land</string>" >> $OUTPUT_land
|
||||
echo "</resources>" >> $OUTPUT_land
|
||||
|
||||
|
||||
Binary file not shown.
@@ -333,5 +333,5 @@
|
||||
<string name="foo_993">9930</string>
|
||||
<string name="foo_996">9960</string>
|
||||
<string name="foo_999">9990</string>
|
||||
<string name="only_v26">only v26</string>
|
||||
<string name="only_land">only land</string>
|
||||
</resources>
|
||||
Binary file not shown.
Reference in New Issue
Block a user