• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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