1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2022 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #include "artd.h"
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include <fcntl.h>
20*795d594fSAndroid Build Coastguard Worker #include <stdlib.h>
21*795d594fSAndroid Build Coastguard Worker #include <sys/stat.h>
22*795d594fSAndroid Build Coastguard Worker #include <sys/types.h>
23*795d594fSAndroid Build Coastguard Worker #include <unistd.h>
24*795d594fSAndroid Build Coastguard Worker
25*795d594fSAndroid Build Coastguard Worker #include <algorithm>
26*795d594fSAndroid Build Coastguard Worker #include <chrono>
27*795d594fSAndroid Build Coastguard Worker #include <condition_variable>
28*795d594fSAndroid Build Coastguard Worker #include <csignal>
29*795d594fSAndroid Build Coastguard Worker #include <cstdint>
30*795d594fSAndroid Build Coastguard Worker #include <cstdio>
31*795d594fSAndroid Build Coastguard Worker #include <cstring>
32*795d594fSAndroid Build Coastguard Worker #include <filesystem>
33*795d594fSAndroid Build Coastguard Worker #include <functional>
34*795d594fSAndroid Build Coastguard Worker #include <memory>
35*795d594fSAndroid Build Coastguard Worker #include <mutex>
36*795d594fSAndroid Build Coastguard Worker #include <optional>
37*795d594fSAndroid Build Coastguard Worker #include <string>
38*795d594fSAndroid Build Coastguard Worker #include <thread>
39*795d594fSAndroid Build Coastguard Worker #include <tuple>
40*795d594fSAndroid Build Coastguard Worker #include <type_traits>
41*795d594fSAndroid Build Coastguard Worker #include <utility>
42*795d594fSAndroid Build Coastguard Worker #include <vector>
43*795d594fSAndroid Build Coastguard Worker
44*795d594fSAndroid Build Coastguard Worker #include "aidl/com/android/server/art/ArtConstants.h"
45*795d594fSAndroid Build Coastguard Worker #include "aidl/com/android/server/art/BnArtd.h"
46*795d594fSAndroid Build Coastguard Worker #include "android-base/collections.h"
47*795d594fSAndroid Build Coastguard Worker #include "android-base/errors.h"
48*795d594fSAndroid Build Coastguard Worker #include "android-base/file.h"
49*795d594fSAndroid Build Coastguard Worker #include "android-base/logging.h"
50*795d594fSAndroid Build Coastguard Worker #include "android-base/parseint.h"
51*795d594fSAndroid Build Coastguard Worker #include "android-base/result-gmock.h"
52*795d594fSAndroid Build Coastguard Worker #include "android-base/result.h"
53*795d594fSAndroid Build Coastguard Worker #include "android-base/scopeguard.h"
54*795d594fSAndroid Build Coastguard Worker #include "android-base/strings.h"
55*795d594fSAndroid Build Coastguard Worker #include "android/binder_auto_utils.h"
56*795d594fSAndroid Build Coastguard Worker #include "android/binder_status.h"
57*795d594fSAndroid Build Coastguard Worker #include "base/array_ref.h"
58*795d594fSAndroid Build Coastguard Worker #include "base/common_art_test.h"
59*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
60*795d594fSAndroid Build Coastguard Worker #include "base/pidfd.h"
61*795d594fSAndroid Build Coastguard Worker #include "exec_utils.h"
62*795d594fSAndroid Build Coastguard Worker #include "file_utils.h"
63*795d594fSAndroid Build Coastguard Worker #include "gmock/gmock.h"
64*795d594fSAndroid Build Coastguard Worker #include "gtest/gtest.h"
65*795d594fSAndroid Build Coastguard Worker #include "oat/oat_file.h"
66*795d594fSAndroid Build Coastguard Worker #include "path_utils.h"
67*795d594fSAndroid Build Coastguard Worker #include "profile/profile_compilation_info.cc"
68*795d594fSAndroid Build Coastguard Worker #include "profman/profman_result.h"
69*795d594fSAndroid Build Coastguard Worker #include "testing.h"
70*795d594fSAndroid Build Coastguard Worker #include "tools/binder_utils.h"
71*795d594fSAndroid Build Coastguard Worker #include "tools/system_properties.h"
72*795d594fSAndroid Build Coastguard Worker #include "tools/testing.h"
73*795d594fSAndroid Build Coastguard Worker #include "vdex_file.h"
74*795d594fSAndroid Build Coastguard Worker #include "ziparchive/zip_writer.h"
75*795d594fSAndroid Build Coastguard Worker
76*795d594fSAndroid Build Coastguard Worker extern char** environ;
77*795d594fSAndroid Build Coastguard Worker
78*795d594fSAndroid Build Coastguard Worker namespace art {
79*795d594fSAndroid Build Coastguard Worker namespace artd {
80*795d594fSAndroid Build Coastguard Worker namespace {
81*795d594fSAndroid Build Coastguard Worker
82*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::ArtConstants;
83*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::ArtdDexoptResult;
84*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::ArtifactsPath;
85*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::CopyAndRewriteProfileResult;
86*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::DexMetadataPath;
87*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::DexoptOptions;
88*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::FileVisibility;
89*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::FsPermission;
90*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::IArtdCancellationSignal;
91*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::IArtdNotification;
92*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::OutputArtifacts;
93*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::OutputProfile;
94*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::PriorityClass;
95*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::ProfilePath;
96*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::RuntimeArtifactsPath;
97*795d594fSAndroid Build Coastguard Worker using ::aidl::com::android::server::art::VdexPath;
98*795d594fSAndroid Build Coastguard Worker using ::android::base::Append;
99*795d594fSAndroid Build Coastguard Worker using ::android::base::Dirname;
100*795d594fSAndroid Build Coastguard Worker using ::android::base::Error;
101*795d594fSAndroid Build Coastguard Worker using ::android::base::make_scope_guard;
102*795d594fSAndroid Build Coastguard Worker using ::android::base::ParseInt;
103*795d594fSAndroid Build Coastguard Worker using ::android::base::ReadFdToString;
104*795d594fSAndroid Build Coastguard Worker using ::android::base::ReadFileToString;
105*795d594fSAndroid Build Coastguard Worker using ::android::base::Result;
106*795d594fSAndroid Build Coastguard Worker using ::android::base::ScopeGuard;
107*795d594fSAndroid Build Coastguard Worker using ::android::base::Split;
108*795d594fSAndroid Build Coastguard Worker using ::android::base::WriteStringToFd;
109*795d594fSAndroid Build Coastguard Worker using ::android::base::WriteStringToFile;
110*795d594fSAndroid Build Coastguard Worker using ::android::base::testing::HasValue;
111*795d594fSAndroid Build Coastguard Worker using ::art::tools::GetBin;
112*795d594fSAndroid Build Coastguard Worker using ::art::tools::ScopedExec;
113*795d594fSAndroid Build Coastguard Worker using ::testing::_;
114*795d594fSAndroid Build Coastguard Worker using ::testing::AllOf;
115*795d594fSAndroid Build Coastguard Worker using ::testing::AnyNumber;
116*795d594fSAndroid Build Coastguard Worker using ::testing::AnyOf;
117*795d594fSAndroid Build Coastguard Worker using ::testing::Contains;
118*795d594fSAndroid Build Coastguard Worker using ::testing::ContainsRegex;
119*795d594fSAndroid Build Coastguard Worker using ::testing::DoAll;
120*795d594fSAndroid Build Coastguard Worker using ::testing::ElementsAre;
121*795d594fSAndroid Build Coastguard Worker using ::testing::Field;
122*795d594fSAndroid Build Coastguard Worker using ::testing::HasSubstr;
123*795d594fSAndroid Build Coastguard Worker using ::testing::InSequence;
124*795d594fSAndroid Build Coastguard Worker using ::testing::IsEmpty;
125*795d594fSAndroid Build Coastguard Worker using ::testing::Matcher;
126*795d594fSAndroid Build Coastguard Worker using ::testing::MockFunction;
127*795d594fSAndroid Build Coastguard Worker using ::testing::NiceMock;
128*795d594fSAndroid Build Coastguard Worker using ::testing::Not;
129*795d594fSAndroid Build Coastguard Worker using ::testing::Property;
130*795d594fSAndroid Build Coastguard Worker using ::testing::ResultOf;
131*795d594fSAndroid Build Coastguard Worker using ::testing::Return;
132*795d594fSAndroid Build Coastguard Worker using ::testing::SetArgPointee;
133*795d594fSAndroid Build Coastguard Worker using ::testing::StrEq;
134*795d594fSAndroid Build Coastguard Worker using ::testing::UnorderedElementsAreArray;
135*795d594fSAndroid Build Coastguard Worker using ::testing::WithArg;
136*795d594fSAndroid Build Coastguard Worker
137*795d594fSAndroid Build Coastguard Worker using PrimaryCurProfilePath = ProfilePath::PrimaryCurProfilePath;
138*795d594fSAndroid Build Coastguard Worker using PrimaryRefProfilePath = ProfilePath::PrimaryRefProfilePath;
139*795d594fSAndroid Build Coastguard Worker using TmpProfilePath = ProfilePath::TmpProfilePath;
140*795d594fSAndroid Build Coastguard Worker using WritableProfilePath = ProfilePath::WritableProfilePath;
141*795d594fSAndroid Build Coastguard Worker
142*795d594fSAndroid Build Coastguard Worker using std::literals::operator""s; // NOLINT
143*795d594fSAndroid Build Coastguard Worker
144*795d594fSAndroid Build Coastguard Worker // User build is missing the SELinux permission for the test process (run as `shell`) to reopen
145*795d594fSAndroid Build Coastguard Worker // the memfd that it creates itself
146*795d594fSAndroid Build Coastguard Worker // (https://cs.android.com/android/platform/superproject/main/+/main:system/sepolicy/private/shell.te;l=221;drc=3335a04676d400bda57d42d4af0ef4b1d311de21).
147*795d594fSAndroid Build Coastguard Worker #define TEST_DISABLED_FOR_SHELL_WITHOUT_MEMFD_ACCESS() TEST_DISABLED_FOR_USER_BUILD()
148*795d594fSAndroid Build Coastguard Worker
ScopedSetLogger(android::base::LogFunction && logger)149*795d594fSAndroid Build Coastguard Worker ScopeGuard<std::function<void()>> ScopedSetLogger(android::base::LogFunction&& logger) {
150*795d594fSAndroid Build Coastguard Worker android::base::LogFunction old_logger = android::base::SetLogger(std::move(logger));
151*795d594fSAndroid Build Coastguard Worker return make_scope_guard([old_logger = std::move(old_logger)]() mutable {
152*795d594fSAndroid Build Coastguard Worker android::base::SetLogger(std::move(old_logger));
153*795d594fSAndroid Build Coastguard Worker });
154*795d594fSAndroid Build Coastguard Worker }
155*795d594fSAndroid Build Coastguard Worker
CheckContent(const std::string & path,const std::string & expected_content)156*795d594fSAndroid Build Coastguard Worker void CheckContent(const std::string& path, const std::string& expected_content) {
157*795d594fSAndroid Build Coastguard Worker std::string actual_content;
158*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(ReadFileToString(path, &actual_content));
159*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(actual_content, expected_content);
160*795d594fSAndroid Build Coastguard Worker }
161*795d594fSAndroid Build Coastguard Worker
CheckOtherReadable(const std::string & path,bool expected_value)162*795d594fSAndroid Build Coastguard Worker void CheckOtherReadable(const std::string& path, bool expected_value) {
163*795d594fSAndroid Build Coastguard Worker EXPECT_EQ((std::filesystem::status(path).permissions() & std::filesystem::perms::others_read) !=
164*795d594fSAndroid Build Coastguard Worker std::filesystem::perms::none,
165*795d594fSAndroid Build Coastguard Worker expected_value);
166*795d594fSAndroid Build Coastguard Worker }
167*795d594fSAndroid Build Coastguard Worker
GetFlagValues(ArrayRef<const std::string> args,std::string_view flag)168*795d594fSAndroid Build Coastguard Worker Result<std::vector<std::string>> GetFlagValues(ArrayRef<const std::string> args,
169*795d594fSAndroid Build Coastguard Worker std::string_view flag) {
170*795d594fSAndroid Build Coastguard Worker std::vector<std::string> values;
171*795d594fSAndroid Build Coastguard Worker for (const std::string& arg : args) {
172*795d594fSAndroid Build Coastguard Worker std::string_view value(arg);
173*795d594fSAndroid Build Coastguard Worker if (android::base::ConsumePrefix(&value, flag)) {
174*795d594fSAndroid Build Coastguard Worker values.emplace_back(value);
175*795d594fSAndroid Build Coastguard Worker }
176*795d594fSAndroid Build Coastguard Worker }
177*795d594fSAndroid Build Coastguard Worker if (values.empty()) {
178*795d594fSAndroid Build Coastguard Worker return Errorf("Flag '{}' not found", flag);
179*795d594fSAndroid Build Coastguard Worker }
180*795d594fSAndroid Build Coastguard Worker return values;
181*795d594fSAndroid Build Coastguard Worker }
182*795d594fSAndroid Build Coastguard Worker
GetFlagValue(ArrayRef<const std::string> args,std::string_view flag)183*795d594fSAndroid Build Coastguard Worker Result<std::string> GetFlagValue(ArrayRef<const std::string> args, std::string_view flag) {
184*795d594fSAndroid Build Coastguard Worker std::vector<std::string> flag_values = OR_RETURN(GetFlagValues(args, flag));
185*795d594fSAndroid Build Coastguard Worker if (flag_values.size() > 1) {
186*795d594fSAndroid Build Coastguard Worker return Errorf("Duplicate flag '{}'", flag);
187*795d594fSAndroid Build Coastguard Worker }
188*795d594fSAndroid Build Coastguard Worker return flag_values[0];
189*795d594fSAndroid Build Coastguard Worker }
190*795d594fSAndroid Build Coastguard Worker
WriteToFdFlagImpl(const std::vector<std::string> & args,std::string_view flag,std::string_view content,bool assume_empty)191*795d594fSAndroid Build Coastguard Worker void WriteToFdFlagImpl(const std::vector<std::string>& args,
192*795d594fSAndroid Build Coastguard Worker std::string_view flag,
193*795d594fSAndroid Build Coastguard Worker std::string_view content,
194*795d594fSAndroid Build Coastguard Worker bool assume_empty) {
195*795d594fSAndroid Build Coastguard Worker std::string value = OR_FAIL(GetFlagValue(ArrayRef<const std::string>(args), flag));
196*795d594fSAndroid Build Coastguard Worker ASSERT_NE(value, "");
197*795d594fSAndroid Build Coastguard Worker int fd;
198*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(ParseInt(value, &fd));
199*795d594fSAndroid Build Coastguard Worker if (assume_empty) {
200*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(lseek(fd, /*offset=*/0, SEEK_CUR), 0);
201*795d594fSAndroid Build Coastguard Worker } else {
202*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ftruncate(fd, /*length=*/0), 0);
203*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(lseek(fd, /*offset=*/0, SEEK_SET), 0);
204*795d594fSAndroid Build Coastguard Worker }
205*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(WriteStringToFd(content, fd));
206*795d594fSAndroid Build Coastguard Worker }
207*795d594fSAndroid Build Coastguard Worker
208*795d594fSAndroid Build Coastguard Worker // Writes `content` to the FD specified by the `flag`.
ACTION_P(WriteToFdFlag,flag,content)209*795d594fSAndroid Build Coastguard Worker ACTION_P(WriteToFdFlag, flag, content) {
210*795d594fSAndroid Build Coastguard Worker WriteToFdFlagImpl(arg0, flag, content, /*assume_empty=*/true);
211*795d594fSAndroid Build Coastguard Worker }
212*795d594fSAndroid Build Coastguard Worker
213*795d594fSAndroid Build Coastguard Worker // Clears any existing content and writes `content` to the FD specified by the `flag`.
ACTION_P(ClearAndWriteToFdFlag,flag,content)214*795d594fSAndroid Build Coastguard Worker ACTION_P(ClearAndWriteToFdFlag, flag, content) {
215*795d594fSAndroid Build Coastguard Worker WriteToFdFlagImpl(arg0, flag, content, /*assume_empty=*/false);
216*795d594fSAndroid Build Coastguard Worker }
217*795d594fSAndroid Build Coastguard Worker
218*795d594fSAndroid Build Coastguard Worker // Matches a flag that starts with `flag` and whose value matches `matcher`.
219*795d594fSAndroid Build Coastguard Worker MATCHER_P2(Flag, flag, matcher, "") {
220*795d594fSAndroid Build Coastguard Worker std::string_view value(arg);
221*795d594fSAndroid Build Coastguard Worker if (!android::base::ConsumePrefix(&value, flag)) {
222*795d594fSAndroid Build Coastguard Worker return false;
223*795d594fSAndroid Build Coastguard Worker }
224*795d594fSAndroid Build Coastguard Worker return ExplainMatchResult(matcher, std::string(value), result_listener);
225*795d594fSAndroid Build Coastguard Worker }
226*795d594fSAndroid Build Coastguard Worker
227*795d594fSAndroid Build Coastguard Worker // Matches a flag that starts with `flag` and whose value is a colon-separated list that matches
228*795d594fSAndroid Build Coastguard Worker // `matcher`. The matcher acts on an `std::vector<std::string>` of the split list argument.
229*795d594fSAndroid Build Coastguard Worker MATCHER_P2(ListFlag, flag, matcher, "") {
230*795d594fSAndroid Build Coastguard Worker return ExplainMatchResult(
231*795d594fSAndroid Build Coastguard Worker Flag(flag, ResultOf(std::bind(Split, std::placeholders::_1, ":"), matcher)),
232*795d594fSAndroid Build Coastguard Worker arg,
233*795d594fSAndroid Build Coastguard Worker result_listener);
234*795d594fSAndroid Build Coastguard Worker }
235*795d594fSAndroid Build Coastguard Worker
236*795d594fSAndroid Build Coastguard Worker // Matches an FD of a file whose path matches `matcher`.
237*795d594fSAndroid Build Coastguard Worker MATCHER_P(FdOf, matcher, "") {
238*795d594fSAndroid Build Coastguard Worker std::string proc_path = ART_FORMAT("/proc/self/fd/{}", arg);
239*795d594fSAndroid Build Coastguard Worker char path[PATH_MAX];
240*795d594fSAndroid Build Coastguard Worker ssize_t len = readlink(proc_path.c_str(), path, sizeof(path));
241*795d594fSAndroid Build Coastguard Worker if (len < 0) {
242*795d594fSAndroid Build Coastguard Worker return false;
243*795d594fSAndroid Build Coastguard Worker }
244*795d594fSAndroid Build Coastguard Worker return ExplainMatchResult(matcher, std::string(path, static_cast<size_t>(len)), result_listener);
245*795d594fSAndroid Build Coastguard Worker }
246*795d594fSAndroid Build Coastguard Worker
247*795d594fSAndroid Build Coastguard Worker // Matches an FD of a file whose content matches `matcher`.
248*795d594fSAndroid Build Coastguard Worker MATCHER_P(FdHasContent, matcher, "") {
249*795d594fSAndroid Build Coastguard Worker int fd;
250*795d594fSAndroid Build Coastguard Worker if (!ParseInt(arg, &fd)) {
251*795d594fSAndroid Build Coastguard Worker return false;
252*795d594fSAndroid Build Coastguard Worker }
253*795d594fSAndroid Build Coastguard Worker std::string actual_content;
254*795d594fSAndroid Build Coastguard Worker if (!ReadFdToString(fd, &actual_content)) {
255*795d594fSAndroid Build Coastguard Worker return false;
256*795d594fSAndroid Build Coastguard Worker }
257*795d594fSAndroid Build Coastguard Worker return ExplainMatchResult(matcher, actual_content, result_listener);
258*795d594fSAndroid Build Coastguard Worker }
259*795d594fSAndroid Build Coastguard Worker
260*795d594fSAndroid Build Coastguard Worker template <typename T, typename U>
SplitBy(const std::vector<T> & list,const U & separator)261*795d594fSAndroid Build Coastguard Worker Result<std::pair<ArrayRef<const T>, ArrayRef<const T>>> SplitBy(const std::vector<T>& list,
262*795d594fSAndroid Build Coastguard Worker const U& separator) {
263*795d594fSAndroid Build Coastguard Worker auto it = std::find(list.begin(), list.end(), separator);
264*795d594fSAndroid Build Coastguard Worker if (it == list.end()) {
265*795d594fSAndroid Build Coastguard Worker return Errorf("'{}' not found", separator);
266*795d594fSAndroid Build Coastguard Worker }
267*795d594fSAndroid Build Coastguard Worker size_t pos = it - list.begin();
268*795d594fSAndroid Build Coastguard Worker return std::make_pair(ArrayRef<const T>(list).SubArray(0, pos),
269*795d594fSAndroid Build Coastguard Worker ArrayRef<const T>(list).SubArray(pos + 1));
270*795d594fSAndroid Build Coastguard Worker }
271*795d594fSAndroid Build Coastguard Worker
272*795d594fSAndroid Build Coastguard Worker // Matches a container that, when split by `separator`, the first part matches `head_matcher`, and
273*795d594fSAndroid Build Coastguard Worker // the second part matches `tail_matcher`.
274*795d594fSAndroid Build Coastguard Worker MATCHER_P3(WhenSplitBy, separator, head_matcher, tail_matcher, "") {
275*795d594fSAndroid Build Coastguard Worker auto [head, tail] = OR_MISMATCH(SplitBy(arg, separator));
276*795d594fSAndroid Build Coastguard Worker return ExplainMatchResult(head_matcher, head, result_listener) &&
277*795d594fSAndroid Build Coastguard Worker ExplainMatchResult(tail_matcher, tail, result_listener);
278*795d594fSAndroid Build Coastguard Worker }
279*795d594fSAndroid Build Coastguard Worker
280*795d594fSAndroid Build Coastguard Worker MATCHER_P(HasKeepFdsForImpl, fd_flags, "") {
281*795d594fSAndroid Build Coastguard Worker auto [head, tail] = OR_MISMATCH(SplitBy(arg, "--"));
282*795d594fSAndroid Build Coastguard Worker std::string keep_fds_value = OR_MISMATCH(GetFlagValue(head, "--keep-fds="));
283*795d594fSAndroid Build Coastguard Worker std::vector<std::string> keep_fds = Split(keep_fds_value, ":");
284*795d594fSAndroid Build Coastguard Worker std::vector<std::string> fd_flag_values;
285*795d594fSAndroid Build Coastguard Worker for (std::string_view fd_flag : fd_flags) {
286*795d594fSAndroid Build Coastguard Worker for (const std::string& fd_flag_value : OR_MISMATCH(GetFlagValues(tail, fd_flag))) {
287*795d594fSAndroid Build Coastguard Worker for (std::string& fd : Split(fd_flag_value, ":")) {
288*795d594fSAndroid Build Coastguard Worker fd_flag_values.push_back(std::move(fd));
289*795d594fSAndroid Build Coastguard Worker }
290*795d594fSAndroid Build Coastguard Worker }
291*795d594fSAndroid Build Coastguard Worker }
292*795d594fSAndroid Build Coastguard Worker return ExplainMatchResult(UnorderedElementsAreArray(fd_flag_values), keep_fds, result_listener);
293*795d594fSAndroid Build Coastguard Worker }
294*795d594fSAndroid Build Coastguard Worker
295*795d594fSAndroid Build Coastguard Worker // Matches an argument list that has the "--keep-fds=" flag before "--", whose value is a
296*795d594fSAndroid Build Coastguard Worker // semicolon-separated list that contains exactly the values of the given flags after "--".
297*795d594fSAndroid Build Coastguard Worker //
298*795d594fSAndroid Build Coastguard Worker // E.g., if the flags after "--" are "--foo=1", "--bar=2:3", "--baz=4", "--baz=5", and the matcher
299*795d594fSAndroid Build Coastguard Worker // is `HasKeepFdsFor("--foo=", "--bar=", "--baz=")`, then it requires the "--keep-fds=" flag before
300*795d594fSAndroid Build Coastguard Worker // "--" to contain exactly 1, 2, 3, 4, and 5.
301*795d594fSAndroid Build Coastguard Worker template <typename... Args>
HasKeepFdsFor(Args &&...args)302*795d594fSAndroid Build Coastguard Worker auto HasKeepFdsFor(Args&&... args) {
303*795d594fSAndroid Build Coastguard Worker std::vector<std::string_view> fd_flags;
304*795d594fSAndroid Build Coastguard Worker Append(fd_flags, std::forward<Args>(args)...);
305*795d594fSAndroid Build Coastguard Worker return HasKeepFdsForImpl(fd_flags);
306*795d594fSAndroid Build Coastguard Worker }
307*795d594fSAndroid Build Coastguard Worker
308*795d594fSAndroid Build Coastguard Worker class MockSystemProperties : public tools::SystemProperties {
309*795d594fSAndroid Build Coastguard Worker public:
310*795d594fSAndroid Build Coastguard Worker MOCK_METHOD(std::string, GetProperty, (const std::string& key), (const, override));
311*795d594fSAndroid Build Coastguard Worker };
312*795d594fSAndroid Build Coastguard Worker
313*795d594fSAndroid Build Coastguard Worker class MockExecUtils : public ExecUtils {
314*795d594fSAndroid Build Coastguard Worker public:
315*795d594fSAndroid Build Coastguard Worker // A workaround to avoid MOCK_METHOD on a method with an `std::string*` parameter, which will lead
316*795d594fSAndroid Build Coastguard Worker // to a conflict between gmock and android-base/logging.h (b/132668253).
ExecAndReturnResult(const std::vector<std::string> & arg_vector,int,const ExecCallbacks & callbacks,bool,ProcessStat * stat,std::string *) const317*795d594fSAndroid Build Coastguard Worker ExecResult ExecAndReturnResult(const std::vector<std::string>& arg_vector,
318*795d594fSAndroid Build Coastguard Worker int,
319*795d594fSAndroid Build Coastguard Worker const ExecCallbacks& callbacks,
320*795d594fSAndroid Build Coastguard Worker bool,
321*795d594fSAndroid Build Coastguard Worker ProcessStat* stat,
322*795d594fSAndroid Build Coastguard Worker std::string*) const override {
323*795d594fSAndroid Build Coastguard Worker Result<int> code = DoExecAndReturnCode(arg_vector, callbacks, stat);
324*795d594fSAndroid Build Coastguard Worker if (code.ok()) {
325*795d594fSAndroid Build Coastguard Worker return {.status = ExecResult::kExited, .exit_code = code.value()};
326*795d594fSAndroid Build Coastguard Worker } else {
327*795d594fSAndroid Build Coastguard Worker return {.status = ExecResult::kSignaled, .signal = SIGKILL};
328*795d594fSAndroid Build Coastguard Worker }
329*795d594fSAndroid Build Coastguard Worker }
330*795d594fSAndroid Build Coastguard Worker
331*795d594fSAndroid Build Coastguard Worker MOCK_METHOD(Result<int>,
332*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode,
333*795d594fSAndroid Build Coastguard Worker (const std::vector<std::string>& arg_vector,
334*795d594fSAndroid Build Coastguard Worker const ExecCallbacks& callbacks,
335*795d594fSAndroid Build Coastguard Worker ProcessStat* stat),
336*795d594fSAndroid Build Coastguard Worker (const));
337*795d594fSAndroid Build Coastguard Worker };
338*795d594fSAndroid Build Coastguard Worker
339*795d594fSAndroid Build Coastguard Worker class ArtdTest : public CommonArtTest {
340*795d594fSAndroid Build Coastguard Worker protected:
SetUp()341*795d594fSAndroid Build Coastguard Worker void SetUp() override {
342*795d594fSAndroid Build Coastguard Worker CommonArtTest::SetUp();
343*795d594fSAndroid Build Coastguard Worker auto mock_props = std::make_unique<MockSystemProperties>();
344*795d594fSAndroid Build Coastguard Worker mock_props_ = mock_props.get();
345*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props_, GetProperty).Times(AnyNumber()).WillRepeatedly(Return(""));
346*795d594fSAndroid Build Coastguard Worker auto mock_exec_utils = std::make_unique<MockExecUtils>();
347*795d594fSAndroid Build Coastguard Worker mock_exec_utils_ = mock_exec_utils.get();
348*795d594fSAndroid Build Coastguard Worker artd_ = ndk::SharedRefBase::make<Artd>(Options(),
349*795d594fSAndroid Build Coastguard Worker std::move(mock_props),
350*795d594fSAndroid Build Coastguard Worker std::move(mock_exec_utils),
351*795d594fSAndroid Build Coastguard Worker mock_kill_.AsStdFunction(),
352*795d594fSAndroid Build Coastguard Worker mock_fstat_.AsStdFunction(),
353*795d594fSAndroid Build Coastguard Worker mock_poll_.AsStdFunction());
354*795d594fSAndroid Build Coastguard Worker scratch_dir_ = std::make_unique<ScratchDir>();
355*795d594fSAndroid Build Coastguard Worker scratch_path_ = scratch_dir_->GetPath();
356*795d594fSAndroid Build Coastguard Worker // Remove the trailing '/';
357*795d594fSAndroid Build Coastguard Worker scratch_path_.resize(scratch_path_.length() - 1);
358*795d594fSAndroid Build Coastguard Worker
359*795d594fSAndroid Build Coastguard Worker TestOnlySetListRootDir(scratch_path_);
360*795d594fSAndroid Build Coastguard Worker
361*795d594fSAndroid Build Coastguard Worker ON_CALL(mock_fstat_, Call).WillByDefault(fstat);
362*795d594fSAndroid Build Coastguard Worker
363*795d594fSAndroid Build Coastguard Worker // Use an arbitrary existing directory as ART root.
364*795d594fSAndroid Build Coastguard Worker art_root_ = scratch_path_ + "/com.android.art";
365*795d594fSAndroid Build Coastguard Worker std::filesystem::create_directories(art_root_);
366*795d594fSAndroid Build Coastguard Worker setenv("ANDROID_ART_ROOT", art_root_.c_str(), /*overwrite=*/1);
367*795d594fSAndroid Build Coastguard Worker
368*795d594fSAndroid Build Coastguard Worker // Use an arbitrary existing directory as Android data.
369*795d594fSAndroid Build Coastguard Worker android_data_ = scratch_path_ + "/data";
370*795d594fSAndroid Build Coastguard Worker std::filesystem::create_directories(android_data_);
371*795d594fSAndroid Build Coastguard Worker setenv("ANDROID_DATA", android_data_.c_str(), /*overwrite=*/1);
372*795d594fSAndroid Build Coastguard Worker
373*795d594fSAndroid Build Coastguard Worker // Use an arbitrary existing directory as Android expand.
374*795d594fSAndroid Build Coastguard Worker android_expand_ = scratch_path_ + "/mnt/expand";
375*795d594fSAndroid Build Coastguard Worker std::filesystem::create_directories(android_expand_);
376*795d594fSAndroid Build Coastguard Worker setenv("ANDROID_EXPAND", android_expand_.c_str(), /*overwrite=*/1);
377*795d594fSAndroid Build Coastguard Worker
378*795d594fSAndroid Build Coastguard Worker dex_file_ = scratch_path_ + "/a/b.apk";
379*795d594fSAndroid Build Coastguard Worker isa_ = "arm64";
380*795d594fSAndroid Build Coastguard Worker artifacts_path_ = ArtifactsPath{
381*795d594fSAndroid Build Coastguard Worker .dexPath = dex_file_,
382*795d594fSAndroid Build Coastguard Worker .isa = isa_,
383*795d594fSAndroid Build Coastguard Worker .isInDalvikCache = false,
384*795d594fSAndroid Build Coastguard Worker };
385*795d594fSAndroid Build Coastguard Worker struct stat st;
386*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(stat(scratch_path_.c_str(), &st), 0);
387*795d594fSAndroid Build Coastguard Worker output_artifacts_ = OutputArtifacts{
388*795d594fSAndroid Build Coastguard Worker .artifactsPath = artifacts_path_,
389*795d594fSAndroid Build Coastguard Worker .permissionSettings =
390*795d594fSAndroid Build Coastguard Worker OutputArtifacts::PermissionSettings{
391*795d594fSAndroid Build Coastguard Worker .dirFsPermission =
392*795d594fSAndroid Build Coastguard Worker FsPermission{
393*795d594fSAndroid Build Coastguard Worker .uid = static_cast<int32_t>(st.st_uid),
394*795d594fSAndroid Build Coastguard Worker .gid = static_cast<int32_t>(st.st_gid),
395*795d594fSAndroid Build Coastguard Worker .isOtherReadable = true,
396*795d594fSAndroid Build Coastguard Worker .isOtherExecutable = true,
397*795d594fSAndroid Build Coastguard Worker },
398*795d594fSAndroid Build Coastguard Worker .fileFsPermission =
399*795d594fSAndroid Build Coastguard Worker FsPermission{
400*795d594fSAndroid Build Coastguard Worker .uid = static_cast<int32_t>(st.st_uid),
401*795d594fSAndroid Build Coastguard Worker .gid = static_cast<int32_t>(st.st_gid),
402*795d594fSAndroid Build Coastguard Worker .isOtherReadable = true,
403*795d594fSAndroid Build Coastguard Worker },
404*795d594fSAndroid Build Coastguard Worker },
405*795d594fSAndroid Build Coastguard Worker };
406*795d594fSAndroid Build Coastguard Worker clc_1_ = GetTestDexFileName("Main");
407*795d594fSAndroid Build Coastguard Worker clc_2_ = GetTestDexFileName("Nested");
408*795d594fSAndroid Build Coastguard Worker class_loader_context_ = ART_FORMAT("PCL[{}:{}]", clc_1_, clc_2_);
409*795d594fSAndroid Build Coastguard Worker compiler_filter_ = "speed";
410*795d594fSAndroid Build Coastguard Worker tmp_profile_path_ =
411*795d594fSAndroid Build Coastguard Worker TmpProfilePath{.finalPath = PrimaryRefProfilePath{.packageName = "com.android.foo",
412*795d594fSAndroid Build Coastguard Worker .profileName = "primary",
413*795d594fSAndroid Build Coastguard Worker .isPreReboot = false},
414*795d594fSAndroid Build Coastguard Worker .id = "12345"};
415*795d594fSAndroid Build Coastguard Worker profile_path_ = tmp_profile_path_;
416*795d594fSAndroid Build Coastguard Worker vdex_path_ = artifacts_path_;
417*795d594fSAndroid Build Coastguard Worker dm_path_ = DexMetadataPath{.dexPath = dex_file_};
418*795d594fSAndroid Build Coastguard Worker std::filesystem::create_directories(
419*795d594fSAndroid Build Coastguard Worker std::filesystem::path(OR_FATAL(BuildFinalProfilePath(tmp_profile_path_))).parent_path());
420*795d594fSAndroid Build Coastguard Worker }
421*795d594fSAndroid Build Coastguard Worker
TearDown()422*795d594fSAndroid Build Coastguard Worker void TearDown() override {
423*795d594fSAndroid Build Coastguard Worker scratch_dir_.reset();
424*795d594fSAndroid Build Coastguard Worker CommonArtTest::TearDown();
425*795d594fSAndroid Build Coastguard Worker }
426*795d594fSAndroid Build Coastguard Worker
RunDexopt(binder_exception_t expected_status=EX_NONE,Matcher<ArtdDexoptResult> aidl_return_matcher=Field (& ArtdDexoptResult::cancelled,false),std::shared_ptr<IArtdCancellationSignal> cancellation_signal=nullptr)427*795d594fSAndroid Build Coastguard Worker void RunDexopt(binder_exception_t expected_status = EX_NONE,
428*795d594fSAndroid Build Coastguard Worker Matcher<ArtdDexoptResult> aidl_return_matcher = Field(&ArtdDexoptResult::cancelled,
429*795d594fSAndroid Build Coastguard Worker false),
430*795d594fSAndroid Build Coastguard Worker std::shared_ptr<IArtdCancellationSignal> cancellation_signal = nullptr) {
431*795d594fSAndroid Build Coastguard Worker RunDexopt(Property(&ndk::ScopedAStatus::getExceptionCode, expected_status),
432*795d594fSAndroid Build Coastguard Worker std::move(aidl_return_matcher),
433*795d594fSAndroid Build Coastguard Worker std::move(cancellation_signal));
434*795d594fSAndroid Build Coastguard Worker }
435*795d594fSAndroid Build Coastguard Worker
RunDexopt(Matcher<ndk::ScopedAStatus> status_matcher,Matcher<ArtdDexoptResult> aidl_return_matcher=Field (& ArtdDexoptResult::cancelled,false),std::shared_ptr<IArtdCancellationSignal> cancellation_signal=nullptr)436*795d594fSAndroid Build Coastguard Worker void RunDexopt(Matcher<ndk::ScopedAStatus> status_matcher,
437*795d594fSAndroid Build Coastguard Worker Matcher<ArtdDexoptResult> aidl_return_matcher = Field(&ArtdDexoptResult::cancelled,
438*795d594fSAndroid Build Coastguard Worker false),
439*795d594fSAndroid Build Coastguard Worker std::shared_ptr<IArtdCancellationSignal> cancellation_signal = nullptr) {
440*795d594fSAndroid Build Coastguard Worker InitFilesBeforeDexopt();
441*795d594fSAndroid Build Coastguard Worker if (cancellation_signal == nullptr) {
442*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(artd_->createCancellationSignal(&cancellation_signal).isOk());
443*795d594fSAndroid Build Coastguard Worker }
444*795d594fSAndroid Build Coastguard Worker ArtdDexoptResult aidl_return;
445*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus status = artd_->dexopt(output_artifacts_,
446*795d594fSAndroid Build Coastguard Worker dex_file_,
447*795d594fSAndroid Build Coastguard Worker isa_,
448*795d594fSAndroid Build Coastguard Worker class_loader_context_,
449*795d594fSAndroid Build Coastguard Worker compiler_filter_,
450*795d594fSAndroid Build Coastguard Worker profile_path_,
451*795d594fSAndroid Build Coastguard Worker vdex_path_,
452*795d594fSAndroid Build Coastguard Worker dm_path_,
453*795d594fSAndroid Build Coastguard Worker priority_class_,
454*795d594fSAndroid Build Coastguard Worker dexopt_options_,
455*795d594fSAndroid Build Coastguard Worker cancellation_signal,
456*795d594fSAndroid Build Coastguard Worker &aidl_return);
457*795d594fSAndroid Build Coastguard Worker ASSERT_THAT(status, std::move(status_matcher)) << status.getMessage();
458*795d594fSAndroid Build Coastguard Worker if (status.isOk()) {
459*795d594fSAndroid Build Coastguard Worker ASSERT_THAT(aidl_return, std::move(aidl_return_matcher));
460*795d594fSAndroid Build Coastguard Worker }
461*795d594fSAndroid Build Coastguard Worker }
462*795d594fSAndroid Build Coastguard Worker
463*795d594fSAndroid Build Coastguard Worker template <bool kExpectOk>
464*795d594fSAndroid Build Coastguard Worker using RunCopyAndRewriteProfileResult = Result<
465*795d594fSAndroid Build Coastguard Worker std::pair<std::conditional_t<kExpectOk, CopyAndRewriteProfileResult, ndk::ScopedAStatus>,
466*795d594fSAndroid Build Coastguard Worker OutputProfile>>;
467*795d594fSAndroid Build Coastguard Worker
468*795d594fSAndroid Build Coastguard Worker // Runs `copyAndRewriteProfile` with `profile_path_` and `dex_file_`.
469*795d594fSAndroid Build Coastguard Worker template <bool kExpectOk = true>
RunCopyAndRewriteProfile()470*795d594fSAndroid Build Coastguard Worker RunCopyAndRewriteProfileResult<kExpectOk> RunCopyAndRewriteProfile() {
471*795d594fSAndroid Build Coastguard Worker OutputProfile dst{.profilePath = tmp_profile_path_,
472*795d594fSAndroid Build Coastguard Worker .fsPermission = FsPermission{.uid = -1, .gid = -1}};
473*795d594fSAndroid Build Coastguard Worker dst.profilePath.id = "";
474*795d594fSAndroid Build Coastguard Worker dst.profilePath.tmpPath = "";
475*795d594fSAndroid Build Coastguard Worker
476*795d594fSAndroid Build Coastguard Worker CopyAndRewriteProfileResult result;
477*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus status =
478*795d594fSAndroid Build Coastguard Worker artd_->copyAndRewriteProfile(profile_path_.value(), &dst, dex_file_, &result);
479*795d594fSAndroid Build Coastguard Worker if constexpr (kExpectOk) {
480*795d594fSAndroid Build Coastguard Worker if (!status.isOk()) {
481*795d594fSAndroid Build Coastguard Worker return Error() << status.getMessage();
482*795d594fSAndroid Build Coastguard Worker }
483*795d594fSAndroid Build Coastguard Worker return std::make_pair(std::move(result), std::move(dst));
484*795d594fSAndroid Build Coastguard Worker } else {
485*795d594fSAndroid Build Coastguard Worker return std::make_pair(std::move(status), std::move(dst));
486*795d594fSAndroid Build Coastguard Worker }
487*795d594fSAndroid Build Coastguard Worker }
488*795d594fSAndroid Build Coastguard Worker
489*795d594fSAndroid Build Coastguard Worker // Runs `copyAndRewriteEmbeddedProfile` with `dex_file_`.
490*795d594fSAndroid Build Coastguard Worker template <bool kExpectOk = true>
RunCopyAndRewriteEmbeddedProfile()491*795d594fSAndroid Build Coastguard Worker RunCopyAndRewriteProfileResult<kExpectOk> RunCopyAndRewriteEmbeddedProfile() {
492*795d594fSAndroid Build Coastguard Worker OutputProfile dst{.profilePath = tmp_profile_path_,
493*795d594fSAndroid Build Coastguard Worker .fsPermission = FsPermission{.uid = -1, .gid = -1}};
494*795d594fSAndroid Build Coastguard Worker dst.profilePath.id = "";
495*795d594fSAndroid Build Coastguard Worker dst.profilePath.tmpPath = "";
496*795d594fSAndroid Build Coastguard Worker
497*795d594fSAndroid Build Coastguard Worker CopyAndRewriteProfileResult result;
498*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus status = artd_->copyAndRewriteEmbeddedProfile(&dst, dex_file_, &result);
499*795d594fSAndroid Build Coastguard Worker if constexpr (kExpectOk) {
500*795d594fSAndroid Build Coastguard Worker if (!status.isOk()) {
501*795d594fSAndroid Build Coastguard Worker return Error() << status.getMessage();
502*795d594fSAndroid Build Coastguard Worker }
503*795d594fSAndroid Build Coastguard Worker return std::make_pair(std::move(result), std::move(dst));
504*795d594fSAndroid Build Coastguard Worker } else {
505*795d594fSAndroid Build Coastguard Worker return std::make_pair(std::move(status), std::move(dst));
506*795d594fSAndroid Build Coastguard Worker }
507*795d594fSAndroid Build Coastguard Worker }
508*795d594fSAndroid Build Coastguard Worker
CreateFile(const std::string & filename,const std::string & content="")509*795d594fSAndroid Build Coastguard Worker void CreateFile(const std::string& filename, const std::string& content = "") {
510*795d594fSAndroid Build Coastguard Worker std::filesystem::path path(filename);
511*795d594fSAndroid Build Coastguard Worker std::filesystem::create_directories(path.parent_path());
512*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(WriteStringToFile(content, filename));
513*795d594fSAndroid Build Coastguard Worker }
514*795d594fSAndroid Build Coastguard Worker
CreateZipWithSingleEntry(const std::string & filename,const std::string & entry_name,const std::string & content="")515*795d594fSAndroid Build Coastguard Worker void CreateZipWithSingleEntry(const std::string& filename,
516*795d594fSAndroid Build Coastguard Worker const std::string& entry_name,
517*795d594fSAndroid Build Coastguard Worker const std::string& content = "") {
518*795d594fSAndroid Build Coastguard Worker std::filesystem::path path(filename);
519*795d594fSAndroid Build Coastguard Worker std::filesystem::create_directories(path.parent_path());
520*795d594fSAndroid Build Coastguard Worker std::unique_ptr<File> file(OS::CreateEmptyFileWriteOnly(filename.c_str()));
521*795d594fSAndroid Build Coastguard Worker ASSERT_NE(file, nullptr) << strerror(errno);
522*795d594fSAndroid Build Coastguard Worker file->MarkUnchecked(); // `writer.Finish()` flushes the file and the destructor closes it.
523*795d594fSAndroid Build Coastguard Worker ZipWriter writer(fdopen(file->Fd(), "wb"));
524*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(writer.StartEntry(entry_name, /*flags=*/0), 0);
525*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(writer.WriteBytes(content.c_str(), content.size()), 0);
526*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(writer.FinishEntry(), 0);
527*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(writer.Finish(), 0);
528*795d594fSAndroid Build Coastguard Worker }
529*795d594fSAndroid Build Coastguard Worker
530*795d594fSAndroid Build Coastguard Worker std::shared_ptr<Artd> artd_;
531*795d594fSAndroid Build Coastguard Worker std::unique_ptr<ScratchDir> scratch_dir_;
532*795d594fSAndroid Build Coastguard Worker std::string scratch_path_;
533*795d594fSAndroid Build Coastguard Worker std::string art_root_;
534*795d594fSAndroid Build Coastguard Worker std::string android_data_;
535*795d594fSAndroid Build Coastguard Worker std::string android_expand_;
536*795d594fSAndroid Build Coastguard Worker MockFunction<android::base::LogFunction> mock_logger_;
537*795d594fSAndroid Build Coastguard Worker ScopedUnsetEnvironmentVariable art_root_env_ = ScopedUnsetEnvironmentVariable("ANDROID_ART_ROOT");
538*795d594fSAndroid Build Coastguard Worker ScopedUnsetEnvironmentVariable android_data_env_ = ScopedUnsetEnvironmentVariable("ANDROID_DATA");
539*795d594fSAndroid Build Coastguard Worker ScopedUnsetEnvironmentVariable android_expand_env_ =
540*795d594fSAndroid Build Coastguard Worker ScopedUnsetEnvironmentVariable("ANDROID_EXPAND");
541*795d594fSAndroid Build Coastguard Worker MockSystemProperties* mock_props_;
542*795d594fSAndroid Build Coastguard Worker MockExecUtils* mock_exec_utils_;
543*795d594fSAndroid Build Coastguard Worker MockFunction<KillFn> mock_kill_;
544*795d594fSAndroid Build Coastguard Worker MockFunction<FstatFn> mock_fstat_;
545*795d594fSAndroid Build Coastguard Worker MockFunction<PollFn> mock_poll_;
546*795d594fSAndroid Build Coastguard Worker
547*795d594fSAndroid Build Coastguard Worker std::string dex_file_;
548*795d594fSAndroid Build Coastguard Worker std::string isa_;
549*795d594fSAndroid Build Coastguard Worker ArtifactsPath artifacts_path_;
550*795d594fSAndroid Build Coastguard Worker OutputArtifacts output_artifacts_;
551*795d594fSAndroid Build Coastguard Worker std::string clc_1_;
552*795d594fSAndroid Build Coastguard Worker std::string clc_2_;
553*795d594fSAndroid Build Coastguard Worker std::optional<std::string> class_loader_context_;
554*795d594fSAndroid Build Coastguard Worker std::string compiler_filter_;
555*795d594fSAndroid Build Coastguard Worker std::optional<VdexPath> vdex_path_;
556*795d594fSAndroid Build Coastguard Worker std::optional<DexMetadataPath> dm_path_;
557*795d594fSAndroid Build Coastguard Worker PriorityClass priority_class_ = PriorityClass::BACKGROUND;
558*795d594fSAndroid Build Coastguard Worker DexoptOptions dexopt_options_;
559*795d594fSAndroid Build Coastguard Worker std::optional<ProfilePath> profile_path_;
560*795d594fSAndroid Build Coastguard Worker TmpProfilePath tmp_profile_path_;
561*795d594fSAndroid Build Coastguard Worker bool dex_file_other_readable_ = true;
562*795d594fSAndroid Build Coastguard Worker bool profile_other_readable_ = true;
563*795d594fSAndroid Build Coastguard Worker
564*795d594fSAndroid Build Coastguard Worker private:
InitFilesBeforeDexopt()565*795d594fSAndroid Build Coastguard Worker void InitFilesBeforeDexopt() {
566*795d594fSAndroid Build Coastguard Worker // Required files.
567*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
568*795d594fSAndroid Build Coastguard Worker std::filesystem::permissions(dex_file_,
569*795d594fSAndroid Build Coastguard Worker std::filesystem::perms::others_read,
570*795d594fSAndroid Build Coastguard Worker dex_file_other_readable_ ? std::filesystem::perm_options::add :
571*795d594fSAndroid Build Coastguard Worker std::filesystem::perm_options::remove);
572*795d594fSAndroid Build Coastguard Worker
573*795d594fSAndroid Build Coastguard Worker // Optional files.
574*795d594fSAndroid Build Coastguard Worker if (vdex_path_.has_value()) {
575*795d594fSAndroid Build Coastguard Worker CreateFile(OR_FATAL(BuildVdexPath(vdex_path_.value())), "old_vdex");
576*795d594fSAndroid Build Coastguard Worker }
577*795d594fSAndroid Build Coastguard Worker if (dm_path_.has_value()) {
578*795d594fSAndroid Build Coastguard Worker CreateFile(OR_FATAL(BuildDexMetadataPath(dm_path_.value())));
579*795d594fSAndroid Build Coastguard Worker }
580*795d594fSAndroid Build Coastguard Worker if (profile_path_.has_value()) {
581*795d594fSAndroid Build Coastguard Worker std::string path = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
582*795d594fSAndroid Build Coastguard Worker CreateFile(path);
583*795d594fSAndroid Build Coastguard Worker std::filesystem::permissions(path,
584*795d594fSAndroid Build Coastguard Worker std::filesystem::perms::others_read,
585*795d594fSAndroid Build Coastguard Worker profile_other_readable_ ? std::filesystem::perm_options::add :
586*795d594fSAndroid Build Coastguard Worker std::filesystem::perm_options::remove);
587*795d594fSAndroid Build Coastguard Worker }
588*795d594fSAndroid Build Coastguard Worker
589*795d594fSAndroid Build Coastguard Worker // Files to be replaced.
590*795d594fSAndroid Build Coastguard Worker RawArtifactsPath artifacts_path = OR_FATAL(BuildArtifactsPath(artifacts_path_));
591*795d594fSAndroid Build Coastguard Worker CreateFile(artifacts_path.oat_path, "old_oat");
592*795d594fSAndroid Build Coastguard Worker CreateFile(artifacts_path.vdex_path, "old_vdex");
593*795d594fSAndroid Build Coastguard Worker CreateFile(artifacts_path.art_path, "old_art");
594*795d594fSAndroid Build Coastguard Worker }
595*795d594fSAndroid Build Coastguard Worker };
596*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,ConstantsAreInSync)597*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, ConstantsAreInSync) {
598*795d594fSAndroid Build Coastguard Worker EXPECT_STREQ(ArtConstants::REASON_VDEX, kReasonVdex);
599*795d594fSAndroid Build Coastguard Worker EXPECT_STREQ(ArtConstants::DEX_METADATA_FILE_EXT, kDmExtension);
600*795d594fSAndroid Build Coastguard Worker EXPECT_STREQ(ArtConstants::SECURE_DEX_METADATA_FILE_EXT, kSdmExtension);
601*795d594fSAndroid Build Coastguard Worker EXPECT_STREQ(ArtConstants::DEX_METADATA_PROFILE_ENTRY,
602*795d594fSAndroid Build Coastguard Worker ProfileCompilationInfo::kDexMetadataProfileEntry);
603*795d594fSAndroid Build Coastguard Worker EXPECT_STREQ(ArtConstants::DEX_METADATA_VDEX_ENTRY, VdexFile::kVdexNameInDmFile);
604*795d594fSAndroid Build Coastguard Worker }
605*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,isAlive)606*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, isAlive) {
607*795d594fSAndroid Build Coastguard Worker bool result = false;
608*795d594fSAndroid Build Coastguard Worker artd_->isAlive(&result);
609*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(result);
610*795d594fSAndroid Build Coastguard Worker }
611*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,deleteArtifacts)612*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, deleteArtifacts) {
613*795d594fSAndroid Build Coastguard Worker std::string oat_dir = scratch_path_ + "/a/oat/arm64";
614*795d594fSAndroid Build Coastguard Worker std::filesystem::create_directories(oat_dir);
615*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(WriteStringToFile("abcd", oat_dir + "/b.odex")); // 4 bytes.
616*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(WriteStringToFile("ab", oat_dir + "/b.vdex")); // 2 bytes.
617*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(WriteStringToFile("a", oat_dir + "/b.art")); // 1 byte.
618*795d594fSAndroid Build Coastguard Worker
619*795d594fSAndroid Build Coastguard Worker int64_t result = -1;
620*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(artd_->deleteArtifacts(artifacts_path_, &result).isOk());
621*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result, 4 + 2 + 1);
622*795d594fSAndroid Build Coastguard Worker
623*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(std::filesystem::exists(oat_dir + "/b.odex"));
624*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(std::filesystem::exists(oat_dir + "/b.vdex"));
625*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(std::filesystem::exists(oat_dir + "/b.art"));
626*795d594fSAndroid Build Coastguard Worker }
627*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,deleteArtifactsMissingFile)628*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, deleteArtifactsMissingFile) {
629*795d594fSAndroid Build Coastguard Worker // Missing VDEX file.
630*795d594fSAndroid Build Coastguard Worker std::string oat_dir = android_data_ + "/dalvik-cache/arm64";
631*795d594fSAndroid Build Coastguard Worker std::filesystem::create_directories(oat_dir);
632*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(WriteStringToFile("abcd", oat_dir + "/[email protected]@classes.dex")); // 4 bytes.
633*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(WriteStringToFile("a", oat_dir + "/[email protected]@classes.art")); // 1 byte.
634*795d594fSAndroid Build Coastguard Worker
635*795d594fSAndroid Build Coastguard Worker auto scoped_set_logger = ScopedSetLogger(mock_logger_.AsStdFunction());
636*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_logger_, Call(_, _, _, _, _, HasSubstr("Failed to get the file size"))).Times(0);
637*795d594fSAndroid Build Coastguard Worker
638*795d594fSAndroid Build Coastguard Worker int64_t result = -1;
639*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(artd_
640*795d594fSAndroid Build Coastguard Worker ->deleteArtifacts(
641*795d594fSAndroid Build Coastguard Worker ArtifactsPath{
642*795d594fSAndroid Build Coastguard Worker .dexPath = "/a/b.apk",
643*795d594fSAndroid Build Coastguard Worker .isa = "arm64",
644*795d594fSAndroid Build Coastguard Worker .isInDalvikCache = true,
645*795d594fSAndroid Build Coastguard Worker },
646*795d594fSAndroid Build Coastguard Worker &result)
647*795d594fSAndroid Build Coastguard Worker .isOk());
648*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result, 4 + 1);
649*795d594fSAndroid Build Coastguard Worker
650*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(std::filesystem::exists(oat_dir + "/[email protected]@classes.dex"));
651*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(std::filesystem::exists(oat_dir + "/[email protected]@classes.art"));
652*795d594fSAndroid Build Coastguard Worker }
653*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,deleteArtifactsNoFile)654*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, deleteArtifactsNoFile) {
655*795d594fSAndroid Build Coastguard Worker auto scoped_set_logger = ScopedSetLogger(mock_logger_.AsStdFunction());
656*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_logger_, Call(_, _, _, _, _, HasSubstr("Failed to get the file size"))).Times(0);
657*795d594fSAndroid Build Coastguard Worker
658*795d594fSAndroid Build Coastguard Worker int64_t result = -1;
659*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(artd_->deleteArtifacts(artifacts_path_, &result).isOk());
660*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result, 0);
661*795d594fSAndroid Build Coastguard Worker }
662*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,deleteArtifactsPermissionDenied)663*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, deleteArtifactsPermissionDenied) {
664*795d594fSAndroid Build Coastguard Worker std::string oat_dir = scratch_path_ + "/a/oat/arm64";
665*795d594fSAndroid Build Coastguard Worker std::filesystem::create_directories(oat_dir);
666*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(WriteStringToFile("abcd", oat_dir + "/b.odex")); // 4 bytes.
667*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(WriteStringToFile("ab", oat_dir + "/b.vdex")); // 2 bytes.
668*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(WriteStringToFile("a", oat_dir + "/b.art")); // 1 byte.
669*795d594fSAndroid Build Coastguard Worker
670*795d594fSAndroid Build Coastguard Worker auto scoped_set_logger = ScopedSetLogger(mock_logger_.AsStdFunction());
671*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_logger_, Call(_, _, _, _, _, HasSubstr("Failed to get the file size"))).Times(3);
672*795d594fSAndroid Build Coastguard Worker
673*795d594fSAndroid Build Coastguard Worker auto scoped_inaccessible = ScopedInaccessible(oat_dir);
674*795d594fSAndroid Build Coastguard Worker auto scoped_unroot = ScopedUnroot();
675*795d594fSAndroid Build Coastguard Worker
676*795d594fSAndroid Build Coastguard Worker int64_t result = -1;
677*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(artd_->deleteArtifacts(artifacts_path_, &result).isOk());
678*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result, 0);
679*795d594fSAndroid Build Coastguard Worker }
680*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,deleteArtifactsFileIsDir)681*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, deleteArtifactsFileIsDir) {
682*795d594fSAndroid Build Coastguard Worker // VDEX file is a directory.
683*795d594fSAndroid Build Coastguard Worker std::string oat_dir = scratch_path_ + "/a/oat/arm64";
684*795d594fSAndroid Build Coastguard Worker std::filesystem::create_directories(oat_dir);
685*795d594fSAndroid Build Coastguard Worker std::filesystem::create_directories(oat_dir + "/b.vdex");
686*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(WriteStringToFile("abcd", oat_dir + "/b.odex")); // 4 bytes.
687*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(WriteStringToFile("a", oat_dir + "/b.art")); // 1 byte.
688*795d594fSAndroid Build Coastguard Worker
689*795d594fSAndroid Build Coastguard Worker auto scoped_set_logger = ScopedSetLogger(mock_logger_.AsStdFunction());
690*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_logger_,
691*795d594fSAndroid Build Coastguard Worker Call(_, _, _, _, _, ContainsRegex(R"re(Failed to get the file size.*b\.vdex)re")))
692*795d594fSAndroid Build Coastguard Worker .Times(1);
693*795d594fSAndroid Build Coastguard Worker
694*795d594fSAndroid Build Coastguard Worker int64_t result = -1;
695*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(artd_->deleteArtifacts(artifacts_path_, &result).isOk());
696*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result, 4 + 1);
697*795d594fSAndroid Build Coastguard Worker
698*795d594fSAndroid Build Coastguard Worker // The directory is kept because getting the file size failed.
699*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(std::filesystem::exists(oat_dir + "/b.odex"));
700*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(std::filesystem::exists(oat_dir + "/b.vdex"));
701*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(std::filesystem::exists(oat_dir + "/b.art"));
702*795d594fSAndroid Build Coastguard Worker }
703*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexopt)704*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexopt) {
705*795d594fSAndroid Build Coastguard Worker dexopt_options_.generateAppImage = true;
706*795d594fSAndroid Build Coastguard Worker
707*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
708*795d594fSAndroid Build Coastguard Worker *mock_exec_utils_,
709*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
710*795d594fSAndroid Build Coastguard Worker AllOf(WhenSplitBy(
711*795d594fSAndroid Build Coastguard Worker "--",
712*795d594fSAndroid Build Coastguard Worker AllOf(Contains(art_root_ + "/bin/art_exec"), Contains("--drop-capabilities")),
713*795d594fSAndroid Build Coastguard Worker AllOf(Contains(art_root_ + "/bin/dex2oat32"),
714*795d594fSAndroid Build Coastguard Worker Contains(Flag("--zip-fd=", FdOf(dex_file_))),
715*795d594fSAndroid Build Coastguard Worker Contains(Flag("--zip-location=", dex_file_)),
716*795d594fSAndroid Build Coastguard Worker Contains(Flag("--oat-location=", scratch_path_ + "/a/oat/arm64/b.odex")),
717*795d594fSAndroid Build Coastguard Worker Contains(Flag("--instruction-set=", "arm64")),
718*795d594fSAndroid Build Coastguard Worker Contains(Flag("--compiler-filter=", "speed")),
719*795d594fSAndroid Build Coastguard Worker Contains(Flag(
720*795d594fSAndroid Build Coastguard Worker "--profile-file-fd=",
721*795d594fSAndroid Build Coastguard Worker FdOf(android_data_ +
722*795d594fSAndroid Build Coastguard Worker "/misc/profiles/ref/com.android.foo/primary.prof.12345.tmp"))),
723*795d594fSAndroid Build Coastguard Worker Contains(Flag("--input-vdex-fd=",
724*795d594fSAndroid Build Coastguard Worker FdOf(scratch_path_ + "/a/oat/arm64/b.vdex"))),
725*795d594fSAndroid Build Coastguard Worker Contains(Flag("--dm-fd=", FdOf(scratch_path_ + "/a/b.dm"))))),
726*795d594fSAndroid Build Coastguard Worker HasKeepFdsFor("--zip-fd=",
727*795d594fSAndroid Build Coastguard Worker "--profile-file-fd=",
728*795d594fSAndroid Build Coastguard Worker "--input-vdex-fd=",
729*795d594fSAndroid Build Coastguard Worker "--dm-fd=",
730*795d594fSAndroid Build Coastguard Worker "--oat-fd=",
731*795d594fSAndroid Build Coastguard Worker "--output-vdex-fd=",
732*795d594fSAndroid Build Coastguard Worker "--app-image-fd=",
733*795d594fSAndroid Build Coastguard Worker "--class-loader-context-fds=",
734*795d594fSAndroid Build Coastguard Worker "--swap-fd=")),
735*795d594fSAndroid Build Coastguard Worker _,
736*795d594fSAndroid Build Coastguard Worker _))
737*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(WithArg<0>(WriteToFdFlag("--oat-fd=", "oat")),
738*795d594fSAndroid Build Coastguard Worker WithArg<0>(WriteToFdFlag("--output-vdex-fd=", "vdex")),
739*795d594fSAndroid Build Coastguard Worker WithArg<0>(WriteToFdFlag("--app-image-fd=", "art")),
740*795d594fSAndroid Build Coastguard Worker SetArgPointee<2>(ProcessStat{.wall_time_ms = 100, .cpu_time_ms = 400}),
741*795d594fSAndroid Build Coastguard Worker Return(0)));
742*795d594fSAndroid Build Coastguard Worker RunDexopt(
743*795d594fSAndroid Build Coastguard Worker EX_NONE,
744*795d594fSAndroid Build Coastguard Worker AllOf(Field(&ArtdDexoptResult::cancelled, false),
745*795d594fSAndroid Build Coastguard Worker Field(&ArtdDexoptResult::wallTimeMs, 100),
746*795d594fSAndroid Build Coastguard Worker Field(&ArtdDexoptResult::cpuTimeMs, 400),
747*795d594fSAndroid Build Coastguard Worker Field(&ArtdDexoptResult::sizeBytes, strlen("art") + strlen("oat") + strlen("vdex")),
748*795d594fSAndroid Build Coastguard Worker Field(&ArtdDexoptResult::sizeBeforeBytes,
749*795d594fSAndroid Build Coastguard Worker strlen("old_art") + strlen("old_oat") + strlen("old_vdex"))));
750*795d594fSAndroid Build Coastguard Worker
751*795d594fSAndroid Build Coastguard Worker CheckContent(scratch_path_ + "/a/oat/arm64/b.odex", "oat");
752*795d594fSAndroid Build Coastguard Worker CheckContent(scratch_path_ + "/a/oat/arm64/b.vdex", "vdex");
753*795d594fSAndroid Build Coastguard Worker CheckContent(scratch_path_ + "/a/oat/arm64/b.art", "art");
754*795d594fSAndroid Build Coastguard Worker CheckOtherReadable(scratch_path_ + "/a/oat/arm64/b.odex", true);
755*795d594fSAndroid Build Coastguard Worker CheckOtherReadable(scratch_path_ + "/a/oat/arm64/b.vdex", true);
756*795d594fSAndroid Build Coastguard Worker CheckOtherReadable(scratch_path_ + "/a/oat/arm64/b.art", true);
757*795d594fSAndroid Build Coastguard Worker }
758*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptClassLoaderContext)759*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptClassLoaderContext) {
760*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
761*795d594fSAndroid Build Coastguard Worker *mock_exec_utils_,
762*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
763*795d594fSAndroid Build Coastguard Worker WhenSplitBy("--",
764*795d594fSAndroid Build Coastguard Worker _,
765*795d594fSAndroid Build Coastguard Worker AllOf(Contains(ListFlag("--class-loader-context-fds=",
766*795d594fSAndroid Build Coastguard Worker ElementsAre(FdOf(clc_1_), FdOf(clc_2_)))),
767*795d594fSAndroid Build Coastguard Worker Contains(Flag("--class-loader-context=", class_loader_context_)),
768*795d594fSAndroid Build Coastguard Worker Contains(Flag("--classpath-dir=", scratch_path_ + "/a")))),
769*795d594fSAndroid Build Coastguard Worker _,
770*795d594fSAndroid Build Coastguard Worker _))
771*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(0));
772*795d594fSAndroid Build Coastguard Worker RunDexopt();
773*795d594fSAndroid Build Coastguard Worker }
774*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptClassLoaderContextNull)775*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptClassLoaderContextNull) {
776*795d594fSAndroid Build Coastguard Worker class_loader_context_ = std::nullopt;
777*795d594fSAndroid Build Coastguard Worker
778*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
779*795d594fSAndroid Build Coastguard Worker *mock_exec_utils_,
780*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(WhenSplitBy("--",
781*795d594fSAndroid Build Coastguard Worker _,
782*795d594fSAndroid Build Coastguard Worker AllOf(Not(Contains(Flag("--class-loader-context-fds=", _))),
783*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("--class-loader-context=", _))),
784*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("--classpath-dir=", _))))),
785*795d594fSAndroid Build Coastguard Worker _,
786*795d594fSAndroid Build Coastguard Worker _))
787*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(0));
788*795d594fSAndroid Build Coastguard Worker RunDexopt();
789*795d594fSAndroid Build Coastguard Worker }
790*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptNoOptionalInputFiles)791*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptNoOptionalInputFiles) {
792*795d594fSAndroid Build Coastguard Worker profile_path_ = std::nullopt;
793*795d594fSAndroid Build Coastguard Worker vdex_path_ = std::nullopt;
794*795d594fSAndroid Build Coastguard Worker dm_path_ = std::nullopt;
795*795d594fSAndroid Build Coastguard Worker
796*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_,
797*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(WhenSplitBy("--",
798*795d594fSAndroid Build Coastguard Worker _,
799*795d594fSAndroid Build Coastguard Worker AllOf(Not(Contains(Flag("--profile-file-fd=", _))),
800*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("--input-vdex-fd=", _))),
801*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("--dm-fd=", _))))),
802*795d594fSAndroid Build Coastguard Worker _,
803*795d594fSAndroid Build Coastguard Worker _))
804*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(0));
805*795d594fSAndroid Build Coastguard Worker RunDexopt();
806*795d594fSAndroid Build Coastguard Worker }
807*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptPriorityClassBoot)808*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptPriorityClassBoot) {
809*795d594fSAndroid Build Coastguard Worker priority_class_ = PriorityClass::BOOT;
810*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_,
811*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(WhenSplitBy("--",
812*795d594fSAndroid Build Coastguard Worker AllOf(Not(Contains(Flag("--set-task-profile=", _))),
813*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("--set-priority=", _)))),
814*795d594fSAndroid Build Coastguard Worker Contains(Flag("--compact-dex-level=", "none"))),
815*795d594fSAndroid Build Coastguard Worker _,
816*795d594fSAndroid Build Coastguard Worker _))
817*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(0));
818*795d594fSAndroid Build Coastguard Worker RunDexopt();
819*795d594fSAndroid Build Coastguard Worker }
820*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptPriorityClassInteractive)821*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptPriorityClassInteractive) {
822*795d594fSAndroid Build Coastguard Worker priority_class_ = PriorityClass::INTERACTIVE;
823*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_,
824*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
825*795d594fSAndroid Build Coastguard Worker WhenSplitBy("--",
826*795d594fSAndroid Build Coastguard Worker AllOf(Contains(Flag("--set-task-profile=", "Dex2OatBootComplete")),
827*795d594fSAndroid Build Coastguard Worker Contains(Flag("--set-priority=", "background"))),
828*795d594fSAndroid Build Coastguard Worker Contains(Flag("--compact-dex-level=", "none"))),
829*795d594fSAndroid Build Coastguard Worker _,
830*795d594fSAndroid Build Coastguard Worker _))
831*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(0));
832*795d594fSAndroid Build Coastguard Worker RunDexopt();
833*795d594fSAndroid Build Coastguard Worker }
834*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptPriorityClassInteractiveFast)835*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptPriorityClassInteractiveFast) {
836*795d594fSAndroid Build Coastguard Worker priority_class_ = PriorityClass::INTERACTIVE_FAST;
837*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_,
838*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
839*795d594fSAndroid Build Coastguard Worker WhenSplitBy("--",
840*795d594fSAndroid Build Coastguard Worker AllOf(Contains(Flag("--set-task-profile=", "Dex2OatBootComplete")),
841*795d594fSAndroid Build Coastguard Worker Contains(Flag("--set-priority=", "background"))),
842*795d594fSAndroid Build Coastguard Worker Contains(Flag("--compact-dex-level=", "none"))),
843*795d594fSAndroid Build Coastguard Worker _,
844*795d594fSAndroid Build Coastguard Worker _))
845*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(0));
846*795d594fSAndroid Build Coastguard Worker RunDexopt();
847*795d594fSAndroid Build Coastguard Worker }
848*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptPriorityClassBackground)849*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptPriorityClassBackground) {
850*795d594fSAndroid Build Coastguard Worker priority_class_ = PriorityClass::BACKGROUND;
851*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_,
852*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
853*795d594fSAndroid Build Coastguard Worker WhenSplitBy("--",
854*795d594fSAndroid Build Coastguard Worker AllOf(Contains(Flag("--set-task-profile=", "Dex2OatBackground")),
855*795d594fSAndroid Build Coastguard Worker Contains(Flag("--set-priority=", "background"))),
856*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("--compact-dex-level=", _)))),
857*795d594fSAndroid Build Coastguard Worker _,
858*795d594fSAndroid Build Coastguard Worker _))
859*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(0));
860*795d594fSAndroid Build Coastguard Worker RunDexopt();
861*795d594fSAndroid Build Coastguard Worker }
862*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptDexoptOptions)863*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptDexoptOptions) {
864*795d594fSAndroid Build Coastguard Worker dexopt_options_ = DexoptOptions{
865*795d594fSAndroid Build Coastguard Worker .compilationReason = "install",
866*795d594fSAndroid Build Coastguard Worker .targetSdkVersion = 123,
867*795d594fSAndroid Build Coastguard Worker .debuggable = false,
868*795d594fSAndroid Build Coastguard Worker .generateAppImage = false,
869*795d594fSAndroid Build Coastguard Worker .hiddenApiPolicyEnabled = false,
870*795d594fSAndroid Build Coastguard Worker .comments = "my-comments",
871*795d594fSAndroid Build Coastguard Worker };
872*795d594fSAndroid Build Coastguard Worker
873*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
874*795d594fSAndroid Build Coastguard Worker *mock_exec_utils_,
875*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(WhenSplitBy("--",
876*795d594fSAndroid Build Coastguard Worker _,
877*795d594fSAndroid Build Coastguard Worker AllOf(Contains(Flag("--compilation-reason=", "install")),
878*795d594fSAndroid Build Coastguard Worker Contains(Flag("-Xtarget-sdk-version:", "123")),
879*795d594fSAndroid Build Coastguard Worker Not(Contains("--debuggable")),
880*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("--app-image-fd=", _))),
881*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("-Xhidden-api-policy:", _))),
882*795d594fSAndroid Build Coastguard Worker Contains(Flag("--comments=", "my-comments")))),
883*795d594fSAndroid Build Coastguard Worker _,
884*795d594fSAndroid Build Coastguard Worker _))
885*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(0));
886*795d594fSAndroid Build Coastguard Worker
887*795d594fSAndroid Build Coastguard Worker // `sizeBeforeBytes` should include the size of the old ART file even if no new ART file is
888*795d594fSAndroid Build Coastguard Worker // generated.
889*795d594fSAndroid Build Coastguard Worker RunDexopt(EX_NONE,
890*795d594fSAndroid Build Coastguard Worker Field(&ArtdDexoptResult::sizeBeforeBytes,
891*795d594fSAndroid Build Coastguard Worker strlen("old_art") + strlen("old_oat") + strlen("old_vdex")));
892*795d594fSAndroid Build Coastguard Worker }
893*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptDexoptOptions2)894*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptDexoptOptions2) {
895*795d594fSAndroid Build Coastguard Worker dexopt_options_ = DexoptOptions{
896*795d594fSAndroid Build Coastguard Worker .compilationReason = "bg-dexopt",
897*795d594fSAndroid Build Coastguard Worker .targetSdkVersion = 456,
898*795d594fSAndroid Build Coastguard Worker .debuggable = true,
899*795d594fSAndroid Build Coastguard Worker .generateAppImage = true,
900*795d594fSAndroid Build Coastguard Worker .hiddenApiPolicyEnabled = true,
901*795d594fSAndroid Build Coastguard Worker };
902*795d594fSAndroid Build Coastguard Worker
903*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
904*795d594fSAndroid Build Coastguard Worker *mock_exec_utils_,
905*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(WhenSplitBy("--",
906*795d594fSAndroid Build Coastguard Worker _,
907*795d594fSAndroid Build Coastguard Worker AllOf(Contains(Flag("--compilation-reason=", "bg-dexopt")),
908*795d594fSAndroid Build Coastguard Worker Contains(Flag("-Xtarget-sdk-version:", "456")),
909*795d594fSAndroid Build Coastguard Worker Contains("--debuggable"),
910*795d594fSAndroid Build Coastguard Worker Contains(Flag("--app-image-fd=", _)),
911*795d594fSAndroid Build Coastguard Worker Contains(Flag("-Xhidden-api-policy:", "enabled")))),
912*795d594fSAndroid Build Coastguard Worker _,
913*795d594fSAndroid Build Coastguard Worker _))
914*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(0));
915*795d594fSAndroid Build Coastguard Worker
916*795d594fSAndroid Build Coastguard Worker RunDexopt();
917*795d594fSAndroid Build Coastguard Worker }
918*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptDefaultFlagsWhenNoSystemProps)919*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptDefaultFlagsWhenNoSystemProps) {
920*795d594fSAndroid Build Coastguard Worker dexopt_options_.generateAppImage = true;
921*795d594fSAndroid Build Coastguard Worker
922*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_,
923*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
924*795d594fSAndroid Build Coastguard Worker WhenSplitBy("--",
925*795d594fSAndroid Build Coastguard Worker _,
926*795d594fSAndroid Build Coastguard Worker AllOf(Contains(Flag("--swap-fd=", FdOf(_))),
927*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("--instruction-set-features=", _))),
928*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("--instruction-set-variant=", _))),
929*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("--max-image-block-size=", _))),
930*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("--very-large-app-threshold=", _))),
931*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("--resolve-startup-const-strings=", _))),
932*795d594fSAndroid Build Coastguard Worker Not(Contains("--generate-debug-info")),
933*795d594fSAndroid Build Coastguard Worker Not(Contains("--generate-mini-debug-info")),
934*795d594fSAndroid Build Coastguard Worker Contains("-Xdeny-art-apex-data-files"),
935*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("--cpu-set=", _))),
936*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("-j", _))),
937*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("-Xms", _))),
938*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("-Xmx", _))),
939*795d594fSAndroid Build Coastguard Worker Not(Contains("--compile-individually")),
940*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("--image-format=", _))),
941*795d594fSAndroid Build Coastguard Worker Not(Contains("--force-jit-zygote")),
942*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("--boot-image=", _))))),
943*795d594fSAndroid Build Coastguard Worker _,
944*795d594fSAndroid Build Coastguard Worker _))
945*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(0));
946*795d594fSAndroid Build Coastguard Worker RunDexopt();
947*795d594fSAndroid Build Coastguard Worker }
948*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptFlagsFromSystemProps)949*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptFlagsFromSystemProps) {
950*795d594fSAndroid Build Coastguard Worker dexopt_options_.generateAppImage = true;
951*795d594fSAndroid Build Coastguard Worker
952*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props_, GetProperty("dalvik.vm.dex2oat-swap")).WillOnce(Return("0"));
953*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props_, GetProperty("dalvik.vm.isa.arm64.features"))
954*795d594fSAndroid Build Coastguard Worker .WillOnce(Return("features"));
955*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props_, GetProperty("dalvik.vm.isa.arm64.variant")).WillOnce(Return("variant"));
956*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props_, GetProperty("dalvik.vm.dex2oat-max-image-block-size"))
957*795d594fSAndroid Build Coastguard Worker .WillOnce(Return("size"));
958*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props_, GetProperty("dalvik.vm.dex2oat-very-large"))
959*795d594fSAndroid Build Coastguard Worker .WillOnce(Return("threshold"));
960*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props_, GetProperty("dalvik.vm.dex2oat-resolve-startup-strings"))
961*795d594fSAndroid Build Coastguard Worker .WillOnce(Return("strings"));
962*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props_, GetProperty("debug.generate-debug-info")).WillOnce(Return("1"));
963*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props_, GetProperty("dalvik.vm.dex2oat-minidebuginfo")).WillOnce(Return("1"));
964*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props_, GetProperty("odsign.verification.success")).WillOnce(Return("1"));
965*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props_, GetProperty("dalvik.vm.dex2oat-Xms")).WillOnce(Return("xms"));
966*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props_, GetProperty("dalvik.vm.dex2oat-Xmx")).WillOnce(Return("xmx"));
967*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props_, GetProperty("ro.config.low_ram")).WillOnce(Return("1"));
968*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props_, GetProperty("dalvik.vm.appimageformat")).WillOnce(Return("imgfmt"));
969*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props_, GetProperty("dalvik.vm.boot-image")).WillOnce(Return("boot-image"));
970*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props_, GetProperty("dalvik.vm.dex2oat-flags"))
971*795d594fSAndroid Build Coastguard Worker .WillOnce(Return("--flag1 --flag2 --flag3"));
972*795d594fSAndroid Build Coastguard Worker
973*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_,
974*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
975*795d594fSAndroid Build Coastguard Worker WhenSplitBy("--",
976*795d594fSAndroid Build Coastguard Worker _,
977*795d594fSAndroid Build Coastguard Worker AllOf(Not(Contains(Flag("--swap-fd=", _))),
978*795d594fSAndroid Build Coastguard Worker Contains(Flag("--instruction-set-features=", "features")),
979*795d594fSAndroid Build Coastguard Worker Contains(Flag("--instruction-set-variant=", "variant")),
980*795d594fSAndroid Build Coastguard Worker Contains(Flag("--max-image-block-size=", "size")),
981*795d594fSAndroid Build Coastguard Worker Contains(Flag("--very-large-app-threshold=", "threshold")),
982*795d594fSAndroid Build Coastguard Worker Contains(Flag("--resolve-startup-const-strings=", "strings")),
983*795d594fSAndroid Build Coastguard Worker Contains("--generate-debug-info"),
984*795d594fSAndroid Build Coastguard Worker Contains("--generate-mini-debug-info"),
985*795d594fSAndroid Build Coastguard Worker Not(Contains("-Xdeny-art-apex-data-files")),
986*795d594fSAndroid Build Coastguard Worker Contains(Flag("-Xms", "xms")),
987*795d594fSAndroid Build Coastguard Worker Contains(Flag("-Xmx", "xmx")),
988*795d594fSAndroid Build Coastguard Worker Contains("--compile-individually"),
989*795d594fSAndroid Build Coastguard Worker Contains(Flag("--image-format=", "imgfmt")),
990*795d594fSAndroid Build Coastguard Worker Not(Contains("--force-jit-zygote")),
991*795d594fSAndroid Build Coastguard Worker Contains(Flag("--boot-image=", "boot-image")),
992*795d594fSAndroid Build Coastguard Worker Contains("--flag1"),
993*795d594fSAndroid Build Coastguard Worker Contains("--flag2"),
994*795d594fSAndroid Build Coastguard Worker Contains("--flag3"))),
995*795d594fSAndroid Build Coastguard Worker _,
996*795d594fSAndroid Build Coastguard Worker _))
997*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(0));
998*795d594fSAndroid Build Coastguard Worker RunDexopt();
999*795d594fSAndroid Build Coastguard Worker }
1000*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptFlagsForceJitZygote)1001*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptFlagsForceJitZygote) {
1002*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props_,
1003*795d594fSAndroid Build Coastguard Worker GetProperty("persist.device_config.runtime_native_boot.profilebootclasspath"))
1004*795d594fSAndroid Build Coastguard Worker .WillOnce(Return("true"));
1005*795d594fSAndroid Build Coastguard Worker ON_CALL(*mock_props_, GetProperty("dalvik.vm.boot-image")).WillByDefault(Return("boot-image"));
1006*795d594fSAndroid Build Coastguard Worker
1007*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_,
1008*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(WhenSplitBy("--",
1009*795d594fSAndroid Build Coastguard Worker _,
1010*795d594fSAndroid Build Coastguard Worker AllOf(Contains("--force-jit-zygote"),
1011*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("--boot-image=", _))))),
1012*795d594fSAndroid Build Coastguard Worker _,
1013*795d594fSAndroid Build Coastguard Worker _))
1014*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(0));
1015*795d594fSAndroid Build Coastguard Worker RunDexopt();
1016*795d594fSAndroid Build Coastguard Worker }
1017*795d594fSAndroid Build Coastguard Worker
SetDefaultResourceControlProps(MockSystemProperties * mock_props)1018*795d594fSAndroid Build Coastguard Worker static void SetDefaultResourceControlProps(MockSystemProperties* mock_props) {
1019*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props, GetProperty("dalvik.vm.dex2oat-cpu-set")).WillRepeatedly(Return("0,2"));
1020*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props, GetProperty("dalvik.vm.dex2oat-threads")).WillRepeatedly(Return("4"));
1021*795d594fSAndroid Build Coastguard Worker }
1022*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptDefaultResourceControlBoot)1023*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptDefaultResourceControlBoot) {
1024*795d594fSAndroid Build Coastguard Worker SetDefaultResourceControlProps(mock_props_);
1025*795d594fSAndroid Build Coastguard Worker
1026*795d594fSAndroid Build Coastguard Worker // The default resource control properties don't apply to BOOT.
1027*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
1028*795d594fSAndroid Build Coastguard Worker *mock_exec_utils_,
1029*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
1030*795d594fSAndroid Build Coastguard Worker WhenSplitBy(
1031*795d594fSAndroid Build Coastguard Worker "--", _, AllOf(Not(Contains(Flag("--cpu-set=", _))), Contains(Not(Flag("-j", _))))),
1032*795d594fSAndroid Build Coastguard Worker _,
1033*795d594fSAndroid Build Coastguard Worker _))
1034*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(0));
1035*795d594fSAndroid Build Coastguard Worker priority_class_ = PriorityClass::BOOT;
1036*795d594fSAndroid Build Coastguard Worker RunDexopt();
1037*795d594fSAndroid Build Coastguard Worker }
1038*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptDefaultResourceControlOther)1039*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptDefaultResourceControlOther) {
1040*795d594fSAndroid Build Coastguard Worker SetDefaultResourceControlProps(mock_props_);
1041*795d594fSAndroid Build Coastguard Worker
1042*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
1043*795d594fSAndroid Build Coastguard Worker *mock_exec_utils_,
1044*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
1045*795d594fSAndroid Build Coastguard Worker WhenSplitBy(
1046*795d594fSAndroid Build Coastguard Worker "--", _, AllOf(Contains(Flag("--cpu-set=", "0,2")), Contains(Flag("-j", "4")))),
1047*795d594fSAndroid Build Coastguard Worker _,
1048*795d594fSAndroid Build Coastguard Worker _))
1049*795d594fSAndroid Build Coastguard Worker .Times(3)
1050*795d594fSAndroid Build Coastguard Worker .WillRepeatedly(Return(0));
1051*795d594fSAndroid Build Coastguard Worker priority_class_ = PriorityClass::INTERACTIVE_FAST;
1052*795d594fSAndroid Build Coastguard Worker RunDexopt();
1053*795d594fSAndroid Build Coastguard Worker priority_class_ = PriorityClass::INTERACTIVE;
1054*795d594fSAndroid Build Coastguard Worker RunDexopt();
1055*795d594fSAndroid Build Coastguard Worker priority_class_ = PriorityClass::BACKGROUND;
1056*795d594fSAndroid Build Coastguard Worker RunDexopt();
1057*795d594fSAndroid Build Coastguard Worker }
1058*795d594fSAndroid Build Coastguard Worker
SetAllResourceControlProps(MockSystemProperties * mock_props)1059*795d594fSAndroid Build Coastguard Worker static void SetAllResourceControlProps(MockSystemProperties* mock_props) {
1060*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props, GetProperty("dalvik.vm.dex2oat-cpu-set")).WillRepeatedly(Return("0,2"));
1061*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props, GetProperty("dalvik.vm.dex2oat-threads")).WillRepeatedly(Return("4"));
1062*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props, GetProperty("dalvik.vm.boot-dex2oat-cpu-set"))
1063*795d594fSAndroid Build Coastguard Worker .WillRepeatedly(Return("0,1,2,3"));
1064*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props, GetProperty("dalvik.vm.boot-dex2oat-threads"))
1065*795d594fSAndroid Build Coastguard Worker .WillRepeatedly(Return("8"));
1066*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props, GetProperty("dalvik.vm.restore-dex2oat-cpu-set"))
1067*795d594fSAndroid Build Coastguard Worker .WillRepeatedly(Return("0,2,3"));
1068*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props, GetProperty("dalvik.vm.restore-dex2oat-threads"))
1069*795d594fSAndroid Build Coastguard Worker .WillRepeatedly(Return("6"));
1070*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props, GetProperty("dalvik.vm.background-dex2oat-cpu-set"))
1071*795d594fSAndroid Build Coastguard Worker .WillRepeatedly(Return("0"));
1072*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props, GetProperty("dalvik.vm.background-dex2oat-threads"))
1073*795d594fSAndroid Build Coastguard Worker .WillRepeatedly(Return("2"));
1074*795d594fSAndroid Build Coastguard Worker }
1075*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptAllResourceControlBoot)1076*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptAllResourceControlBoot) {
1077*795d594fSAndroid Build Coastguard Worker SetAllResourceControlProps(mock_props_);
1078*795d594fSAndroid Build Coastguard Worker
1079*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
1080*795d594fSAndroid Build Coastguard Worker *mock_exec_utils_,
1081*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
1082*795d594fSAndroid Build Coastguard Worker WhenSplitBy(
1083*795d594fSAndroid Build Coastguard Worker "--", _, AllOf(Contains(Flag("--cpu-set=", "0,1,2,3")), Contains(Flag("-j", "8")))),
1084*795d594fSAndroid Build Coastguard Worker _,
1085*795d594fSAndroid Build Coastguard Worker _))
1086*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(0));
1087*795d594fSAndroid Build Coastguard Worker priority_class_ = PriorityClass::BOOT;
1088*795d594fSAndroid Build Coastguard Worker RunDexopt();
1089*795d594fSAndroid Build Coastguard Worker }
1090*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptAllResourceControlInteractiveFast)1091*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptAllResourceControlInteractiveFast) {
1092*795d594fSAndroid Build Coastguard Worker SetAllResourceControlProps(mock_props_);
1093*795d594fSAndroid Build Coastguard Worker
1094*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
1095*795d594fSAndroid Build Coastguard Worker *mock_exec_utils_,
1096*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
1097*795d594fSAndroid Build Coastguard Worker WhenSplitBy(
1098*795d594fSAndroid Build Coastguard Worker "--", _, AllOf(Contains(Flag("--cpu-set=", "0,2,3")), Contains(Flag("-j", "6")))),
1099*795d594fSAndroid Build Coastguard Worker _,
1100*795d594fSAndroid Build Coastguard Worker _))
1101*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(0));
1102*795d594fSAndroid Build Coastguard Worker priority_class_ = PriorityClass::INTERACTIVE_FAST;
1103*795d594fSAndroid Build Coastguard Worker RunDexopt();
1104*795d594fSAndroid Build Coastguard Worker }
1105*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptAllResourceControlInteractive)1106*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptAllResourceControlInteractive) {
1107*795d594fSAndroid Build Coastguard Worker SetAllResourceControlProps(mock_props_);
1108*795d594fSAndroid Build Coastguard Worker
1109*795d594fSAndroid Build Coastguard Worker // INTERACTIVE always uses the default resource control properties.
1110*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
1111*795d594fSAndroid Build Coastguard Worker *mock_exec_utils_,
1112*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
1113*795d594fSAndroid Build Coastguard Worker WhenSplitBy(
1114*795d594fSAndroid Build Coastguard Worker "--", _, AllOf(Contains(Flag("--cpu-set=", "0,2")), Contains(Flag("-j", "4")))),
1115*795d594fSAndroid Build Coastguard Worker _,
1116*795d594fSAndroid Build Coastguard Worker _))
1117*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(0));
1118*795d594fSAndroid Build Coastguard Worker priority_class_ = PriorityClass::INTERACTIVE;
1119*795d594fSAndroid Build Coastguard Worker RunDexopt();
1120*795d594fSAndroid Build Coastguard Worker }
1121*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptAllResourceControlBackground)1122*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptAllResourceControlBackground) {
1123*795d594fSAndroid Build Coastguard Worker SetAllResourceControlProps(mock_props_);
1124*795d594fSAndroid Build Coastguard Worker
1125*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
1126*795d594fSAndroid Build Coastguard Worker *mock_exec_utils_,
1127*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
1128*795d594fSAndroid Build Coastguard Worker WhenSplitBy("--", _, AllOf(Contains(Flag("--cpu-set=", "0")), Contains(Flag("-j", "2")))),
1129*795d594fSAndroid Build Coastguard Worker _,
1130*795d594fSAndroid Build Coastguard Worker _))
1131*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(0));
1132*795d594fSAndroid Build Coastguard Worker priority_class_ = PriorityClass::BACKGROUND;
1133*795d594fSAndroid Build Coastguard Worker RunDexopt();
1134*795d594fSAndroid Build Coastguard Worker }
1135*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptTerminatedBySignal)1136*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptTerminatedBySignal) {
1137*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _))
1138*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(Result<int>(Error())));
1139*795d594fSAndroid Build Coastguard Worker RunDexopt(AllOf(Property(&ndk::ScopedAStatus::getExceptionCode, EX_SERVICE_SPECIFIC),
1140*795d594fSAndroid Build Coastguard Worker Property(&ndk::ScopedAStatus::getMessage,
1141*795d594fSAndroid Build Coastguard Worker HasSubstr(ART_FORMAT("[status={},exit_code=-1,signal={}]",
1142*795d594fSAndroid Build Coastguard Worker static_cast<int>(ExecResult::kSignaled),
1143*795d594fSAndroid Build Coastguard Worker SIGKILL)))));
1144*795d594fSAndroid Build Coastguard Worker }
1145*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptFailed)1146*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptFailed) {
1147*795d594fSAndroid Build Coastguard Worker dexopt_options_.generateAppImage = true;
1148*795d594fSAndroid Build Coastguard Worker constexpr int kExitCode = 135;
1149*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _))
1150*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(WithArg<0>(WriteToFdFlag("--oat-fd=", "new_oat")),
1151*795d594fSAndroid Build Coastguard Worker WithArg<0>(WriteToFdFlag("--output-vdex-fd=", "new_vdex")),
1152*795d594fSAndroid Build Coastguard Worker WithArg<0>(WriteToFdFlag("--app-image-fd=", "new_art")),
1153*795d594fSAndroid Build Coastguard Worker Return(kExitCode)));
1154*795d594fSAndroid Build Coastguard Worker RunDexopt(AllOf(Property(&ndk::ScopedAStatus::getExceptionCode, EX_SERVICE_SPECIFIC),
1155*795d594fSAndroid Build Coastguard Worker Property(&ndk::ScopedAStatus::getMessage,
1156*795d594fSAndroid Build Coastguard Worker HasSubstr(ART_FORMAT("[status={},exit_code={},signal=0]",
1157*795d594fSAndroid Build Coastguard Worker static_cast<int>(ExecResult::kExited),
1158*795d594fSAndroid Build Coastguard Worker kExitCode)))));
1159*795d594fSAndroid Build Coastguard Worker
1160*795d594fSAndroid Build Coastguard Worker CheckContent(scratch_path_ + "/a/oat/arm64/b.odex", "old_oat");
1161*795d594fSAndroid Build Coastguard Worker CheckContent(scratch_path_ + "/a/oat/arm64/b.vdex", "old_vdex");
1162*795d594fSAndroid Build Coastguard Worker CheckContent(scratch_path_ + "/a/oat/arm64/b.art", "old_art");
1163*795d594fSAndroid Build Coastguard Worker }
1164*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptFailedToCommit)1165*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptFailedToCommit) {
1166*795d594fSAndroid Build Coastguard Worker std::unique_ptr<ScopeGuard<std::function<void()>>> scoped_inaccessible;
1167*795d594fSAndroid Build Coastguard Worker std::unique_ptr<ScopeGuard<std::function<void()>>> scoped_unroot;
1168*795d594fSAndroid Build Coastguard Worker
1169*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _))
1170*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(WithArg<0>(WriteToFdFlag("--oat-fd=", "new_oat")),
1171*795d594fSAndroid Build Coastguard Worker WithArg<0>(WriteToFdFlag("--output-vdex-fd=", "new_vdex")),
1172*795d594fSAndroid Build Coastguard Worker [&](auto, auto, auto) {
1173*795d594fSAndroid Build Coastguard Worker scoped_inaccessible = std::make_unique<ScopeGuard<std::function<void()>>>(
1174*795d594fSAndroid Build Coastguard Worker ScopedInaccessible(scratch_path_ + "/a/oat/arm64"));
1175*795d594fSAndroid Build Coastguard Worker scoped_unroot =
1176*795d594fSAndroid Build Coastguard Worker std::make_unique<ScopeGuard<std::function<void()>>>(ScopedUnroot());
1177*795d594fSAndroid Build Coastguard Worker return 0;
1178*795d594fSAndroid Build Coastguard Worker }));
1179*795d594fSAndroid Build Coastguard Worker
1180*795d594fSAndroid Build Coastguard Worker RunDexopt(
1181*795d594fSAndroid Build Coastguard Worker EX_SERVICE_SPECIFIC,
1182*795d594fSAndroid Build Coastguard Worker AllOf(Field(&ArtdDexoptResult::sizeBytes, 0), Field(&ArtdDexoptResult::sizeBeforeBytes, 0)));
1183*795d594fSAndroid Build Coastguard Worker }
1184*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptCancelledBeforeDex2oat)1185*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptCancelledBeforeDex2oat) {
1186*795d594fSAndroid Build Coastguard Worker std::shared_ptr<IArtdCancellationSignal> cancellation_signal;
1187*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(artd_->createCancellationSignal(&cancellation_signal).isOk());
1188*795d594fSAndroid Build Coastguard Worker
1189*795d594fSAndroid Build Coastguard Worker constexpr pid_t kPid = 123;
1190*795d594fSAndroid Build Coastguard Worker
1191*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _))
1192*795d594fSAndroid Build Coastguard Worker .WillOnce([&](auto, const ExecCallbacks& callbacks, auto) {
1193*795d594fSAndroid Build Coastguard Worker callbacks.on_start(kPid);
1194*795d594fSAndroid Build Coastguard Worker callbacks.on_end(kPid);
1195*795d594fSAndroid Build Coastguard Worker return Error();
1196*795d594fSAndroid Build Coastguard Worker });
1197*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_kill_, Call(-kPid, SIGKILL));
1198*795d594fSAndroid Build Coastguard Worker
1199*795d594fSAndroid Build Coastguard Worker cancellation_signal->cancel();
1200*795d594fSAndroid Build Coastguard Worker
1201*795d594fSAndroid Build Coastguard Worker RunDexopt(EX_NONE, Field(&ArtdDexoptResult::cancelled, true), cancellation_signal);
1202*795d594fSAndroid Build Coastguard Worker
1203*795d594fSAndroid Build Coastguard Worker CheckContent(scratch_path_ + "/a/oat/arm64/b.odex", "old_oat");
1204*795d594fSAndroid Build Coastguard Worker CheckContent(scratch_path_ + "/a/oat/arm64/b.vdex", "old_vdex");
1205*795d594fSAndroid Build Coastguard Worker CheckContent(scratch_path_ + "/a/oat/arm64/b.art", "old_art");
1206*795d594fSAndroid Build Coastguard Worker }
1207*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptCancelledDuringDex2oat)1208*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptCancelledDuringDex2oat) {
1209*795d594fSAndroid Build Coastguard Worker std::shared_ptr<IArtdCancellationSignal> cancellation_signal;
1210*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(artd_->createCancellationSignal(&cancellation_signal).isOk());
1211*795d594fSAndroid Build Coastguard Worker
1212*795d594fSAndroid Build Coastguard Worker constexpr pid_t kPid = 123;
1213*795d594fSAndroid Build Coastguard Worker constexpr std::chrono::duration<int> kTimeout = std::chrono::seconds(1);
1214*795d594fSAndroid Build Coastguard Worker
1215*795d594fSAndroid Build Coastguard Worker std::condition_variable process_started_cv, process_killed_cv;
1216*795d594fSAndroid Build Coastguard Worker std::mutex mu;
1217*795d594fSAndroid Build Coastguard Worker
1218*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _))
1219*795d594fSAndroid Build Coastguard Worker .WillOnce([&](auto, const ExecCallbacks& callbacks, auto) {
1220*795d594fSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mu);
1221*795d594fSAndroid Build Coastguard Worker // Step 2.
1222*795d594fSAndroid Build Coastguard Worker callbacks.on_start(kPid);
1223*795d594fSAndroid Build Coastguard Worker process_started_cv.notify_one();
1224*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(process_killed_cv.wait_for(lock, kTimeout), std::cv_status::no_timeout);
1225*795d594fSAndroid Build Coastguard Worker // Step 5.
1226*795d594fSAndroid Build Coastguard Worker callbacks.on_end(kPid);
1227*795d594fSAndroid Build Coastguard Worker return Error();
1228*795d594fSAndroid Build Coastguard Worker });
1229*795d594fSAndroid Build Coastguard Worker
1230*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_kill_, Call(-kPid, SIGKILL)).WillOnce([&](auto, auto) {
1231*795d594fSAndroid Build Coastguard Worker // Step 4.
1232*795d594fSAndroid Build Coastguard Worker process_killed_cv.notify_one();
1233*795d594fSAndroid Build Coastguard Worker return 0;
1234*795d594fSAndroid Build Coastguard Worker });
1235*795d594fSAndroid Build Coastguard Worker
1236*795d594fSAndroid Build Coastguard Worker std::thread t;
1237*795d594fSAndroid Build Coastguard Worker {
1238*795d594fSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mu);
1239*795d594fSAndroid Build Coastguard Worker // Step 1.
1240*795d594fSAndroid Build Coastguard Worker t = std::thread([&] {
1241*795d594fSAndroid Build Coastguard Worker RunDexopt(EX_NONE, Field(&ArtdDexoptResult::cancelled, true), cancellation_signal);
1242*795d594fSAndroid Build Coastguard Worker });
1243*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(process_started_cv.wait_for(lock, kTimeout), std::cv_status::no_timeout);
1244*795d594fSAndroid Build Coastguard Worker // Step 3.
1245*795d594fSAndroid Build Coastguard Worker cancellation_signal->cancel();
1246*795d594fSAndroid Build Coastguard Worker }
1247*795d594fSAndroid Build Coastguard Worker
1248*795d594fSAndroid Build Coastguard Worker t.join();
1249*795d594fSAndroid Build Coastguard Worker
1250*795d594fSAndroid Build Coastguard Worker // Step 6.
1251*795d594fSAndroid Build Coastguard Worker CheckContent(scratch_path_ + "/a/oat/arm64/b.odex", "old_oat");
1252*795d594fSAndroid Build Coastguard Worker CheckContent(scratch_path_ + "/a/oat/arm64/b.vdex", "old_vdex");
1253*795d594fSAndroid Build Coastguard Worker CheckContent(scratch_path_ + "/a/oat/arm64/b.art", "old_art");
1254*795d594fSAndroid Build Coastguard Worker }
1255*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptCancelledAfterDex2oat)1256*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptCancelledAfterDex2oat) {
1257*795d594fSAndroid Build Coastguard Worker std::shared_ptr<IArtdCancellationSignal> cancellation_signal;
1258*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(artd_->createCancellationSignal(&cancellation_signal).isOk());
1259*795d594fSAndroid Build Coastguard Worker
1260*795d594fSAndroid Build Coastguard Worker constexpr pid_t kPid = 123;
1261*795d594fSAndroid Build Coastguard Worker
1262*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _))
1263*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(WithArg<0>(WriteToFdFlag("--oat-fd=", "new_oat")),
1264*795d594fSAndroid Build Coastguard Worker WithArg<0>(WriteToFdFlag("--output-vdex-fd=", "new_vdex")),
1265*795d594fSAndroid Build Coastguard Worker [&](auto, const ExecCallbacks& callbacks, auto) {
1266*795d594fSAndroid Build Coastguard Worker callbacks.on_start(kPid);
1267*795d594fSAndroid Build Coastguard Worker callbacks.on_end(kPid);
1268*795d594fSAndroid Build Coastguard Worker return 0;
1269*795d594fSAndroid Build Coastguard Worker }));
1270*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_kill_, Call).Times(0);
1271*795d594fSAndroid Build Coastguard Worker
1272*795d594fSAndroid Build Coastguard Worker RunDexopt(EX_NONE, Field(&ArtdDexoptResult::cancelled, false), cancellation_signal);
1273*795d594fSAndroid Build Coastguard Worker
1274*795d594fSAndroid Build Coastguard Worker // This signal should be ignored.
1275*795d594fSAndroid Build Coastguard Worker cancellation_signal->cancel();
1276*795d594fSAndroid Build Coastguard Worker
1277*795d594fSAndroid Build Coastguard Worker CheckContent(scratch_path_ + "/a/oat/arm64/b.odex", "new_oat");
1278*795d594fSAndroid Build Coastguard Worker CheckContent(scratch_path_ + "/a/oat/arm64/b.vdex", "new_vdex");
1279*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(std::filesystem::exists(scratch_path_ + "/a/oat/arm64/b.art"));
1280*795d594fSAndroid Build Coastguard Worker }
1281*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptDexFileNotOtherReadable)1282*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptDexFileNotOtherReadable) {
1283*795d594fSAndroid Build Coastguard Worker dex_file_other_readable_ = false;
1284*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _)).Times(0);
1285*795d594fSAndroid Build Coastguard Worker RunDexopt(AllOf(Property(&ndk::ScopedAStatus::getExceptionCode, EX_SERVICE_SPECIFIC),
1286*795d594fSAndroid Build Coastguard Worker Property(&ndk::ScopedAStatus::getMessage,
1287*795d594fSAndroid Build Coastguard Worker HasSubstr("Outputs cannot be other-readable because the dex file"))));
1288*795d594fSAndroid Build Coastguard Worker }
1289*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptProfileNotOtherReadable)1290*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptProfileNotOtherReadable) {
1291*795d594fSAndroid Build Coastguard Worker profile_other_readable_ = false;
1292*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _)).Times(0);
1293*795d594fSAndroid Build Coastguard Worker RunDexopt(AllOf(Property(&ndk::ScopedAStatus::getExceptionCode, EX_SERVICE_SPECIFIC),
1294*795d594fSAndroid Build Coastguard Worker Property(&ndk::ScopedAStatus::getMessage,
1295*795d594fSAndroid Build Coastguard Worker HasSubstr("Outputs cannot be other-readable because the profile"))));
1296*795d594fSAndroid Build Coastguard Worker }
1297*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptOutputNotOtherReadable)1298*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptOutputNotOtherReadable) {
1299*795d594fSAndroid Build Coastguard Worker output_artifacts_.permissionSettings.fileFsPermission.isOtherReadable = false;
1300*795d594fSAndroid Build Coastguard Worker dex_file_other_readable_ = false;
1301*795d594fSAndroid Build Coastguard Worker profile_other_readable_ = false;
1302*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _)).WillOnce(Return(0));
1303*795d594fSAndroid Build Coastguard Worker RunDexopt();
1304*795d594fSAndroid Build Coastguard Worker CheckOtherReadable(scratch_path_ + "/a/oat/arm64/b.odex", false);
1305*795d594fSAndroid Build Coastguard Worker CheckOtherReadable(scratch_path_ + "/a/oat/arm64/b.vdex", false);
1306*795d594fSAndroid Build Coastguard Worker }
1307*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptUidMismatch)1308*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptUidMismatch) {
1309*795d594fSAndroid Build Coastguard Worker output_artifacts_.permissionSettings.fileFsPermission.uid = 12345;
1310*795d594fSAndroid Build Coastguard Worker output_artifacts_.permissionSettings.fileFsPermission.isOtherReadable = false;
1311*795d594fSAndroid Build Coastguard Worker dex_file_other_readable_ = false;
1312*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _)).Times(0);
1313*795d594fSAndroid Build Coastguard Worker RunDexopt(AllOf(Property(&ndk::ScopedAStatus::getExceptionCode, EX_SERVICE_SPECIFIC),
1314*795d594fSAndroid Build Coastguard Worker Property(&ndk::ScopedAStatus::getMessage,
1315*795d594fSAndroid Build Coastguard Worker HasSubstr("Outputs' owner doesn't match the dex file"))));
1316*795d594fSAndroid Build Coastguard Worker }
1317*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptGidMismatch)1318*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptGidMismatch) {
1319*795d594fSAndroid Build Coastguard Worker output_artifacts_.permissionSettings.fileFsPermission.gid = 12345;
1320*795d594fSAndroid Build Coastguard Worker output_artifacts_.permissionSettings.fileFsPermission.isOtherReadable = false;
1321*795d594fSAndroid Build Coastguard Worker dex_file_other_readable_ = false;
1322*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _)).Times(0);
1323*795d594fSAndroid Build Coastguard Worker RunDexopt(AllOf(Property(&ndk::ScopedAStatus::getExceptionCode, EX_SERVICE_SPECIFIC),
1324*795d594fSAndroid Build Coastguard Worker Property(&ndk::ScopedAStatus::getMessage,
1325*795d594fSAndroid Build Coastguard Worker HasSubstr("Outputs' owner doesn't match the dex file"))));
1326*795d594fSAndroid Build Coastguard Worker }
1327*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptGidMatchesUid)1328*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptGidMatchesUid) {
1329*795d594fSAndroid Build Coastguard Worker output_artifacts_.permissionSettings.fileFsPermission = {
1330*795d594fSAndroid Build Coastguard Worker .uid = 123, .gid = 123, .isOtherReadable = false};
1331*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_fstat_, Call(_, _)).WillRepeatedly(fstat); // For profile.
1332*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_fstat_, Call(FdOf(dex_file_), _))
1333*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(SetArgPointee<1>((struct stat){
1334*795d594fSAndroid Build Coastguard Worker .st_mode = S_IRUSR | S_IRGRP, .st_uid = 123, .st_gid = 456}),
1335*795d594fSAndroid Build Coastguard Worker Return(0)));
1336*795d594fSAndroid Build Coastguard Worker ON_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _)).WillByDefault(Return(0));
1337*795d594fSAndroid Build Coastguard Worker // It's okay to fail on chown. This happens when the test is not run as root.
1338*795d594fSAndroid Build Coastguard Worker RunDexopt(AnyOf(Property(&ndk::ScopedAStatus::getExceptionCode, EX_NONE),
1339*795d594fSAndroid Build Coastguard Worker AllOf(Property(&ndk::ScopedAStatus::getExceptionCode, EX_SERVICE_SPECIFIC),
1340*795d594fSAndroid Build Coastguard Worker Property(&ndk::ScopedAStatus::getMessage, HasSubstr("Failed to chown")))));
1341*795d594fSAndroid Build Coastguard Worker }
1342*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptGidMatchesGid)1343*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptGidMatchesGid) {
1344*795d594fSAndroid Build Coastguard Worker output_artifacts_.permissionSettings.fileFsPermission = {
1345*795d594fSAndroid Build Coastguard Worker .uid = 123, .gid = 456, .isOtherReadable = false};
1346*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_fstat_, Call(_, _)).WillRepeatedly(fstat); // For profile.
1347*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_fstat_, Call(FdOf(dex_file_), _))
1348*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(SetArgPointee<1>((struct stat){
1349*795d594fSAndroid Build Coastguard Worker .st_mode = S_IRUSR | S_IRGRP, .st_uid = 123, .st_gid = 456}),
1350*795d594fSAndroid Build Coastguard Worker Return(0)));
1351*795d594fSAndroid Build Coastguard Worker ON_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _)).WillByDefault(Return(0));
1352*795d594fSAndroid Build Coastguard Worker // It's okay to fail on chown. This happens when the test is not run as root.
1353*795d594fSAndroid Build Coastguard Worker RunDexopt(AnyOf(Property(&ndk::ScopedAStatus::getExceptionCode, EX_NONE),
1354*795d594fSAndroid Build Coastguard Worker AllOf(Property(&ndk::ScopedAStatus::getExceptionCode, EX_SERVICE_SPECIFIC),
1355*795d594fSAndroid Build Coastguard Worker Property(&ndk::ScopedAStatus::getMessage, HasSubstr("Failed to chown")))));
1356*795d594fSAndroid Build Coastguard Worker }
1357*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptUidGidChangeOk)1358*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptUidGidChangeOk) {
1359*795d594fSAndroid Build Coastguard Worker // The dex file is other-readable, so we don't check uid and gid.
1360*795d594fSAndroid Build Coastguard Worker output_artifacts_.permissionSettings.fileFsPermission = {
1361*795d594fSAndroid Build Coastguard Worker .uid = 12345, .gid = 12345, .isOtherReadable = false};
1362*795d594fSAndroid Build Coastguard Worker ON_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _)).WillByDefault(Return(0));
1363*795d594fSAndroid Build Coastguard Worker // It's okay to fail on chown. This happens when the test is not run as root.
1364*795d594fSAndroid Build Coastguard Worker RunDexopt(AnyOf(Property(&ndk::ScopedAStatus::getExceptionCode, EX_NONE),
1365*795d594fSAndroid Build Coastguard Worker AllOf(Property(&ndk::ScopedAStatus::getExceptionCode, EX_SERVICE_SPECIFIC),
1366*795d594fSAndroid Build Coastguard Worker Property(&ndk::ScopedAStatus::getMessage, HasSubstr("Failed to chown")))));
1367*795d594fSAndroid Build Coastguard Worker }
1368*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,dexoptNoUidGidChange)1369*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, dexoptNoUidGidChange) {
1370*795d594fSAndroid Build Coastguard Worker output_artifacts_.permissionSettings.fileFsPermission = {
1371*795d594fSAndroid Build Coastguard Worker .uid = -1, .gid = -1, .isOtherReadable = false};
1372*795d594fSAndroid Build Coastguard Worker dex_file_other_readable_ = false;
1373*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _)).WillOnce(Return(0));
1374*795d594fSAndroid Build Coastguard Worker RunDexopt();
1375*795d594fSAndroid Build Coastguard Worker }
1376*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,isProfileUsable)1377*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, isProfileUsable) {
1378*795d594fSAndroid Build Coastguard Worker std::string profile_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
1379*795d594fSAndroid Build Coastguard Worker CreateFile(profile_file);
1380*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
1381*795d594fSAndroid Build Coastguard Worker
1382*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
1383*795d594fSAndroid Build Coastguard Worker *mock_exec_utils_,
1384*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
1385*795d594fSAndroid Build Coastguard Worker AllOf(WhenSplitBy(
1386*795d594fSAndroid Build Coastguard Worker "--",
1387*795d594fSAndroid Build Coastguard Worker AllOf(Contains(art_root_ + "/bin/art_exec"), Contains("--drop-capabilities")),
1388*795d594fSAndroid Build Coastguard Worker AllOf(Contains(art_root_ + "/bin/profman"),
1389*795d594fSAndroid Build Coastguard Worker Contains(Flag("--reference-profile-file-fd=", FdOf(profile_file))),
1390*795d594fSAndroid Build Coastguard Worker Contains(Flag("--apk-fd=", FdOf(dex_file_))))),
1391*795d594fSAndroid Build Coastguard Worker HasKeepFdsFor("--reference-profile-file-fd=", "--apk-fd=")),
1392*795d594fSAndroid Build Coastguard Worker _,
1393*795d594fSAndroid Build Coastguard Worker _))
1394*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(ProfmanResult::kSkipCompilationSmallDelta));
1395*795d594fSAndroid Build Coastguard Worker
1396*795d594fSAndroid Build Coastguard Worker bool result;
1397*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(artd_->isProfileUsable(profile_path_.value(), dex_file_, &result).isOk());
1398*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(result);
1399*795d594fSAndroid Build Coastguard Worker }
1400*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,isProfileUsableFalse)1401*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, isProfileUsableFalse) {
1402*795d594fSAndroid Build Coastguard Worker std::string profile_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
1403*795d594fSAndroid Build Coastguard Worker CreateFile(profile_file);
1404*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
1405*795d594fSAndroid Build Coastguard Worker
1406*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _))
1407*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(ProfmanResult::kSkipCompilationEmptyProfiles));
1408*795d594fSAndroid Build Coastguard Worker
1409*795d594fSAndroid Build Coastguard Worker bool result;
1410*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(artd_->isProfileUsable(profile_path_.value(), dex_file_, &result).isOk());
1411*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(result);
1412*795d594fSAndroid Build Coastguard Worker }
1413*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,isProfileUsableNotFound)1414*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, isProfileUsableNotFound) {
1415*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
1416*795d594fSAndroid Build Coastguard Worker
1417*795d594fSAndroid Build Coastguard Worker bool result;
1418*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(artd_->isProfileUsable(profile_path_.value(), dex_file_, &result).isOk());
1419*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(result);
1420*795d594fSAndroid Build Coastguard Worker }
1421*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,isProfileUsableFailed)1422*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, isProfileUsableFailed) {
1423*795d594fSAndroid Build Coastguard Worker std::string profile_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
1424*795d594fSAndroid Build Coastguard Worker CreateFile(profile_file);
1425*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
1426*795d594fSAndroid Build Coastguard Worker
1427*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _)).WillOnce(Return(100));
1428*795d594fSAndroid Build Coastguard Worker
1429*795d594fSAndroid Build Coastguard Worker bool result;
1430*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus status = artd_->isProfileUsable(profile_path_.value(), dex_file_, &result);
1431*795d594fSAndroid Build Coastguard Worker
1432*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(status.isOk());
1433*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(status.getExceptionCode(), EX_SERVICE_SPECIFIC);
1434*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(status.getMessage(), HasSubstr("profman returned an unexpected code: 100"));
1435*795d594fSAndroid Build Coastguard Worker }
1436*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,copyAndRewriteProfileSuccess)1437*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, copyAndRewriteProfileSuccess) {
1438*795d594fSAndroid Build Coastguard Worker std::string src_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
1439*795d594fSAndroid Build Coastguard Worker CreateFile(src_file, "valid_profile");
1440*795d594fSAndroid Build Coastguard Worker
1441*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
1442*795d594fSAndroid Build Coastguard Worker
1443*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
1444*795d594fSAndroid Build Coastguard Worker *mock_exec_utils_,
1445*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
1446*795d594fSAndroid Build Coastguard Worker AllOf(WhenSplitBy(
1447*795d594fSAndroid Build Coastguard Worker "--",
1448*795d594fSAndroid Build Coastguard Worker AllOf(Contains(art_root_ + "/bin/art_exec"), Contains("--drop-capabilities")),
1449*795d594fSAndroid Build Coastguard Worker AllOf(Contains(art_root_ + "/bin/profman"),
1450*795d594fSAndroid Build Coastguard Worker Contains("--copy-and-update-profile-key"),
1451*795d594fSAndroid Build Coastguard Worker Contains(Flag("--profile-file-fd=", FdOf(src_file))),
1452*795d594fSAndroid Build Coastguard Worker Contains(Flag("--apk-fd=", FdOf(dex_file_))))),
1453*795d594fSAndroid Build Coastguard Worker HasKeepFdsFor("--profile-file-fd=", "--reference-profile-file-fd=", "--apk-fd=")),
1454*795d594fSAndroid Build Coastguard Worker _,
1455*795d594fSAndroid Build Coastguard Worker _))
1456*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(WithArg<0>(WriteToFdFlag("--reference-profile-file-fd=", "def")),
1457*795d594fSAndroid Build Coastguard Worker Return(ProfmanResult::kCopyAndUpdateSuccess)));
1458*795d594fSAndroid Build Coastguard Worker
1459*795d594fSAndroid Build Coastguard Worker auto [result, dst] = OR_FAIL(RunCopyAndRewriteProfile());
1460*795d594fSAndroid Build Coastguard Worker
1461*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result.status, CopyAndRewriteProfileResult::Status::SUCCESS);
1462*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.id, Not(IsEmpty()));
1463*795d594fSAndroid Build Coastguard Worker std::string real_path = OR_FATAL(BuildTmpProfilePath(dst.profilePath));
1464*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(dst.profilePath.tmpPath, real_path);
1465*795d594fSAndroid Build Coastguard Worker CheckContent(real_path, "def");
1466*795d594fSAndroid Build Coastguard Worker }
1467*795d594fSAndroid Build Coastguard Worker
1468*795d594fSAndroid Build Coastguard Worker // The input is a plain profile file in the wrong format.
TEST_F(ArtdTest,copyAndRewriteProfileBadProfileWrongFormat)1469*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, copyAndRewriteProfileBadProfileWrongFormat) {
1470*795d594fSAndroid Build Coastguard Worker std::string src_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
1471*795d594fSAndroid Build Coastguard Worker CreateFile(src_file, "wrong_format");
1472*795d594fSAndroid Build Coastguard Worker
1473*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
1474*795d594fSAndroid Build Coastguard Worker
1475*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _))
1476*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(ProfmanResult::kCopyAndUpdateErrorFailedToLoadProfile));
1477*795d594fSAndroid Build Coastguard Worker
1478*795d594fSAndroid Build Coastguard Worker auto [result, dst] = OR_FAIL(RunCopyAndRewriteProfile());
1479*795d594fSAndroid Build Coastguard Worker
1480*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result.status, CopyAndRewriteProfileResult::Status::BAD_PROFILE);
1481*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(result.errorMsg,
1482*795d594fSAndroid Build Coastguard Worker HasSubstr("The profile is in the wrong format or an I/O error has occurred"));
1483*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.id, IsEmpty());
1484*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.tmpPath, IsEmpty());
1485*795d594fSAndroid Build Coastguard Worker }
1486*795d594fSAndroid Build Coastguard Worker
1487*795d594fSAndroid Build Coastguard Worker // The input is a plain profile file that doesn't match the APK.
TEST_F(ArtdTest,copyAndRewriteProfileBadProfileNoMatch)1488*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, copyAndRewriteProfileBadProfileNoMatch) {
1489*795d594fSAndroid Build Coastguard Worker std::string src_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
1490*795d594fSAndroid Build Coastguard Worker CreateFile(src_file, "no_match");
1491*795d594fSAndroid Build Coastguard Worker
1492*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
1493*795d594fSAndroid Build Coastguard Worker
1494*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _))
1495*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(ProfmanResult::kCopyAndUpdateNoMatch));
1496*795d594fSAndroid Build Coastguard Worker
1497*795d594fSAndroid Build Coastguard Worker auto [result, dst] = OR_FAIL(RunCopyAndRewriteProfile());
1498*795d594fSAndroid Build Coastguard Worker
1499*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result.status, CopyAndRewriteProfileResult::Status::BAD_PROFILE);
1500*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(result.errorMsg, HasSubstr("The profile does not match the APK"));
1501*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.id, IsEmpty());
1502*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.tmpPath, IsEmpty());
1503*795d594fSAndroid Build Coastguard Worker }
1504*795d594fSAndroid Build Coastguard Worker
1505*795d594fSAndroid Build Coastguard Worker // The input is a plain profile file that is empty.
TEST_F(ArtdTest,copyAndRewriteProfileNoProfileEmpty)1506*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, copyAndRewriteProfileNoProfileEmpty) {
1507*795d594fSAndroid Build Coastguard Worker std::string src_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
1508*795d594fSAndroid Build Coastguard Worker CreateFile(src_file, "");
1509*795d594fSAndroid Build Coastguard Worker
1510*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
1511*795d594fSAndroid Build Coastguard Worker
1512*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _))
1513*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(ProfmanResult::kCopyAndUpdateNoMatch));
1514*795d594fSAndroid Build Coastguard Worker
1515*795d594fSAndroid Build Coastguard Worker auto [result, dst] = OR_FAIL(RunCopyAndRewriteProfile());
1516*795d594fSAndroid Build Coastguard Worker
1517*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result.status, CopyAndRewriteProfileResult::Status::NO_PROFILE);
1518*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.id, IsEmpty());
1519*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.tmpPath, IsEmpty());
1520*795d594fSAndroid Build Coastguard Worker }
1521*795d594fSAndroid Build Coastguard Worker
1522*795d594fSAndroid Build Coastguard Worker // The input does not exist.
TEST_F(ArtdTest,copyAndRewriteProfileNoProfileNoFile)1523*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, copyAndRewriteProfileNoProfileNoFile) {
1524*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
1525*795d594fSAndroid Build Coastguard Worker
1526*795d594fSAndroid Build Coastguard Worker auto [result, dst] = OR_FAIL(RunCopyAndRewriteProfile());
1527*795d594fSAndroid Build Coastguard Worker
1528*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result.status, CopyAndRewriteProfileResult::Status::NO_PROFILE);
1529*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.id, IsEmpty());
1530*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.tmpPath, IsEmpty());
1531*795d594fSAndroid Build Coastguard Worker }
1532*795d594fSAndroid Build Coastguard Worker
1533*795d594fSAndroid Build Coastguard Worker // The input is a dm file with a profile entry in the wrong format.
TEST_F(ArtdTest,copyAndRewriteProfileNoProfileDmWrongFormat)1534*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, copyAndRewriteProfileNoProfileDmWrongFormat) {
1535*795d594fSAndroid Build Coastguard Worker std::string src_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
1536*795d594fSAndroid Build Coastguard Worker CreateZipWithSingleEntry(src_file, "primary.prof", "wrong_format");
1537*795d594fSAndroid Build Coastguard Worker
1538*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
1539*795d594fSAndroid Build Coastguard Worker
1540*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _))
1541*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(ProfmanResult::kCopyAndUpdateErrorFailedToLoadProfile));
1542*795d594fSAndroid Build Coastguard Worker
1543*795d594fSAndroid Build Coastguard Worker auto [result, dst] = OR_FAIL(RunCopyAndRewriteProfile());
1544*795d594fSAndroid Build Coastguard Worker
1545*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result.status, CopyAndRewriteProfileResult::Status::BAD_PROFILE);
1546*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(result.errorMsg,
1547*795d594fSAndroid Build Coastguard Worker HasSubstr("The profile is in the wrong format or an I/O error has occurred"));
1548*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.id, IsEmpty());
1549*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.tmpPath, IsEmpty());
1550*795d594fSAndroid Build Coastguard Worker }
1551*795d594fSAndroid Build Coastguard Worker
1552*795d594fSAndroid Build Coastguard Worker // The input is a dm file with a profile entry that doesn't match the APK.
TEST_F(ArtdTest,copyAndRewriteProfileNoProfileDmNoMatch)1553*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, copyAndRewriteProfileNoProfileDmNoMatch) {
1554*795d594fSAndroid Build Coastguard Worker std::string src_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
1555*795d594fSAndroid Build Coastguard Worker CreateZipWithSingleEntry(src_file, "primary.prof", "no_match");
1556*795d594fSAndroid Build Coastguard Worker
1557*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
1558*795d594fSAndroid Build Coastguard Worker
1559*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _))
1560*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(ProfmanResult::kCopyAndUpdateNoMatch));
1561*795d594fSAndroid Build Coastguard Worker
1562*795d594fSAndroid Build Coastguard Worker auto [result, dst] = OR_FAIL(RunCopyAndRewriteProfile());
1563*795d594fSAndroid Build Coastguard Worker
1564*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result.status, CopyAndRewriteProfileResult::Status::BAD_PROFILE);
1565*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(result.errorMsg, HasSubstr("The profile does not match the APK"));
1566*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.id, IsEmpty());
1567*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.tmpPath, IsEmpty());
1568*795d594fSAndroid Build Coastguard Worker }
1569*795d594fSAndroid Build Coastguard Worker
1570*795d594fSAndroid Build Coastguard Worker // The input is a dm file with a profile entry that is empty.
TEST_F(ArtdTest,copyAndRewriteProfileNoProfileDmEmpty)1571*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, copyAndRewriteProfileNoProfileDmEmpty) {
1572*795d594fSAndroid Build Coastguard Worker std::string src_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
1573*795d594fSAndroid Build Coastguard Worker CreateZipWithSingleEntry(src_file, "primary.prof");
1574*795d594fSAndroid Build Coastguard Worker
1575*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
1576*795d594fSAndroid Build Coastguard Worker
1577*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _))
1578*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(ProfmanResult::kCopyAndUpdateNoMatch));
1579*795d594fSAndroid Build Coastguard Worker
1580*795d594fSAndroid Build Coastguard Worker auto [result, dst] = OR_FAIL(RunCopyAndRewriteProfile());
1581*795d594fSAndroid Build Coastguard Worker
1582*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result.status, CopyAndRewriteProfileResult::Status::NO_PROFILE);
1583*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.id, IsEmpty());
1584*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.tmpPath, IsEmpty());
1585*795d594fSAndroid Build Coastguard Worker }
1586*795d594fSAndroid Build Coastguard Worker
1587*795d594fSAndroid Build Coastguard Worker // The input is a dm file without a profile entry.
TEST_F(ArtdTest,copyAndRewriteProfileNoProfileDmNoEntry)1588*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, copyAndRewriteProfileNoProfileDmNoEntry) {
1589*795d594fSAndroid Build Coastguard Worker std::string src_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
1590*795d594fSAndroid Build Coastguard Worker CreateZipWithSingleEntry(src_file, "primary.vdex");
1591*795d594fSAndroid Build Coastguard Worker
1592*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
1593*795d594fSAndroid Build Coastguard Worker
1594*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _))
1595*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(ProfmanResult::kCopyAndUpdateNoMatch));
1596*795d594fSAndroid Build Coastguard Worker
1597*795d594fSAndroid Build Coastguard Worker auto [result, dst] = OR_FAIL(RunCopyAndRewriteProfile());
1598*795d594fSAndroid Build Coastguard Worker
1599*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result.status, CopyAndRewriteProfileResult::Status::NO_PROFILE);
1600*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.id, IsEmpty());
1601*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.tmpPath, IsEmpty());
1602*795d594fSAndroid Build Coastguard Worker }
1603*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,copyAndRewriteProfileException)1604*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, copyAndRewriteProfileException) {
1605*795d594fSAndroid Build Coastguard Worker std::string src_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
1606*795d594fSAndroid Build Coastguard Worker CreateFile(src_file, "valid_profile");
1607*795d594fSAndroid Build Coastguard Worker
1608*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
1609*795d594fSAndroid Build Coastguard Worker
1610*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _)).WillOnce(Return(100));
1611*795d594fSAndroid Build Coastguard Worker
1612*795d594fSAndroid Build Coastguard Worker auto [status, dst] = OR_FAIL(RunCopyAndRewriteProfile</*kExpectOk=*/false>());
1613*795d594fSAndroid Build Coastguard Worker
1614*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(status.isOk());
1615*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(status.getExceptionCode(), EX_SERVICE_SPECIFIC);
1616*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(status.getMessage(), HasSubstr("profman returned an unexpected code: 100"));
1617*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.id, IsEmpty());
1618*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.tmpPath, IsEmpty());
1619*795d594fSAndroid Build Coastguard Worker }
1620*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,copyAndRewriteEmbeddedProfileSuccess)1621*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, copyAndRewriteEmbeddedProfileSuccess) {
1622*795d594fSAndroid Build Coastguard Worker TEST_DISABLED_FOR_SHELL_WITHOUT_MEMFD_ACCESS();
1623*795d594fSAndroid Build Coastguard Worker
1624*795d594fSAndroid Build Coastguard Worker CreateZipWithSingleEntry(dex_file_, "assets/art-profile/baseline.prof", "valid_profile");
1625*795d594fSAndroid Build Coastguard Worker
1626*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
1627*795d594fSAndroid Build Coastguard Worker *mock_exec_utils_,
1628*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
1629*795d594fSAndroid Build Coastguard Worker AllOf(WhenSplitBy(
1630*795d594fSAndroid Build Coastguard Worker "--",
1631*795d594fSAndroid Build Coastguard Worker AllOf(Contains(art_root_ + "/bin/art_exec"), Contains("--drop-capabilities")),
1632*795d594fSAndroid Build Coastguard Worker AllOf(Contains(art_root_ + "/bin/profman"),
1633*795d594fSAndroid Build Coastguard Worker Contains("--copy-and-update-profile-key"),
1634*795d594fSAndroid Build Coastguard Worker Contains(Flag("--profile-file-fd=", FdHasContent("valid_profile"))),
1635*795d594fSAndroid Build Coastguard Worker Contains(Flag("--apk-fd=", FdOf(dex_file_))))),
1636*795d594fSAndroid Build Coastguard Worker HasKeepFdsFor("--profile-file-fd=", "--reference-profile-file-fd=", "--apk-fd=")),
1637*795d594fSAndroid Build Coastguard Worker _,
1638*795d594fSAndroid Build Coastguard Worker _))
1639*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(WithArg<0>(WriteToFdFlag("--reference-profile-file-fd=", "def")),
1640*795d594fSAndroid Build Coastguard Worker Return(ProfmanResult::kCopyAndUpdateSuccess)));
1641*795d594fSAndroid Build Coastguard Worker
1642*795d594fSAndroid Build Coastguard Worker auto [result, dst] = OR_FAIL(RunCopyAndRewriteEmbeddedProfile());
1643*795d594fSAndroid Build Coastguard Worker
1644*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result.status, CopyAndRewriteProfileResult::Status::SUCCESS);
1645*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.id, Not(IsEmpty()));
1646*795d594fSAndroid Build Coastguard Worker std::string real_path = OR_FATAL(BuildTmpProfilePath(dst.profilePath));
1647*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(dst.profilePath.tmpPath, real_path);
1648*795d594fSAndroid Build Coastguard Worker CheckContent(real_path, "def");
1649*795d594fSAndroid Build Coastguard Worker }
1650*795d594fSAndroid Build Coastguard Worker
1651*795d594fSAndroid Build Coastguard Worker // The input is a plain dex file.
TEST_F(ArtdTest,copyAndRewriteEmbeddedProfileNoProfilePlainDex)1652*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, copyAndRewriteEmbeddedProfileNoProfilePlainDex) {
1653*795d594fSAndroid Build Coastguard Worker TEST_DISABLED_FOR_SHELL_WITHOUT_MEMFD_ACCESS();
1654*795d594fSAndroid Build Coastguard Worker
1655*795d594fSAndroid Build Coastguard Worker constexpr const char* kDexMagic = "dex\n";
1656*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_, kDexMagic + "dex_code"s);
1657*795d594fSAndroid Build Coastguard Worker
1658*795d594fSAndroid Build Coastguard Worker auto [result, dst] = OR_FAIL(RunCopyAndRewriteEmbeddedProfile());
1659*795d594fSAndroid Build Coastguard Worker
1660*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result.status, CopyAndRewriteProfileResult::Status::NO_PROFILE);
1661*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.id, IsEmpty());
1662*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.tmpPath, IsEmpty());
1663*795d594fSAndroid Build Coastguard Worker }
1664*795d594fSAndroid Build Coastguard Worker
1665*795d594fSAndroid Build Coastguard Worker // The input is neither a zip nor a plain dex file.
TEST_F(ArtdTest,copyAndRewriteEmbeddedProfileNotZipNotDex)1666*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, copyAndRewriteEmbeddedProfileNotZipNotDex) {
1667*795d594fSAndroid Build Coastguard Worker TEST_DISABLED_FOR_SHELL_WITHOUT_MEMFD_ACCESS();
1668*795d594fSAndroid Build Coastguard Worker
1669*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_, "wrong_format");
1670*795d594fSAndroid Build Coastguard Worker
1671*795d594fSAndroid Build Coastguard Worker auto [status, dst] = OR_FAIL(RunCopyAndRewriteEmbeddedProfile</*kExpectOk=*/false>());
1672*795d594fSAndroid Build Coastguard Worker
1673*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(status.isOk());
1674*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(status.getExceptionCode(), EX_SERVICE_SPECIFIC);
1675*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(status.getMessage(), HasSubstr("File is neither a zip file nor a plain dex file"));
1676*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.id, IsEmpty());
1677*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.tmpPath, IsEmpty());
1678*795d594fSAndroid Build Coastguard Worker }
1679*795d594fSAndroid Build Coastguard Worker
1680*795d594fSAndroid Build Coastguard Worker // The input is a zip file without a profile entry.
TEST_F(ArtdTest,copyAndRewriteEmbeddedProfileNoProfileZipNoEntry)1681*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, copyAndRewriteEmbeddedProfileNoProfileZipNoEntry) {
1682*795d594fSAndroid Build Coastguard Worker TEST_DISABLED_FOR_SHELL_WITHOUT_MEMFD_ACCESS();
1683*795d594fSAndroid Build Coastguard Worker
1684*795d594fSAndroid Build Coastguard Worker CreateZipWithSingleEntry(dex_file_, "classes.dex", "dex_code");
1685*795d594fSAndroid Build Coastguard Worker
1686*795d594fSAndroid Build Coastguard Worker auto [result, dst] = OR_FAIL(RunCopyAndRewriteEmbeddedProfile());
1687*795d594fSAndroid Build Coastguard Worker
1688*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result.status, CopyAndRewriteProfileResult::Status::NO_PROFILE);
1689*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.id, IsEmpty());
1690*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.tmpPath, IsEmpty());
1691*795d594fSAndroid Build Coastguard Worker }
1692*795d594fSAndroid Build Coastguard Worker
1693*795d594fSAndroid Build Coastguard Worker // The input is a zip file with a profile entry that doesn't match itself.
TEST_F(ArtdTest,copyAndRewriteEmbeddedProfileBadProfileNoMatch)1694*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, copyAndRewriteEmbeddedProfileBadProfileNoMatch) {
1695*795d594fSAndroid Build Coastguard Worker TEST_DISABLED_FOR_SHELL_WITHOUT_MEMFD_ACCESS();
1696*795d594fSAndroid Build Coastguard Worker
1697*795d594fSAndroid Build Coastguard Worker CreateZipWithSingleEntry(dex_file_, "assets/art-profile/baseline.prof", "no_match");
1698*795d594fSAndroid Build Coastguard Worker
1699*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_, _, _))
1700*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(ProfmanResult::kCopyAndUpdateNoMatch));
1701*795d594fSAndroid Build Coastguard Worker
1702*795d594fSAndroid Build Coastguard Worker auto [result, dst] = OR_FAIL(RunCopyAndRewriteEmbeddedProfile());
1703*795d594fSAndroid Build Coastguard Worker
1704*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result.status, CopyAndRewriteProfileResult::Status::BAD_PROFILE);
1705*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(result.errorMsg, HasSubstr("The profile does not match the APK"));
1706*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.id, IsEmpty());
1707*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.tmpPath, IsEmpty());
1708*795d594fSAndroid Build Coastguard Worker }
1709*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,commitTmpProfile)1710*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, commitTmpProfile) {
1711*795d594fSAndroid Build Coastguard Worker std::string tmp_profile_file = OR_FATAL(BuildTmpProfilePath(tmp_profile_path_));
1712*795d594fSAndroid Build Coastguard Worker CreateFile(tmp_profile_file);
1713*795d594fSAndroid Build Coastguard Worker
1714*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(artd_->commitTmpProfile(tmp_profile_path_).isOk());
1715*795d594fSAndroid Build Coastguard Worker
1716*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(std::filesystem::exists(tmp_profile_file));
1717*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(std::filesystem::exists(OR_FATAL(BuildFinalProfilePath(tmp_profile_path_))));
1718*795d594fSAndroid Build Coastguard Worker }
1719*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,commitTmpProfileFailed)1720*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, commitTmpProfileFailed) {
1721*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus status = artd_->commitTmpProfile(tmp_profile_path_);
1722*795d594fSAndroid Build Coastguard Worker
1723*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(status.isOk());
1724*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(status.getExceptionCode(), EX_SERVICE_SPECIFIC);
1725*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(
1726*795d594fSAndroid Build Coastguard Worker status.getMessage(),
1727*795d594fSAndroid Build Coastguard Worker ContainsRegex(R"re(Failed to move .*primary\.prof\.12345\.tmp.* to .*primary\.prof)re"));
1728*795d594fSAndroid Build Coastguard Worker
1729*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(std::filesystem::exists(OR_FATAL(BuildFinalProfilePath(tmp_profile_path_))));
1730*795d594fSAndroid Build Coastguard Worker }
1731*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,deleteProfile)1732*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, deleteProfile) {
1733*795d594fSAndroid Build Coastguard Worker std::string profile_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
1734*795d594fSAndroid Build Coastguard Worker CreateFile(profile_file);
1735*795d594fSAndroid Build Coastguard Worker
1736*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(artd_->deleteProfile(profile_path_.value()).isOk());
1737*795d594fSAndroid Build Coastguard Worker
1738*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(std::filesystem::exists(profile_file));
1739*795d594fSAndroid Build Coastguard Worker }
1740*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,deleteProfileDoesNotExist)1741*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, deleteProfileDoesNotExist) {
1742*795d594fSAndroid Build Coastguard Worker auto scoped_set_logger = ScopedSetLogger(mock_logger_.AsStdFunction());
1743*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_logger_, Call).Times(0);
1744*795d594fSAndroid Build Coastguard Worker
1745*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(artd_->deleteProfile(profile_path_.value()).isOk());
1746*795d594fSAndroid Build Coastguard Worker }
1747*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,deleteProfileFailed)1748*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, deleteProfileFailed) {
1749*795d594fSAndroid Build Coastguard Worker auto scoped_set_logger = ScopedSetLogger(mock_logger_.AsStdFunction());
1750*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
1751*795d594fSAndroid Build Coastguard Worker mock_logger_,
1752*795d594fSAndroid Build Coastguard Worker Call(_, _, _, _, _, ContainsRegex(R"re(Failed to remove .*primary\.prof\.12345\.tmp)re")));
1753*795d594fSAndroid Build Coastguard Worker
1754*795d594fSAndroid Build Coastguard Worker std::string profile_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
1755*795d594fSAndroid Build Coastguard Worker auto scoped_inaccessible = ScopedInaccessible(std::filesystem::path(profile_file).parent_path());
1756*795d594fSAndroid Build Coastguard Worker auto scoped_unroot = ScopedUnroot();
1757*795d594fSAndroid Build Coastguard Worker
1758*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(artd_->deleteProfile(profile_path_.value()).isOk());
1759*795d594fSAndroid Build Coastguard Worker }
1760*795d594fSAndroid Build Coastguard Worker
1761*795d594fSAndroid Build Coastguard Worker class ArtdGetVisibilityTest : public ArtdTest {
1762*795d594fSAndroid Build Coastguard Worker protected:
1763*795d594fSAndroid Build Coastguard Worker template <typename PathType>
1764*795d594fSAndroid Build Coastguard Worker using Method = ndk::ScopedAStatus (Artd::*)(const PathType&, FileVisibility*);
1765*795d594fSAndroid Build Coastguard Worker
1766*795d594fSAndroid Build Coastguard Worker template <typename PathType>
TestGetVisibilityOtherReadable(Method<PathType> method,const PathType & input,const std::string & path)1767*795d594fSAndroid Build Coastguard Worker void TestGetVisibilityOtherReadable(Method<PathType> method,
1768*795d594fSAndroid Build Coastguard Worker const PathType& input,
1769*795d594fSAndroid Build Coastguard Worker const std::string& path) {
1770*795d594fSAndroid Build Coastguard Worker CreateFile(path);
1771*795d594fSAndroid Build Coastguard Worker std::filesystem::permissions(
1772*795d594fSAndroid Build Coastguard Worker path, std::filesystem::perms::others_read, std::filesystem::perm_options::add);
1773*795d594fSAndroid Build Coastguard Worker
1774*795d594fSAndroid Build Coastguard Worker FileVisibility result;
1775*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(((*artd_).*method)(input, &result).isOk());
1776*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result, FileVisibility::OTHER_READABLE);
1777*795d594fSAndroid Build Coastguard Worker }
1778*795d594fSAndroid Build Coastguard Worker
1779*795d594fSAndroid Build Coastguard Worker template <typename PathType>
TestGetVisibilityNotOtherReadable(Method<PathType> method,const PathType & input,const std::string & path)1780*795d594fSAndroid Build Coastguard Worker void TestGetVisibilityNotOtherReadable(Method<PathType> method,
1781*795d594fSAndroid Build Coastguard Worker const PathType& input,
1782*795d594fSAndroid Build Coastguard Worker const std::string& path) {
1783*795d594fSAndroid Build Coastguard Worker CreateFile(path);
1784*795d594fSAndroid Build Coastguard Worker std::filesystem::permissions(
1785*795d594fSAndroid Build Coastguard Worker path, std::filesystem::perms::others_read, std::filesystem::perm_options::remove);
1786*795d594fSAndroid Build Coastguard Worker
1787*795d594fSAndroid Build Coastguard Worker FileVisibility result;
1788*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(((*artd_).*method)(input, &result).isOk());
1789*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result, FileVisibility::NOT_OTHER_READABLE);
1790*795d594fSAndroid Build Coastguard Worker }
1791*795d594fSAndroid Build Coastguard Worker
1792*795d594fSAndroid Build Coastguard Worker template <typename PathType>
TestGetVisibilityNotFound(Method<PathType> method,const PathType & input)1793*795d594fSAndroid Build Coastguard Worker void TestGetVisibilityNotFound(Method<PathType> method, const PathType& input) {
1794*795d594fSAndroid Build Coastguard Worker FileVisibility result;
1795*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(((*artd_).*method)(input, &result).isOk());
1796*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result, FileVisibility::NOT_FOUND);
1797*795d594fSAndroid Build Coastguard Worker }
1798*795d594fSAndroid Build Coastguard Worker
1799*795d594fSAndroid Build Coastguard Worker template <typename PathType>
TestGetVisibilityPermissionDenied(Method<PathType> method,const PathType & input,const std::string & path)1800*795d594fSAndroid Build Coastguard Worker void TestGetVisibilityPermissionDenied(Method<PathType> method,
1801*795d594fSAndroid Build Coastguard Worker const PathType& input,
1802*795d594fSAndroid Build Coastguard Worker const std::string& path) {
1803*795d594fSAndroid Build Coastguard Worker CreateFile(path);
1804*795d594fSAndroid Build Coastguard Worker
1805*795d594fSAndroid Build Coastguard Worker auto scoped_inaccessible = ScopedInaccessible(std::filesystem::path(path).parent_path());
1806*795d594fSAndroid Build Coastguard Worker auto scoped_unroot = ScopedUnroot();
1807*795d594fSAndroid Build Coastguard Worker
1808*795d594fSAndroid Build Coastguard Worker FileVisibility result;
1809*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus status = ((*artd_).*method)(input, &result);
1810*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(status.isOk());
1811*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(status.getExceptionCode(), EX_SERVICE_SPECIFIC);
1812*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(status.getMessage(), HasSubstr("Failed to get status of"));
1813*795d594fSAndroid Build Coastguard Worker }
1814*795d594fSAndroid Build Coastguard Worker };
1815*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdGetVisibilityTest,getProfileVisibilityOtherReadable)1816*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdGetVisibilityTest, getProfileVisibilityOtherReadable) {
1817*795d594fSAndroid Build Coastguard Worker TestGetVisibilityOtherReadable(&Artd::getProfileVisibility,
1818*795d594fSAndroid Build Coastguard Worker profile_path_.value(),
1819*795d594fSAndroid Build Coastguard Worker OR_FATAL(BuildProfileOrDmPath(profile_path_.value())));
1820*795d594fSAndroid Build Coastguard Worker }
1821*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdGetVisibilityTest,getProfileVisibilityNotOtherReadable)1822*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdGetVisibilityTest, getProfileVisibilityNotOtherReadable) {
1823*795d594fSAndroid Build Coastguard Worker TestGetVisibilityNotOtherReadable(&Artd::getProfileVisibility,
1824*795d594fSAndroid Build Coastguard Worker profile_path_.value(),
1825*795d594fSAndroid Build Coastguard Worker OR_FATAL(BuildProfileOrDmPath(profile_path_.value())));
1826*795d594fSAndroid Build Coastguard Worker }
1827*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdGetVisibilityTest,getProfileVisibilityNotFound)1828*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdGetVisibilityTest, getProfileVisibilityNotFound) {
1829*795d594fSAndroid Build Coastguard Worker TestGetVisibilityNotFound(&Artd::getProfileVisibility, profile_path_.value());
1830*795d594fSAndroid Build Coastguard Worker }
1831*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdGetVisibilityTest,getProfileVisibilityPermissionDenied)1832*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdGetVisibilityTest, getProfileVisibilityPermissionDenied) {
1833*795d594fSAndroid Build Coastguard Worker TestGetVisibilityPermissionDenied(&Artd::getProfileVisibility,
1834*795d594fSAndroid Build Coastguard Worker profile_path_.value(),
1835*795d594fSAndroid Build Coastguard Worker OR_FATAL(BuildProfileOrDmPath(profile_path_.value())));
1836*795d594fSAndroid Build Coastguard Worker }
1837*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdGetVisibilityTest,getArtifactsVisibilityOtherReadable)1838*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdGetVisibilityTest, getArtifactsVisibilityOtherReadable) {
1839*795d594fSAndroid Build Coastguard Worker TestGetVisibilityOtherReadable(&Artd::getArtifactsVisibility,
1840*795d594fSAndroid Build Coastguard Worker artifacts_path_,
1841*795d594fSAndroid Build Coastguard Worker OR_FATAL(BuildArtifactsPath(artifacts_path_)).oat_path);
1842*795d594fSAndroid Build Coastguard Worker }
1843*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdGetVisibilityTest,getArtifactsVisibilityNotOtherReadable)1844*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdGetVisibilityTest, getArtifactsVisibilityNotOtherReadable) {
1845*795d594fSAndroid Build Coastguard Worker TestGetVisibilityNotOtherReadable(&Artd::getArtifactsVisibility,
1846*795d594fSAndroid Build Coastguard Worker artifacts_path_,
1847*795d594fSAndroid Build Coastguard Worker OR_FATAL(BuildArtifactsPath(artifacts_path_)).oat_path);
1848*795d594fSAndroid Build Coastguard Worker }
1849*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdGetVisibilityTest,getArtifactsVisibilityNotFound)1850*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdGetVisibilityTest, getArtifactsVisibilityNotFound) {
1851*795d594fSAndroid Build Coastguard Worker TestGetVisibilityNotFound(&Artd::getArtifactsVisibility, artifacts_path_);
1852*795d594fSAndroid Build Coastguard Worker }
1853*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdGetVisibilityTest,getArtifactsVisibilityPermissionDenied)1854*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdGetVisibilityTest, getArtifactsVisibilityPermissionDenied) {
1855*795d594fSAndroid Build Coastguard Worker TestGetVisibilityPermissionDenied(&Artd::getArtifactsVisibility,
1856*795d594fSAndroid Build Coastguard Worker artifacts_path_,
1857*795d594fSAndroid Build Coastguard Worker OR_FATAL(BuildArtifactsPath(artifacts_path_)).oat_path);
1858*795d594fSAndroid Build Coastguard Worker }
1859*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdGetVisibilityTest,getDexFileVisibilityOtherReadable)1860*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdGetVisibilityTest, getDexFileVisibilityOtherReadable) {
1861*795d594fSAndroid Build Coastguard Worker TestGetVisibilityOtherReadable(&Artd::getDexFileVisibility, dex_file_, dex_file_);
1862*795d594fSAndroid Build Coastguard Worker }
1863*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdGetVisibilityTest,getDexFileVisibilityNotOtherReadable)1864*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdGetVisibilityTest, getDexFileVisibilityNotOtherReadable) {
1865*795d594fSAndroid Build Coastguard Worker TestGetVisibilityNotOtherReadable(&Artd::getDexFileVisibility, dex_file_, dex_file_);
1866*795d594fSAndroid Build Coastguard Worker }
1867*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdGetVisibilityTest,getDexFileVisibilityNotFound)1868*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdGetVisibilityTest, getDexFileVisibilityNotFound) {
1869*795d594fSAndroid Build Coastguard Worker TestGetVisibilityNotFound(&Artd::getDexFileVisibility, dex_file_);
1870*795d594fSAndroid Build Coastguard Worker }
1871*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdGetVisibilityTest,getDexFileVisibilityPermissionDenied)1872*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdGetVisibilityTest, getDexFileVisibilityPermissionDenied) {
1873*795d594fSAndroid Build Coastguard Worker TestGetVisibilityPermissionDenied(&Artd::getDexFileVisibility, dex_file_, dex_file_);
1874*795d594fSAndroid Build Coastguard Worker }
1875*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdGetVisibilityTest,getDmFileVisibilityOtherReadable)1876*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdGetVisibilityTest, getDmFileVisibilityOtherReadable) {
1877*795d594fSAndroid Build Coastguard Worker TestGetVisibilityOtherReadable(&Artd::getDmFileVisibility,
1878*795d594fSAndroid Build Coastguard Worker dm_path_.value(),
1879*795d594fSAndroid Build Coastguard Worker OR_FATAL(BuildDexMetadataPath(dm_path_.value())));
1880*795d594fSAndroid Build Coastguard Worker }
1881*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdGetVisibilityTest,getDmFileVisibilityNotOtherReadable)1882*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdGetVisibilityTest, getDmFileVisibilityNotOtherReadable) {
1883*795d594fSAndroid Build Coastguard Worker TestGetVisibilityNotOtherReadable(&Artd::getDmFileVisibility,
1884*795d594fSAndroid Build Coastguard Worker dm_path_.value(),
1885*795d594fSAndroid Build Coastguard Worker OR_FATAL(BuildDexMetadataPath(dm_path_.value())));
1886*795d594fSAndroid Build Coastguard Worker }
1887*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdGetVisibilityTest,getDmFileVisibilityNotFound)1888*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdGetVisibilityTest, getDmFileVisibilityNotFound) {
1889*795d594fSAndroid Build Coastguard Worker TestGetVisibilityNotFound(&Artd::getDmFileVisibility, dm_path_.value());
1890*795d594fSAndroid Build Coastguard Worker }
1891*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdGetVisibilityTest,getDmFileVisibilityPermissionDenied)1892*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdGetVisibilityTest, getDmFileVisibilityPermissionDenied) {
1893*795d594fSAndroid Build Coastguard Worker TestGetVisibilityPermissionDenied(&Artd::getDmFileVisibility,
1894*795d594fSAndroid Build Coastguard Worker dm_path_.value(),
1895*795d594fSAndroid Build Coastguard Worker OR_FATAL(BuildDexMetadataPath(dm_path_.value())));
1896*795d594fSAndroid Build Coastguard Worker }
1897*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,mergeProfiles)1898*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, mergeProfiles) {
1899*795d594fSAndroid Build Coastguard Worker std::string reference_profile_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
1900*795d594fSAndroid Build Coastguard Worker CreateFile(reference_profile_file, "abc");
1901*795d594fSAndroid Build Coastguard Worker
1902*795d594fSAndroid Build Coastguard Worker // Doesn't exist.
1903*795d594fSAndroid Build Coastguard Worker PrimaryCurProfilePath profile_0_path{
1904*795d594fSAndroid Build Coastguard Worker .userId = 0, .packageName = "com.android.foo", .profileName = "primary"};
1905*795d594fSAndroid Build Coastguard Worker std::string profile_0_file = OR_FATAL(BuildPrimaryCurProfilePath(profile_0_path));
1906*795d594fSAndroid Build Coastguard Worker
1907*795d594fSAndroid Build Coastguard Worker PrimaryCurProfilePath profile_1_path{
1908*795d594fSAndroid Build Coastguard Worker .userId = 1, .packageName = "com.android.foo", .profileName = "primary"};
1909*795d594fSAndroid Build Coastguard Worker std::string profile_1_file = OR_FATAL(BuildPrimaryCurProfilePath(profile_1_path));
1910*795d594fSAndroid Build Coastguard Worker CreateFile(profile_1_file, "def");
1911*795d594fSAndroid Build Coastguard Worker
1912*795d594fSAndroid Build Coastguard Worker OutputProfile output_profile{.profilePath = tmp_profile_path_,
1913*795d594fSAndroid Build Coastguard Worker .fsPermission = FsPermission{.uid = -1, .gid = -1}};
1914*795d594fSAndroid Build Coastguard Worker output_profile.profilePath.id = "";
1915*795d594fSAndroid Build Coastguard Worker output_profile.profilePath.tmpPath = "";
1916*795d594fSAndroid Build Coastguard Worker
1917*795d594fSAndroid Build Coastguard Worker std::string dex_file_1 = scratch_path_ + "/a/b.apk";
1918*795d594fSAndroid Build Coastguard Worker std::string dex_file_2 = scratch_path_ + "/a/c.apk";
1919*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_1);
1920*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_2);
1921*795d594fSAndroid Build Coastguard Worker
1922*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
1923*795d594fSAndroid Build Coastguard Worker *mock_exec_utils_,
1924*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
1925*795d594fSAndroid Build Coastguard Worker AllOf(WhenSplitBy(
1926*795d594fSAndroid Build Coastguard Worker "--",
1927*795d594fSAndroid Build Coastguard Worker AllOf(Contains(art_root_ + "/bin/art_exec"), Contains("--drop-capabilities")),
1928*795d594fSAndroid Build Coastguard Worker AllOf(Contains(art_root_ + "/bin/profman"),
1929*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("--profile-file-fd=", FdOf(profile_0_file)))),
1930*795d594fSAndroid Build Coastguard Worker Contains(Flag("--profile-file-fd=", FdOf(profile_1_file))),
1931*795d594fSAndroid Build Coastguard Worker Contains(Flag("--reference-profile-file-fd=", FdHasContent("abc"))),
1932*795d594fSAndroid Build Coastguard Worker Contains(Flag("--apk-fd=", FdOf(dex_file_1))),
1933*795d594fSAndroid Build Coastguard Worker Contains(Flag("--apk-fd=", FdOf(dex_file_2))),
1934*795d594fSAndroid Build Coastguard Worker Not(Contains("--force-merge-and-analyze")),
1935*795d594fSAndroid Build Coastguard Worker Not(Contains("--boot-image-merge")))),
1936*795d594fSAndroid Build Coastguard Worker HasKeepFdsFor("--profile-file-fd=", "--reference-profile-file-fd=", "--apk-fd=")),
1937*795d594fSAndroid Build Coastguard Worker _,
1938*795d594fSAndroid Build Coastguard Worker _))
1939*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(WithArg<0>(ClearAndWriteToFdFlag("--reference-profile-file-fd=", "merged")),
1940*795d594fSAndroid Build Coastguard Worker Return(ProfmanResult::kCompile)));
1941*795d594fSAndroid Build Coastguard Worker
1942*795d594fSAndroid Build Coastguard Worker bool result;
1943*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(artd_
1944*795d594fSAndroid Build Coastguard Worker ->mergeProfiles({profile_0_path, profile_1_path},
1945*795d594fSAndroid Build Coastguard Worker profile_path_,
1946*795d594fSAndroid Build Coastguard Worker &output_profile,
1947*795d594fSAndroid Build Coastguard Worker {dex_file_1, dex_file_2},
1948*795d594fSAndroid Build Coastguard Worker /*in_options=*/{},
1949*795d594fSAndroid Build Coastguard Worker &result)
1950*795d594fSAndroid Build Coastguard Worker .isOk());
1951*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(result);
1952*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(output_profile.profilePath.id, Not(IsEmpty()));
1953*795d594fSAndroid Build Coastguard Worker std::string real_path = OR_FATAL(BuildTmpProfilePath(output_profile.profilePath));
1954*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(output_profile.profilePath.tmpPath, real_path);
1955*795d594fSAndroid Build Coastguard Worker CheckContent(real_path, "merged");
1956*795d594fSAndroid Build Coastguard Worker }
1957*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,mergeProfilesEmptyReferenceProfile)1958*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, mergeProfilesEmptyReferenceProfile) {
1959*795d594fSAndroid Build Coastguard Worker PrimaryCurProfilePath profile_0_path{
1960*795d594fSAndroid Build Coastguard Worker .userId = 0, .packageName = "com.android.foo", .profileName = "primary"};
1961*795d594fSAndroid Build Coastguard Worker std::string profile_0_file = OR_FATAL(BuildPrimaryCurProfilePath(profile_0_path));
1962*795d594fSAndroid Build Coastguard Worker CreateFile(profile_0_file, "def");
1963*795d594fSAndroid Build Coastguard Worker
1964*795d594fSAndroid Build Coastguard Worker OutputProfile output_profile{.profilePath = tmp_profile_path_,
1965*795d594fSAndroid Build Coastguard Worker .fsPermission = FsPermission{.uid = -1, .gid = -1}};
1966*795d594fSAndroid Build Coastguard Worker output_profile.profilePath.id = "";
1967*795d594fSAndroid Build Coastguard Worker output_profile.profilePath.tmpPath = "";
1968*795d594fSAndroid Build Coastguard Worker
1969*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
1970*795d594fSAndroid Build Coastguard Worker
1971*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
1972*795d594fSAndroid Build Coastguard Worker *mock_exec_utils_,
1973*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
1974*795d594fSAndroid Build Coastguard Worker WhenSplitBy("--",
1975*795d594fSAndroid Build Coastguard Worker AllOf(Contains(art_root_ + "/bin/art_exec"), Contains("--drop-capabilities")),
1976*795d594fSAndroid Build Coastguard Worker AllOf(Contains(art_root_ + "/bin/profman"),
1977*795d594fSAndroid Build Coastguard Worker Contains(Flag("--profile-file-fd=", FdOf(profile_0_file))),
1978*795d594fSAndroid Build Coastguard Worker Contains(Flag("--reference-profile-file-fd=", FdHasContent(""))),
1979*795d594fSAndroid Build Coastguard Worker Contains(Flag("--apk-fd=", FdOf(dex_file_))))),
1980*795d594fSAndroid Build Coastguard Worker _,
1981*795d594fSAndroid Build Coastguard Worker _))
1982*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(WithArg<0>(WriteToFdFlag("--reference-profile-file-fd=", "merged")),
1983*795d594fSAndroid Build Coastguard Worker Return(ProfmanResult::kCompile)));
1984*795d594fSAndroid Build Coastguard Worker
1985*795d594fSAndroid Build Coastguard Worker bool result;
1986*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(artd_
1987*795d594fSAndroid Build Coastguard Worker ->mergeProfiles({profile_0_path},
1988*795d594fSAndroid Build Coastguard Worker std::nullopt,
1989*795d594fSAndroid Build Coastguard Worker &output_profile,
1990*795d594fSAndroid Build Coastguard Worker {dex_file_},
1991*795d594fSAndroid Build Coastguard Worker /*in_options=*/{},
1992*795d594fSAndroid Build Coastguard Worker &result)
1993*795d594fSAndroid Build Coastguard Worker .isOk());
1994*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(result);
1995*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(output_profile.profilePath.id, Not(IsEmpty()));
1996*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(output_profile.profilePath.tmpPath, Not(IsEmpty()));
1997*795d594fSAndroid Build Coastguard Worker }
1998*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,mergeProfilesProfilesDontExist)1999*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, mergeProfilesProfilesDontExist) {
2000*795d594fSAndroid Build Coastguard Worker // Doesn't exist.
2001*795d594fSAndroid Build Coastguard Worker PrimaryCurProfilePath profile_0_path{
2002*795d594fSAndroid Build Coastguard Worker .userId = 0, .packageName = "com.android.foo", .profileName = "primary"};
2003*795d594fSAndroid Build Coastguard Worker std::string profile_0_file = OR_FATAL(BuildPrimaryCurProfilePath(profile_0_path));
2004*795d594fSAndroid Build Coastguard Worker
2005*795d594fSAndroid Build Coastguard Worker // Doesn't exist.
2006*795d594fSAndroid Build Coastguard Worker PrimaryCurProfilePath profile_1_path{
2007*795d594fSAndroid Build Coastguard Worker .userId = 1, .packageName = "com.android.foo", .profileName = "primary"};
2008*795d594fSAndroid Build Coastguard Worker std::string profile_1_file = OR_FATAL(BuildPrimaryCurProfilePath(profile_1_path));
2009*795d594fSAndroid Build Coastguard Worker
2010*795d594fSAndroid Build Coastguard Worker OutputProfile output_profile{.profilePath = tmp_profile_path_,
2011*795d594fSAndroid Build Coastguard Worker .fsPermission = FsPermission{.uid = -1, .gid = -1}};
2012*795d594fSAndroid Build Coastguard Worker output_profile.profilePath.id = "";
2013*795d594fSAndroid Build Coastguard Worker output_profile.profilePath.tmpPath = "";
2014*795d594fSAndroid Build Coastguard Worker
2015*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
2016*795d594fSAndroid Build Coastguard Worker
2017*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode).Times(0);
2018*795d594fSAndroid Build Coastguard Worker
2019*795d594fSAndroid Build Coastguard Worker bool result;
2020*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(artd_
2021*795d594fSAndroid Build Coastguard Worker ->mergeProfiles({profile_0_path},
2022*795d594fSAndroid Build Coastguard Worker /*in_referenceProfile=*/std::nullopt,
2023*795d594fSAndroid Build Coastguard Worker &output_profile,
2024*795d594fSAndroid Build Coastguard Worker {dex_file_},
2025*795d594fSAndroid Build Coastguard Worker /*in_options=*/{},
2026*795d594fSAndroid Build Coastguard Worker &result)
2027*795d594fSAndroid Build Coastguard Worker .isOk());
2028*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(result);
2029*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(output_profile.profilePath.id, IsEmpty());
2030*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(output_profile.profilePath.tmpPath, IsEmpty());
2031*795d594fSAndroid Build Coastguard Worker }
2032*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,mergeProfilesWithOptionsForceMerge)2033*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, mergeProfilesWithOptionsForceMerge) {
2034*795d594fSAndroid Build Coastguard Worker PrimaryCurProfilePath profile_0_path{
2035*795d594fSAndroid Build Coastguard Worker .userId = 0, .packageName = "com.android.foo", .profileName = "primary"};
2036*795d594fSAndroid Build Coastguard Worker std::string profile_0_file = OR_FATAL(BuildPrimaryCurProfilePath(profile_0_path));
2037*795d594fSAndroid Build Coastguard Worker CreateFile(profile_0_file, "def");
2038*795d594fSAndroid Build Coastguard Worker
2039*795d594fSAndroid Build Coastguard Worker OutputProfile output_profile{.profilePath = tmp_profile_path_,
2040*795d594fSAndroid Build Coastguard Worker .fsPermission = FsPermission{.uid = -1, .gid = -1}};
2041*795d594fSAndroid Build Coastguard Worker output_profile.profilePath.id = "";
2042*795d594fSAndroid Build Coastguard Worker output_profile.profilePath.tmpPath = "";
2043*795d594fSAndroid Build Coastguard Worker
2044*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
2045*795d594fSAndroid Build Coastguard Worker
2046*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_,
2047*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(WhenSplitBy("--",
2048*795d594fSAndroid Build Coastguard Worker _,
2049*795d594fSAndroid Build Coastguard Worker AllOf(Contains("--force-merge-and-analyze"),
2050*795d594fSAndroid Build Coastguard Worker Contains("--boot-image-merge"))),
2051*795d594fSAndroid Build Coastguard Worker _,
2052*795d594fSAndroid Build Coastguard Worker _))
2053*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(ProfmanResult::kCompile));
2054*795d594fSAndroid Build Coastguard Worker
2055*795d594fSAndroid Build Coastguard Worker bool result;
2056*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(artd_
2057*795d594fSAndroid Build Coastguard Worker ->mergeProfiles({profile_0_path},
2058*795d594fSAndroid Build Coastguard Worker std::nullopt,
2059*795d594fSAndroid Build Coastguard Worker &output_profile,
2060*795d594fSAndroid Build Coastguard Worker {dex_file_},
2061*795d594fSAndroid Build Coastguard Worker {.forceMerge = true, .forBootImage = true},
2062*795d594fSAndroid Build Coastguard Worker &result)
2063*795d594fSAndroid Build Coastguard Worker .isOk());
2064*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(result);
2065*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(output_profile.profilePath.id, Not(IsEmpty()));
2066*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(output_profile.profilePath.tmpPath, Not(IsEmpty()));
2067*795d594fSAndroid Build Coastguard Worker }
2068*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,mergeProfilesWithOptionsDumpOnly)2069*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, mergeProfilesWithOptionsDumpOnly) {
2070*795d594fSAndroid Build Coastguard Worker PrimaryCurProfilePath profile_0_path{
2071*795d594fSAndroid Build Coastguard Worker .userId = 0, .packageName = "com.android.foo", .profileName = "primary"};
2072*795d594fSAndroid Build Coastguard Worker std::string profile_0_file = OR_FATAL(BuildPrimaryCurProfilePath(profile_0_path));
2073*795d594fSAndroid Build Coastguard Worker CreateFile(profile_0_file, "def");
2074*795d594fSAndroid Build Coastguard Worker
2075*795d594fSAndroid Build Coastguard Worker OutputProfile output_profile{.profilePath = tmp_profile_path_,
2076*795d594fSAndroid Build Coastguard Worker .fsPermission = FsPermission{.uid = -1, .gid = -1}};
2077*795d594fSAndroid Build Coastguard Worker output_profile.profilePath.id = "";
2078*795d594fSAndroid Build Coastguard Worker output_profile.profilePath.tmpPath = "";
2079*795d594fSAndroid Build Coastguard Worker
2080*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
2081*795d594fSAndroid Build Coastguard Worker
2082*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_,
2083*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
2084*795d594fSAndroid Build Coastguard Worker AllOf(WhenSplitBy("--",
2085*795d594fSAndroid Build Coastguard Worker _,
2086*795d594fSAndroid Build Coastguard Worker AllOf(Contains("--dump-only"),
2087*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("--reference-profile-file-fd=", _))))),
2088*795d594fSAndroid Build Coastguard Worker HasKeepFdsFor("--profile-file-fd=", "--apk-fd=", "--dump-output-to-fd=")),
2089*795d594fSAndroid Build Coastguard Worker _,
2090*795d594fSAndroid Build Coastguard Worker _))
2091*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(WithArg<0>(WriteToFdFlag("--dump-output-to-fd=", "dump")),
2092*795d594fSAndroid Build Coastguard Worker Return(ProfmanResult::kSuccess)));
2093*795d594fSAndroid Build Coastguard Worker
2094*795d594fSAndroid Build Coastguard Worker bool result;
2095*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(artd_
2096*795d594fSAndroid Build Coastguard Worker ->mergeProfiles({profile_0_path},
2097*795d594fSAndroid Build Coastguard Worker std::nullopt,
2098*795d594fSAndroid Build Coastguard Worker &output_profile,
2099*795d594fSAndroid Build Coastguard Worker {dex_file_},
2100*795d594fSAndroid Build Coastguard Worker {.dumpOnly = true},
2101*795d594fSAndroid Build Coastguard Worker &result)
2102*795d594fSAndroid Build Coastguard Worker .isOk());
2103*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(result);
2104*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(output_profile.profilePath.id, Not(IsEmpty()));
2105*795d594fSAndroid Build Coastguard Worker CheckContent(output_profile.profilePath.tmpPath, "dump");
2106*795d594fSAndroid Build Coastguard Worker }
2107*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,mergeProfilesWithOptionsDumpClassesAndMethods)2108*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, mergeProfilesWithOptionsDumpClassesAndMethods) {
2109*795d594fSAndroid Build Coastguard Worker PrimaryCurProfilePath profile_0_path{
2110*795d594fSAndroid Build Coastguard Worker .userId = 0, .packageName = "com.android.foo", .profileName = "primary"};
2111*795d594fSAndroid Build Coastguard Worker std::string profile_0_file = OR_FATAL(BuildPrimaryCurProfilePath(profile_0_path));
2112*795d594fSAndroid Build Coastguard Worker CreateFile(profile_0_file, "def");
2113*795d594fSAndroid Build Coastguard Worker
2114*795d594fSAndroid Build Coastguard Worker OutputProfile output_profile{.profilePath = tmp_profile_path_,
2115*795d594fSAndroid Build Coastguard Worker .fsPermission = FsPermission{.uid = -1, .gid = -1}};
2116*795d594fSAndroid Build Coastguard Worker output_profile.profilePath.id = "";
2117*795d594fSAndroid Build Coastguard Worker output_profile.profilePath.tmpPath = "";
2118*795d594fSAndroid Build Coastguard Worker
2119*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
2120*795d594fSAndroid Build Coastguard Worker
2121*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_,
2122*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
2123*795d594fSAndroid Build Coastguard Worker WhenSplitBy("--",
2124*795d594fSAndroid Build Coastguard Worker _,
2125*795d594fSAndroid Build Coastguard Worker AllOf(Contains("--dump-classes-and-methods"),
2126*795d594fSAndroid Build Coastguard Worker Not(Contains(Flag("--reference-profile-file-fd=", _))))),
2127*795d594fSAndroid Build Coastguard Worker _,
2128*795d594fSAndroid Build Coastguard Worker _))
2129*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(WithArg<0>(WriteToFdFlag("--dump-output-to-fd=", "dump")),
2130*795d594fSAndroid Build Coastguard Worker Return(ProfmanResult::kSuccess)));
2131*795d594fSAndroid Build Coastguard Worker
2132*795d594fSAndroid Build Coastguard Worker bool result;
2133*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(artd_
2134*795d594fSAndroid Build Coastguard Worker ->mergeProfiles({profile_0_path},
2135*795d594fSAndroid Build Coastguard Worker std::nullopt,
2136*795d594fSAndroid Build Coastguard Worker &output_profile,
2137*795d594fSAndroid Build Coastguard Worker {dex_file_},
2138*795d594fSAndroid Build Coastguard Worker {.dumpClassesAndMethods = true},
2139*795d594fSAndroid Build Coastguard Worker &result)
2140*795d594fSAndroid Build Coastguard Worker .isOk());
2141*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(result);
2142*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(output_profile.profilePath.id, Not(IsEmpty()));
2143*795d594fSAndroid Build Coastguard Worker CheckContent(output_profile.profilePath.tmpPath, "dump");
2144*795d594fSAndroid Build Coastguard Worker }
2145*795d594fSAndroid Build Coastguard Worker
2146*795d594fSAndroid Build Coastguard Worker class ArtdCleanupTest : public ArtdTest {
2147*795d594fSAndroid Build Coastguard Worker protected:
SetUpForCleanup()2148*795d594fSAndroid Build Coastguard Worker void SetUpForCleanup() {
2149*795d594fSAndroid Build Coastguard Worker // Unmanaged files.
2150*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/user_de/0/com.android.foo/1.odex");
2151*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/user_de/0/com.android.foo/oat/1.odex");
2152*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/user_de/0/com.android.foo/oat/1.txt");
2153*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/user_de/0/com.android.foo/oat/arm64/1.txt");
2154*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/user_de/0/com.android.foo/oat/arm64/1.tmp");
2155*795d594fSAndroid Build Coastguard Worker
2156*795d594fSAndroid Build Coastguard Worker // Files to keep.
2157*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/misc/profiles/cur/1/com.android.foo/primary.prof");
2158*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/misc/profiles/cur/3/com.android.foo/primary.prof");
2159*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/dalvik-cache/arm64/system@app@[email protected]@classes.dex");
2160*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/dalvik-cache/arm64/system@app@[email protected]@classes.vdex");
2161*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/dalvik-cache/arm64/system@app@[email protected]@classes.art");
2162*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/user_de/0/com.android.foo/aaa/oat/arm64/1.vdex");
2163*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(
2164*795d594fSAndroid Build Coastguard Worker android_expand_ +
2165*795d594fSAndroid Build Coastguard Worker "/123456-7890/app/~~nkfeankfna==/com.android.bar-jfoeaofiew==/oat/arm64/base.odex");
2166*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(
2167*795d594fSAndroid Build Coastguard Worker android_expand_ +
2168*795d594fSAndroid Build Coastguard Worker "/123456-7890/app/~~nkfeankfna==/com.android.bar-jfoeaofiew==/oat/arm64/base.vdex");
2169*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(
2170*795d594fSAndroid Build Coastguard Worker android_expand_ +
2171*795d594fSAndroid Build Coastguard Worker "/123456-7890/app/~~nkfeankfna==/com.android.bar-jfoeaofiew==/oat/arm64/base.art");
2172*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/user_de/0/com.android.foo/aaa/oat/arm64/2.odex");
2173*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/user_de/0/com.android.foo/aaa/oat/arm64/2.vdex");
2174*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/user_de/0/com.android.foo/aaa/oat/arm64/2.art");
2175*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/user_de/0/com.android.foo/cache/oat_primary/arm64/base.art");
2176*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/user/0/com.android.foo/cache/oat_primary/arm64/base.art");
2177*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/user/1/com.android.foo/cache/oat_primary/arm64/base.art");
2178*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_expand_ +
2179*795d594fSAndroid Build Coastguard Worker "/123456-7890/user/1/com.android.foo/cache/oat_primary/arm64/base.art");
2180*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ +
2181*795d594fSAndroid Build Coastguard Worker "/user/0/com.android.foo/cache/not_oat_dir/oat_primary/arm64/base.art");
2182*795d594fSAndroid Build Coastguard Worker
2183*795d594fSAndroid Build Coastguard Worker // Files to remove.
2184*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof");
2185*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/misc/profiles/cur/2/com.android.foo/primary.prof");
2186*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/misc/profiles/cur/3/com.android.bar/primary.prof");
2187*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/dalvik-cache/arm64/extra.odex");
2188*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/dalvik-cache/arm64/system@app@[email protected]@classes.dex");
2189*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/dalvik-cache/arm64/system@app@[email protected]@classes.vdex");
2190*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/dalvik-cache/arm64/system@app@[email protected]@classes.art");
2191*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(
2192*795d594fSAndroid Build Coastguard Worker android_expand_ +
2193*795d594fSAndroid Build Coastguard Worker "/123456-7890/app/~~daewfweaf==/com.android.foo-fjuwidhia==/oat/arm64/base.odex");
2194*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(
2195*795d594fSAndroid Build Coastguard Worker android_expand_ +
2196*795d594fSAndroid Build Coastguard Worker "/123456-7890/app/~~daewfweaf==/com.android.foo-fjuwidhia==/oat/arm64/base.vdex");
2197*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(
2198*795d594fSAndroid Build Coastguard Worker android_expand_ +
2199*795d594fSAndroid Build Coastguard Worker "/123456-7890/app/~~daewfweaf==/com.android.foo-fjuwidhia==/oat/arm64/base.art");
2200*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/user_de/0/com.android.foo/oat/1.prof");
2201*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/user_de/0/com.android.foo/oat/1.prof.123456.tmp");
2202*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/user_de/0/com.android.foo/oat/arm64/1.odex");
2203*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/user_de/0/com.android.foo/oat/arm64/1.vdex");
2204*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/user_de/0/com.android.foo/oat/arm64/1.art");
2205*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/user_de/0/com.android.foo/oat/arm64/1.odex.123456.tmp");
2206*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/user_de/0/com.android.foo/oat/arm64/2.odex.123456.tmp");
2207*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/user_de/0/com.android.foo/aaa/oat/arm64/1.odex");
2208*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/user_de/0/com.android.foo/aaa/oat/arm64/1.art");
2209*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ +
2210*795d594fSAndroid Build Coastguard Worker "/user_de/0/com.android.foo/aaa/oat/arm64/1.vdex.123456.tmp");
2211*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/user_de/0/com.android.foo/aaa/bbb/oat/arm64/1.odex");
2212*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/user_de/0/com.android.foo/aaa/bbb/oat/arm64/1.vdex");
2213*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/user_de/0/com.android.foo/aaa/bbb/oat/arm64/1.art");
2214*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ +
2215*795d594fSAndroid Build Coastguard Worker "/user_de/0/com.android.foo/aaa/bbb/oat/arm64/1.art.123456.tmp");
2216*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/user_de/0/com.android.bar/aaa/oat/arm64/1.vdex");
2217*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ +
2218*795d594fSAndroid Build Coastguard Worker "/user/0/com.android.different_package/cache/oat_primary/arm64/base.art");
2219*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ +
2220*795d594fSAndroid Build Coastguard Worker "/user/0/com.android.foo/cache/oat_primary/arm64/different_dex.art");
2221*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ +
2222*795d594fSAndroid Build Coastguard Worker "/user/0/com.android.foo/cache/oat_primary/different_isa/base.art");
2223*795d594fSAndroid Build Coastguard Worker }
2224*795d594fSAndroid Build Coastguard Worker
CreateGcRemovedFile(const std::string & path)2225*795d594fSAndroid Build Coastguard Worker void CreateGcRemovedFile(const std::string& path) {
2226*795d594fSAndroid Build Coastguard Worker CreateFile(path);
2227*795d594fSAndroid Build Coastguard Worker gc_removed_files_.push_back(path);
2228*795d594fSAndroid Build Coastguard Worker }
2229*795d594fSAndroid Build Coastguard Worker
CreateGcKeptFile(const std::string & path)2230*795d594fSAndroid Build Coastguard Worker void CreateGcKeptFile(const std::string& path) {
2231*795d594fSAndroid Build Coastguard Worker CreateFile(path);
2232*795d594fSAndroid Build Coastguard Worker gc_kept_files_.push_back(path);
2233*795d594fSAndroid Build Coastguard Worker }
2234*795d594fSAndroid Build Coastguard Worker
RunCleanup(bool keepPreRebootStagedFiles)2235*795d594fSAndroid Build Coastguard Worker void RunCleanup(bool keepPreRebootStagedFiles) {
2236*795d594fSAndroid Build Coastguard Worker int64_t aidl_return;
2237*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(artd_->cleanup(
2238*795d594fSAndroid Build Coastguard Worker {
2239*795d594fSAndroid Build Coastguard Worker PrimaryCurProfilePath{
2240*795d594fSAndroid Build Coastguard Worker .userId = 1, .packageName = "com.android.foo", .profileName = "primary"},
2241*795d594fSAndroid Build Coastguard Worker PrimaryCurProfilePath{
2242*795d594fSAndroid Build Coastguard Worker .userId = 3, .packageName = "com.android.foo", .profileName = "primary"},
2243*795d594fSAndroid Build Coastguard Worker },
2244*795d594fSAndroid Build Coastguard Worker {
2245*795d594fSAndroid Build Coastguard Worker ArtifactsPath{
2246*795d594fSAndroid Build Coastguard Worker .dexPath = "/system/app/Foo/Foo.apk", .isa = "arm64", .isInDalvikCache = true},
2247*795d594fSAndroid Build Coastguard Worker ArtifactsPath{
2248*795d594fSAndroid Build Coastguard Worker .dexPath = android_expand_ +
2249*795d594fSAndroid Build Coastguard Worker "/123456-7890/app/~~nkfeankfna==/com.android.bar-jfoeaofiew==/base.apk",
2250*795d594fSAndroid Build Coastguard Worker .isa = "arm64",
2251*795d594fSAndroid Build Coastguard Worker .isInDalvikCache = false},
2252*795d594fSAndroid Build Coastguard Worker ArtifactsPath{.dexPath = android_data_ + "/user_de/0/com.android.foo/aaa/2.apk",
2253*795d594fSAndroid Build Coastguard Worker .isa = "arm64",
2254*795d594fSAndroid Build Coastguard Worker .isInDalvikCache = false},
2255*795d594fSAndroid Build Coastguard Worker },
2256*795d594fSAndroid Build Coastguard Worker {
2257*795d594fSAndroid Build Coastguard Worker VdexPath{
2258*795d594fSAndroid Build Coastguard Worker ArtifactsPath{.dexPath = android_data_ + "/user_de/0/com.android.foo/aaa/1.apk",
2259*795d594fSAndroid Build Coastguard Worker .isa = "arm64",
2260*795d594fSAndroid Build Coastguard Worker .isInDalvikCache = false}},
2261*795d594fSAndroid Build Coastguard Worker },
2262*795d594fSAndroid Build Coastguard Worker {
2263*795d594fSAndroid Build Coastguard Worker RuntimeArtifactsPath{
2264*795d594fSAndroid Build Coastguard Worker .packageName = "com.android.foo", .dexPath = "/a/b/base.apk", .isa = "arm64"},
2265*795d594fSAndroid Build Coastguard Worker },
2266*795d594fSAndroid Build Coastguard Worker keepPreRebootStagedFiles,
2267*795d594fSAndroid Build Coastguard Worker &aidl_return));
2268*795d594fSAndroid Build Coastguard Worker }
2269*795d594fSAndroid Build Coastguard Worker
Verify()2270*795d594fSAndroid Build Coastguard Worker void Verify() {
2271*795d594fSAndroid Build Coastguard Worker for (const std::string& path : gc_removed_files_) {
2272*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(std::filesystem::exists(path)) << ART_FORMAT("'{}' should be removed", path);
2273*795d594fSAndroid Build Coastguard Worker }
2274*795d594fSAndroid Build Coastguard Worker
2275*795d594fSAndroid Build Coastguard Worker for (const std::string& path : gc_kept_files_) {
2276*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(std::filesystem::exists(path)) << ART_FORMAT("'{}' should be kept", path);
2277*795d594fSAndroid Build Coastguard Worker }
2278*795d594fSAndroid Build Coastguard Worker }
2279*795d594fSAndroid Build Coastguard Worker
2280*795d594fSAndroid Build Coastguard Worker private:
2281*795d594fSAndroid Build Coastguard Worker std::vector<std::string> gc_removed_files_;
2282*795d594fSAndroid Build Coastguard Worker std::vector<std::string> gc_kept_files_;
2283*795d594fSAndroid Build Coastguard Worker };
2284*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdCleanupTest,cleanupKeepingPreRebootStagedFiles)2285*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdCleanupTest, cleanupKeepingPreRebootStagedFiles) {
2286*795d594fSAndroid Build Coastguard Worker SetUpForCleanup();
2287*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(
2288*795d594fSAndroid Build Coastguard Worker android_expand_ +
2289*795d594fSAndroid Build Coastguard Worker "/123456-7890/app/~~nkfeankfna==/com.android.bar-jfoeaofiew==/oat/arm64/base.odex.staged");
2290*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/user_de/0/com.android.foo/aaa/oat/arm64/2.odex.staged");
2291*795d594fSAndroid Build Coastguard Worker
2292*795d594fSAndroid Build Coastguard Worker ASSERT_NO_FATAL_FAILURE(RunCleanup(/*keepPreRebootStagedFiles=*/true));
2293*795d594fSAndroid Build Coastguard Worker Verify();
2294*795d594fSAndroid Build Coastguard Worker }
2295*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdCleanupTest,cleanupRemovingPreRebootStagedFiles)2296*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdCleanupTest, cleanupRemovingPreRebootStagedFiles) {
2297*795d594fSAndroid Build Coastguard Worker SetUpForCleanup();
2298*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(
2299*795d594fSAndroid Build Coastguard Worker android_expand_ +
2300*795d594fSAndroid Build Coastguard Worker "/123456-7890/app/~~nkfeankfna==/com.android.bar-jfoeaofiew==/oat/arm64/base.odex.staged");
2301*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/user_de/0/com.android.foo/aaa/oat/arm64/2.odex.staged");
2302*795d594fSAndroid Build Coastguard Worker
2303*795d594fSAndroid Build Coastguard Worker ASSERT_NO_FATAL_FAILURE(RunCleanup(/*keepPreRebootStagedFiles=*/false));
2304*795d594fSAndroid Build Coastguard Worker Verify();
2305*795d594fSAndroid Build Coastguard Worker }
2306*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdCleanupTest,cleanUpPreRebootStagedFiles)2307*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdCleanupTest, cleanUpPreRebootStagedFiles) {
2308*795d594fSAndroid Build Coastguard Worker // Unmanaged file.
2309*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/user_de/0/com.android.foo/1.odex.staged");
2310*795d594fSAndroid Build Coastguard Worker
2311*795d594fSAndroid Build Coastguard Worker // Not Pre-reboot staged files.
2312*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof");
2313*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(
2314*795d594fSAndroid Build Coastguard Worker android_expand_ +
2315*795d594fSAndroid Build Coastguard Worker "/123456-7890/app/~~nkfeankfna==/com.android.bar-jfoeaofiew==/oat/arm64/base.odex");
2316*795d594fSAndroid Build Coastguard Worker CreateGcKeptFile(android_data_ + "/user_de/0/com.android.foo/aaa/oat/arm64/2.odex");
2317*795d594fSAndroid Build Coastguard Worker
2318*795d594fSAndroid Build Coastguard Worker // Pre-reboot staged files.
2319*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof.staged");
2320*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(
2321*795d594fSAndroid Build Coastguard Worker android_expand_ +
2322*795d594fSAndroid Build Coastguard Worker "/123456-7890/app/~~nkfeankfna==/com.android.bar-jfoeaofiew==/oat/arm64/base.odex.staged");
2323*795d594fSAndroid Build Coastguard Worker CreateGcRemovedFile(android_data_ + "/user_de/0/com.android.foo/aaa/oat/arm64/2.odex.staged");
2324*795d594fSAndroid Build Coastguard Worker
2325*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(artd_->cleanUpPreRebootStagedFiles());
2326*795d594fSAndroid Build Coastguard Worker Verify();
2327*795d594fSAndroid Build Coastguard Worker }
2328*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,isInDalvikCache)2329*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, isInDalvikCache) {
2330*795d594fSAndroid Build Coastguard Worker TEST_DISABLED_FOR_HOST();
2331*795d594fSAndroid Build Coastguard Worker
2332*795d594fSAndroid Build Coastguard Worker auto is_in_dalvik_cache = [this](const std::string& dex_file) -> Result<bool> {
2333*795d594fSAndroid Build Coastguard Worker bool result;
2334*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus status = artd_->isInDalvikCache(dex_file, &result);
2335*795d594fSAndroid Build Coastguard Worker if (!status.isOk()) {
2336*795d594fSAndroid Build Coastguard Worker return Error() << status.getMessage();
2337*795d594fSAndroid Build Coastguard Worker }
2338*795d594fSAndroid Build Coastguard Worker return result;
2339*795d594fSAndroid Build Coastguard Worker };
2340*795d594fSAndroid Build Coastguard Worker
2341*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(is_in_dalvik_cache("/system/app/base.apk"), HasValue(true));
2342*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(is_in_dalvik_cache("/system_ext/app/base.apk"), HasValue(true));
2343*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(is_in_dalvik_cache("/vendor/app/base.apk"), HasValue(true));
2344*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(is_in_dalvik_cache("/product/app/base.apk"), HasValue(true));
2345*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(is_in_dalvik_cache("/data/app/base.apk"), HasValue(false));
2346*795d594fSAndroid Build Coastguard Worker
2347*795d594fSAndroid Build Coastguard Worker // Test a path where we don't expect to find packages. The method should still work.
2348*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(is_in_dalvik_cache("/foo"), HasValue(true));
2349*795d594fSAndroid Build Coastguard Worker }
2350*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,deleteRuntimeArtifacts)2351*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, deleteRuntimeArtifacts) {
2352*795d594fSAndroid Build Coastguard Worker std::vector<std::string> removed_files;
2353*795d594fSAndroid Build Coastguard Worker std::vector<std::string> kept_files;
2354*795d594fSAndroid Build Coastguard Worker
2355*795d594fSAndroid Build Coastguard Worker auto CreateRemovedFile = [&](const std::string& path) {
2356*795d594fSAndroid Build Coastguard Worker CreateFile(path);
2357*795d594fSAndroid Build Coastguard Worker removed_files.push_back(path);
2358*795d594fSAndroid Build Coastguard Worker };
2359*795d594fSAndroid Build Coastguard Worker
2360*795d594fSAndroid Build Coastguard Worker auto CreateKeptFile = [&](const std::string& path) {
2361*795d594fSAndroid Build Coastguard Worker CreateFile(path);
2362*795d594fSAndroid Build Coastguard Worker kept_files.push_back(path);
2363*795d594fSAndroid Build Coastguard Worker };
2364*795d594fSAndroid Build Coastguard Worker
2365*795d594fSAndroid Build Coastguard Worker CreateKeptFile(android_data_ +
2366*795d594fSAndroid Build Coastguard Worker "/user/0/com.android.different_package/cache/oat_primary/arm64/base.art");
2367*795d594fSAndroid Build Coastguard Worker CreateKeptFile(android_data_ +
2368*795d594fSAndroid Build Coastguard Worker "/user/0/com.android.foo/cache/oat_primary/arm64/different_dex.art");
2369*795d594fSAndroid Build Coastguard Worker CreateKeptFile(android_data_ +
2370*795d594fSAndroid Build Coastguard Worker "/user/0/com.android.foo/cache/oat_primary/different_isa/base.art");
2371*795d594fSAndroid Build Coastguard Worker CreateKeptFile(android_data_ +
2372*795d594fSAndroid Build Coastguard Worker "/user/0/com.android.foo/cache/not_oat_dir/oat_primary/arm64/base.art");
2373*795d594fSAndroid Build Coastguard Worker
2374*795d594fSAndroid Build Coastguard Worker CreateRemovedFile(android_data_ + "/user_de/0/com.android.foo/cache/oat_primary/arm64/base.art");
2375*795d594fSAndroid Build Coastguard Worker CreateRemovedFile(android_data_ + "/user/0/com.android.foo/cache/oat_primary/arm64/base.art");
2376*795d594fSAndroid Build Coastguard Worker CreateRemovedFile(android_data_ + "/user/1/com.android.foo/cache/oat_primary/arm64/base.art");
2377*795d594fSAndroid Build Coastguard Worker CreateRemovedFile(android_expand_ +
2378*795d594fSAndroid Build Coastguard Worker "/123456-7890/user/1/com.android.foo/cache/oat_primary/arm64/base.art");
2379*795d594fSAndroid Build Coastguard Worker
2380*795d594fSAndroid Build Coastguard Worker int64_t aidl_return;
2381*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(
2382*795d594fSAndroid Build Coastguard Worker artd_
2383*795d594fSAndroid Build Coastguard Worker ->deleteRuntimeArtifacts(
2384*795d594fSAndroid Build Coastguard Worker {.packageName = "com.android.foo", .dexPath = "/a/b/base.apk", .isa = "arm64"},
2385*795d594fSAndroid Build Coastguard Worker &aidl_return)
2386*795d594fSAndroid Build Coastguard Worker .isOk());
2387*795d594fSAndroid Build Coastguard Worker
2388*795d594fSAndroid Build Coastguard Worker for (const std::string& path : removed_files) {
2389*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(std::filesystem::exists(path)) << ART_FORMAT("'{}' should be removed", path);
2390*795d594fSAndroid Build Coastguard Worker }
2391*795d594fSAndroid Build Coastguard Worker
2392*795d594fSAndroid Build Coastguard Worker for (const std::string& path : kept_files) {
2393*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(std::filesystem::exists(path)) << ART_FORMAT("'{}' should be kept", path);
2394*795d594fSAndroid Build Coastguard Worker }
2395*795d594fSAndroid Build Coastguard Worker }
2396*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,deleteRuntimeArtifactsAndroidDataNotExist)2397*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, deleteRuntimeArtifactsAndroidDataNotExist) {
2398*795d594fSAndroid Build Coastguard Worker // Will be cleaned up by `android_data_env_`
2399*795d594fSAndroid Build Coastguard Worker setenv("ANDROID_DATA", "/non-existing", /*replace=*/1);
2400*795d594fSAndroid Build Coastguard Worker
2401*795d594fSAndroid Build Coastguard Worker auto scoped_set_logger = ScopedSetLogger(mock_logger_.AsStdFunction());
2402*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_logger_,
2403*795d594fSAndroid Build Coastguard Worker Call(_, _, _, _, _, HasSubstr("Failed to find directory /non-existing")));
2404*795d594fSAndroid Build Coastguard Worker
2405*795d594fSAndroid Build Coastguard Worker int64_t aidl_return;
2406*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(
2407*795d594fSAndroid Build Coastguard Worker artd_
2408*795d594fSAndroid Build Coastguard Worker ->deleteRuntimeArtifacts(
2409*795d594fSAndroid Build Coastguard Worker {.packageName = "com.android.foo", .dexPath = "/a/b/base.apk", .isa = "arm64"},
2410*795d594fSAndroid Build Coastguard Worker &aidl_return)
2411*795d594fSAndroid Build Coastguard Worker .isOk());
2412*795d594fSAndroid Build Coastguard Worker
2413*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(aidl_return, 0);
2414*795d594fSAndroid Build Coastguard Worker }
2415*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,deleteRuntimeArtifactsSpecialChars)2416*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, deleteRuntimeArtifactsSpecialChars) {
2417*795d594fSAndroid Build Coastguard Worker std::vector<std::string> removed_files;
2418*795d594fSAndroid Build Coastguard Worker std::vector<std::string> kept_files;
2419*795d594fSAndroid Build Coastguard Worker
2420*795d594fSAndroid Build Coastguard Worker auto CreateRemovedFile = [&](const std::string& path) {
2421*795d594fSAndroid Build Coastguard Worker CreateFile(path);
2422*795d594fSAndroid Build Coastguard Worker removed_files.push_back(path);
2423*795d594fSAndroid Build Coastguard Worker };
2424*795d594fSAndroid Build Coastguard Worker
2425*795d594fSAndroid Build Coastguard Worker auto CreateKeptFile = [&](const std::string& path) {
2426*795d594fSAndroid Build Coastguard Worker CreateFile(path);
2427*795d594fSAndroid Build Coastguard Worker kept_files.push_back(path);
2428*795d594fSAndroid Build Coastguard Worker };
2429*795d594fSAndroid Build Coastguard Worker
2430*795d594fSAndroid Build Coastguard Worker CreateKeptFile(android_data_ + "/user/0/com.android.foo/cache/oat_primary/arm64/base.art");
2431*795d594fSAndroid Build Coastguard Worker
2432*795d594fSAndroid Build Coastguard Worker CreateRemovedFile(android_data_ + "/user/0/*/cache/oat_primary/arm64/base.art");
2433*795d594fSAndroid Build Coastguard Worker CreateRemovedFile(android_data_ + "/user/0/com.android.foo/cache/oat_primary/*/base.art");
2434*795d594fSAndroid Build Coastguard Worker CreateRemovedFile(android_data_ + "/user/0/com.android.foo/cache/oat_primary/arm64/*.art");
2435*795d594fSAndroid Build Coastguard Worker
2436*795d594fSAndroid Build Coastguard Worker int64_t aidl_return;
2437*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(
2438*795d594fSAndroid Build Coastguard Worker artd_
2439*795d594fSAndroid Build Coastguard Worker ->deleteRuntimeArtifacts({.packageName = "*", .dexPath = "/a/b/base.apk", .isa = "arm64"},
2440*795d594fSAndroid Build Coastguard Worker &aidl_return)
2441*795d594fSAndroid Build Coastguard Worker .isOk());
2442*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(artd_
2443*795d594fSAndroid Build Coastguard Worker ->deleteRuntimeArtifacts(
2444*795d594fSAndroid Build Coastguard Worker {.packageName = "com.android.foo", .dexPath = "/a/b/*.apk", .isa = "arm64"},
2445*795d594fSAndroid Build Coastguard Worker &aidl_return)
2446*795d594fSAndroid Build Coastguard Worker .isOk());
2447*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(artd_
2448*795d594fSAndroid Build Coastguard Worker ->deleteRuntimeArtifacts(
2449*795d594fSAndroid Build Coastguard Worker {.packageName = "com.android.foo", .dexPath = "/a/b/base.apk", .isa = "*"},
2450*795d594fSAndroid Build Coastguard Worker &aidl_return)
2451*795d594fSAndroid Build Coastguard Worker .isOk());
2452*795d594fSAndroid Build Coastguard Worker
2453*795d594fSAndroid Build Coastguard Worker for (const std::string& path : removed_files) {
2454*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(std::filesystem::exists(path)) << ART_FORMAT("'{}' should be removed", path);
2455*795d594fSAndroid Build Coastguard Worker }
2456*795d594fSAndroid Build Coastguard Worker
2457*795d594fSAndroid Build Coastguard Worker for (const std::string& path : kept_files) {
2458*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(std::filesystem::exists(path)) << ART_FORMAT("'{}' should be kept", path);
2459*795d594fSAndroid Build Coastguard Worker }
2460*795d594fSAndroid Build Coastguard Worker }
2461*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,getArtifactsSize)2462*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, getArtifactsSize) {
2463*795d594fSAndroid Build Coastguard Worker std::string oat_dir = scratch_path_ + "/a/oat/arm64";
2464*795d594fSAndroid Build Coastguard Worker CreateFile(oat_dir + "/b.odex", std::string(1, '*'));
2465*795d594fSAndroid Build Coastguard Worker CreateFile(oat_dir + "/b.vdex", std::string(2, '*'));
2466*795d594fSAndroid Build Coastguard Worker CreateFile(oat_dir + "/b.art", std::string(4, '*'));
2467*795d594fSAndroid Build Coastguard Worker
2468*795d594fSAndroid Build Coastguard Worker // Irrelevant.
2469*795d594fSAndroid Build Coastguard Worker CreateFile(oat_dir + "/c.vdex", std::string(8, '*'));
2470*795d594fSAndroid Build Coastguard Worker
2471*795d594fSAndroid Build Coastguard Worker int64_t aidl_return = -1;
2472*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(
2473*795d594fSAndroid Build Coastguard Worker artd_
2474*795d594fSAndroid Build Coastguard Worker ->getArtifactsSize(
2475*795d594fSAndroid Build Coastguard Worker {.dexPath = scratch_path_ + "/a/b.apk", .isa = "arm64", .isInDalvikCache = false},
2476*795d594fSAndroid Build Coastguard Worker &aidl_return)
2477*795d594fSAndroid Build Coastguard Worker .isOk());
2478*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(aidl_return, 1 + 2 + 4);
2479*795d594fSAndroid Build Coastguard Worker }
2480*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,getVdexFileSize)2481*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, getVdexFileSize) {
2482*795d594fSAndroid Build Coastguard Worker std::string oat_dir = scratch_path_ + "/a/oat/arm64";
2483*795d594fSAndroid Build Coastguard Worker CreateFile(oat_dir + "/b.vdex", std::string(1, '*'));
2484*795d594fSAndroid Build Coastguard Worker
2485*795d594fSAndroid Build Coastguard Worker // Irrelevant.
2486*795d594fSAndroid Build Coastguard Worker CreateFile(oat_dir + "/b.odex", std::string(2, '*'));
2487*795d594fSAndroid Build Coastguard Worker CreateFile(oat_dir + "/b.art", std::string(4, '*'));
2488*795d594fSAndroid Build Coastguard Worker CreateFile(oat_dir + "/c.vdex", std::string(8, '*'));
2489*795d594fSAndroid Build Coastguard Worker
2490*795d594fSAndroid Build Coastguard Worker int64_t aidl_return = -1;
2491*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(artd_
2492*795d594fSAndroid Build Coastguard Worker ->getVdexFileSize(ArtifactsPath{.dexPath = scratch_path_ + "/a/b.apk",
2493*795d594fSAndroid Build Coastguard Worker .isa = "arm64",
2494*795d594fSAndroid Build Coastguard Worker .isInDalvikCache = false},
2495*795d594fSAndroid Build Coastguard Worker &aidl_return)
2496*795d594fSAndroid Build Coastguard Worker .isOk());
2497*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(aidl_return, 1);
2498*795d594fSAndroid Build Coastguard Worker }
2499*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,getRuntimeArtifactsSize)2500*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, getRuntimeArtifactsSize) {
2501*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/user_de/0/com.android.foo/cache/oat_primary/arm64/base.art",
2502*795d594fSAndroid Build Coastguard Worker std::string(1, '*'));
2503*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/user/0/com.android.foo/cache/oat_primary/arm64/base.art",
2504*795d594fSAndroid Build Coastguard Worker std::string(2, '*'));
2505*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/user/1/com.android.foo/cache/oat_primary/arm64/base.art",
2506*795d594fSAndroid Build Coastguard Worker std::string(4, '*'));
2507*795d594fSAndroid Build Coastguard Worker CreateFile(
2508*795d594fSAndroid Build Coastguard Worker android_expand_ + "/123456-7890/user/1/com.android.foo/cache/oat_primary/arm64/base.art",
2509*795d594fSAndroid Build Coastguard Worker std::string(8, '*'));
2510*795d594fSAndroid Build Coastguard Worker
2511*795d594fSAndroid Build Coastguard Worker // Irrelevant.
2512*795d594fSAndroid Build Coastguard Worker CreateFile(android_expand_ + "/user/0/com.android.foo/cache/oat_primary/arm64/different_dex.art",
2513*795d594fSAndroid Build Coastguard Worker std::string(16, '*'));
2514*795d594fSAndroid Build Coastguard Worker
2515*795d594fSAndroid Build Coastguard Worker int64_t aidl_return = -1;
2516*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(
2517*795d594fSAndroid Build Coastguard Worker artd_
2518*795d594fSAndroid Build Coastguard Worker ->getRuntimeArtifactsSize(
2519*795d594fSAndroid Build Coastguard Worker {.packageName = "com.android.foo", .dexPath = "/a/b/base.apk", .isa = "arm64"},
2520*795d594fSAndroid Build Coastguard Worker &aidl_return)
2521*795d594fSAndroid Build Coastguard Worker .isOk());
2522*795d594fSAndroid Build Coastguard Worker
2523*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(aidl_return, 1 + 2 + 4 + 8);
2524*795d594fSAndroid Build Coastguard Worker }
2525*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,getProfileSize)2526*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, getProfileSize) {
2527*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/misc/profiles/cur/0/com.android.foo/primary.prof",
2528*795d594fSAndroid Build Coastguard Worker std::string(1, '*'));
2529*795d594fSAndroid Build Coastguard Worker
2530*795d594fSAndroid Build Coastguard Worker // Irrelevant.
2531*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/misc/profiles/cur/0/com.android.foo/split_0.split.prof",
2532*795d594fSAndroid Build Coastguard Worker std::string(2, '*'));
2533*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/misc/profiles/cur/0/com.android.bar/primary.prof",
2534*795d594fSAndroid Build Coastguard Worker std::string(4, '*'));
2535*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof",
2536*795d594fSAndroid Build Coastguard Worker std::string(8, '*'));
2537*795d594fSAndroid Build Coastguard Worker
2538*795d594fSAndroid Build Coastguard Worker int64_t aidl_return = -1;
2539*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(artd_
2540*795d594fSAndroid Build Coastguard Worker ->getProfileSize(
2541*795d594fSAndroid Build Coastguard Worker PrimaryCurProfilePath{
2542*795d594fSAndroid Build Coastguard Worker .userId = 0, .packageName = "com.android.foo", .profileName = "primary"},
2543*795d594fSAndroid Build Coastguard Worker &aidl_return)
2544*795d594fSAndroid Build Coastguard Worker .isOk());
2545*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(aidl_return, 1);
2546*795d594fSAndroid Build Coastguard Worker }
2547*795d594fSAndroid Build Coastguard Worker
2548*795d594fSAndroid Build Coastguard Worker class ArtdProfileSaveNotificationTest : public ArtdTest {
2549*795d594fSAndroid Build Coastguard Worker protected:
SetUp()2550*795d594fSAndroid Build Coastguard Worker void SetUp() override {
2551*795d594fSAndroid Build Coastguard Worker ArtdTest::SetUp();
2552*795d594fSAndroid Build Coastguard Worker
2553*795d594fSAndroid Build Coastguard Worker std::vector<std::string> args{GetBin("sleep"), "10"};
2554*795d594fSAndroid Build Coastguard Worker std::tie(pid_, scope_guard_) = ScopedExec(args, /*wait=*/false);
2555*795d594fSAndroid Build Coastguard Worker notification_file_ = OR_FAIL(BuildPrimaryCurProfilePath(profile_path_));
2556*795d594fSAndroid Build Coastguard Worker std::filesystem::create_directories(Dirname(notification_file_));
2557*795d594fSAndroid Build Coastguard Worker }
2558*795d594fSAndroid Build Coastguard Worker
2559*795d594fSAndroid Build Coastguard Worker const PrimaryCurProfilePath profile_path_{
2560*795d594fSAndroid Build Coastguard Worker .userId = 0,
2561*795d594fSAndroid Build Coastguard Worker .packageName = "com.android.foo",
2562*795d594fSAndroid Build Coastguard Worker .profileName = "primary",
2563*795d594fSAndroid Build Coastguard Worker };
2564*795d594fSAndroid Build Coastguard Worker std::string notification_file_;
2565*795d594fSAndroid Build Coastguard Worker int pid_;
2566*795d594fSAndroid Build Coastguard Worker std::unique_ptr<ScopeGuard<std::function<void()>>> scope_guard_;
2567*795d594fSAndroid Build Coastguard Worker };
2568*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdProfileSaveNotificationTest,initAndWaitSuccess)2569*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdProfileSaveNotificationTest, initAndWaitSuccess) {
2570*795d594fSAndroid Build Coastguard Worker // Use a condvar to sequence the NewFile::CommitOrAbandon calls.
2571*795d594fSAndroid Build Coastguard Worker constexpr std::chrono::duration<int> kTimeout = std::chrono::seconds(1);
2572*795d594fSAndroid Build Coastguard Worker std::condition_variable wait_started_cv;
2573*795d594fSAndroid Build Coastguard Worker std::mutex mu;
2574*795d594fSAndroid Build Coastguard Worker
2575*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_poll_, Call)
2576*795d594fSAndroid Build Coastguard Worker .Times(2)
2577*795d594fSAndroid Build Coastguard Worker .WillRepeatedly(DoAll(
2578*795d594fSAndroid Build Coastguard Worker [&](auto, auto, auto) {
2579*795d594fSAndroid Build Coastguard Worker // Step 3, 5.
2580*795d594fSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mu);
2581*795d594fSAndroid Build Coastguard Worker wait_started_cv.notify_one();
2582*795d594fSAndroid Build Coastguard Worker },
2583*795d594fSAndroid Build Coastguard Worker poll));
2584*795d594fSAndroid Build Coastguard Worker
2585*795d594fSAndroid Build Coastguard Worker std::shared_ptr<IArtdNotification> notification;
2586*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(artd_->initProfileSaveNotification(profile_path_, pid_, ¬ification));
2587*795d594fSAndroid Build Coastguard Worker
2588*795d594fSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mu);
2589*795d594fSAndroid Build Coastguard Worker
2590*795d594fSAndroid Build Coastguard Worker // Step 1.
2591*795d594fSAndroid Build Coastguard Worker std::thread t([&] {
2592*795d594fSAndroid Build Coastguard Worker // Step 2.
2593*795d594fSAndroid Build Coastguard Worker bool aidl_return;
2594*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(notification->wait(/*in_timeoutMs=*/1000, &aidl_return));
2595*795d594fSAndroid Build Coastguard Worker // Step 7.
2596*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(aidl_return);
2597*795d594fSAndroid Build Coastguard Worker });
2598*795d594fSAndroid Build Coastguard Worker wait_started_cv.wait_for(lock, kTimeout);
2599*795d594fSAndroid Build Coastguard Worker
2600*795d594fSAndroid Build Coastguard Worker // Step 4.
2601*795d594fSAndroid Build Coastguard Worker std::unique_ptr<NewFile> unrelated_file = OR_FAIL(NewFile::Create(
2602*795d594fSAndroid Build Coastguard Worker Dirname(notification_file_) + "/unrelated.prof", FsPermission{.uid = -1, .gid = -1}));
2603*795d594fSAndroid Build Coastguard Worker OR_FAIL(unrelated_file->CommitOrAbandon());
2604*795d594fSAndroid Build Coastguard Worker wait_started_cv.wait_for(lock, kTimeout);
2605*795d594fSAndroid Build Coastguard Worker
2606*795d594fSAndroid Build Coastguard Worker // Step 6.
2607*795d594fSAndroid Build Coastguard Worker std::unique_ptr<NewFile> file =
2608*795d594fSAndroid Build Coastguard Worker OR_FAIL(NewFile::Create(notification_file_, FsPermission{.uid = -1, .gid = -1}));
2609*795d594fSAndroid Build Coastguard Worker OR_FAIL(file->CommitOrAbandon());
2610*795d594fSAndroid Build Coastguard Worker
2611*795d594fSAndroid Build Coastguard Worker t.join();
2612*795d594fSAndroid Build Coastguard Worker }
2613*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdProfileSaveNotificationTest,initAndWaitProcessGone)2614*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdProfileSaveNotificationTest, initAndWaitProcessGone) {
2615*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_poll_, Call).WillOnce(poll);
2616*795d594fSAndroid Build Coastguard Worker
2617*795d594fSAndroid Build Coastguard Worker std::shared_ptr<IArtdNotification> notification;
2618*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(artd_->initProfileSaveNotification(profile_path_, pid_, ¬ification));
2619*795d594fSAndroid Build Coastguard Worker
2620*795d594fSAndroid Build Coastguard Worker std::thread t([&] {
2621*795d594fSAndroid Build Coastguard Worker bool aidl_return;
2622*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(notification->wait(/*in_timeoutMs=*/1000, &aidl_return));
2623*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(aidl_return);
2624*795d594fSAndroid Build Coastguard Worker });
2625*795d594fSAndroid Build Coastguard Worker
2626*795d594fSAndroid Build Coastguard Worker kill(pid_, SIGKILL);
2627*795d594fSAndroid Build Coastguard Worker
2628*795d594fSAndroid Build Coastguard Worker t.join();
2629*795d594fSAndroid Build Coastguard Worker }
2630*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdProfileSaveNotificationTest,initAndWaitTimeout)2631*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdProfileSaveNotificationTest, initAndWaitTimeout) {
2632*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_poll_, Call).WillOnce(poll).WillOnce(Return(0));
2633*795d594fSAndroid Build Coastguard Worker
2634*795d594fSAndroid Build Coastguard Worker std::shared_ptr<IArtdNotification> notification;
2635*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(artd_->initProfileSaveNotification(profile_path_, pid_, ¬ification));
2636*795d594fSAndroid Build Coastguard Worker
2637*795d594fSAndroid Build Coastguard Worker std::unique_ptr<NewFile> unrelated_file = OR_FAIL(NewFile::Create(
2638*795d594fSAndroid Build Coastguard Worker Dirname(notification_file_) + "/unrelated.prof", FsPermission{.uid = -1, .gid = -1}));
2639*795d594fSAndroid Build Coastguard Worker OR_FAIL(unrelated_file->CommitOrAbandon());
2640*795d594fSAndroid Build Coastguard Worker
2641*795d594fSAndroid Build Coastguard Worker bool aidl_return;
2642*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(notification->wait(/*in_timeoutMs=*/1000, &aidl_return));
2643*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(aidl_return);
2644*795d594fSAndroid Build Coastguard Worker }
2645*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdProfileSaveNotificationTest,initProcessGone)2646*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdProfileSaveNotificationTest, initProcessGone) {
2647*795d594fSAndroid Build Coastguard Worker // Kill the process before pidfd_open.
2648*795d594fSAndroid Build Coastguard Worker scope_guard_.reset();
2649*795d594fSAndroid Build Coastguard Worker
2650*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_poll_, Call).Times(0);
2651*795d594fSAndroid Build Coastguard Worker
2652*795d594fSAndroid Build Coastguard Worker std::shared_ptr<IArtdNotification> notification;
2653*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(artd_->initProfileSaveNotification(profile_path_, pid_, ¬ification));
2654*795d594fSAndroid Build Coastguard Worker
2655*795d594fSAndroid Build Coastguard Worker bool aidl_return;
2656*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(notification->wait(/*in_timeoutMs=*/1000, &aidl_return));
2657*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(aidl_return);
2658*795d594fSAndroid Build Coastguard Worker }
2659*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,commitPreRebootStagedFiles)2660*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, commitPreRebootStagedFiles) {
2661*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/dalvik-cache/arm64/system@app@[email protected]@classes.dex.staged",
2662*795d594fSAndroid Build Coastguard Worker "new_odex_1");
2663*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/dalvik-cache/arm64/system@app@[email protected]@classes.vdex.staged",
2664*795d594fSAndroid Build Coastguard Worker "new_vdex_1");
2665*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/dalvik-cache/arm64/system@app@[email protected]@classes.art.staged",
2666*795d594fSAndroid Build Coastguard Worker "new_art_1");
2667*795d594fSAndroid Build Coastguard Worker
2668*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/dalvik-cache/arm64/system@app@[email protected]@classes.dex",
2669*795d594fSAndroid Build Coastguard Worker "old_odex_1");
2670*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/dalvik-cache/arm64/system@app@[email protected]@classes.vdex",
2671*795d594fSAndroid Build Coastguard Worker "old_vdex_1");
2672*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/dalvik-cache/arm64/system@app@[email protected]@classes.art", "old_art_1");
2673*795d594fSAndroid Build Coastguard Worker
2674*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/app/com.android.foo/oat/arm64/base.odex", "old_odex_2");
2675*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/app/com.android.foo/oat/arm64/base.vdex", "old_vdex_2");
2676*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/app/com.android.foo/oat/arm64/base.art", "old_art_2");
2677*795d594fSAndroid Build Coastguard Worker
2678*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/app/com.android.foo/oat/arm64/base.odex.staged", "new_odex_2");
2679*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/app/com.android.foo/oat/arm64/base.vdex.staged", "new_vdex_2");
2680*795d594fSAndroid Build Coastguard Worker
2681*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/app/com.android.foo/oat/arm/base.odex", "old_odex_3");
2682*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/app/com.android.foo/oat/arm/base.vdex", "old_vdex_3");
2683*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/app/com.android.foo/oat/arm/base.art", "old_art_3");
2684*795d594fSAndroid Build Coastguard Worker
2685*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof", "old_prof_1");
2686*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof.staged",
2687*795d594fSAndroid Build Coastguard Worker "new_prof_1");
2688*795d594fSAndroid Build Coastguard Worker
2689*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/misc/profiles/ref/com.android.bar/primary.prof", "old_prof_2");
2690*795d594fSAndroid Build Coastguard Worker
2691*795d594fSAndroid Build Coastguard Worker bool aidl_return;
2692*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(artd_->commitPreRebootStagedFiles(
2693*795d594fSAndroid Build Coastguard Worker {
2694*795d594fSAndroid Build Coastguard Worker // Has all new files. All old files should be replaced.
2695*795d594fSAndroid Build Coastguard Worker ArtifactsPath{
2696*795d594fSAndroid Build Coastguard Worker .dexPath = "/system/app/Foo/Foo.apk", .isa = "arm64", .isInDalvikCache = true},
2697*795d594fSAndroid Build Coastguard Worker // Has new files but not ".art" file. Old ".odex" and ".vdex" files should be replaced,
2698*795d594fSAndroid Build Coastguard Worker // and old ".art" file should be removed.
2699*795d594fSAndroid Build Coastguard Worker ArtifactsPath{.dexPath = android_data_ + "/app/com.android.foo/base.apk",
2700*795d594fSAndroid Build Coastguard Worker .isa = "arm64",
2701*795d594fSAndroid Build Coastguard Worker .isInDalvikCache = false},
2702*795d594fSAndroid Build Coastguard Worker // Has no new file. All old files should be kept.
2703*795d594fSAndroid Build Coastguard Worker ArtifactsPath{.dexPath = android_data_ + "/app/com.android.foo/base.apk",
2704*795d594fSAndroid Build Coastguard Worker .isa = "arm",
2705*795d594fSAndroid Build Coastguard Worker .isInDalvikCache = false},
2706*795d594fSAndroid Build Coastguard Worker },
2707*795d594fSAndroid Build Coastguard Worker {
2708*795d594fSAndroid Build Coastguard Worker // Has new file.
2709*795d594fSAndroid Build Coastguard Worker PrimaryRefProfilePath{.packageName = "com.android.foo", .profileName = "primary"},
2710*795d594fSAndroid Build Coastguard Worker // Has no new file.
2711*795d594fSAndroid Build Coastguard Worker PrimaryRefProfilePath{.packageName = "com.android.bar", .profileName = "primary"},
2712*795d594fSAndroid Build Coastguard Worker },
2713*795d594fSAndroid Build Coastguard Worker &aidl_return));
2714*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(aidl_return);
2715*795d594fSAndroid Build Coastguard Worker
2716*795d594fSAndroid Build Coastguard Worker CheckContent(android_data_ + "/dalvik-cache/arm64/system@app@[email protected]@classes.dex",
2717*795d594fSAndroid Build Coastguard Worker "new_odex_1");
2718*795d594fSAndroid Build Coastguard Worker CheckContent(android_data_ + "/dalvik-cache/arm64/system@app@[email protected]@classes.vdex",
2719*795d594fSAndroid Build Coastguard Worker "new_vdex_1");
2720*795d594fSAndroid Build Coastguard Worker CheckContent(android_data_ + "/dalvik-cache/arm64/system@app@[email protected]@classes.art",
2721*795d594fSAndroid Build Coastguard Worker "new_art_1");
2722*795d594fSAndroid Build Coastguard Worker
2723*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/app/com.android.foo/oat/arm64/base.odex", "new_odex_2");
2724*795d594fSAndroid Build Coastguard Worker CreateFile(android_data_ + "/app/com.android.foo/oat/arm64/base.vdex", "new_vdex_2");
2725*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(std::filesystem::exists(android_data_ + "/app/com.android.foo/oat/arm64/base.art"));
2726*795d594fSAndroid Build Coastguard Worker
2727*795d594fSAndroid Build Coastguard Worker CheckContent(android_data_ + "/app/com.android.foo/oat/arm/base.odex", "old_odex_3");
2728*795d594fSAndroid Build Coastguard Worker CheckContent(android_data_ + "/app/com.android.foo/oat/arm/base.vdex", "old_vdex_3");
2729*795d594fSAndroid Build Coastguard Worker CheckContent(android_data_ + "/app/com.android.foo/oat/arm/base.art", "old_art_3");
2730*795d594fSAndroid Build Coastguard Worker
2731*795d594fSAndroid Build Coastguard Worker CheckContent(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof", "new_prof_1");
2732*795d594fSAndroid Build Coastguard Worker
2733*795d594fSAndroid Build Coastguard Worker CheckContent(android_data_ + "/misc/profiles/ref/com.android.bar/primary.prof", "old_prof_2");
2734*795d594fSAndroid Build Coastguard Worker
2735*795d594fSAndroid Build Coastguard Worker // All staged files are gone.
2736*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(std::filesystem::exists(
2737*795d594fSAndroid Build Coastguard Worker android_data_ + "/dalvik-cache/arm64/system@app@[email protected]@classes.dex.staged"));
2738*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(std::filesystem::exists(
2739*795d594fSAndroid Build Coastguard Worker android_data_ + "/dalvik-cache/arm64/system@app@[email protected]@classes.vdex.staged"));
2740*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(std::filesystem::exists(
2741*795d594fSAndroid Build Coastguard Worker android_data_ + "/dalvik-cache/arm64/system@app@[email protected]@classes.art.staged"));
2742*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(
2743*795d594fSAndroid Build Coastguard Worker std::filesystem::exists(android_data_ + "/app/com.android.foo/oat/arm64/base.odex.staged"));
2744*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(
2745*795d594fSAndroid Build Coastguard Worker std::filesystem::exists(android_data_ + "/app/com.android.foo/oat/arm64/base.vdex.staged"));
2746*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(std::filesystem::exists(android_data_ +
2747*795d594fSAndroid Build Coastguard Worker "/misc/profiles/ref/com.android.foo/primary.prof.staged"));
2748*795d594fSAndroid Build Coastguard Worker }
2749*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,commitPreRebootStagedFilesNoNewFile)2750*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, commitPreRebootStagedFilesNoNewFile) {
2751*795d594fSAndroid Build Coastguard Worker bool aidl_return;
2752*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(artd_->commitPreRebootStagedFiles(
2753*795d594fSAndroid Build Coastguard Worker {
2754*795d594fSAndroid Build Coastguard Worker ArtifactsPath{.dexPath = android_data_ + "/app/com.android.foo/base.apk",
2755*795d594fSAndroid Build Coastguard Worker .isa = "arm",
2756*795d594fSAndroid Build Coastguard Worker .isInDalvikCache = false},
2757*795d594fSAndroid Build Coastguard Worker },
2758*795d594fSAndroid Build Coastguard Worker {},
2759*795d594fSAndroid Build Coastguard Worker &aidl_return));
2760*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(aidl_return);
2761*795d594fSAndroid Build Coastguard Worker }
2762*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,checkPreRebootSystemRequirements)2763*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, checkPreRebootSystemRequirements) {
2764*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_props_, GetProperty("ro.build.version.release")).WillRepeatedly(Return("15"));
2765*795d594fSAndroid Build Coastguard Worker std::string chroot_dir = scratch_path_ + "/chroot";
2766*795d594fSAndroid Build Coastguard Worker bool aidl_return;
2767*795d594fSAndroid Build Coastguard Worker
2768*795d594fSAndroid Build Coastguard Worker constexpr const char* kTemplate = R"(
2769*795d594fSAndroid Build Coastguard Worker # Comment.
2770*795d594fSAndroid Build Coastguard Worker unrelated.system.property=abc
2771*795d594fSAndroid Build Coastguard Worker
2772*795d594fSAndroid Build Coastguard Worker ro.build.version.release={}
2773*795d594fSAndroid Build Coastguard Worker )";
2774*795d594fSAndroid Build Coastguard Worker
2775*795d594fSAndroid Build Coastguard Worker CreateFile(chroot_dir + "/system/build.prop", ART_FORMAT(kTemplate, 15));
2776*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(artd_->checkPreRebootSystemRequirements(chroot_dir, &aidl_return));
2777*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(aidl_return);
2778*795d594fSAndroid Build Coastguard Worker
2779*795d594fSAndroid Build Coastguard Worker CreateFile(chroot_dir + "/system/build.prop", ART_FORMAT(kTemplate, 16));
2780*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(artd_->checkPreRebootSystemRequirements(chroot_dir, &aidl_return));
2781*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(aidl_return);
2782*795d594fSAndroid Build Coastguard Worker
2783*795d594fSAndroid Build Coastguard Worker CreateFile(chroot_dir + "/system/build.prop", ART_FORMAT(kTemplate, 17));
2784*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(artd_->checkPreRebootSystemRequirements(chroot_dir, &aidl_return));
2785*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(aidl_return);
2786*795d594fSAndroid Build Coastguard Worker }
2787*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdTest,BuildSystemProperties)2788*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdTest, BuildSystemProperties) {
2789*795d594fSAndroid Build Coastguard Worker constexpr const char* kContent = R"(
2790*795d594fSAndroid Build Coastguard Worker # Comment.
2791*795d594fSAndroid Build Coastguard Worker property.foo=123
2792*795d594fSAndroid Build Coastguard Worker property.foo?=456
2793*795d594fSAndroid Build Coastguard Worker property.bar?=000
2794*795d594fSAndroid Build Coastguard Worker property.bar=789
2795*795d594fSAndroid Build Coastguard Worker property.baz?=111
2796*795d594fSAndroid Build Coastguard Worker import /vendor/my_import.prop ro.*
2797*795d594fSAndroid Build Coastguard Worker import=222
2798*795d594fSAndroid Build Coastguard Worker )";
2799*795d594fSAndroid Build Coastguard Worker
2800*795d594fSAndroid Build Coastguard Worker CreateFile(scratch_path_ + "/build.prop", kContent);
2801*795d594fSAndroid Build Coastguard Worker BuildSystemProperties props =
2802*795d594fSAndroid Build Coastguard Worker OR_FAIL(BuildSystemProperties::Create(scratch_path_ + "/build.prop"));
2803*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(props.GetOrEmpty("property.foo"), "123");
2804*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(props.GetOrEmpty("property.bar"), "789");
2805*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(props.GetOrEmpty("property.baz"), "111");
2806*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(props.GetOrEmpty("import"), "222");
2807*795d594fSAndroid Build Coastguard Worker }
2808*795d594fSAndroid Build Coastguard Worker
2809*795d594fSAndroid Build Coastguard Worker class ArtdPreRebootTest : public ArtdTest {
2810*795d594fSAndroid Build Coastguard Worker protected:
SetUp()2811*795d594fSAndroid Build Coastguard Worker void SetUp() override {
2812*795d594fSAndroid Build Coastguard Worker ArtdTest::SetUp();
2813*795d594fSAndroid Build Coastguard Worker
2814*795d594fSAndroid Build Coastguard Worker pre_reboot_tmp_dir_ = scratch_path_ + "/artd_tmp";
2815*795d594fSAndroid Build Coastguard Worker std::filesystem::create_directories(pre_reboot_tmp_dir_);
2816*795d594fSAndroid Build Coastguard Worker init_environ_rc_path_ = scratch_path_ + "/init.environ.rc";
2817*795d594fSAndroid Build Coastguard Worker
2818*795d594fSAndroid Build Coastguard Worker auto mock_props = std::make_unique<NiceMock<MockSystemProperties>>();
2819*795d594fSAndroid Build Coastguard Worker mock_props_ = mock_props.get();
2820*795d594fSAndroid Build Coastguard Worker ON_CALL(*mock_props_, GetProperty).WillByDefault(Return(""));
2821*795d594fSAndroid Build Coastguard Worker auto mock_exec_utils = std::make_unique<MockExecUtils>();
2822*795d594fSAndroid Build Coastguard Worker mock_exec_utils_ = mock_exec_utils.get();
2823*795d594fSAndroid Build Coastguard Worker artd_ = ndk::SharedRefBase::make<Artd>(Options{.is_pre_reboot = true},
2824*795d594fSAndroid Build Coastguard Worker std::move(mock_props),
2825*795d594fSAndroid Build Coastguard Worker std::move(mock_exec_utils),
2826*795d594fSAndroid Build Coastguard Worker mock_kill_.AsStdFunction(),
2827*795d594fSAndroid Build Coastguard Worker mock_fstat_.AsStdFunction(),
2828*795d594fSAndroid Build Coastguard Worker mock_poll_.AsStdFunction(),
2829*795d594fSAndroid Build Coastguard Worker mock_mount_.AsStdFunction(),
2830*795d594fSAndroid Build Coastguard Worker mock_restorecon_.AsStdFunction(),
2831*795d594fSAndroid Build Coastguard Worker pre_reboot_tmp_dir_,
2832*795d594fSAndroid Build Coastguard Worker init_environ_rc_path_);
2833*795d594fSAndroid Build Coastguard Worker
2834*795d594fSAndroid Build Coastguard Worker ON_CALL(mock_restorecon_, Call).WillByDefault(Return(Result<void>()));
2835*795d594fSAndroid Build Coastguard Worker
2836*795d594fSAndroid Build Coastguard Worker constexpr const char* kInitEnvironRcTmpl = R"(
2837*795d594fSAndroid Build Coastguard Worker on early-init
2838*795d594fSAndroid Build Coastguard Worker export ANDROID_ART_ROOT {}
2839*795d594fSAndroid Build Coastguard Worker export ANDROID_DATA {}
2840*795d594fSAndroid Build Coastguard Worker )";
2841*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(WriteStringToFile(ART_FORMAT(kInitEnvironRcTmpl, art_root_, android_data_),
2842*795d594fSAndroid Build Coastguard Worker init_environ_rc_path_));
2843*795d594fSAndroid Build Coastguard Worker
2844*795d594fSAndroid Build Coastguard Worker tmp_profile_path_.finalPath.get<WritableProfilePath::forPrimary>().isPreReboot = true;
2845*795d594fSAndroid Build Coastguard Worker output_artifacts_.artifactsPath.isPreReboot = true;
2846*795d594fSAndroid Build Coastguard Worker }
2847*795d594fSAndroid Build Coastguard Worker
2848*795d594fSAndroid Build Coastguard Worker std::string pre_reboot_tmp_dir_;
2849*795d594fSAndroid Build Coastguard Worker std::string init_environ_rc_path_;
2850*795d594fSAndroid Build Coastguard Worker MockFunction<int(const char*, const char*, const char*, uint32_t, const void*)> mock_mount_;
2851*795d594fSAndroid Build Coastguard Worker MockFunction<Result<void>(const std::string&,
2852*795d594fSAndroid Build Coastguard Worker const std::optional<OutputArtifacts::PermissionSettings::SeContext>&,
2853*795d594fSAndroid Build Coastguard Worker bool)>
2854*795d594fSAndroid Build Coastguard Worker mock_restorecon_;
2855*795d594fSAndroid Build Coastguard Worker };
2856*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdPreRebootTest,preRebootInit)2857*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdPreRebootTest, preRebootInit) {
2858*795d594fSAndroid Build Coastguard Worker // Color the env vars to make sure that the expected values are not from the parent process but
2859*795d594fSAndroid Build Coastguard Worker // from "/init.environ.rc".
2860*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(setenv("ANDROID_ART_ROOT", "old_value", /*replace=*/1), 0);
2861*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(setenv("ANDROID_DATA", "old_value", /*replace=*/1), 0);
2862*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(setenv("BOOTCLASSPATH", "old_value", /*replace=*/1), 0);
2863*795d594fSAndroid Build Coastguard Worker
2864*795d594fSAndroid Build Coastguard Worker // Add an env var that doesn't get overridden, to check that it gets removed.
2865*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(setenv("FOO", "old_value", /*replace=*/1), 0);
2866*795d594fSAndroid Build Coastguard Worker
2867*795d594fSAndroid Build Coastguard Worker InSequence seq;
2868*795d594fSAndroid Build Coastguard Worker
2869*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_,
2870*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
2871*795d594fSAndroid Build Coastguard Worker AllOf(WhenSplitBy("--",
2872*795d594fSAndroid Build Coastguard Worker AllOf(Contains(art_root_ + "/bin/art_exec"),
2873*795d594fSAndroid Build Coastguard Worker Contains("--drop-capabilities")),
2874*795d594fSAndroid Build Coastguard Worker Contains("/apex/com.android.sdkext/bin/derive_classpath")),
2875*795d594fSAndroid Build Coastguard Worker HasKeepFdsFor("/proc/self/fd/")),
2876*795d594fSAndroid Build Coastguard Worker _,
2877*795d594fSAndroid Build Coastguard Worker _))
2878*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(WithArg<0>(WriteToFdFlag("/proc/self/fd/", "export BOOTCLASSPATH /foo:/bar")),
2879*795d594fSAndroid Build Coastguard Worker Return(0)));
2880*795d594fSAndroid Build Coastguard Worker
2881*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_mount_,
2882*795d594fSAndroid Build Coastguard Worker Call(StrEq(pre_reboot_tmp_dir_ + "/art_apex_data"),
2883*795d594fSAndroid Build Coastguard Worker StrEq("/data/misc/apexdata/com.android.art"),
2884*795d594fSAndroid Build Coastguard Worker /*fs_type=*/nullptr,
2885*795d594fSAndroid Build Coastguard Worker MS_BIND | MS_PRIVATE,
2886*795d594fSAndroid Build Coastguard Worker /*data=*/nullptr))
2887*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(0));
2888*795d594fSAndroid Build Coastguard Worker
2889*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_mount_,
2890*795d594fSAndroid Build Coastguard Worker Call(StrEq(pre_reboot_tmp_dir_ + "/odrefresh"),
2891*795d594fSAndroid Build Coastguard Worker StrEq("/data/misc/odrefresh"),
2892*795d594fSAndroid Build Coastguard Worker /*fs_type=*/nullptr,
2893*795d594fSAndroid Build Coastguard Worker MS_BIND | MS_PRIVATE,
2894*795d594fSAndroid Build Coastguard Worker /*data=*/nullptr))
2895*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(0));
2896*795d594fSAndroid Build Coastguard Worker
2897*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_,
2898*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(WhenSplitBy("--",
2899*795d594fSAndroid Build Coastguard Worker AllOf(Contains(art_root_ + "/bin/art_exec"),
2900*795d594fSAndroid Build Coastguard Worker Contains("--drop-capabilities")),
2901*795d594fSAndroid Build Coastguard Worker AllOf(Contains(art_root_ + "/bin/odrefresh"),
2902*795d594fSAndroid Build Coastguard Worker Contains("--only-boot-images"),
2903*795d594fSAndroid Build Coastguard Worker Contains("--compile"))),
2904*795d594fSAndroid Build Coastguard Worker _,
2905*795d594fSAndroid Build Coastguard Worker _))
2906*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(0));
2907*795d594fSAndroid Build Coastguard Worker
2908*795d594fSAndroid Build Coastguard Worker std::shared_ptr<IArtdCancellationSignal> cancellation_signal;
2909*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(artd_->createCancellationSignal(&cancellation_signal));
2910*795d594fSAndroid Build Coastguard Worker
2911*795d594fSAndroid Build Coastguard Worker bool aidl_return;
2912*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(artd_->preRebootInit(cancellation_signal, &aidl_return));
2913*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(aidl_return);
2914*795d594fSAndroid Build Coastguard Worker
2915*795d594fSAndroid Build Coastguard Worker auto env_var_count = []() {
2916*795d594fSAndroid Build Coastguard Worker int count = 0;
2917*795d594fSAndroid Build Coastguard Worker for (char** it = environ; *it != nullptr; it++) {
2918*795d594fSAndroid Build Coastguard Worker count++;
2919*795d594fSAndroid Build Coastguard Worker }
2920*795d594fSAndroid Build Coastguard Worker return count;
2921*795d594fSAndroid Build Coastguard Worker };
2922*795d594fSAndroid Build Coastguard Worker
2923*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(getenv("ANDROID_ART_ROOT"), art_root_);
2924*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(getenv("ANDROID_DATA"), android_data_);
2925*795d594fSAndroid Build Coastguard Worker EXPECT_STREQ(getenv("BOOTCLASSPATH"), "/foo:/bar");
2926*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(env_var_count(), 3);
2927*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(std::filesystem::exists(pre_reboot_tmp_dir_ + "/preparation_done"));
2928*795d594fSAndroid Build Coastguard Worker
2929*795d594fSAndroid Build Coastguard Worker // Color the env vars again to simulate that artd died and restarted.
2930*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(setenv("ANDROID_ART_ROOT", "old_value", /*replace=*/1), 0);
2931*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(setenv("ANDROID_DATA", "old_value", /*replace=*/1), 0);
2932*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(setenv("BOOTCLASSPATH", "old_value", /*replace=*/1), 0);
2933*795d594fSAndroid Build Coastguard Worker
2934*795d594fSAndroid Build Coastguard Worker // Calling again will not involve `mount`, `derive_classpath`, or `odrefresh` but only restore env
2935*795d594fSAndroid Build Coastguard Worker // vars.
2936*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(artd_->preRebootInit(/*in_cancellationSignal=*/nullptr, &aidl_return));
2937*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(aidl_return);
2938*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(getenv("ANDROID_ART_ROOT"), art_root_);
2939*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(getenv("ANDROID_DATA"), android_data_);
2940*795d594fSAndroid Build Coastguard Worker EXPECT_STREQ(getenv("BOOTCLASSPATH"), "/foo:/bar");
2941*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(env_var_count(), 3);
2942*795d594fSAndroid Build Coastguard Worker }
2943*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdPreRebootTest,preRebootInitFailed)2944*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdPreRebootTest, preRebootInitFailed) {
2945*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_,
2946*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(Contains("/apex/com.android.sdkext/bin/derive_classpath"), _, _))
2947*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(WithArg<0>(WriteToFdFlag("/proc/self/fd/", "export BOOTCLASSPATH /foo:/bar")),
2948*795d594fSAndroid Build Coastguard Worker Return(0)));
2949*795d594fSAndroid Build Coastguard Worker
2950*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_mount_, Call).Times(2).WillRepeatedly(Return(0));
2951*795d594fSAndroid Build Coastguard Worker
2952*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(Contains(art_root_ + "/bin/odrefresh"), _, _))
2953*795d594fSAndroid Build Coastguard Worker .WillOnce(Return(1));
2954*795d594fSAndroid Build Coastguard Worker
2955*795d594fSAndroid Build Coastguard Worker std::shared_ptr<IArtdCancellationSignal> cancellation_signal;
2956*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(artd_->createCancellationSignal(&cancellation_signal));
2957*795d594fSAndroid Build Coastguard Worker
2958*795d594fSAndroid Build Coastguard Worker bool aidl_return;
2959*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus status = artd_->preRebootInit(cancellation_signal, &aidl_return);
2960*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(status.isOk());
2961*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(status.getExceptionCode(), EX_SERVICE_SPECIFIC);
2962*795d594fSAndroid Build Coastguard Worker EXPECT_STREQ(status.getMessage(), "odrefresh returned an unexpected code: 1");
2963*795d594fSAndroid Build Coastguard Worker }
2964*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdPreRebootTest,preRebootInitNoRetry)2965*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdPreRebootTest, preRebootInitNoRetry) {
2966*795d594fSAndroid Build Coastguard Worker // Simulate that a previous attempt failed halfway.
2967*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(WriteStringToFile("", pre_reboot_tmp_dir_ + "/classpath.txt"));
2968*795d594fSAndroid Build Coastguard Worker
2969*795d594fSAndroid Build Coastguard Worker bool aidl_return;
2970*795d594fSAndroid Build Coastguard Worker ndk::ScopedAStatus status = artd_->preRebootInit(/*in_cancellationSignal=*/nullptr, &aidl_return);
2971*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(status.isOk());
2972*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(status.getExceptionCode(), EX_ILLEGAL_STATE);
2973*795d594fSAndroid Build Coastguard Worker EXPECT_STREQ(
2974*795d594fSAndroid Build Coastguard Worker status.getMessage(),
2975*795d594fSAndroid Build Coastguard Worker "preRebootInit must not be concurrently called or retried after cancellation or failure");
2976*795d594fSAndroid Build Coastguard Worker }
2977*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdPreRebootTest,preRebootInitCancelled)2978*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdPreRebootTest, preRebootInitCancelled) {
2979*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_,
2980*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(Contains("/apex/com.android.sdkext/bin/derive_classpath"), _, _))
2981*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(WithArg<0>(WriteToFdFlag("/proc/self/fd/", "export BOOTCLASSPATH /foo:/bar")),
2982*795d594fSAndroid Build Coastguard Worker Return(0)));
2983*795d594fSAndroid Build Coastguard Worker
2984*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_mount_, Call).Times(2).WillRepeatedly(Return(0));
2985*795d594fSAndroid Build Coastguard Worker
2986*795d594fSAndroid Build Coastguard Worker std::shared_ptr<IArtdCancellationSignal> cancellation_signal;
2987*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(artd_->createCancellationSignal(&cancellation_signal));
2988*795d594fSAndroid Build Coastguard Worker
2989*795d594fSAndroid Build Coastguard Worker constexpr pid_t kPid = 123;
2990*795d594fSAndroid Build Coastguard Worker constexpr std::chrono::duration<int> kTimeout = std::chrono::seconds(1);
2991*795d594fSAndroid Build Coastguard Worker
2992*795d594fSAndroid Build Coastguard Worker std::condition_variable process_started_cv, process_killed_cv;
2993*795d594fSAndroid Build Coastguard Worker std::mutex mu;
2994*795d594fSAndroid Build Coastguard Worker
2995*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(Contains(art_root_ + "/bin/odrefresh"), _, _))
2996*795d594fSAndroid Build Coastguard Worker .WillOnce([&](auto, const ExecCallbacks& callbacks, auto) {
2997*795d594fSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mu);
2998*795d594fSAndroid Build Coastguard Worker // Step 2.
2999*795d594fSAndroid Build Coastguard Worker callbacks.on_start(kPid);
3000*795d594fSAndroid Build Coastguard Worker process_started_cv.notify_one();
3001*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(process_killed_cv.wait_for(lock, kTimeout), std::cv_status::no_timeout);
3002*795d594fSAndroid Build Coastguard Worker // Step 5.
3003*795d594fSAndroid Build Coastguard Worker callbacks.on_end(kPid);
3004*795d594fSAndroid Build Coastguard Worker return Error();
3005*795d594fSAndroid Build Coastguard Worker });
3006*795d594fSAndroid Build Coastguard Worker
3007*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(mock_kill_, Call(-kPid, SIGKILL)).WillOnce([&](auto, auto) {
3008*795d594fSAndroid Build Coastguard Worker // Step 4.
3009*795d594fSAndroid Build Coastguard Worker process_killed_cv.notify_one();
3010*795d594fSAndroid Build Coastguard Worker return 0;
3011*795d594fSAndroid Build Coastguard Worker });
3012*795d594fSAndroid Build Coastguard Worker
3013*795d594fSAndroid Build Coastguard Worker std::thread t;
3014*795d594fSAndroid Build Coastguard Worker bool aidl_return;
3015*795d594fSAndroid Build Coastguard Worker {
3016*795d594fSAndroid Build Coastguard Worker std::unique_lock<std::mutex> lock(mu);
3017*795d594fSAndroid Build Coastguard Worker // Step 1.
3018*795d594fSAndroid Build Coastguard Worker t = std::thread(
3019*795d594fSAndroid Build Coastguard Worker [&] { ASSERT_STATUS_OK(artd_->preRebootInit(cancellation_signal, &aidl_return)); });
3020*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(process_started_cv.wait_for(lock, kTimeout), std::cv_status::no_timeout);
3021*795d594fSAndroid Build Coastguard Worker // Step 3.
3022*795d594fSAndroid Build Coastguard Worker cancellation_signal->cancel();
3023*795d594fSAndroid Build Coastguard Worker }
3024*795d594fSAndroid Build Coastguard Worker
3025*795d594fSAndroid Build Coastguard Worker t.join();
3026*795d594fSAndroid Build Coastguard Worker
3027*795d594fSAndroid Build Coastguard Worker // Step 6.
3028*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(aidl_return);
3029*795d594fSAndroid Build Coastguard Worker }
3030*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdPreRebootTest,dexopt)3031*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdPreRebootTest, dexopt) {
3032*795d594fSAndroid Build Coastguard Worker std::string profile_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
3033*795d594fSAndroid Build Coastguard Worker
3034*795d594fSAndroid Build Coastguard Worker dexopt_options_.generateAppImage = true;
3035*795d594fSAndroid Build Coastguard Worker
3036*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
3037*795d594fSAndroid Build Coastguard Worker *mock_exec_utils_,
3038*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
3039*795d594fSAndroid Build Coastguard Worker WhenSplitBy("--", _, Contains(Flag("--profile-file-fd=", FdOf(profile_file)))), _, _))
3040*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(WithArg<0>(WriteToFdFlag("--oat-fd=", "oat")),
3041*795d594fSAndroid Build Coastguard Worker WithArg<0>(WriteToFdFlag("--output-vdex-fd=", "vdex")),
3042*795d594fSAndroid Build Coastguard Worker WithArg<0>(WriteToFdFlag("--app-image-fd=", "art")),
3043*795d594fSAndroid Build Coastguard Worker Return(0)));
3044*795d594fSAndroid Build Coastguard Worker RunDexopt();
3045*795d594fSAndroid Build Coastguard Worker
3046*795d594fSAndroid Build Coastguard Worker CheckContent(scratch_path_ + "/a/oat/arm64/b.odex.staged", "oat");
3047*795d594fSAndroid Build Coastguard Worker CheckContent(scratch_path_ + "/a/oat/arm64/b.vdex.staged", "vdex");
3048*795d594fSAndroid Build Coastguard Worker CheckContent(scratch_path_ + "/a/oat/arm64/b.art.staged", "art");
3049*795d594fSAndroid Build Coastguard Worker }
3050*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdPreRebootTest,dexoptPreRebootProfile)3051*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdPreRebootTest, dexoptPreRebootProfile) {
3052*795d594fSAndroid Build Coastguard Worker profile_path_->get<ProfilePath::tmpProfilePath>()
3053*795d594fSAndroid Build Coastguard Worker .finalPath.get<WritableProfilePath::forPrimary>()
3054*795d594fSAndroid Build Coastguard Worker .isPreReboot = true;
3055*795d594fSAndroid Build Coastguard Worker std::string profile_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
3056*795d594fSAndroid Build Coastguard Worker
3057*795d594fSAndroid Build Coastguard Worker dexopt_options_.generateAppImage = true;
3058*795d594fSAndroid Build Coastguard Worker
3059*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
3060*795d594fSAndroid Build Coastguard Worker *mock_exec_utils_,
3061*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
3062*795d594fSAndroid Build Coastguard Worker WhenSplitBy("--", _, Contains(Flag("--profile-file-fd=", FdOf(profile_file)))), _, _))
3063*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(WithArg<0>(WriteToFdFlag("--oat-fd=", "oat")),
3064*795d594fSAndroid Build Coastguard Worker WithArg<0>(WriteToFdFlag("--output-vdex-fd=", "vdex")),
3065*795d594fSAndroid Build Coastguard Worker WithArg<0>(WriteToFdFlag("--app-image-fd=", "art")),
3066*795d594fSAndroid Build Coastguard Worker Return(0)));
3067*795d594fSAndroid Build Coastguard Worker RunDexopt();
3068*795d594fSAndroid Build Coastguard Worker
3069*795d594fSAndroid Build Coastguard Worker CheckContent(scratch_path_ + "/a/oat/arm64/b.odex.staged", "oat");
3070*795d594fSAndroid Build Coastguard Worker CheckContent(scratch_path_ + "/a/oat/arm64/b.vdex.staged", "vdex");
3071*795d594fSAndroid Build Coastguard Worker CheckContent(scratch_path_ + "/a/oat/arm64/b.art.staged", "art");
3072*795d594fSAndroid Build Coastguard Worker }
3073*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdPreRebootTest,copyAndRewriteProfile)3074*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdPreRebootTest, copyAndRewriteProfile) {
3075*795d594fSAndroid Build Coastguard Worker std::string src_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
3076*795d594fSAndroid Build Coastguard Worker CreateFile(src_file, "valid_profile");
3077*795d594fSAndroid Build Coastguard Worker
3078*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_);
3079*795d594fSAndroid Build Coastguard Worker
3080*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode)
3081*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(WithArg<0>(WriteToFdFlag("--reference-profile-file-fd=", "def")),
3082*795d594fSAndroid Build Coastguard Worker Return(ProfmanResult::kCopyAndUpdateSuccess)));
3083*795d594fSAndroid Build Coastguard Worker
3084*795d594fSAndroid Build Coastguard Worker auto [result, dst] = OR_FAIL(RunCopyAndRewriteProfile());
3085*795d594fSAndroid Build Coastguard Worker
3086*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result.status, CopyAndRewriteProfileResult::Status::SUCCESS);
3087*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.tmpPath, ContainsRegex(R"re(/primary\.prof\.staged\.\w+\.tmp$)re"));
3088*795d594fSAndroid Build Coastguard Worker CheckContent(dst.profilePath.tmpPath, "def");
3089*795d594fSAndroid Build Coastguard Worker }
3090*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdPreRebootTest,copyAndRewriteEmbeddedProfile)3091*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdPreRebootTest, copyAndRewriteEmbeddedProfile) {
3092*795d594fSAndroid Build Coastguard Worker TEST_DISABLED_FOR_SHELL_WITHOUT_MEMFD_ACCESS();
3093*795d594fSAndroid Build Coastguard Worker
3094*795d594fSAndroid Build Coastguard Worker CreateZipWithSingleEntry(dex_file_, "assets/art-profile/baseline.prof", "valid_profile");
3095*795d594fSAndroid Build Coastguard Worker
3096*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode)
3097*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(WithArg<0>(WriteToFdFlag("--reference-profile-file-fd=", "def")),
3098*795d594fSAndroid Build Coastguard Worker Return(ProfmanResult::kCopyAndUpdateSuccess)));
3099*795d594fSAndroid Build Coastguard Worker
3100*795d594fSAndroid Build Coastguard Worker auto [result, dst] = OR_FAIL(RunCopyAndRewriteEmbeddedProfile());
3101*795d594fSAndroid Build Coastguard Worker
3102*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(result.status, CopyAndRewriteProfileResult::Status::SUCCESS);
3103*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(dst.profilePath.tmpPath, ContainsRegex(R"re(/primary\.prof\.staged\.\w+\.tmp$)re"));
3104*795d594fSAndroid Build Coastguard Worker CheckContent(dst.profilePath.tmpPath, "def");
3105*795d594fSAndroid Build Coastguard Worker }
3106*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdPreRebootTest,mergeProfiles)3107*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdPreRebootTest, mergeProfiles) {
3108*795d594fSAndroid Build Coastguard Worker std::string reference_profile_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
3109*795d594fSAndroid Build Coastguard Worker CreateFile(reference_profile_file, "abc");
3110*795d594fSAndroid Build Coastguard Worker
3111*795d594fSAndroid Build Coastguard Worker PrimaryCurProfilePath profile_1_path{
3112*795d594fSAndroid Build Coastguard Worker .userId = 1, .packageName = "com.android.foo", .profileName = "primary"};
3113*795d594fSAndroid Build Coastguard Worker std::string profile_1_file = OR_FATAL(BuildPrimaryCurProfilePath(profile_1_path));
3114*795d594fSAndroid Build Coastguard Worker CreateFile(profile_1_file, "def");
3115*795d594fSAndroid Build Coastguard Worker
3116*795d594fSAndroid Build Coastguard Worker OutputProfile output_profile{.profilePath = tmp_profile_path_,
3117*795d594fSAndroid Build Coastguard Worker .fsPermission = FsPermission{.uid = -1, .gid = -1}};
3118*795d594fSAndroid Build Coastguard Worker output_profile.profilePath.id = "";
3119*795d594fSAndroid Build Coastguard Worker output_profile.profilePath.tmpPath = "";
3120*795d594fSAndroid Build Coastguard Worker
3121*795d594fSAndroid Build Coastguard Worker std::string dex_file_1 = scratch_path_ + "/a/b.apk";
3122*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_1);
3123*795d594fSAndroid Build Coastguard Worker
3124*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
3125*795d594fSAndroid Build Coastguard Worker *mock_exec_utils_,
3126*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
3127*795d594fSAndroid Build Coastguard Worker WhenSplitBy("--",
3128*795d594fSAndroid Build Coastguard Worker _,
3129*795d594fSAndroid Build Coastguard Worker AllOf(Contains(Flag("--reference-profile-file-fd=", FdHasContent("abc"))),
3130*795d594fSAndroid Build Coastguard Worker Contains(Flag("--profile-file-fd=", FdHasContent("def"))))),
3131*795d594fSAndroid Build Coastguard Worker _,
3132*795d594fSAndroid Build Coastguard Worker _))
3133*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(WithArg<0>(ClearAndWriteToFdFlag("--reference-profile-file-fd=", "merged")),
3134*795d594fSAndroid Build Coastguard Worker Return(ProfmanResult::kCompile)));
3135*795d594fSAndroid Build Coastguard Worker
3136*795d594fSAndroid Build Coastguard Worker bool result;
3137*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(artd_->mergeProfiles({profile_1_path},
3138*795d594fSAndroid Build Coastguard Worker profile_path_,
3139*795d594fSAndroid Build Coastguard Worker &output_profile,
3140*795d594fSAndroid Build Coastguard Worker {dex_file_1},
3141*795d594fSAndroid Build Coastguard Worker /*in_options=*/{},
3142*795d594fSAndroid Build Coastguard Worker &result));
3143*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(result);
3144*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(output_profile.profilePath.tmpPath,
3145*795d594fSAndroid Build Coastguard Worker ContainsRegex(R"re(/primary\.prof\.staged\.\w+\.tmp$)re"));
3146*795d594fSAndroid Build Coastguard Worker CheckContent(output_profile.profilePath.tmpPath, "merged");
3147*795d594fSAndroid Build Coastguard Worker }
3148*795d594fSAndroid Build Coastguard Worker
TEST_F(ArtdPreRebootTest,mergeProfilesPreRebootReference)3149*795d594fSAndroid Build Coastguard Worker TEST_F(ArtdPreRebootTest, mergeProfilesPreRebootReference) {
3150*795d594fSAndroid Build Coastguard Worker profile_path_->get<ProfilePath::tmpProfilePath>()
3151*795d594fSAndroid Build Coastguard Worker .finalPath.get<WritableProfilePath::forPrimary>()
3152*795d594fSAndroid Build Coastguard Worker .isPreReboot = true;
3153*795d594fSAndroid Build Coastguard Worker std::string reference_profile_file = OR_FATAL(BuildProfileOrDmPath(profile_path_.value()));
3154*795d594fSAndroid Build Coastguard Worker CreateFile(reference_profile_file, "abc");
3155*795d594fSAndroid Build Coastguard Worker
3156*795d594fSAndroid Build Coastguard Worker PrimaryCurProfilePath profile_1_path{
3157*795d594fSAndroid Build Coastguard Worker .userId = 1, .packageName = "com.android.foo", .profileName = "primary"};
3158*795d594fSAndroid Build Coastguard Worker std::string profile_1_file = OR_FATAL(BuildPrimaryCurProfilePath(profile_1_path));
3159*795d594fSAndroid Build Coastguard Worker CreateFile(profile_1_file, "def");
3160*795d594fSAndroid Build Coastguard Worker
3161*795d594fSAndroid Build Coastguard Worker OutputProfile output_profile{.profilePath = tmp_profile_path_,
3162*795d594fSAndroid Build Coastguard Worker .fsPermission = FsPermission{.uid = -1, .gid = -1}};
3163*795d594fSAndroid Build Coastguard Worker output_profile.profilePath.id = "";
3164*795d594fSAndroid Build Coastguard Worker output_profile.profilePath.tmpPath = "";
3165*795d594fSAndroid Build Coastguard Worker
3166*795d594fSAndroid Build Coastguard Worker std::string dex_file_1 = scratch_path_ + "/a/b.apk";
3167*795d594fSAndroid Build Coastguard Worker CreateFile(dex_file_1);
3168*795d594fSAndroid Build Coastguard Worker
3169*795d594fSAndroid Build Coastguard Worker EXPECT_CALL(
3170*795d594fSAndroid Build Coastguard Worker *mock_exec_utils_,
3171*795d594fSAndroid Build Coastguard Worker DoExecAndReturnCode(
3172*795d594fSAndroid Build Coastguard Worker WhenSplitBy("--",
3173*795d594fSAndroid Build Coastguard Worker _,
3174*795d594fSAndroid Build Coastguard Worker AllOf(Contains(Flag("--reference-profile-file-fd=", FdHasContent("abc"))),
3175*795d594fSAndroid Build Coastguard Worker Contains(Flag("--profile-file-fd=", FdHasContent("def"))))),
3176*795d594fSAndroid Build Coastguard Worker _,
3177*795d594fSAndroid Build Coastguard Worker _))
3178*795d594fSAndroid Build Coastguard Worker .WillOnce(DoAll(WithArg<0>(ClearAndWriteToFdFlag("--reference-profile-file-fd=", "merged")),
3179*795d594fSAndroid Build Coastguard Worker Return(ProfmanResult::kCompile)));
3180*795d594fSAndroid Build Coastguard Worker
3181*795d594fSAndroid Build Coastguard Worker bool result;
3182*795d594fSAndroid Build Coastguard Worker ASSERT_STATUS_OK(artd_->mergeProfiles({profile_1_path},
3183*795d594fSAndroid Build Coastguard Worker profile_path_,
3184*795d594fSAndroid Build Coastguard Worker &output_profile,
3185*795d594fSAndroid Build Coastguard Worker {dex_file_1},
3186*795d594fSAndroid Build Coastguard Worker /*in_options=*/{},
3187*795d594fSAndroid Build Coastguard Worker &result));
3188*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(result);
3189*795d594fSAndroid Build Coastguard Worker EXPECT_THAT(output_profile.profilePath.tmpPath,
3190*795d594fSAndroid Build Coastguard Worker ContainsRegex(R"re(/primary\.prof\.staged\.\w+\.tmp$)re"));
3191*795d594fSAndroid Build Coastguard Worker CheckContent(output_profile.profilePath.tmpPath, "merged");
3192*795d594fSAndroid Build Coastguard Worker }
3193*795d594fSAndroid Build Coastguard Worker
3194*795d594fSAndroid Build Coastguard Worker } // namespace
3195*795d594fSAndroid Build Coastguard Worker } // namespace artd
3196*795d594fSAndroid Build Coastguard Worker } // namespace art
3197