265 lines
12 KiB
C++
265 lines
12 KiB
C++
/*
|
|
* Copyright (C) 2022 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 "path_utils.h"
|
|
|
|
#include "aidl/com/android/server/art/BnArtd.h"
|
|
#include "android-base/result-gmock.h"
|
|
#include "base/common_art_test.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
namespace art {
|
|
namespace artd {
|
|
namespace {
|
|
|
|
using ::aidl::com::android::server::art::ArtifactsPath;
|
|
using ::aidl::com::android::server::art::DexMetadataPath;
|
|
using ::aidl::com::android::server::art::ProfilePath;
|
|
using ::aidl::com::android::server::art::VdexPath;
|
|
using ::android::base::testing::HasError;
|
|
using ::android::base::testing::HasValue;
|
|
using ::android::base::testing::WithMessage;
|
|
|
|
using PrebuiltProfilePath = ProfilePath::PrebuiltProfilePath;
|
|
using PrimaryCurProfilePath = ProfilePath::PrimaryCurProfilePath;
|
|
using PrimaryRefProfilePath = ProfilePath::PrimaryRefProfilePath;
|
|
using SecondaryCurProfilePath = ProfilePath::SecondaryCurProfilePath;
|
|
using SecondaryRefProfilePath = ProfilePath::SecondaryRefProfilePath;
|
|
using TmpProfilePath = ProfilePath::TmpProfilePath;
|
|
|
|
using std::literals::operator""s; // NOLINT
|
|
|
|
class PathUtilsTest : public CommonArtTest {};
|
|
|
|
TEST_F(PathUtilsTest, BuildArtBinPath) {
|
|
auto scratch_dir = std::make_unique<ScratchDir>();
|
|
auto art_root_env = ScopedUnsetEnvironmentVariable("ANDROID_ART_ROOT");
|
|
setenv("ANDROID_ART_ROOT", scratch_dir->GetPath().c_str(), /*overwrite=*/1);
|
|
EXPECT_THAT(BuildArtBinPath("foo"), HasValue(scratch_dir->GetPath() + "/bin/foo"));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildOatPath) {
|
|
EXPECT_THAT(
|
|
BuildOatPath(ArtifactsPath{.dexPath = "/a/b.apk", .isa = "arm64", .isInDalvikCache = false}),
|
|
HasValue("/a/oat/arm64/b.odex"));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildOatPathDalvikCache) {
|
|
EXPECT_THAT(
|
|
BuildOatPath(ArtifactsPath{.dexPath = "/a/b.apk", .isa = "arm64", .isInDalvikCache = true}),
|
|
HasValue(android_data_ + "/dalvik-cache/arm64/a@b.apk@classes.dex"));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildOatPathEmptyDexPath) {
|
|
EXPECT_THAT(BuildOatPath(ArtifactsPath{.dexPath = "", .isa = "arm64", .isInDalvikCache = false}),
|
|
HasError(WithMessage("Path is empty")));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildOatPathRelativeDexPath) {
|
|
EXPECT_THAT(
|
|
BuildOatPath(ArtifactsPath{.dexPath = "a/b.apk", .isa = "arm64", .isInDalvikCache = false}),
|
|
HasError(WithMessage("Path 'a/b.apk' is not an absolute path")));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildOatPathNonNormalDexPath) {
|
|
EXPECT_THAT(BuildOatPath(ArtifactsPath{
|
|
.dexPath = "/a/c/../b.apk", .isa = "arm64", .isInDalvikCache = false}),
|
|
HasError(WithMessage("Path '/a/c/../b.apk' is not in normal form")));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildOatPathNul) {
|
|
EXPECT_THAT(BuildOatPath(ArtifactsPath{
|
|
.dexPath = "/a/\0/b.apk"s, .isa = "arm64", .isInDalvikCache = false}),
|
|
HasError(WithMessage("Path '/a/\0/b.apk' has invalid character '\\0'"s)));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildOatPathInvalidIsa) {
|
|
EXPECT_THAT(BuildOatPath(
|
|
ArtifactsPath{.dexPath = "/a/b.apk", .isa = "invalid", .isInDalvikCache = false}),
|
|
HasError(WithMessage("Instruction set 'invalid' is invalid")));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, OatPathToVdexPath) {
|
|
EXPECT_EQ(OatPathToVdexPath("/a/oat/arm64/b.odex"), "/a/oat/arm64/b.vdex");
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, OatPathToArtPath) {
|
|
EXPECT_EQ(OatPathToArtPath("/a/oat/arm64/b.odex"), "/a/oat/arm64/b.art");
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildPrimaryRefProfilePath) {
|
|
EXPECT_THAT(BuildPrimaryRefProfilePath(PrimaryRefProfilePath{.packageName = "com.android.foo",
|
|
.profileName = "primary"}),
|
|
HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof"));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildPrimaryRefProfilePathPackageNameOk) {
|
|
EXPECT_THAT(BuildPrimaryRefProfilePath(
|
|
PrimaryRefProfilePath{.packageName = "...", .profileName = "primary"}),
|
|
HasValue(android_data_ + "/misc/profiles/ref/.../primary.prof"));
|
|
EXPECT_THAT(BuildPrimaryRefProfilePath(
|
|
PrimaryRefProfilePath{.packageName = "!@#$%^&*()_+-=", .profileName = "primary"}),
|
|
HasValue(android_data_ + "/misc/profiles/ref/!@#$%^&*()_+-=/primary.prof"));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildPrimaryRefProfilePathPackageNameWrong) {
|
|
EXPECT_THAT(BuildPrimaryRefProfilePath(
|
|
PrimaryRefProfilePath{.packageName = "", .profileName = "primary"}),
|
|
HasError(WithMessage("packageName is empty")));
|
|
EXPECT_THAT(BuildPrimaryRefProfilePath(
|
|
PrimaryRefProfilePath{.packageName = ".", .profileName = "primary"}),
|
|
HasError(WithMessage("Invalid packageName '.'")));
|
|
EXPECT_THAT(BuildPrimaryRefProfilePath(
|
|
PrimaryRefProfilePath{.packageName = "..", .profileName = "primary"}),
|
|
HasError(WithMessage("Invalid packageName '..'")));
|
|
EXPECT_THAT(BuildPrimaryRefProfilePath(
|
|
PrimaryRefProfilePath{.packageName = "a/b", .profileName = "primary"}),
|
|
HasError(WithMessage("packageName 'a/b' has invalid character '/'")));
|
|
EXPECT_THAT(BuildPrimaryRefProfilePath(
|
|
PrimaryRefProfilePath{.packageName = "a\0b"s, .profileName = "primary"}),
|
|
HasError(WithMessage("packageName 'a\0b' has invalid character '\\0'"s)));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildPrimaryRefProfilePathProfileNameOk) {
|
|
EXPECT_THAT(BuildPrimaryRefProfilePath(
|
|
PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = "."}),
|
|
HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/..prof"));
|
|
EXPECT_THAT(BuildPrimaryRefProfilePath(
|
|
PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = ".."}),
|
|
HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/...prof"));
|
|
EXPECT_THAT(BuildPrimaryRefProfilePath(PrimaryRefProfilePath{.packageName = "com.android.foo",
|
|
.profileName = "!@#$%^&*()_+-="}),
|
|
HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/!@#$%^&*()_+-=.prof"));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildPrimaryRefProfilePathProfileNameWrong) {
|
|
EXPECT_THAT(BuildPrimaryRefProfilePath(
|
|
PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = ""}),
|
|
HasError(WithMessage("profileName is empty")));
|
|
EXPECT_THAT(BuildPrimaryRefProfilePath(
|
|
PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = "a/b"}),
|
|
HasError(WithMessage("profileName 'a/b' has invalid character '/'")));
|
|
EXPECT_THAT(BuildPrimaryRefProfilePath(
|
|
PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = "a\0b"s}),
|
|
HasError(WithMessage("profileName 'a\0b' has invalid character '\\0'"s)));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildFinalProfilePathForPrimary) {
|
|
EXPECT_THAT(BuildFinalProfilePath(TmpProfilePath{
|
|
.finalPath = PrimaryRefProfilePath{.packageName = "com.android.foo",
|
|
.profileName = "primary"},
|
|
.id = "12345"}),
|
|
HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof"));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildFinalProfilePathForSecondary) {
|
|
EXPECT_THAT(BuildFinalProfilePath(TmpProfilePath{
|
|
.finalPath = SecondaryRefProfilePath{.dexPath = android_data_ +
|
|
"/user/0/com.android.foo/a.apk"},
|
|
.id = "12345"}),
|
|
HasValue(android_data_ + "/user/0/com.android.foo/oat/a.apk.prof"));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildTmpProfilePathForPrimary) {
|
|
EXPECT_THAT(
|
|
BuildTmpProfilePath(TmpProfilePath{
|
|
.finalPath =
|
|
PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = "primary"},
|
|
.id = "12345"}),
|
|
HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof.12345.tmp"));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildTmpProfilePathForSecondary) {
|
|
EXPECT_THAT(BuildTmpProfilePath(TmpProfilePath{
|
|
.finalPath = SecondaryRefProfilePath{.dexPath = android_data_ +
|
|
"/user/0/com.android.foo/a.apk"},
|
|
.id = "12345"}),
|
|
HasValue(android_data_ + "/user/0/com.android.foo/oat/a.apk.prof.12345.tmp"));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildTmpProfilePathIdWrong) {
|
|
EXPECT_THAT(BuildTmpProfilePath(TmpProfilePath{
|
|
.finalPath = PrimaryRefProfilePath{.packageName = "com.android.foo",
|
|
.profileName = "primary"},
|
|
.id = ""}),
|
|
HasError(WithMessage("id is empty")));
|
|
EXPECT_THAT(BuildTmpProfilePath(TmpProfilePath{
|
|
.finalPath = PrimaryRefProfilePath{.packageName = "com.android.foo",
|
|
.profileName = "primary"},
|
|
.id = "123/45"}),
|
|
HasError(WithMessage("id '123/45' has invalid character '/'")));
|
|
EXPECT_THAT(BuildTmpProfilePath(TmpProfilePath{
|
|
.finalPath = PrimaryRefProfilePath{.packageName = "com.android.foo",
|
|
.profileName = "primary"},
|
|
.id = "123\0a"s}),
|
|
HasError(WithMessage("id '123\0a' has invalid character '\\0'"s)));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildPrebuiltProfilePath) {
|
|
EXPECT_THAT(BuildPrebuiltProfilePath(PrebuiltProfilePath{.dexPath = "/a/b.apk"}),
|
|
HasValue("/a/b.apk.prof"));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildPrimaryCurProfilePath) {
|
|
EXPECT_THAT(BuildPrimaryCurProfilePath(PrimaryCurProfilePath{
|
|
.userId = 1, .packageName = "com.android.foo", .profileName = "primary"}),
|
|
HasValue(android_data_ + "/misc/profiles/cur/1/com.android.foo/primary.prof"));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildSecondaryRefProfilePath) {
|
|
EXPECT_THAT(BuildSecondaryRefProfilePath(SecondaryRefProfilePath{
|
|
.dexPath = android_data_ + "/user/0/com.android.foo/a.apk"}),
|
|
HasValue(android_data_ + "/user/0/com.android.foo/oat/a.apk.prof"));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildSecondaryCurProfilePath) {
|
|
EXPECT_THAT(BuildSecondaryCurProfilePath(SecondaryCurProfilePath{
|
|
.dexPath = android_data_ + "/user/0/com.android.foo/a.apk"}),
|
|
HasValue(android_data_ + "/user/0/com.android.foo/oat/a.apk.cur.prof"));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildDexMetadataPath) {
|
|
EXPECT_THAT(BuildDexMetadataPath(DexMetadataPath{.dexPath = "/a/b.apk"}), HasValue("/a/b.dm"));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildProfilePath) {
|
|
EXPECT_THAT(BuildProfileOrDmPath(PrimaryRefProfilePath{.packageName = "com.android.foo",
|
|
.profileName = "primary"}),
|
|
HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof"));
|
|
EXPECT_THAT(
|
|
BuildProfileOrDmPath(TmpProfilePath{
|
|
.finalPath =
|
|
PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = "primary"},
|
|
.id = "12345"}),
|
|
HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof.12345.tmp"));
|
|
EXPECT_THAT(BuildProfileOrDmPath(PrebuiltProfilePath{.dexPath = "/a/b.apk"}),
|
|
HasValue("/a/b.apk.prof"));
|
|
EXPECT_THAT(BuildProfileOrDmPath(PrimaryCurProfilePath{
|
|
.userId = 1, .packageName = "com.android.foo", .profileName = "primary"}),
|
|
HasValue(android_data_ + "/misc/profiles/cur/1/com.android.foo/primary.prof"));
|
|
EXPECT_THAT(BuildProfileOrDmPath(DexMetadataPath{.dexPath = "/a/b.apk"}), HasValue("/a/b.dm"));
|
|
}
|
|
|
|
TEST_F(PathUtilsTest, BuildVdexPath) {
|
|
EXPECT_THAT(
|
|
BuildVdexPath(ArtifactsPath{.dexPath = "/a/b.apk", .isa = "arm64", .isInDalvikCache = false}),
|
|
HasValue("/a/oat/arm64/b.vdex"));
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace artd
|
|
} // namespace art
|