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