| /* |
| * 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 "gmock/gmock.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 ::android::base::testing::HasError; |
| using ::android::base::testing::HasValue; |
| using ::android::base::testing::WithMessage; |
| using ::testing::AllOf; |
| using ::testing::Field; |
| |
| 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, BuildArtifactsPath) { |
| EXPECT_THAT( |
| BuildArtifactsPath(ArtifactsPath{ |
| .dexPath = "/a/b.apk", .isa = "arm64", .isInDalvikCache = false, .isPreReboot = false}), |
| HasValue(AllOf(Field(&RawArtifactsPath::oat_path, "/a/oat/arm64/b.odex"), |
| Field(&RawArtifactsPath::vdex_path, "/a/oat/arm64/b.vdex"), |
| Field(&RawArtifactsPath::art_path, "/a/oat/arm64/b.art")))); |
| } |
| |
| TEST_F(PathUtilsTest, BuildArtifactsPathPreReboot) { |
| EXPECT_THAT( |
| BuildArtifactsPath(ArtifactsPath{ |
| .dexPath = "/a/b.apk", .isa = "arm64", .isInDalvikCache = false, .isPreReboot = true}), |
| HasValue(AllOf(Field(&RawArtifactsPath::oat_path, "/a/oat/arm64/b.odex.staged"), |
| Field(&RawArtifactsPath::vdex_path, "/a/oat/arm64/b.vdex.staged"), |
| Field(&RawArtifactsPath::art_path, "/a/oat/arm64/b.art.staged")))); |
| } |
| |
| TEST_F(PathUtilsTest, BuildArtifactsPathDalvikCache) { |
| EXPECT_THAT( |
| BuildArtifactsPath(ArtifactsPath{ |
| .dexPath = "/a/b.apk", .isa = "arm64", .isInDalvikCache = true, .isPreReboot = false}), |
| HasValue(AllOf(Field(&RawArtifactsPath::oat_path, |
| android_data_ + "/dalvik-cache/arm64/[email protected]@classes.dex"), |
| Field(&RawArtifactsPath::vdex_path, |
| android_data_ + "/dalvik-cache/arm64/[email protected]@classes.vdex"), |
| Field(&RawArtifactsPath::art_path, |
| android_data_ + "/dalvik-cache/arm64/[email protected]@classes.art")))); |
| } |
| |
| TEST_F(PathUtilsTest, BuildArtifactsPathDalvikCachePreReboot) { |
| EXPECT_THAT( |
| BuildArtifactsPath(ArtifactsPath{ |
| .dexPath = "/a/b.apk", .isa = "arm64", .isInDalvikCache = true, .isPreReboot = true}), |
| HasValue(AllOf(Field(&RawArtifactsPath::oat_path, |
| android_data_ + "/dalvik-cache/arm64/[email protected]@classes.dex.staged"), |
| Field(&RawArtifactsPath::vdex_path, |
| android_data_ + "/dalvik-cache/arm64/[email protected]@classes.vdex.staged"), |
| Field(&RawArtifactsPath::art_path, |
| android_data_ + "/dalvik-cache/arm64/[email protected]@classes.art.staged")))); |
| } |
| |
| TEST_F(PathUtilsTest, BuildOatPathInvalidDexPath) { |
| EXPECT_THAT( |
| BuildArtifactsPath(ArtifactsPath{ |
| .dexPath = "a/b.apk", .isa = "arm64", .isInDalvikCache = false, .isPreReboot = false}), |
| HasError(WithMessage("Path 'a/b.apk' is not an absolute path"))); |
| } |
| |
| TEST_F(PathUtilsTest, BuildOatPathInvalidIsa) { |
| EXPECT_THAT( |
| BuildArtifactsPath(ArtifactsPath{ |
| .dexPath = "/a/b.apk", .isa = "invalid", .isInDalvikCache = false, .isPreReboot = false}), |
| HasError(WithMessage("Instruction set 'invalid' is invalid"))); |
| } |
| |
| TEST_F(PathUtilsTest, BuildPrimaryRefProfilePath) { |
| EXPECT_THAT( |
| BuildPrimaryRefProfilePath(PrimaryRefProfilePath{ |
| .packageName = "com.android.foo", .profileName = "primary", .isPreReboot = false}), |
| HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof")); |
| } |
| |
| TEST_F(PathUtilsTest, BuildPrimaryRefProfilePathPreReboot) { |
| EXPECT_THAT(BuildPrimaryRefProfilePath(PrimaryRefProfilePath{ |
| .packageName = "com.android.foo", .profileName = "primary", .isPreReboot = true}), |
| HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof.staged")); |
| } |
| |
| TEST_F(PathUtilsTest, BuildPrimaryRefProfilePathPackageNameOk) { |
| EXPECT_THAT(BuildPrimaryRefProfilePath(PrimaryRefProfilePath{ |
| .packageName = "...", .profileName = "primary", .isPreReboot = false}), |
| HasValue(android_data_ + "/misc/profiles/ref/.../primary.prof")); |
| } |
| |
| TEST_F(PathUtilsTest, BuildPrimaryRefProfilePathPackageNameWrong) { |
| EXPECT_THAT(BuildPrimaryRefProfilePath(PrimaryRefProfilePath{ |
| .packageName = "..", .profileName = "primary", .isPreReboot = false}), |
| HasError(WithMessage("Invalid packageName '..'"))); |
| EXPECT_THAT(BuildPrimaryRefProfilePath(PrimaryRefProfilePath{ |
| .packageName = "a/b", .profileName = "primary", .isPreReboot = false}), |
| HasError(WithMessage("packageName 'a/b' has invalid character '/'"))); |
| } |
| |
| TEST_F(PathUtilsTest, BuildPrimaryRefProfilePathProfileNameOk) { |
| EXPECT_THAT(BuildPrimaryRefProfilePath(PrimaryRefProfilePath{ |
| .packageName = "com.android.foo", .profileName = "..", .isPreReboot = false}), |
| HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/...prof")); |
| } |
| |
| TEST_F(PathUtilsTest, BuildPrimaryRefProfilePathProfileNameWrong) { |
| EXPECT_THAT(BuildPrimaryRefProfilePath(PrimaryRefProfilePath{ |
| .packageName = "com.android.foo", .profileName = "a/b", .isPreReboot = false}), |
| HasError(WithMessage("profileName 'a/b' has invalid character '/'"))); |
| } |
| |
| TEST_F(PathUtilsTest, BuildFinalProfilePathForPrimary) { |
| EXPECT_THAT(BuildFinalProfilePath(TmpProfilePath{ |
| .finalPath = PrimaryRefProfilePath{.packageName = "com.android.foo", |
| .profileName = "primary", |
| .isPreReboot = false}, |
| .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", |
| .isPreReboot = false}, |
| .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", .isPreReboot = false}, |
| .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", |
| .isPreReboot = false}, |
| .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", |
| .isPreReboot = false}, |
| .id = "123/45"}), |
| HasError(WithMessage("id '123/45' has invalid character '/'"))); |
| } |
| |
| 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", .isPreReboot = false}), |
| HasValue(android_data_ + "/user/0/com.android.foo/oat/a.apk.prof")); |
| } |
| |
| TEST_F(PathUtilsTest, BuildSecondaryRefProfilePathPreReboot) { |
| EXPECT_THAT(BuildSecondaryRefProfilePath(SecondaryRefProfilePath{ |
| .dexPath = android_data_ + "/user/0/com.android.foo/a.apk", .isPreReboot = true}), |
| HasValue(android_data_ + "/user/0/com.android.foo/oat/a.apk.prof.staged")); |
| } |
| |
| 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", .isPreReboot = false}), |
| HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof")); |
| EXPECT_THAT( |
| BuildProfileOrDmPath(TmpProfilePath{ |
| .finalPath = |
| PrimaryRefProfilePath{ |
| .packageName = "com.android.foo", .profileName = "primary", .isPreReboot = false}, |
| .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 |