1 /*
2 * Copyright (C) 2022 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 "path_utils.h"
18
19 #include "aidl/com/android/server/art/BnArtd.h"
20 #include "android-base/result-gmock.h"
21 #include "base/common_art_test.h"
22 #include "gtest/gtest.h"
23
24 namespace art {
25 namespace artd {
26 namespace {
27
28 using ::aidl::com::android::server::art::ArtifactsPath;
29 using ::aidl::com::android::server::art::DexMetadataPath;
30 using ::aidl::com::android::server::art::ProfilePath;
31 using ::aidl::com::android::server::art::VdexPath;
32 using ::android::base::testing::HasError;
33 using ::android::base::testing::HasValue;
34 using ::android::base::testing::WithMessage;
35
36 using PrebuiltProfilePath = ProfilePath::PrebuiltProfilePath;
37 using PrimaryCurProfilePath = ProfilePath::PrimaryCurProfilePath;
38 using PrimaryRefProfilePath = ProfilePath::PrimaryRefProfilePath;
39 using SecondaryCurProfilePath = ProfilePath::SecondaryCurProfilePath;
40 using SecondaryRefProfilePath = ProfilePath::SecondaryRefProfilePath;
41 using TmpProfilePath = ProfilePath::TmpProfilePath;
42
43 using std::literals::operator""s; // NOLINT
44
45 class PathUtilsTest : public CommonArtTest {};
46
TEST_F(PathUtilsTest,BuildArtBinPath)47 TEST_F(PathUtilsTest, BuildArtBinPath) {
48 auto scratch_dir = std::make_unique<ScratchDir>();
49 auto art_root_env = ScopedUnsetEnvironmentVariable("ANDROID_ART_ROOT");
50 setenv("ANDROID_ART_ROOT", scratch_dir->GetPath().c_str(), /*overwrite=*/1);
51 EXPECT_THAT(BuildArtBinPath("foo"), HasValue(scratch_dir->GetPath() + "/bin/foo"));
52 }
53
TEST_F(PathUtilsTest,BuildOatPath)54 TEST_F(PathUtilsTest, BuildOatPath) {
55 EXPECT_THAT(
56 BuildOatPath(ArtifactsPath{.dexPath = "/a/b.apk", .isa = "arm64", .isInDalvikCache = false}),
57 HasValue("/a/oat/arm64/b.odex"));
58 }
59
TEST_F(PathUtilsTest,BuildOatPathDalvikCache)60 TEST_F(PathUtilsTest, BuildOatPathDalvikCache) {
61 EXPECT_THAT(
62 BuildOatPath(ArtifactsPath{.dexPath = "/a/b.apk", .isa = "arm64", .isInDalvikCache = true}),
63 HasValue(android_data_ + "/dalvik-cache/arm64/a@b.apk@classes.dex"));
64 }
65
TEST_F(PathUtilsTest,BuildOatPathEmptyDexPath)66 TEST_F(PathUtilsTest, BuildOatPathEmptyDexPath) {
67 EXPECT_THAT(BuildOatPath(ArtifactsPath{.dexPath = "", .isa = "arm64", .isInDalvikCache = false}),
68 HasError(WithMessage("Path is empty")));
69 }
70
TEST_F(PathUtilsTest,BuildOatPathRelativeDexPath)71 TEST_F(PathUtilsTest, BuildOatPathRelativeDexPath) {
72 EXPECT_THAT(
73 BuildOatPath(ArtifactsPath{.dexPath = "a/b.apk", .isa = "arm64", .isInDalvikCache = false}),
74 HasError(WithMessage("Path 'a/b.apk' is not an absolute path")));
75 }
76
TEST_F(PathUtilsTest,BuildOatPathNonNormalDexPath)77 TEST_F(PathUtilsTest, BuildOatPathNonNormalDexPath) {
78 EXPECT_THAT(BuildOatPath(ArtifactsPath{
79 .dexPath = "/a/c/../b.apk", .isa = "arm64", .isInDalvikCache = false}),
80 HasError(WithMessage("Path '/a/c/../b.apk' is not in normal form")));
81 }
82
TEST_F(PathUtilsTest,BuildOatPathNul)83 TEST_F(PathUtilsTest, BuildOatPathNul) {
84 EXPECT_THAT(BuildOatPath(ArtifactsPath{
85 .dexPath = "/a/\0/b.apk"s, .isa = "arm64", .isInDalvikCache = false}),
86 HasError(WithMessage("Path '/a/\0/b.apk' has invalid character '\\0'"s)));
87 }
88
TEST_F(PathUtilsTest,BuildOatPathInvalidIsa)89 TEST_F(PathUtilsTest, BuildOatPathInvalidIsa) {
90 EXPECT_THAT(BuildOatPath(
91 ArtifactsPath{.dexPath = "/a/b.apk", .isa = "invalid", .isInDalvikCache = false}),
92 HasError(WithMessage("Instruction set 'invalid' is invalid")));
93 }
94
TEST_F(PathUtilsTest,OatPathToVdexPath)95 TEST_F(PathUtilsTest, OatPathToVdexPath) {
96 EXPECT_EQ(OatPathToVdexPath("/a/oat/arm64/b.odex"), "/a/oat/arm64/b.vdex");
97 }
98
TEST_F(PathUtilsTest,OatPathToArtPath)99 TEST_F(PathUtilsTest, OatPathToArtPath) {
100 EXPECT_EQ(OatPathToArtPath("/a/oat/arm64/b.odex"), "/a/oat/arm64/b.art");
101 }
102
TEST_F(PathUtilsTest,BuildPrimaryRefProfilePath)103 TEST_F(PathUtilsTest, BuildPrimaryRefProfilePath) {
104 EXPECT_THAT(BuildPrimaryRefProfilePath(PrimaryRefProfilePath{.packageName = "com.android.foo",
105 .profileName = "primary"}),
106 HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof"));
107 }
108
TEST_F(PathUtilsTest,BuildPrimaryRefProfilePathPackageNameOk)109 TEST_F(PathUtilsTest, BuildPrimaryRefProfilePathPackageNameOk) {
110 EXPECT_THAT(BuildPrimaryRefProfilePath(
111 PrimaryRefProfilePath{.packageName = "...", .profileName = "primary"}),
112 HasValue(android_data_ + "/misc/profiles/ref/.../primary.prof"));
113 EXPECT_THAT(BuildPrimaryRefProfilePath(
114 PrimaryRefProfilePath{.packageName = "!@#$%^&*()_+-=", .profileName = "primary"}),
115 HasValue(android_data_ + "/misc/profiles/ref/!@#$%^&*()_+-=/primary.prof"));
116 }
117
TEST_F(PathUtilsTest,BuildPrimaryRefProfilePathPackageNameWrong)118 TEST_F(PathUtilsTest, BuildPrimaryRefProfilePathPackageNameWrong) {
119 EXPECT_THAT(BuildPrimaryRefProfilePath(
120 PrimaryRefProfilePath{.packageName = "", .profileName = "primary"}),
121 HasError(WithMessage("packageName is empty")));
122 EXPECT_THAT(BuildPrimaryRefProfilePath(
123 PrimaryRefProfilePath{.packageName = ".", .profileName = "primary"}),
124 HasError(WithMessage("Invalid packageName '.'")));
125 EXPECT_THAT(BuildPrimaryRefProfilePath(
126 PrimaryRefProfilePath{.packageName = "..", .profileName = "primary"}),
127 HasError(WithMessage("Invalid packageName '..'")));
128 EXPECT_THAT(BuildPrimaryRefProfilePath(
129 PrimaryRefProfilePath{.packageName = "a/b", .profileName = "primary"}),
130 HasError(WithMessage("packageName 'a/b' has invalid character '/'")));
131 EXPECT_THAT(BuildPrimaryRefProfilePath(
132 PrimaryRefProfilePath{.packageName = "a\0b"s, .profileName = "primary"}),
133 HasError(WithMessage("packageName 'a\0b' has invalid character '\\0'"s)));
134 }
135
TEST_F(PathUtilsTest,BuildPrimaryRefProfilePathProfileNameOk)136 TEST_F(PathUtilsTest, BuildPrimaryRefProfilePathProfileNameOk) {
137 EXPECT_THAT(BuildPrimaryRefProfilePath(
138 PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = "."}),
139 HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/..prof"));
140 EXPECT_THAT(BuildPrimaryRefProfilePath(
141 PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = ".."}),
142 HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/...prof"));
143 EXPECT_THAT(BuildPrimaryRefProfilePath(PrimaryRefProfilePath{.packageName = "com.android.foo",
144 .profileName = "!@#$%^&*()_+-="}),
145 HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/!@#$%^&*()_+-=.prof"));
146 }
147
TEST_F(PathUtilsTest,BuildPrimaryRefProfilePathProfileNameWrong)148 TEST_F(PathUtilsTest, BuildPrimaryRefProfilePathProfileNameWrong) {
149 EXPECT_THAT(BuildPrimaryRefProfilePath(
150 PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = ""}),
151 HasError(WithMessage("profileName is empty")));
152 EXPECT_THAT(BuildPrimaryRefProfilePath(
153 PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = "a/b"}),
154 HasError(WithMessage("profileName 'a/b' has invalid character '/'")));
155 EXPECT_THAT(BuildPrimaryRefProfilePath(
156 PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = "a\0b"s}),
157 HasError(WithMessage("profileName 'a\0b' has invalid character '\\0'"s)));
158 }
159
TEST_F(PathUtilsTest,BuildFinalProfilePathForPrimary)160 TEST_F(PathUtilsTest, BuildFinalProfilePathForPrimary) {
161 EXPECT_THAT(BuildFinalProfilePath(TmpProfilePath{
162 .finalPath = PrimaryRefProfilePath{.packageName = "com.android.foo",
163 .profileName = "primary"},
164 .id = "12345"}),
165 HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof"));
166 }
167
TEST_F(PathUtilsTest,BuildFinalProfilePathForSecondary)168 TEST_F(PathUtilsTest, BuildFinalProfilePathForSecondary) {
169 EXPECT_THAT(BuildFinalProfilePath(TmpProfilePath{
170 .finalPath = SecondaryRefProfilePath{.dexPath = android_data_ +
171 "/user/0/com.android.foo/a.apk"},
172 .id = "12345"}),
173 HasValue(android_data_ + "/user/0/com.android.foo/oat/a.apk.prof"));
174 }
175
TEST_F(PathUtilsTest,BuildTmpProfilePathForPrimary)176 TEST_F(PathUtilsTest, BuildTmpProfilePathForPrimary) {
177 EXPECT_THAT(
178 BuildTmpProfilePath(TmpProfilePath{
179 .finalPath =
180 PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = "primary"},
181 .id = "12345"}),
182 HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof.12345.tmp"));
183 }
184
TEST_F(PathUtilsTest,BuildTmpProfilePathForSecondary)185 TEST_F(PathUtilsTest, BuildTmpProfilePathForSecondary) {
186 EXPECT_THAT(BuildTmpProfilePath(TmpProfilePath{
187 .finalPath = SecondaryRefProfilePath{.dexPath = android_data_ +
188 "/user/0/com.android.foo/a.apk"},
189 .id = "12345"}),
190 HasValue(android_data_ + "/user/0/com.android.foo/oat/a.apk.prof.12345.tmp"));
191 }
192
TEST_F(PathUtilsTest,BuildTmpProfilePathIdWrong)193 TEST_F(PathUtilsTest, BuildTmpProfilePathIdWrong) {
194 EXPECT_THAT(BuildTmpProfilePath(TmpProfilePath{
195 .finalPath = PrimaryRefProfilePath{.packageName = "com.android.foo",
196 .profileName = "primary"},
197 .id = ""}),
198 HasError(WithMessage("id is empty")));
199 EXPECT_THAT(BuildTmpProfilePath(TmpProfilePath{
200 .finalPath = PrimaryRefProfilePath{.packageName = "com.android.foo",
201 .profileName = "primary"},
202 .id = "123/45"}),
203 HasError(WithMessage("id '123/45' has invalid character '/'")));
204 EXPECT_THAT(BuildTmpProfilePath(TmpProfilePath{
205 .finalPath = PrimaryRefProfilePath{.packageName = "com.android.foo",
206 .profileName = "primary"},
207 .id = "123\0a"s}),
208 HasError(WithMessage("id '123\0a' has invalid character '\\0'"s)));
209 }
210
TEST_F(PathUtilsTest,BuildPrebuiltProfilePath)211 TEST_F(PathUtilsTest, BuildPrebuiltProfilePath) {
212 EXPECT_THAT(BuildPrebuiltProfilePath(PrebuiltProfilePath{.dexPath = "/a/b.apk"}),
213 HasValue("/a/b.apk.prof"));
214 }
215
TEST_F(PathUtilsTest,BuildPrimaryCurProfilePath)216 TEST_F(PathUtilsTest, BuildPrimaryCurProfilePath) {
217 EXPECT_THAT(BuildPrimaryCurProfilePath(PrimaryCurProfilePath{
218 .userId = 1, .packageName = "com.android.foo", .profileName = "primary"}),
219 HasValue(android_data_ + "/misc/profiles/cur/1/com.android.foo/primary.prof"));
220 }
221
TEST_F(PathUtilsTest,BuildSecondaryRefProfilePath)222 TEST_F(PathUtilsTest, BuildSecondaryRefProfilePath) {
223 EXPECT_THAT(BuildSecondaryRefProfilePath(SecondaryRefProfilePath{
224 .dexPath = android_data_ + "/user/0/com.android.foo/a.apk"}),
225 HasValue(android_data_ + "/user/0/com.android.foo/oat/a.apk.prof"));
226 }
227
TEST_F(PathUtilsTest,BuildSecondaryCurProfilePath)228 TEST_F(PathUtilsTest, BuildSecondaryCurProfilePath) {
229 EXPECT_THAT(BuildSecondaryCurProfilePath(SecondaryCurProfilePath{
230 .dexPath = android_data_ + "/user/0/com.android.foo/a.apk"}),
231 HasValue(android_data_ + "/user/0/com.android.foo/oat/a.apk.cur.prof"));
232 }
233
TEST_F(PathUtilsTest,BuildDexMetadataPath)234 TEST_F(PathUtilsTest, BuildDexMetadataPath) {
235 EXPECT_THAT(BuildDexMetadataPath(DexMetadataPath{.dexPath = "/a/b.apk"}), HasValue("/a/b.dm"));
236 }
237
TEST_F(PathUtilsTest,BuildProfilePath)238 TEST_F(PathUtilsTest, BuildProfilePath) {
239 EXPECT_THAT(BuildProfileOrDmPath(PrimaryRefProfilePath{.packageName = "com.android.foo",
240 .profileName = "primary"}),
241 HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof"));
242 EXPECT_THAT(
243 BuildProfileOrDmPath(TmpProfilePath{
244 .finalPath =
245 PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = "primary"},
246 .id = "12345"}),
247 HasValue(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof.12345.tmp"));
248 EXPECT_THAT(BuildProfileOrDmPath(PrebuiltProfilePath{.dexPath = "/a/b.apk"}),
249 HasValue("/a/b.apk.prof"));
250 EXPECT_THAT(BuildProfileOrDmPath(PrimaryCurProfilePath{
251 .userId = 1, .packageName = "com.android.foo", .profileName = "primary"}),
252 HasValue(android_data_ + "/misc/profiles/cur/1/com.android.foo/primary.prof"));
253 EXPECT_THAT(BuildProfileOrDmPath(DexMetadataPath{.dexPath = "/a/b.apk"}), HasValue("/a/b.dm"));
254 }
255
TEST_F(PathUtilsTest,BuildVdexPath)256 TEST_F(PathUtilsTest, BuildVdexPath) {
257 EXPECT_THAT(
258 BuildVdexPath(ArtifactsPath{.dexPath = "/a/b.apk", .isa = "arm64", .isInDalvikCache = false}),
259 HasValue("/a/oat/arm64/b.vdex"));
260 }
261
262 } // namespace
263 } // namespace artd
264 } // namespace art
265