1 /*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "odrefresh.h"
18
19 #include <unistd.h>
20
21 #include <functional>
22 #include <memory>
23 #include <string_view>
24 #include <utility>
25 #include <vector>
26
27 #include "android-base/file.h"
28 #include "android-base/parseint.h"
29 #include "android-base/scopeguard.h"
30 #include "android-base/stringprintf.h"
31 #include "android-base/strings.h"
32 #include "android-modules-utils/sdk_level.h"
33 #include "arch/instruction_set.h"
34 #include "base/common_art_test.h"
35 #include "base/file_utils.h"
36 #include "base/macros.h"
37 #include "base/stl_util.h"
38 #include "exec_utils.h"
39 #include "gmock/gmock.h"
40 #include "gtest/gtest.h"
41 #include "odr_artifacts.h"
42 #include "odr_common.h"
43 #include "odr_config.h"
44 #include "odr_fs_utils.h"
45 #include "odr_metrics.h"
46 #include "odrefresh/odrefresh.h"
47
48 namespace art {
49 namespace odrefresh {
50
51 using ::android::base::Basename;
52 using ::android::base::Split;
53 using ::android::modules::sdklevel::IsAtLeastU;
54 using ::testing::_;
55 using ::testing::AllOf;
56 using ::testing::Contains;
57 using ::testing::ElementsAre;
58 using ::testing::EndsWith;
59 using ::testing::Not;
60 using ::testing::ResultOf;
61 using ::testing::Return;
62
63 constexpr int kReplace = 1;
64
CreateEmptyFile(const std::string & name)65 void CreateEmptyFile(const std::string& name) {
66 File* file = OS::CreateEmptyFile(name.c_str());
67 ASSERT_TRUE(file != nullptr) << "Cannot create file " << name;
68 file->Release();
69 delete file;
70 }
71
ScopedCreateEmptyFile(const std::string & name)72 android::base::ScopeGuard<std::function<void()>> ScopedCreateEmptyFile(const std::string& name) {
73 CreateEmptyFile(name);
74 return android::base::ScopeGuard([=]() { unlink(name.c_str()); });
75 }
76
77 class MockExecUtils : public ExecUtils {
78 public:
79 // A workaround to avoid MOCK_METHOD on a method with an `std::string*` parameter, which will lead
80 // to a conflict between gmock and android-base/logging.h (b/132668253).
ExecAndReturnResult(const std::vector<std::string> & arg_vector,int,std::string *) const81 ExecResult ExecAndReturnResult(const std::vector<std::string>& arg_vector,
82 int,
83 std::string*) const override {
84 return {.status = ExecResult::kExited, .exit_code = DoExecAndReturnCode(arg_vector)};
85 }
86
87 MOCK_METHOD(int, DoExecAndReturnCode, (const std::vector<std::string>& arg_vector), (const));
88 };
89
90 // Matches a flag that starts with `flag` and whose value matches `matcher`.
91 MATCHER_P2(Flag, flag, matcher, "") {
92 std::string_view value(arg);
93 if (!android::base::ConsumePrefix(&value, flag)) {
94 return false;
95 }
96 return ExplainMatchResult(matcher, std::string(value), result_listener);
97 }
98
99 // Matches a flag that starts with `flag` and whose value is a colon-separated list that matches
100 // `matcher`. The matcher acts on an `std::vector<std::string>` of the split list argument.
101 MATCHER_P2(ListFlag, flag, matcher, "") {
102 return ExplainMatchResult(
103 Flag(flag, ResultOf(std::bind(Split, std::placeholders::_1, ":"), matcher)),
104 arg,
105 result_listener);
106 }
107
108 // Matches an FD of a file whose path matches `matcher`.
109 MATCHER_P(FdOf, matcher, "") {
110 char path[PATH_MAX];
111 int fd;
112 if (!android::base::ParseInt(std::string{arg}, &fd)) {
113 return false;
114 }
115 std::string proc_path = android::base::StringPrintf("/proc/self/fd/%d", fd);
116 ssize_t len = readlink(proc_path.c_str(), path, sizeof(path));
117 if (len < 0) {
118 return false;
119 }
120 std::string path_str{path, static_cast<size_t>(len)};
121 return ExplainMatchResult(matcher, path_str, result_listener);
122 }
123
WriteFakeApexInfoList(const std::string & filename)124 void WriteFakeApexInfoList(const std::string& filename) {
125 std::string content = R"xml(
126 <?xml version="1.0" encoding="utf-8"?>
127 <apex-info-list>
128 <apex-info
129 moduleName="com.android.art"
130 modulePath="/data/apex/active/com.android.art@319999900.apex"
131 preinstalledModulePath="/system/apex/com.android.art.capex"
132 versionCode="319999900"
133 versionName=""
134 isFactory="false"
135 isActive="true"
136 lastUpdateMillis="12345678">
137 </apex-info>
138 </apex-info-list>
139 )xml";
140 android::base::WriteStringToFile(content, filename);
141 }
142
143 class OdRefreshTest : public CommonArtTest {
144 public:
OdRefreshTest()145 OdRefreshTest() : config_("odrefresh") {}
146
147 protected:
SetUp()148 void SetUp() override {
149 CommonArtTest::SetUp();
150
151 temp_dir_ = std::make_unique<ScratchDir>();
152 std::string temp_dir_path = temp_dir_->GetPath();
153 // Remove the trailing '/';
154 temp_dir_path.resize(temp_dir_path.length() - 1);
155
156 std::string android_root_path = temp_dir_path + "/system";
157 ASSERT_TRUE(EnsureDirectoryExists(android_root_path));
158 android_root_env_ = std::make_unique<ScopedUnsetEnvironmentVariable>("ANDROID_ROOT");
159 setenv("ANDROID_ROOT", android_root_path.c_str(), kReplace);
160
161 std::string android_art_root_path = temp_dir_path + "/apex/com.android.art";
162 ASSERT_TRUE(EnsureDirectoryExists(android_art_root_path));
163 android_art_root_env_ = std::make_unique<ScopedUnsetEnvironmentVariable>("ANDROID_ART_ROOT");
164 setenv("ANDROID_ART_ROOT", android_art_root_path.c_str(), kReplace);
165
166 std::string art_apex_data_path = temp_dir_path + kArtApexDataDefaultPath;
167 ASSERT_TRUE(EnsureDirectoryExists(art_apex_data_path));
168 art_apex_data_env_ = std::make_unique<ScopedUnsetEnvironmentVariable>("ART_APEX_DATA");
169 setenv("ART_APEX_DATA", art_apex_data_path.c_str(), kReplace);
170
171 dalvik_cache_dir_ = art_apex_data_path + "/dalvik-cache";
172 ASSERT_TRUE(EnsureDirectoryExists(dalvik_cache_dir_ + "/x86_64"));
173
174 std::string system_etc_dir = android_root_path + "/etc";
175 ASSERT_TRUE(EnsureDirectoryExists(system_etc_dir));
176 framework_profile_ = system_etc_dir + "/boot-image.prof";
177 CreateEmptyFile(framework_profile_);
178 dirty_image_objects_file_ = system_etc_dir + "/dirty-image-objects";
179 CreateEmptyFile(dirty_image_objects_file_);
180 preloaded_classes_file_ = system_etc_dir + "/preloaded-classes";
181 CreateEmptyFile(preloaded_classes_file_);
182 art_etc_dir_ = android_art_root_path + "/etc";
183 ASSERT_TRUE(EnsureDirectoryExists(art_etc_dir_));
184 art_profile_ = art_etc_dir_ + "/boot-image.prof";
185 CreateEmptyFile(art_profile_);
186
187 framework_dir_ = android_root_path + "/framework";
188 framework_jar_ = framework_dir_ + "/framework.jar";
189 location_provider_jar_ = framework_dir_ + "/com.android.location.provider.jar";
190 services_jar_ = framework_dir_ + "/services.jar";
191 services_foo_jar_ = framework_dir_ + "/services-foo.jar";
192 services_bar_jar_ = framework_dir_ + "/services-bar.jar";
193 services_jar_profile_ = framework_dir_ + "/services.jar.prof";
194 std::string art_javalib_dir = android_art_root_path + "/javalib";
195 core_oj_jar_ = art_javalib_dir + "/core-oj.jar";
196 std::string conscrypt_javalib_dir = temp_dir_path + "/apex/com.android.conscrypt/javalib";
197 conscrypt_jar_ = conscrypt_javalib_dir + "/conscrypt.jar";
198 std::string wifi_javalib_dir = temp_dir_path + "/apex/com.android.wifi/javalib";
199 framework_wifi_jar_ = wifi_javalib_dir + "/framework-wifi.jar";
200
201 // Create placeholder files.
202 ASSERT_TRUE(EnsureDirectoryExists(framework_dir_ + "/x86_64"));
203 CreateEmptyFile(framework_jar_);
204 CreateEmptyFile(location_provider_jar_);
205 CreateEmptyFile(services_jar_);
206 CreateEmptyFile(services_foo_jar_);
207 CreateEmptyFile(services_bar_jar_);
208 CreateEmptyFile(services_jar_profile_);
209 ASSERT_TRUE(EnsureDirectoryExists(art_javalib_dir));
210 CreateEmptyFile(core_oj_jar_);
211 ASSERT_TRUE(EnsureDirectoryExists(conscrypt_javalib_dir));
212 CreateEmptyFile(conscrypt_jar_);
213 ASSERT_TRUE(EnsureDirectoryExists(wifi_javalib_dir));
214 CreateEmptyFile(framework_wifi_jar_);
215
216 std::string apex_info_filename = temp_dir_path + "/apex-info-list.xml";
217 WriteFakeApexInfoList(apex_info_filename);
218 config_.SetApexInfoListFile(apex_info_filename);
219
220 config_.SetArtBinDir(temp_dir_path + "/bin");
221 config_.SetBootClasspath(core_oj_jar_ + ":" + framework_jar_ + ":" + conscrypt_jar_ + ":" +
222 framework_wifi_jar_);
223 config_.SetDex2oatBootclasspath(core_oj_jar_ + ":" + framework_jar_);
224 config_.SetSystemServerClasspath(location_provider_jar_ + ":" + services_jar_);
225 config_.SetStandaloneSystemServerJars(services_foo_jar_ + ":" + services_bar_jar_);
226 config_.SetIsa(InstructionSet::kX86_64);
227 config_.SetZygoteKind(ZygoteKind::kZygote64_32);
228 config_.SetSystemServerCompilerFilter("");
229 config_.SetArtifactDirectory(dalvik_cache_dir_);
230
231 auto mock_exec_utils = std::make_unique<MockExecUtils>();
232 mock_exec_utils_ = mock_exec_utils.get();
233
234 metrics_ = std::make_unique<OdrMetrics>(dalvik_cache_dir_);
235 cache_info_xml_ = dalvik_cache_dir_ + "/cache-info.xml";
236 check_compilation_space_ = [] { return true; };
237 setfilecon_ = [](auto, auto) { return 0; };
238 restorecon_ = [](auto, auto) { return 0; };
239 odrefresh_ = std::make_unique<OnDeviceRefresh>(config_,
240 setfilecon_,
241 restorecon_,
242 cache_info_xml_,
243 std::move(mock_exec_utils),
244 check_compilation_space_);
245 }
246
TearDown()247 void TearDown() override {
248 metrics_.reset();
249 temp_dir_.reset();
250 android_root_env_.reset();
251 android_art_root_env_.reset();
252 art_apex_data_env_.reset();
253
254 CommonArtTest::TearDown();
255 }
256
257 std::unique_ptr<ScratchDir> temp_dir_;
258 std::unique_ptr<ScopedUnsetEnvironmentVariable> android_root_env_;
259 std::unique_ptr<ScopedUnsetEnvironmentVariable> android_art_root_env_;
260 std::unique_ptr<ScopedUnsetEnvironmentVariable> art_apex_data_env_;
261 OdrConfig config_;
262 MockExecUtils* mock_exec_utils_;
263 std::unique_ptr<OnDeviceRefresh> odrefresh_;
264 std::unique_ptr<OdrMetrics> metrics_;
265 std::string core_oj_jar_;
266 std::string framework_jar_;
267 std::string conscrypt_jar_;
268 std::string framework_wifi_jar_;
269 std::string location_provider_jar_;
270 std::string services_jar_;
271 std::string services_foo_jar_;
272 std::string services_bar_jar_;
273 std::string dalvik_cache_dir_;
274 std::string art_etc_dir_;
275 std::string framework_dir_;
276 std::string framework_profile_;
277 std::string art_profile_;
278 std::string services_jar_profile_;
279 std::string dirty_image_objects_file_;
280 std::string preloaded_classes_file_;
281 std::string cache_info_xml_;
282 std::function<bool()> check_compilation_space_;
283 std::function<int(const char*, const char*)> setfilecon_;
284 std::function<int(const char*, unsigned int)> restorecon_;
285 };
286
TEST_F(OdRefreshTest,PrimaryBootImage)287 TEST_F(OdRefreshTest, PrimaryBootImage) {
288 EXPECT_CALL(*mock_exec_utils_,
289 DoExecAndReturnCode(AllOf(
290 Contains(Flag("--dex-file=", core_oj_jar_)),
291 Contains(Flag("--dex-file=", framework_jar_)),
292 Not(Contains(Flag("--dex-file=", conscrypt_jar_))),
293 Not(Contains(Flag("--dex-file=", framework_wifi_jar_))),
294 Contains(Flag("--dex-fd=", FdOf(core_oj_jar_))),
295 Contains(Flag("--dex-fd=", FdOf(framework_jar_))),
296 Not(Contains(Flag("--dex-fd=", FdOf(conscrypt_jar_)))),
297 Not(Contains(Flag("--dex-fd=", FdOf(framework_wifi_jar_)))),
298 Contains(ListFlag("-Xbootclasspath:", ElementsAre(core_oj_jar_, framework_jar_))),
299 Contains(ListFlag("-Xbootclasspathfds:",
300 ElementsAre(FdOf(core_oj_jar_), FdOf(framework_jar_)))),
301 Contains(Flag("--oat-location=", dalvik_cache_dir_ + "/x86_64/boot.oat")),
302 Contains(Flag("--base=", _)),
303 Not(Contains(Flag("--boot-image=", _))),
304 Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_))))))
305 .WillOnce(Return(0));
306
307 // Ignore the invocation for the mainline extension.
308 EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(Contains(Flag("--dex-file=", conscrypt_jar_))))
309 .WillOnce(Return(0));
310
311 EXPECT_EQ(odrefresh_->Compile(
312 *metrics_,
313 CompilationOptions{
314 .boot_images_to_generate_for_isas{
315 {InstructionSet::kX86_64,
316 {.primary_boot_image = true, .boot_image_mainline_extension = true}}},
317 }),
318 ExitCode::kCompilationSuccess);
319 }
320
TEST_F(OdRefreshTest,BootImageMainlineExtension)321 TEST_F(OdRefreshTest, BootImageMainlineExtension) {
322 EXPECT_CALL(
323 *mock_exec_utils_,
324 DoExecAndReturnCode(AllOf(
325 Not(Contains(Flag("--dex-file=", core_oj_jar_))),
326 Not(Contains(Flag("--dex-file=", framework_jar_))),
327 Contains(Flag("--dex-file=", conscrypt_jar_)),
328 Contains(Flag("--dex-file=", framework_wifi_jar_)),
329 Not(Contains(Flag("--dex-fd=", FdOf(core_oj_jar_)))),
330 Not(Contains(Flag("--dex-fd=", FdOf(framework_jar_)))),
331 Contains(Flag("--dex-fd=", FdOf(conscrypt_jar_))),
332 Contains(Flag("--dex-fd=", FdOf(framework_wifi_jar_))),
333 Contains(ListFlag(
334 "-Xbootclasspath:",
335 ElementsAre(core_oj_jar_, framework_jar_, conscrypt_jar_, framework_wifi_jar_))),
336 Contains(ListFlag("-Xbootclasspathfds:",
337 ElementsAre(FdOf(core_oj_jar_),
338 FdOf(framework_jar_),
339 FdOf(conscrypt_jar_),
340 FdOf(framework_wifi_jar_)))),
341 Contains(Flag("--oat-location=", dalvik_cache_dir_ + "/x86_64/boot.oat")),
342 Not(Contains(Flag("--base=", _))),
343 Contains(Flag("--boot-image=", _)),
344 Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_))))))
345 .WillOnce(Return(0));
346
347 EXPECT_EQ(odrefresh_->Compile(
348 *metrics_,
349 CompilationOptions{
350 .boot_images_to_generate_for_isas{
351 {InstructionSet::kX86_64, {.boot_image_mainline_extension = true}}},
352 }),
353 ExitCode::kCompilationSuccess);
354 }
355
TEST_F(OdRefreshTest,BootClasspathJarsWithExplicitCompilerFilter)356 TEST_F(OdRefreshTest, BootClasspathJarsWithExplicitCompilerFilter) {
357 config_.SetBootImageCompilerFilter("speed");
358
359 // Profiles should still be passed for primary boot image.
360 EXPECT_CALL(
361 *mock_exec_utils_,
362 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", core_oj_jar_)),
363 Contains(Flag("--profile-file-fd=", FdOf(art_profile_))),
364 Contains(Flag("--profile-file-fd=", FdOf(framework_profile_))),
365 Contains("--compiler-filter=speed"))))
366 .WillOnce(Return(0));
367
368 // "verify" should always be used for boot image mainline extension.
369 EXPECT_CALL(*mock_exec_utils_,
370 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", conscrypt_jar_)),
371 Not(Contains(Flag("--profile-file-fd=", _))),
372 Contains("--compiler-filter=verify"))))
373 .WillOnce(Return(0));
374
375 EXPECT_EQ(odrefresh_->Compile(
376 *metrics_,
377 CompilationOptions{
378 .boot_images_to_generate_for_isas{
379 {InstructionSet::kX86_64,
380 {.primary_boot_image = true, .boot_image_mainline_extension = true}}},
381 }),
382 ExitCode::kCompilationSuccess);
383 }
384
TEST_F(OdRefreshTest,BootClasspathJarsWithDefaultCompilerFilter)385 TEST_F(OdRefreshTest, BootClasspathJarsWithDefaultCompilerFilter) {
386 EXPECT_CALL(
387 *mock_exec_utils_,
388 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", core_oj_jar_)),
389 Contains(Flag("--profile-file-fd=", FdOf(art_profile_))),
390 Contains(Flag("--profile-file-fd=", FdOf(framework_profile_))),
391 Contains("--compiler-filter=speed-profile"))))
392 .WillOnce(Return(0));
393
394 // "verify" should always be used for boot image mainline extension.
395 EXPECT_CALL(*mock_exec_utils_,
396 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", conscrypt_jar_)),
397 Not(Contains(Flag("--profile-file-fd=", _))),
398 Contains("--compiler-filter=verify"))))
399 .WillOnce(Return(0));
400
401 EXPECT_EQ(odrefresh_->Compile(
402 *metrics_,
403 CompilationOptions{
404 .boot_images_to_generate_for_isas{
405 {InstructionSet::kX86_64,
406 {.primary_boot_image = true, .boot_image_mainline_extension = true}}},
407 }),
408 ExitCode::kCompilationSuccess);
409 }
410
TEST_F(OdRefreshTest,BootClasspathJarsFallback)411 TEST_F(OdRefreshTest, BootClasspathJarsFallback) {
412 // Simulate the case where dex2oat fails when generating the full boot image.
413 EXPECT_CALL(*mock_exec_utils_,
414 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", core_oj_jar_)),
415 Contains(Flag("--dex-file=", framework_jar_)))))
416 .Times(2)
417 .WillRepeatedly(Return(1));
418
419 // It should fall back to generating a minimal boot image.
420 EXPECT_CALL(*mock_exec_utils_,
421 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", core_oj_jar_)),
422 Not(Contains(Flag("--dex-file=", framework_jar_))))))
423 .Times(2)
424 .WillOnce(Return(0));
425
426 EXPECT_EQ(odrefresh_->Compile(
427 *metrics_,
428 CompilationOptions{
429 .boot_images_to_generate_for_isas{
430 {InstructionSet::kX86_64,
431 {.primary_boot_image = true, .boot_image_mainline_extension = true}},
432 {InstructionSet::kX86,
433 {.primary_boot_image = true, .boot_image_mainline_extension = true}}},
434 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
435 }),
436 ExitCode::kCompilationFailed);
437 }
438
TEST_F(OdRefreshTest,AllSystemServerJars)439 TEST_F(OdRefreshTest, AllSystemServerJars) {
440 EXPECT_CALL(
441 *mock_exec_utils_,
442 DoExecAndReturnCode(AllOf(
443 Contains(Flag("--dex-file=", location_provider_jar_)),
444 Contains("--class-loader-context=PCL[]"),
445 Not(Contains(Flag("--class-loader-context-fds=", _))),
446 Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_))),
447 Contains(Flag("--oat-location=",
448 EndsWith("@" + Basename(location_provider_jar_) + "@classes.odex"))))))
449 .WillOnce(Return(0));
450 EXPECT_CALL(
451 *mock_exec_utils_,
452 DoExecAndReturnCode(AllOf(
453 Contains(Flag("--dex-file=", services_jar_)),
454 Contains(Flag("--class-loader-context=", ART_FORMAT("PCL[{}]", location_provider_jar_))),
455 Contains(Flag("--class-loader-context-fds=", FdOf(location_provider_jar_))),
456 Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_))),
457 Contains(
458 Flag("--oat-location=", EndsWith("@" + Basename(services_jar_) + "@classes.odex"))))))
459 .WillOnce(Return(0));
460 EXPECT_CALL(
461 *mock_exec_utils_,
462 DoExecAndReturnCode(AllOf(
463 Contains(Flag("--dex-file=", services_foo_jar_)),
464 Contains(Flag("--class-loader-context=",
465 ART_FORMAT("PCL[];PCL[{}:{}]", location_provider_jar_, services_jar_))),
466 Contains(ListFlag("--class-loader-context-fds=",
467 ElementsAre(FdOf(location_provider_jar_), FdOf(services_jar_)))),
468 Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_))),
469 Contains(Flag("--oat-location=",
470 EndsWith("@" + Basename(services_foo_jar_) + "@classes.odex"))))))
471 .WillOnce(Return(0));
472 EXPECT_CALL(
473 *mock_exec_utils_,
474 DoExecAndReturnCode(AllOf(
475 Contains(Flag("--dex-file=", services_bar_jar_)),
476 Contains(Flag("--class-loader-context=",
477 ART_FORMAT("PCL[];PCL[{}:{}]", location_provider_jar_, services_jar_))),
478 Contains(ListFlag("--class-loader-context-fds=",
479 ElementsAre(FdOf(location_provider_jar_), FdOf(services_jar_)))),
480 Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_))),
481 Contains(Flag("--oat-location=",
482 EndsWith("@" + Basename(services_bar_jar_) + "@classes.odex"))))))
483 .WillOnce(Return(0));
484
485 EXPECT_EQ(
486 odrefresh_->Compile(*metrics_,
487 CompilationOptions{
488 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
489 }),
490 ExitCode::kCompilationSuccess);
491 }
492
TEST_F(OdRefreshTest,PartialSystemServerJars)493 TEST_F(OdRefreshTest, PartialSystemServerJars) {
494 EXPECT_CALL(
495 *mock_exec_utils_,
496 DoExecAndReturnCode(AllOf(
497 Contains(Flag("--dex-file=", services_jar_)),
498 Contains(Flag("--class-loader-context=", ART_FORMAT("PCL[{}]", location_provider_jar_))),
499 Contains(Flag("--class-loader-context-fds=", FdOf(location_provider_jar_))))))
500 .WillOnce(Return(0));
501 EXPECT_CALL(
502 *mock_exec_utils_,
503 DoExecAndReturnCode(AllOf(
504 Contains(Flag("--dex-file=", services_bar_jar_)),
505 Contains(Flag("--class-loader-context=",
506 ART_FORMAT("PCL[];PCL[{}:{}]", location_provider_jar_, services_jar_))),
507 Contains(ListFlag("--class-loader-context-fds=",
508 ElementsAre(FdOf(location_provider_jar_), FdOf(services_jar_)))))))
509 .WillOnce(Return(0));
510
511 EXPECT_EQ(
512 odrefresh_->Compile(*metrics_,
513 CompilationOptions{
514 .system_server_jars_to_compile = {services_jar_, services_bar_jar_},
515 }),
516 ExitCode::kCompilationSuccess);
517 }
518
519 // Verifies that odrefresh can run properly when the STANDALONE_SYSTEM_SERVER_JARS variable is
520 // missing, which is expected on Android S.
TEST_F(OdRefreshTest,MissingStandaloneSystemServerJars)521 TEST_F(OdRefreshTest, MissingStandaloneSystemServerJars) {
522 config_.SetStandaloneSystemServerJars("");
523 EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_)).WillRepeatedly(Return(0));
524 EXPECT_EQ(
525 odrefresh_->Compile(*metrics_,
526 CompilationOptions{
527 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
528 }),
529 ExitCode::kCompilationSuccess);
530 }
531
TEST_F(OdRefreshTest,ContinueWhenBcpCompilationFailed)532 TEST_F(OdRefreshTest, ContinueWhenBcpCompilationFailed) {
533 // Simulate that the compilation of BCP for the system server ISA succeeds.
534 EXPECT_CALL(*mock_exec_utils_,
535 DoExecAndReturnCode(AllOf(Contains("--instruction-set=x86_64"),
536 Contains(Flag("--dex-file=", core_oj_jar_)))))
537 .WillOnce(Return(0));
538 EXPECT_CALL(*mock_exec_utils_,
539 DoExecAndReturnCode(AllOf(Contains("--instruction-set=x86_64"),
540 Contains(Flag("--dex-file=", conscrypt_jar_)))))
541 .WillOnce(Return(0));
542
543 // Simulate that the compilation of BCP for the other ISA fails.
544 EXPECT_CALL(*mock_exec_utils_,
545 DoExecAndReturnCode(AllOf(Contains("--instruction-set=x86"),
546 Contains(Flag("--dex-file=", core_oj_jar_)))))
547 .Times(2)
548 .WillRepeatedly(Return(1));
549
550 // It should still compile system server.
551 EXPECT_CALL(*mock_exec_utils_,
552 DoExecAndReturnCode(Contains(Flag("--dex-file=", location_provider_jar_))))
553 .WillOnce(Return(0));
554 EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(Contains(Flag("--dex-file=", services_jar_))))
555 .WillOnce(Return(0));
556 EXPECT_CALL(*mock_exec_utils_,
557 DoExecAndReturnCode(Contains(Flag("--dex-file=", services_foo_jar_))))
558 .WillOnce(Return(0));
559 EXPECT_CALL(*mock_exec_utils_,
560 DoExecAndReturnCode(Contains(Flag("--dex-file=", services_bar_jar_))))
561 .WillOnce(Return(0));
562
563 EXPECT_EQ(odrefresh_->Compile(
564 *metrics_,
565 CompilationOptions{
566 .boot_images_to_generate_for_isas{
567 {InstructionSet::kX86_64,
568 {.primary_boot_image = true, .boot_image_mainline_extension = true}},
569 {InstructionSet::kX86,
570 {.primary_boot_image = true, .boot_image_mainline_extension = true}}},
571 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
572 }),
573 ExitCode::kCompilationFailed);
574 }
575
TEST_F(OdRefreshTest,ContinueWhenSystemServerCompilationFailed)576 TEST_F(OdRefreshTest, ContinueWhenSystemServerCompilationFailed) {
577 // Simulate that the compilation of "services.jar" fails, while others still succeed.
578 EXPECT_CALL(*mock_exec_utils_,
579 DoExecAndReturnCode(Contains(Flag("--dex-file=", location_provider_jar_))))
580 .WillOnce(Return(0));
581 EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(Contains(Flag("--dex-file=", services_jar_))))
582 .WillOnce(Return(1));
583 EXPECT_CALL(*mock_exec_utils_,
584 DoExecAndReturnCode(Contains(Flag("--dex-file=", services_foo_jar_))))
585 .WillOnce(Return(0));
586 EXPECT_CALL(*mock_exec_utils_,
587 DoExecAndReturnCode(Contains(Flag("--dex-file=", services_bar_jar_))))
588 .WillOnce(Return(0));
589
590 EXPECT_EQ(
591 odrefresh_->Compile(*metrics_,
592 CompilationOptions{
593 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
594 }),
595 ExitCode::kCompilationFailed);
596 }
597
598 // Test setup: The compiler filter is explicitly set to "speed-profile". Use it regardless of
599 // whether the profile exists or not. Dex2oat will fall back to "verify" if the profile doesn't
600 // exist.
TEST_F(OdRefreshTest,CompileSetsCompilerFilterWithExplicitValue)601 TEST_F(OdRefreshTest, CompileSetsCompilerFilterWithExplicitValue) {
602 config_.SetSystemServerCompilerFilter("speed-profile");
603
604 // Uninteresting calls.
605 EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_))
606 .Times(odrefresh_->AllSystemServerJars().size() - 2)
607 .WillRepeatedly(Return(0));
608
609 EXPECT_CALL(*mock_exec_utils_,
610 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", location_provider_jar_)),
611 Not(Contains(Flag("--profile-file-fd=", _))),
612 Contains("--compiler-filter=speed-profile"))))
613 .WillOnce(Return(0));
614 EXPECT_CALL(
615 *mock_exec_utils_,
616 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", services_jar_)),
617 Contains(Flag("--profile-file-fd=", FdOf(services_jar_profile_))),
618 Contains("--compiler-filter=speed-profile"))))
619 .WillOnce(Return(0));
620 EXPECT_EQ(
621 odrefresh_->Compile(*metrics_,
622 CompilationOptions{
623 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
624 }),
625 ExitCode::kCompilationSuccess);
626 }
627
628 // Test setup: The compiler filter is not explicitly set. Use "speed-profile" if there is a vetted
629 // profile (on U+), otherwise fall back to "speed".
TEST_F(OdRefreshTest,CompileSetsCompilerFilterWithDefaultValue)630 TEST_F(OdRefreshTest, CompileSetsCompilerFilterWithDefaultValue) {
631 // Uninteresting calls.
632 EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_))
633 .Times(odrefresh_->AllSystemServerJars().size() - 2)
634 .WillRepeatedly(Return(0));
635
636 // services.jar has a profile, while location.provider.jar does not.
637 EXPECT_CALL(*mock_exec_utils_,
638 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", location_provider_jar_)),
639 Not(Contains(Flag("--profile-file-fd=", _))),
640 Contains("--compiler-filter=speed"))))
641 .WillOnce(Return(0));
642 // Only on U+ should we use the profile by default if available.
643 if (IsAtLeastU()) {
644 EXPECT_CALL(
645 *mock_exec_utils_,
646 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", services_jar_)),
647 Contains(Flag("--profile-file-fd=", FdOf(services_jar_profile_))),
648 Contains("--compiler-filter=speed-profile"))))
649 .WillOnce(Return(0));
650 } else {
651 EXPECT_CALL(*mock_exec_utils_,
652 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", services_jar_)),
653 Not(Contains(Flag("--profile-file-fd=", _))),
654 Contains("--compiler-filter=speed"))))
655 .WillOnce(Return(0));
656 }
657 EXPECT_EQ(
658 odrefresh_->Compile(*metrics_,
659 CompilationOptions{
660 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
661 }),
662 ExitCode::kCompilationSuccess);
663 }
664
TEST_F(OdRefreshTest,OutputFilesAndIsa)665 TEST_F(OdRefreshTest, OutputFilesAndIsa) {
666 config_.MutableSystemProperties()->emplace("dalvik.vm.isa.x86_64.features", "foo");
667 config_.MutableSystemProperties()->emplace("dalvik.vm.isa.x86_64.variant", "bar");
668
669 EXPECT_CALL(*mock_exec_utils_,
670 DoExecAndReturnCode(AllOf(Contains("--instruction-set=x86_64"),
671 Contains(Flag("--instruction-set-features=", "foo")),
672 Contains(Flag("--instruction-set-variant=", "bar")),
673 Contains(Flag("--image-fd=", FdOf(_))),
674 Contains(Flag("--output-vdex-fd=", FdOf(_))),
675 Contains(Flag("--oat-fd=", FdOf(_))))))
676 .Times(2)
677 .WillRepeatedly(Return(0));
678
679 EXPECT_CALL(*mock_exec_utils_,
680 DoExecAndReturnCode(AllOf(Contains("--instruction-set=x86_64"),
681 Contains(Flag("--instruction-set-features=", "foo")),
682 Contains(Flag("--instruction-set-variant=", "bar")),
683 Contains(Flag("--app-image-fd=", FdOf(_))),
684 Contains(Flag("--output-vdex-fd=", FdOf(_))),
685 Contains(Flag("--oat-fd=", FdOf(_))))))
686 .Times(odrefresh_->AllSystemServerJars().size())
687 .WillRepeatedly(Return(0));
688
689 // No instruction set features or variant set for x86.
690 EXPECT_CALL(*mock_exec_utils_,
691 DoExecAndReturnCode(AllOf(Contains("--instruction-set=x86"),
692 Not(Contains(Flag("--instruction-set-features=", _))),
693 Not(Contains(Flag("--instruction-set-variant=", _))))))
694 .Times(2)
695 .WillRepeatedly(Return(0));
696
697 EXPECT_EQ(odrefresh_->Compile(
698 *metrics_,
699 CompilationOptions{
700 .boot_images_to_generate_for_isas{
701 {InstructionSet::kX86_64,
702 {.primary_boot_image = true, .boot_image_mainline_extension = true}},
703 {InstructionSet::kX86,
704 {.primary_boot_image = true, .boot_image_mainline_extension = true}}},
705 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
706 }),
707 ExitCode::kCompilationSuccess);
708 }
709
TEST_F(OdRefreshTest,RuntimeOptions)710 TEST_F(OdRefreshTest, RuntimeOptions) {
711 config_.MutableSystemProperties()->emplace("dalvik.vm.image-dex2oat-Xms", "10");
712 config_.MutableSystemProperties()->emplace("dalvik.vm.image-dex2oat-Xmx", "20");
713 config_.MutableSystemProperties()->emplace("dalvik.vm.dex2oat-Xms", "30");
714 config_.MutableSystemProperties()->emplace("dalvik.vm.dex2oat-Xmx", "40");
715
716 EXPECT_CALL(*mock_exec_utils_,
717 DoExecAndReturnCode(AllOf(Contains(Flag("--image-fd=", FdOf(_))),
718 Contains(Flag("-Xms", "10")),
719 Contains(Flag("-Xmx", "20")))))
720 .Times(2)
721 .WillRepeatedly(Return(0));
722
723 EXPECT_CALL(*mock_exec_utils_,
724 DoExecAndReturnCode(AllOf(Contains(Flag("--app-image-fd=", FdOf(_))),
725 Contains(Flag("-Xms", "30")),
726 Contains(Flag("-Xmx", "40")))))
727 .Times(odrefresh_->AllSystemServerJars().size())
728 .WillRepeatedly(Return(0));
729
730 EXPECT_EQ(odrefresh_->Compile(
731 *metrics_,
732 CompilationOptions{
733 .boot_images_to_generate_for_isas{
734 {InstructionSet::kX86_64,
735 {.primary_boot_image = true, .boot_image_mainline_extension = true}}},
736 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
737 }),
738 ExitCode::kCompilationSuccess);
739 }
740
TEST_F(OdRefreshTest,GenerateBootImageMainlineExtensionChoosesBootImage_OnData)741 TEST_F(OdRefreshTest, GenerateBootImageMainlineExtensionChoosesBootImage_OnData) {
742 // Primary boot image is on /data.
743 OdrArtifacts primary = OdrArtifacts::ForBootImage(dalvik_cache_dir_ + "/x86_64/boot.art");
744 auto file1 = ScopedCreateEmptyFile(primary.ImagePath());
745 auto file2 = ScopedCreateEmptyFile(primary.VdexPath());
746 auto file3 = ScopedCreateEmptyFile(primary.OatPath());
747
748 EXPECT_CALL(*mock_exec_utils_,
749 DoExecAndReturnCode(AllOf(
750 Contains(Flag("--dex-file=", conscrypt_jar_)),
751 Contains(Flag("--boot-image=", dalvik_cache_dir_ + "/boot.art")),
752 Contains(ListFlag("-Xbootclasspathimagefds:",
753 ElementsAre(FdOf(primary.ImagePath()), "-1", "-1", "-1"))),
754 Contains(ListFlag("-Xbootclasspathvdexfds:",
755 ElementsAre(FdOf(primary.VdexPath()), "-1", "-1", "-1"))),
756 Contains(ListFlag("-Xbootclasspathoatfds:",
757 ElementsAre(FdOf(primary.OatPath()), "-1", "-1", "-1"))))))
758 .WillOnce(Return(0));
759
760 EXPECT_EQ(odrefresh_->Compile(
761 *metrics_,
762 CompilationOptions{
763 .boot_images_to_generate_for_isas{
764 {InstructionSet::kX86_64, {.boot_image_mainline_extension = true}}},
765 }),
766 ExitCode::kCompilationSuccess);
767 }
768
TEST_F(OdRefreshTest,GenerateBootImageMainlineExtensionChoosesBootImage_OnSystem)769 TEST_F(OdRefreshTest, GenerateBootImageMainlineExtensionChoosesBootImage_OnSystem) {
770 // Primary boot image and framework extension are on /system.
771 OdrArtifacts primary = OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot.art");
772 auto file1 = ScopedCreateEmptyFile(primary.ImagePath());
773 auto file2 = ScopedCreateEmptyFile(primary.VdexPath());
774 auto file3 = ScopedCreateEmptyFile(primary.OatPath());
775 OdrArtifacts framework_ext =
776 OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot-framework.art");
777 auto file4 = ScopedCreateEmptyFile(framework_ext.ImagePath());
778 auto file5 = ScopedCreateEmptyFile(framework_ext.VdexPath());
779 auto file6 = ScopedCreateEmptyFile(framework_ext.OatPath());
780
781 if (IsAtLeastU()) {
782 EXPECT_CALL(
783 *mock_exec_utils_,
784 DoExecAndReturnCode(AllOf(
785 Contains(Flag("--dex-file=", conscrypt_jar_)),
786 Contains(ListFlag("--boot-image=", ElementsAre(framework_dir_ + "/boot.art"))),
787 Contains(ListFlag(
788 "-Xbootclasspathimagefds:",
789 ElementsAre(
790 FdOf(primary.ImagePath()), FdOf(framework_ext.ImagePath()), "-1", "-1"))),
791 Contains(ListFlag(
792 "-Xbootclasspathvdexfds:",
793 ElementsAre(FdOf(primary.VdexPath()), FdOf(framework_ext.VdexPath()), "-1", "-1"))),
794 Contains(ListFlag(
795 "-Xbootclasspathoatfds:",
796 ElementsAre(FdOf(primary.OatPath()), FdOf(framework_ext.OatPath()), "-1", "-1"))))))
797 .WillOnce(Return(0));
798 } else {
799 EXPECT_CALL(
800 *mock_exec_utils_,
801 DoExecAndReturnCode(AllOf(
802 Contains(Flag("--dex-file=", conscrypt_jar_)),
803 Contains(ListFlag(
804 "--boot-image=",
805 ElementsAre(framework_dir_ + "/boot.art", framework_dir_ + "/boot-framework.art"))),
806 Contains(ListFlag(
807 "-Xbootclasspathimagefds:",
808 ElementsAre(
809 FdOf(primary.ImagePath()), FdOf(framework_ext.ImagePath()), "-1", "-1"))),
810 Contains(ListFlag(
811 "-Xbootclasspathvdexfds:",
812 ElementsAre(FdOf(primary.VdexPath()), FdOf(framework_ext.VdexPath()), "-1", "-1"))),
813 Contains(ListFlag(
814 "-Xbootclasspathoatfds:",
815 ElementsAre(FdOf(primary.OatPath()), FdOf(framework_ext.OatPath()), "-1", "-1"))))))
816 .WillOnce(Return(0));
817 }
818
819 EXPECT_EQ(odrefresh_->Compile(
820 *metrics_,
821 CompilationOptions{
822 .boot_images_to_generate_for_isas{
823 {InstructionSet::kX86_64, {.boot_image_mainline_extension = true}}},
824 }),
825 ExitCode::kCompilationSuccess);
826 }
827
TEST_F(OdRefreshTest,CompileSystemServerChoosesBootImage_OnData)828 TEST_F(OdRefreshTest, CompileSystemServerChoosesBootImage_OnData) {
829 // Boot images are on /data.
830 OdrArtifacts primary = OdrArtifacts::ForBootImage(dalvik_cache_dir_ + "/x86_64/boot.art");
831 auto file1 = ScopedCreateEmptyFile(primary.ImagePath());
832 auto file2 = ScopedCreateEmptyFile(primary.VdexPath());
833 auto file3 = ScopedCreateEmptyFile(primary.OatPath());
834 OdrArtifacts mainline_ext =
835 OdrArtifacts::ForBootImage(dalvik_cache_dir_ + "/x86_64/boot-conscrypt.art");
836 auto file4 = ScopedCreateEmptyFile(mainline_ext.ImagePath());
837 auto file5 = ScopedCreateEmptyFile(mainline_ext.VdexPath());
838 auto file6 = ScopedCreateEmptyFile(mainline_ext.OatPath());
839
840 EXPECT_CALL(
841 *mock_exec_utils_,
842 DoExecAndReturnCode(AllOf(
843 Contains(ListFlag("--boot-image=",
844 ElementsAre(dalvik_cache_dir_ + "/boot.art",
845 dalvik_cache_dir_ + "/boot-conscrypt.art"))),
846 Contains(ListFlag(
847 "-Xbootclasspathimagefds:",
848 ElementsAre(FdOf(primary.ImagePath()), "-1", FdOf(mainline_ext.ImagePath()), "-1"))),
849 Contains(ListFlag(
850 "-Xbootclasspathvdexfds:",
851 ElementsAre(FdOf(primary.VdexPath()), "-1", FdOf(mainline_ext.VdexPath()), "-1"))),
852 Contains(ListFlag(
853 "-Xbootclasspathoatfds:",
854 ElementsAre(FdOf(primary.OatPath()), "-1", FdOf(mainline_ext.OatPath()), "-1"))))))
855 .Times(odrefresh_->AllSystemServerJars().size())
856 .WillRepeatedly(Return(0));
857 EXPECT_EQ(
858 odrefresh_->Compile(*metrics_,
859 CompilationOptions{
860 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
861 }),
862 ExitCode::kCompilationSuccess);
863 }
864
TEST_F(OdRefreshTest,CompileSystemServerChoosesBootImage_OnSystemAndData)865 TEST_F(OdRefreshTest, CompileSystemServerChoosesBootImage_OnSystemAndData) {
866 // The mainline extension is on /data, while others are on /system.
867 OdrArtifacts primary = OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot.art");
868 auto file1 = ScopedCreateEmptyFile(primary.ImagePath());
869 auto file2 = ScopedCreateEmptyFile(primary.VdexPath());
870 auto file3 = ScopedCreateEmptyFile(primary.OatPath());
871 OdrArtifacts framework_ext =
872 OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot-framework.art");
873 auto file4 = ScopedCreateEmptyFile(framework_ext.ImagePath());
874 auto file5 = ScopedCreateEmptyFile(framework_ext.VdexPath());
875 auto file6 = ScopedCreateEmptyFile(framework_ext.OatPath());
876 OdrArtifacts mainline_ext =
877 OdrArtifacts::ForBootImage(dalvik_cache_dir_ + "/x86_64/boot-conscrypt.art");
878 auto file7 = ScopedCreateEmptyFile(mainline_ext.ImagePath());
879 auto file8 = ScopedCreateEmptyFile(mainline_ext.VdexPath());
880 auto file9 = ScopedCreateEmptyFile(mainline_ext.OatPath());
881
882 if (IsAtLeastU()) {
883 EXPECT_CALL(*mock_exec_utils_,
884 DoExecAndReturnCode(AllOf(
885 Contains(ListFlag("--boot-image=",
886 ElementsAre(GetPrebuiltPrimaryBootImageDir() + "/boot.art",
887 dalvik_cache_dir_ + "/boot-conscrypt.art"))),
888 Contains(ListFlag("-Xbootclasspathimagefds:",
889 ElementsAre(FdOf(primary.ImagePath()),
890 FdOf(framework_ext.ImagePath()),
891 FdOf(mainline_ext.ImagePath()),
892 "-1"))),
893 Contains(ListFlag("-Xbootclasspathvdexfds:",
894 ElementsAre(FdOf(primary.VdexPath()),
895 FdOf(framework_ext.VdexPath()),
896 FdOf(mainline_ext.VdexPath()),
897 "-1"))),
898 Contains(ListFlag("-Xbootclasspathoatfds:",
899 ElementsAre(FdOf(primary.OatPath()),
900 FdOf(framework_ext.OatPath()),
901 FdOf(mainline_ext.OatPath()),
902 "-1"))))))
903 .Times(odrefresh_->AllSystemServerJars().size())
904 .WillRepeatedly(Return(0));
905 } else {
906 EXPECT_CALL(*mock_exec_utils_,
907 DoExecAndReturnCode(AllOf(
908 Contains(ListFlag("--boot-image=",
909 ElementsAre(GetPrebuiltPrimaryBootImageDir() + "/boot.art",
910 framework_dir_ + "/boot-framework.art",
911 dalvik_cache_dir_ + "/boot-conscrypt.art"))),
912 Contains(ListFlag("-Xbootclasspathimagefds:",
913 ElementsAre(FdOf(primary.ImagePath()),
914 FdOf(framework_ext.ImagePath()),
915 FdOf(mainline_ext.ImagePath()),
916 "-1"))),
917 Contains(ListFlag("-Xbootclasspathvdexfds:",
918 ElementsAre(FdOf(primary.VdexPath()),
919 FdOf(framework_ext.VdexPath()),
920 FdOf(mainline_ext.VdexPath()),
921 "-1"))),
922 Contains(ListFlag("-Xbootclasspathoatfds:",
923 ElementsAre(FdOf(primary.OatPath()),
924 FdOf(framework_ext.OatPath()),
925 FdOf(mainline_ext.OatPath()),
926 "-1"))))))
927 .Times(odrefresh_->AllSystemServerJars().size())
928 .WillRepeatedly(Return(0));
929 }
930
931 EXPECT_EQ(
932 odrefresh_->Compile(*metrics_,
933 CompilationOptions{
934 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
935 }),
936 ExitCode::kCompilationSuccess);
937 }
938
TEST_F(OdRefreshTest,CompileSystemServerChoosesBootImage_OnSystem)939 TEST_F(OdRefreshTest, CompileSystemServerChoosesBootImage_OnSystem) {
940 // Boot images are on /system.
941 OdrArtifacts primary = OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot.art");
942 auto file1 = ScopedCreateEmptyFile(primary.ImagePath());
943 auto file2 = ScopedCreateEmptyFile(primary.VdexPath());
944 auto file3 = ScopedCreateEmptyFile(primary.OatPath());
945 OdrArtifacts framework_ext =
946 OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot-framework.art");
947 auto file4 = ScopedCreateEmptyFile(framework_ext.ImagePath());
948 auto file5 = ScopedCreateEmptyFile(framework_ext.VdexPath());
949 auto file6 = ScopedCreateEmptyFile(framework_ext.OatPath());
950 OdrArtifacts mainline_ext =
951 OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot-conscrypt.art");
952 auto file7 = ScopedCreateEmptyFile(mainline_ext.ImagePath());
953 auto file8 = ScopedCreateEmptyFile(mainline_ext.VdexPath());
954 auto file9 = ScopedCreateEmptyFile(mainline_ext.OatPath());
955
956 if (IsAtLeastU()) {
957 EXPECT_CALL(*mock_exec_utils_,
958 DoExecAndReturnCode(AllOf(
959 Contains(ListFlag("--boot-image=",
960 ElementsAre(GetPrebuiltPrimaryBootImageDir() + "/boot.art",
961 framework_dir_ + "/boot-conscrypt.art"))),
962 Contains(ListFlag("-Xbootclasspathimagefds:",
963 ElementsAre(FdOf(primary.ImagePath()),
964 FdOf(framework_ext.ImagePath()),
965 FdOf(mainline_ext.ImagePath()),
966 "-1"))),
967 Contains(ListFlag("-Xbootclasspathvdexfds:",
968 ElementsAre(FdOf(primary.VdexPath()),
969 FdOf(framework_ext.VdexPath()),
970 FdOf(mainline_ext.VdexPath()),
971 "-1"))),
972 Contains(ListFlag("-Xbootclasspathoatfds:",
973 ElementsAre(FdOf(primary.OatPath()),
974 FdOf(framework_ext.OatPath()),
975 FdOf(mainline_ext.OatPath()),
976 "-1"))))))
977 .Times(odrefresh_->AllSystemServerJars().size())
978 .WillRepeatedly(Return(0));
979 } else {
980 EXPECT_CALL(*mock_exec_utils_,
981 DoExecAndReturnCode(AllOf(
982 Contains(ListFlag("--boot-image=",
983 ElementsAre(GetPrebuiltPrimaryBootImageDir() + "/boot.art",
984 framework_dir_ + "/boot-framework.art",
985 framework_dir_ + "/boot-conscrypt.art"))),
986 Contains(ListFlag("-Xbootclasspathimagefds:",
987 ElementsAre(FdOf(primary.ImagePath()),
988 FdOf(framework_ext.ImagePath()),
989 FdOf(mainline_ext.ImagePath()),
990 "-1"))),
991 Contains(ListFlag("-Xbootclasspathvdexfds:",
992 ElementsAre(FdOf(primary.VdexPath()),
993 FdOf(framework_ext.VdexPath()),
994 FdOf(mainline_ext.VdexPath()),
995 "-1"))),
996 Contains(ListFlag("-Xbootclasspathoatfds:",
997 ElementsAre(FdOf(primary.OatPath()),
998 FdOf(framework_ext.OatPath()),
999 FdOf(mainline_ext.OatPath()),
1000 "-1"))))))
1001 .Times(odrefresh_->AllSystemServerJars().size())
1002 .WillRepeatedly(Return(0));
1003 }
1004
1005 EXPECT_EQ(
1006 odrefresh_->Compile(*metrics_,
1007 CompilationOptions{
1008 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
1009 }),
1010 ExitCode::kCompilationSuccess);
1011 }
1012
TEST_F(OdRefreshTest,OnlyBootImages)1013 TEST_F(OdRefreshTest, OnlyBootImages) {
1014 config_.SetOnlyBootImages(true);
1015
1016 // Primary.
1017 EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(Contains(Flag("--dex-file=", core_oj_jar_))))
1018 .Times(2)
1019 .WillRepeatedly(Return(0));
1020
1021 // Mainline extension.
1022 EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(Contains(Flag("--dex-file=", conscrypt_jar_))))
1023 .Times(2)
1024 .WillRepeatedly(Return(0));
1025
1026 EXPECT_EQ(odrefresh_->Compile(*metrics_, CompilationOptions::CompileAll(*odrefresh_)),
1027 ExitCode::kCompilationSuccess);
1028 }
1029
TEST_F(OdRefreshTest,DirtyImageObjects)1030 TEST_F(OdRefreshTest, DirtyImageObjects) {
1031 // Primary.
1032 EXPECT_CALL(*mock_exec_utils_,
1033 DoExecAndReturnCode(AllOf(
1034 Contains(Flag("--dirty-image-objects-fd=", FdOf(dirty_image_objects_file_))),
1035 Contains(Flag("--dex-file=", core_oj_jar_)))))
1036 .WillOnce(Return(0));
1037
1038 // Mainline extension.
1039 EXPECT_CALL(*mock_exec_utils_,
1040 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", conscrypt_jar_)))))
1041 .WillOnce(Return(0));
1042
1043 EXPECT_EQ(odrefresh_->Compile(
1044 *metrics_,
1045 CompilationOptions{
1046 .boot_images_to_generate_for_isas{
1047 {InstructionSet::kX86_64,
1048 {.primary_boot_image = true, .boot_image_mainline_extension = true}}},
1049 }),
1050 ExitCode::kCompilationSuccess);
1051 }
1052
TEST_F(OdRefreshTest,DirtyImageObjectsMultipleFiles)1053 TEST_F(OdRefreshTest, DirtyImageObjectsMultipleFiles) {
1054 std::string art_dirty_image_objects = art_etc_dir_ + "/dirty-image-objects";
1055 auto file = ScopedCreateEmptyFile(art_dirty_image_objects);
1056
1057 // Primary.
1058 EXPECT_CALL(*mock_exec_utils_,
1059 DoExecAndReturnCode(AllOf(
1060 Contains(Flag("--dirty-image-objects-fd=", FdOf(dirty_image_objects_file_))),
1061 Contains(Flag("--dirty-image-objects-fd=", FdOf(art_dirty_image_objects))),
1062 Contains(Flag("--dex-file=", core_oj_jar_)))))
1063 .WillOnce(Return(0));
1064
1065 // Mainline extension.
1066 EXPECT_CALL(*mock_exec_utils_,
1067 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", conscrypt_jar_)))))
1068 .WillOnce(Return(0));
1069
1070 EXPECT_EQ(odrefresh_->Compile(
1071 *metrics_,
1072 CompilationOptions{
1073 .boot_images_to_generate_for_isas{
1074 {InstructionSet::kX86_64,
1075 {.primary_boot_image = true, .boot_image_mainline_extension = true}}},
1076 }),
1077 ExitCode::kCompilationSuccess);
1078 }
1079
1080 } // namespace odrefresh
1081 } // namespace art
1082