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 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 restorecon_ = [](auto, auto) { return 0; };
237 odrefresh_ = std::make_unique<OnDeviceRefresh>(config_,
238 setfilecon_,
239 restorecon_,
240 cache_info_xml_,
241 std::move(mock_exec_utils),
242 check_compilation_space_);
243 }
244
TearDown()245 void TearDown() override {
246 metrics_.reset();
247 temp_dir_.reset();
248 android_root_env_.reset();
249 android_art_root_env_.reset();
250 art_apex_data_env_.reset();
251
252 CommonArtTest::TearDown();
253 }
254
255 std::unique_ptr<ScratchDir> temp_dir_;
256 std::unique_ptr<ScopedUnsetEnvironmentVariable> android_root_env_;
257 std::unique_ptr<ScopedUnsetEnvironmentVariable> android_art_root_env_;
258 std::unique_ptr<ScopedUnsetEnvironmentVariable> art_apex_data_env_;
259 OdrConfig config_;
260 MockExecUtils* mock_exec_utils_;
261 std::unique_ptr<OnDeviceRefresh> odrefresh_;
262 std::unique_ptr<OdrMetrics> metrics_;
263 std::string core_oj_jar_;
264 std::string framework_jar_;
265 std::string conscrypt_jar_;
266 std::string framework_wifi_jar_;
267 std::string location_provider_jar_;
268 std::string services_jar_;
269 std::string services_foo_jar_;
270 std::string services_bar_jar_;
271 std::string dalvik_cache_dir_;
272 std::string art_etc_dir_;
273 std::string framework_dir_;
274 std::string framework_profile_;
275 std::string art_profile_;
276 std::string services_jar_profile_;
277 std::string dirty_image_objects_file_;
278 std::string preloaded_classes_file_;
279 std::string cache_info_xml_;
280 std::function<bool()> check_compilation_space_;
281 std::function<int(const char*, const char*)> setfilecon_;
282 std::function<int(const char*, unsigned int)> restorecon_;
283 };
284
TEST_F(OdRefreshTest,PrimaryBootImage)285 TEST_F(OdRefreshTest, PrimaryBootImage) {
286 EXPECT_CALL(*mock_exec_utils_,
287 DoExecAndReturnCode(AllOf(
288 Contains(Flag("--dex-file=", core_oj_jar_)),
289 Contains(Flag("--dex-file=", framework_jar_)),
290 Not(Contains(Flag("--dex-file=", conscrypt_jar_))),
291 Not(Contains(Flag("--dex-file=", framework_wifi_jar_))),
292 Contains(Flag("--dex-fd=", FdOf(core_oj_jar_))),
293 Contains(Flag("--dex-fd=", FdOf(framework_jar_))),
294 Not(Contains(Flag("--dex-fd=", FdOf(conscrypt_jar_)))),
295 Not(Contains(Flag("--dex-fd=", FdOf(framework_wifi_jar_)))),
296 Contains(ListFlag("-Xbootclasspath:", ElementsAre(core_oj_jar_, framework_jar_))),
297 Contains(ListFlag("-Xbootclasspathfds:",
298 ElementsAre(FdOf(core_oj_jar_), FdOf(framework_jar_)))),
299 Contains(Flag("--oat-location=", dalvik_cache_dir_ + "/x86_64/boot.oat")),
300 Contains(Flag("--base=", _)),
301 Not(Contains(Flag("--boot-image=", _))),
302 Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_))))))
303 .WillOnce(Return(0));
304
305 // Ignore the invocation for the mainline extension.
306 EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(Contains(Flag("--dex-file=", conscrypt_jar_))))
307 .WillOnce(Return(0));
308
309 EXPECT_EQ(odrefresh_->Compile(
310 *metrics_,
311 CompilationOptions{
312 .boot_images_to_generate_for_isas{
313 {InstructionSet::kX86_64,
314 {.primary_boot_image = true, .boot_image_mainline_extension = true}}},
315 }),
316 ExitCode::kCompilationSuccess);
317 }
318
TEST_F(OdRefreshTest,BootImageMainlineExtension)319 TEST_F(OdRefreshTest, BootImageMainlineExtension) {
320 EXPECT_CALL(
321 *mock_exec_utils_,
322 DoExecAndReturnCode(AllOf(
323 Not(Contains(Flag("--dex-file=", core_oj_jar_))),
324 Not(Contains(Flag("--dex-file=", framework_jar_))),
325 Contains(Flag("--dex-file=", conscrypt_jar_)),
326 Contains(Flag("--dex-file=", framework_wifi_jar_)),
327 Not(Contains(Flag("--dex-fd=", FdOf(core_oj_jar_)))),
328 Not(Contains(Flag("--dex-fd=", FdOf(framework_jar_)))),
329 Contains(Flag("--dex-fd=", FdOf(conscrypt_jar_))),
330 Contains(Flag("--dex-fd=", FdOf(framework_wifi_jar_))),
331 Contains(ListFlag(
332 "-Xbootclasspath:",
333 ElementsAre(core_oj_jar_, framework_jar_, conscrypt_jar_, framework_wifi_jar_))),
334 Contains(ListFlag("-Xbootclasspathfds:",
335 ElementsAre(FdOf(core_oj_jar_),
336 FdOf(framework_jar_),
337 FdOf(conscrypt_jar_),
338 FdOf(framework_wifi_jar_)))),
339 Contains(Flag("--oat-location=", dalvik_cache_dir_ + "/x86_64/boot-conscrypt.oat")),
340 Not(Contains(Flag("--base=", _))),
341 Contains(Flag("--boot-image=", _)),
342 Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_))))))
343 .WillOnce(Return(0));
344
345 EXPECT_EQ(odrefresh_->Compile(
346 *metrics_,
347 CompilationOptions{
348 .boot_images_to_generate_for_isas{
349 {InstructionSet::kX86_64, {.boot_image_mainline_extension = true}}},
350 }),
351 ExitCode::kCompilationSuccess);
352 }
353
TEST_F(OdRefreshTest,BootClasspathJarsWithExplicitCompilerFilter)354 TEST_F(OdRefreshTest, BootClasspathJarsWithExplicitCompilerFilter) {
355 config_.SetBootImageCompilerFilter("speed");
356
357 // Profiles should still be passed for primary boot image.
358 EXPECT_CALL(
359 *mock_exec_utils_,
360 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", core_oj_jar_)),
361 Contains(Flag("--profile-file-fd=", FdOf(art_profile_))),
362 Contains(Flag("--profile-file-fd=", FdOf(framework_profile_))),
363 Contains("--compiler-filter=speed"))))
364 .WillOnce(Return(0));
365
366 // "verify" should always be used for boot image mainline extension.
367 EXPECT_CALL(*mock_exec_utils_,
368 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", conscrypt_jar_)),
369 Not(Contains(Flag("--profile-file-fd=", _))),
370 Contains("--compiler-filter=verify"))))
371 .WillOnce(Return(0));
372
373 EXPECT_EQ(odrefresh_->Compile(
374 *metrics_,
375 CompilationOptions{
376 .boot_images_to_generate_for_isas{
377 {InstructionSet::kX86_64,
378 {.primary_boot_image = true, .boot_image_mainline_extension = true}}},
379 }),
380 ExitCode::kCompilationSuccess);
381 }
382
TEST_F(OdRefreshTest,BootClasspathJarsWithDefaultCompilerFilter)383 TEST_F(OdRefreshTest, BootClasspathJarsWithDefaultCompilerFilter) {
384 EXPECT_CALL(
385 *mock_exec_utils_,
386 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", core_oj_jar_)),
387 Contains(Flag("--profile-file-fd=", FdOf(art_profile_))),
388 Contains(Flag("--profile-file-fd=", FdOf(framework_profile_))),
389 Contains("--compiler-filter=speed-profile"))))
390 .WillOnce(Return(0));
391
392 // "verify" should always be used for boot image mainline extension.
393 EXPECT_CALL(*mock_exec_utils_,
394 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", conscrypt_jar_)),
395 Not(Contains(Flag("--profile-file-fd=", _))),
396 Contains("--compiler-filter=verify"))))
397 .WillOnce(Return(0));
398
399 EXPECT_EQ(odrefresh_->Compile(
400 *metrics_,
401 CompilationOptions{
402 .boot_images_to_generate_for_isas{
403 {InstructionSet::kX86_64,
404 {.primary_boot_image = true, .boot_image_mainline_extension = true}}},
405 }),
406 ExitCode::kCompilationSuccess);
407 }
408
TEST_F(OdRefreshTest,BootClasspathJarsFallback)409 TEST_F(OdRefreshTest, BootClasspathJarsFallback) {
410 // Simulate the case where dex2oat fails when generating the full boot image.
411 EXPECT_CALL(*mock_exec_utils_,
412 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", core_oj_jar_)),
413 Contains(Flag("--dex-file=", framework_jar_)))))
414 .Times(2)
415 .WillRepeatedly(Return(1));
416
417 // It should fall back to generating a minimal boot image.
418 EXPECT_CALL(*mock_exec_utils_,
419 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", core_oj_jar_)),
420 Not(Contains(Flag("--dex-file=", framework_jar_))))))
421 .Times(2)
422 .WillOnce(Return(0));
423
424 EXPECT_EQ(odrefresh_->Compile(
425 *metrics_,
426 CompilationOptions{
427 .boot_images_to_generate_for_isas{
428 {InstructionSet::kX86_64,
429 {.primary_boot_image = true, .boot_image_mainline_extension = true}},
430 {InstructionSet::kX86,
431 {.primary_boot_image = true, .boot_image_mainline_extension = true}}},
432 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
433 }),
434 ExitCode::kCompilationFailed);
435 }
436
TEST_F(OdRefreshTest,AllSystemServerJars)437 TEST_F(OdRefreshTest, AllSystemServerJars) {
438 EXPECT_CALL(*mock_exec_utils_,
439 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", location_provider_jar_)),
440 Contains("--class-loader-context=PCL[]"),
441 Not(Contains(Flag("--class-loader-context-fds=", _))),
442 Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_))))))
443 .WillOnce(Return(0));
444 EXPECT_CALL(
445 *mock_exec_utils_,
446 DoExecAndReturnCode(AllOf(
447 Contains(Flag("--dex-file=", services_jar_)),
448 Contains(Flag("--class-loader-context=", ART_FORMAT("PCL[{}]", location_provider_jar_))),
449 Contains(Flag("--class-loader-context-fds=", FdOf(location_provider_jar_))),
450 Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_))))))
451 .WillOnce(Return(0));
452 EXPECT_CALL(
453 *mock_exec_utils_,
454 DoExecAndReturnCode(AllOf(
455 Contains(Flag("--dex-file=", services_foo_jar_)),
456 Contains(Flag("--class-loader-context=",
457 ART_FORMAT("PCL[];PCL[{}:{}]", location_provider_jar_, services_jar_))),
458 Contains(ListFlag("--class-loader-context-fds=",
459 ElementsAre(FdOf(location_provider_jar_), FdOf(services_jar_)))),
460 Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_))))))
461 .WillOnce(Return(0));
462 EXPECT_CALL(
463 *mock_exec_utils_,
464 DoExecAndReturnCode(AllOf(
465 Contains(Flag("--dex-file=", services_bar_jar_)),
466 Contains(Flag("--class-loader-context=",
467 ART_FORMAT("PCL[];PCL[{}:{}]", location_provider_jar_, services_jar_))),
468 Contains(ListFlag("--class-loader-context-fds=",
469 ElementsAre(FdOf(location_provider_jar_), FdOf(services_jar_)))),
470 Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_))))))
471 .WillOnce(Return(0));
472
473 EXPECT_EQ(
474 odrefresh_->Compile(*metrics_,
475 CompilationOptions{
476 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
477 }),
478 ExitCode::kCompilationSuccess);
479 }
480
TEST_F(OdRefreshTest,PartialSystemServerJars)481 TEST_F(OdRefreshTest, PartialSystemServerJars) {
482 EXPECT_CALL(
483 *mock_exec_utils_,
484 DoExecAndReturnCode(AllOf(
485 Contains(Flag("--dex-file=", services_jar_)),
486 Contains(Flag("--class-loader-context=", ART_FORMAT("PCL[{}]", location_provider_jar_))),
487 Contains(Flag("--class-loader-context-fds=", FdOf(location_provider_jar_))))))
488 .WillOnce(Return(0));
489 EXPECT_CALL(
490 *mock_exec_utils_,
491 DoExecAndReturnCode(AllOf(
492 Contains(Flag("--dex-file=", services_bar_jar_)),
493 Contains(Flag("--class-loader-context=",
494 ART_FORMAT("PCL[];PCL[{}:{}]", location_provider_jar_, services_jar_))),
495 Contains(ListFlag("--class-loader-context-fds=",
496 ElementsAre(FdOf(location_provider_jar_), FdOf(services_jar_)))))))
497 .WillOnce(Return(0));
498
499 EXPECT_EQ(
500 odrefresh_->Compile(*metrics_,
501 CompilationOptions{
502 .system_server_jars_to_compile = {services_jar_, services_bar_jar_},
503 }),
504 ExitCode::kCompilationSuccess);
505 }
506
507 // Verifies that odrefresh can run properly when the STANDALONE_SYSTEM_SERVER_JARS variable is
508 // missing, which is expected on Android S.
TEST_F(OdRefreshTest,MissingStandaloneSystemServerJars)509 TEST_F(OdRefreshTest, MissingStandaloneSystemServerJars) {
510 config_.SetStandaloneSystemServerJars("");
511 EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_)).WillRepeatedly(Return(0));
512 EXPECT_EQ(
513 odrefresh_->Compile(*metrics_,
514 CompilationOptions{
515 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
516 }),
517 ExitCode::kCompilationSuccess);
518 }
519
TEST_F(OdRefreshTest,ContinueWhenBcpCompilationFailed)520 TEST_F(OdRefreshTest, ContinueWhenBcpCompilationFailed) {
521 // Simulate that the compilation of BCP for the system server ISA succeeds.
522 EXPECT_CALL(*mock_exec_utils_,
523 DoExecAndReturnCode(AllOf(Contains("--instruction-set=x86_64"),
524 Contains(Flag("--dex-file=", core_oj_jar_)))))
525 .WillOnce(Return(0));
526 EXPECT_CALL(*mock_exec_utils_,
527 DoExecAndReturnCode(AllOf(Contains("--instruction-set=x86_64"),
528 Contains(Flag("--dex-file=", conscrypt_jar_)))))
529 .WillOnce(Return(0));
530
531 // Simulate that the compilation of BCP for the other ISA fails.
532 EXPECT_CALL(*mock_exec_utils_,
533 DoExecAndReturnCode(AllOf(Contains("--instruction-set=x86"),
534 Contains(Flag("--dex-file=", core_oj_jar_)))))
535 .Times(2)
536 .WillRepeatedly(Return(1));
537
538 // It should still compile system server.
539 EXPECT_CALL(*mock_exec_utils_,
540 DoExecAndReturnCode(Contains(Flag("--dex-file=", location_provider_jar_))))
541 .WillOnce(Return(0));
542 EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(Contains(Flag("--dex-file=", services_jar_))))
543 .WillOnce(Return(0));
544 EXPECT_CALL(*mock_exec_utils_,
545 DoExecAndReturnCode(Contains(Flag("--dex-file=", services_foo_jar_))))
546 .WillOnce(Return(0));
547 EXPECT_CALL(*mock_exec_utils_,
548 DoExecAndReturnCode(Contains(Flag("--dex-file=", services_bar_jar_))))
549 .WillOnce(Return(0));
550
551 EXPECT_EQ(odrefresh_->Compile(
552 *metrics_,
553 CompilationOptions{
554 .boot_images_to_generate_for_isas{
555 {InstructionSet::kX86_64,
556 {.primary_boot_image = true, .boot_image_mainline_extension = true}},
557 {InstructionSet::kX86,
558 {.primary_boot_image = true, .boot_image_mainline_extension = true}}},
559 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
560 }),
561 ExitCode::kCompilationFailed);
562 }
563
TEST_F(OdRefreshTest,ContinueWhenSystemServerCompilationFailed)564 TEST_F(OdRefreshTest, ContinueWhenSystemServerCompilationFailed) {
565 // Simulate that the compilation of "services.jar" fails, while others still succeed.
566 EXPECT_CALL(*mock_exec_utils_,
567 DoExecAndReturnCode(Contains(Flag("--dex-file=", location_provider_jar_))))
568 .WillOnce(Return(0));
569 EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(Contains(Flag("--dex-file=", services_jar_))))
570 .WillOnce(Return(1));
571 EXPECT_CALL(*mock_exec_utils_,
572 DoExecAndReturnCode(Contains(Flag("--dex-file=", services_foo_jar_))))
573 .WillOnce(Return(0));
574 EXPECT_CALL(*mock_exec_utils_,
575 DoExecAndReturnCode(Contains(Flag("--dex-file=", services_bar_jar_))))
576 .WillOnce(Return(0));
577
578 EXPECT_EQ(
579 odrefresh_->Compile(*metrics_,
580 CompilationOptions{
581 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
582 }),
583 ExitCode::kCompilationFailed);
584 }
585
586 // Test setup: The compiler filter is explicitly set to "speed-profile". Use it regardless of
587 // whether the profile exists or not. Dex2oat will fall back to "verify" if the profile doesn't
588 // exist.
TEST_F(OdRefreshTest,CompileSetsCompilerFilterWithExplicitValue)589 TEST_F(OdRefreshTest, CompileSetsCompilerFilterWithExplicitValue) {
590 config_.SetSystemServerCompilerFilter("speed-profile");
591
592 // Uninteresting calls.
593 EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_))
594 .Times(odrefresh_->AllSystemServerJars().size() - 2)
595 .WillRepeatedly(Return(0));
596
597 EXPECT_CALL(*mock_exec_utils_,
598 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", location_provider_jar_)),
599 Not(Contains(Flag("--profile-file-fd=", _))),
600 Contains("--compiler-filter=speed-profile"))))
601 .WillOnce(Return(0));
602 EXPECT_CALL(
603 *mock_exec_utils_,
604 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", services_jar_)),
605 Contains(Flag("--profile-file-fd=", FdOf(services_jar_profile_))),
606 Contains("--compiler-filter=speed-profile"))))
607 .WillOnce(Return(0));
608 EXPECT_EQ(
609 odrefresh_->Compile(*metrics_,
610 CompilationOptions{
611 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
612 }),
613 ExitCode::kCompilationSuccess);
614 }
615
616 // Test setup: The compiler filter is not explicitly set. Use "speed-profile" if there is a vetted
617 // profile (on U+), otherwise fall back to "speed".
TEST_F(OdRefreshTest,CompileSetsCompilerFilterWithDefaultValue)618 TEST_F(OdRefreshTest, CompileSetsCompilerFilterWithDefaultValue) {
619 // Uninteresting calls.
620 EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_))
621 .Times(odrefresh_->AllSystemServerJars().size() - 2)
622 .WillRepeatedly(Return(0));
623
624 // services.jar has a profile, while location.provider.jar does not.
625 EXPECT_CALL(*mock_exec_utils_,
626 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", location_provider_jar_)),
627 Not(Contains(Flag("--profile-file-fd=", _))),
628 Contains("--compiler-filter=speed"))))
629 .WillOnce(Return(0));
630 // Only on U+ should we use the profile by default if available.
631 if (IsAtLeastU()) {
632 EXPECT_CALL(
633 *mock_exec_utils_,
634 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", services_jar_)),
635 Contains(Flag("--profile-file-fd=", FdOf(services_jar_profile_))),
636 Contains("--compiler-filter=speed-profile"))))
637 .WillOnce(Return(0));
638 } else {
639 EXPECT_CALL(*mock_exec_utils_,
640 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", services_jar_)),
641 Not(Contains(Flag("--profile-file-fd=", _))),
642 Contains("--compiler-filter=speed"))))
643 .WillOnce(Return(0));
644 }
645 EXPECT_EQ(
646 odrefresh_->Compile(*metrics_,
647 CompilationOptions{
648 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
649 }),
650 ExitCode::kCompilationSuccess);
651 }
652
TEST_F(OdRefreshTest,OutputFilesAndIsa)653 TEST_F(OdRefreshTest, OutputFilesAndIsa) {
654 config_.MutableSystemProperties()->emplace("dalvik.vm.isa.x86_64.features", "foo");
655 config_.MutableSystemProperties()->emplace("dalvik.vm.isa.x86_64.variant", "bar");
656
657 EXPECT_CALL(*mock_exec_utils_,
658 DoExecAndReturnCode(AllOf(Contains("--instruction-set=x86_64"),
659 Contains(Flag("--instruction-set-features=", "foo")),
660 Contains(Flag("--instruction-set-variant=", "bar")),
661 Contains(Flag("--image-fd=", FdOf(_))),
662 Contains(Flag("--output-vdex-fd=", FdOf(_))),
663 Contains(Flag("--oat-fd=", FdOf(_))))))
664 .Times(2)
665 .WillRepeatedly(Return(0));
666
667 EXPECT_CALL(*mock_exec_utils_,
668 DoExecAndReturnCode(AllOf(Contains("--instruction-set=x86_64"),
669 Contains(Flag("--instruction-set-features=", "foo")),
670 Contains(Flag("--instruction-set-variant=", "bar")),
671 Contains(Flag("--app-image-fd=", FdOf(_))),
672 Contains(Flag("--output-vdex-fd=", FdOf(_))),
673 Contains(Flag("--oat-fd=", FdOf(_))))))
674 .Times(odrefresh_->AllSystemServerJars().size())
675 .WillRepeatedly(Return(0));
676
677 // No instruction set features or variant set for x86.
678 EXPECT_CALL(*mock_exec_utils_,
679 DoExecAndReturnCode(AllOf(Contains("--instruction-set=x86"),
680 Not(Contains(Flag("--instruction-set-features=", _))),
681 Not(Contains(Flag("--instruction-set-variant=", _))))))
682 .Times(2)
683 .WillRepeatedly(Return(0));
684
685 EXPECT_EQ(odrefresh_->Compile(
686 *metrics_,
687 CompilationOptions{
688 .boot_images_to_generate_for_isas{
689 {InstructionSet::kX86_64,
690 {.primary_boot_image = true, .boot_image_mainline_extension = true}},
691 {InstructionSet::kX86,
692 {.primary_boot_image = true, .boot_image_mainline_extension = true}}},
693 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
694 }),
695 ExitCode::kCompilationSuccess);
696 }
697
TEST_F(OdRefreshTest,RuntimeOptions)698 TEST_F(OdRefreshTest, RuntimeOptions) {
699 config_.MutableSystemProperties()->emplace("dalvik.vm.image-dex2oat-Xms", "10");
700 config_.MutableSystemProperties()->emplace("dalvik.vm.image-dex2oat-Xmx", "20");
701 config_.MutableSystemProperties()->emplace("dalvik.vm.dex2oat-Xms", "30");
702 config_.MutableSystemProperties()->emplace("dalvik.vm.dex2oat-Xmx", "40");
703
704 EXPECT_CALL(*mock_exec_utils_,
705 DoExecAndReturnCode(AllOf(Contains(Flag("--image-fd=", FdOf(_))),
706 Contains(Flag("-Xms", "10")),
707 Contains(Flag("-Xmx", "20")))))
708 .Times(2)
709 .WillRepeatedly(Return(0));
710
711 EXPECT_CALL(*mock_exec_utils_,
712 DoExecAndReturnCode(AllOf(Contains(Flag("--app-image-fd=", FdOf(_))),
713 Contains(Flag("-Xms", "30")),
714 Contains(Flag("-Xmx", "40")))))
715 .Times(odrefresh_->AllSystemServerJars().size())
716 .WillRepeatedly(Return(0));
717
718 EXPECT_EQ(odrefresh_->Compile(
719 *metrics_,
720 CompilationOptions{
721 .boot_images_to_generate_for_isas{
722 {InstructionSet::kX86_64,
723 {.primary_boot_image = true, .boot_image_mainline_extension = true}}},
724 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
725 }),
726 ExitCode::kCompilationSuccess);
727 }
728
TEST_F(OdRefreshTest,GenerateBootImageMainlineExtensionChoosesBootImage_OnData)729 TEST_F(OdRefreshTest, GenerateBootImageMainlineExtensionChoosesBootImage_OnData) {
730 // Primary boot image is on /data.
731 OdrArtifacts primary = OdrArtifacts::ForBootImage(dalvik_cache_dir_ + "/x86_64/boot.art");
732 auto file1 = ScopedCreateEmptyFile(primary.ImagePath());
733 auto file2 = ScopedCreateEmptyFile(primary.VdexPath());
734 auto file3 = ScopedCreateEmptyFile(primary.OatPath());
735
736 EXPECT_CALL(*mock_exec_utils_,
737 DoExecAndReturnCode(AllOf(
738 Contains(Flag("--dex-file=", conscrypt_jar_)),
739 Contains(Flag("--boot-image=", dalvik_cache_dir_ + "/boot.art")),
740 Contains(ListFlag("-Xbootclasspathimagefds:",
741 ElementsAre(FdOf(primary.ImagePath()), "-1", "-1", "-1"))),
742 Contains(ListFlag("-Xbootclasspathvdexfds:",
743 ElementsAre(FdOf(primary.VdexPath()), "-1", "-1", "-1"))),
744 Contains(ListFlag("-Xbootclasspathoatfds:",
745 ElementsAre(FdOf(primary.OatPath()), "-1", "-1", "-1"))))))
746 .WillOnce(Return(0));
747
748 EXPECT_EQ(odrefresh_->Compile(
749 *metrics_,
750 CompilationOptions{
751 .boot_images_to_generate_for_isas{
752 {InstructionSet::kX86_64, {.boot_image_mainline_extension = true}}},
753 }),
754 ExitCode::kCompilationSuccess);
755 }
756
TEST_F(OdRefreshTest,GenerateBootImageMainlineExtensionChoosesBootImage_OnSystem)757 TEST_F(OdRefreshTest, GenerateBootImageMainlineExtensionChoosesBootImage_OnSystem) {
758 // Primary boot image and framework extension are on /system.
759 OdrArtifacts primary = OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot.art");
760 auto file1 = ScopedCreateEmptyFile(primary.ImagePath());
761 auto file2 = ScopedCreateEmptyFile(primary.VdexPath());
762 auto file3 = ScopedCreateEmptyFile(primary.OatPath());
763 OdrArtifacts framework_ext =
764 OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot-framework.art");
765 auto file4 = ScopedCreateEmptyFile(framework_ext.ImagePath());
766 auto file5 = ScopedCreateEmptyFile(framework_ext.VdexPath());
767 auto file6 = ScopedCreateEmptyFile(framework_ext.OatPath());
768
769 if (IsAtLeastU()) {
770 EXPECT_CALL(
771 *mock_exec_utils_,
772 DoExecAndReturnCode(AllOf(
773 Contains(Flag("--dex-file=", conscrypt_jar_)),
774 Contains(ListFlag("--boot-image=", ElementsAre(framework_dir_ + "/boot.art"))),
775 Contains(ListFlag(
776 "-Xbootclasspathimagefds:",
777 ElementsAre(
778 FdOf(primary.ImagePath()), FdOf(framework_ext.ImagePath()), "-1", "-1"))),
779 Contains(ListFlag(
780 "-Xbootclasspathvdexfds:",
781 ElementsAre(FdOf(primary.VdexPath()), FdOf(framework_ext.VdexPath()), "-1", "-1"))),
782 Contains(ListFlag(
783 "-Xbootclasspathoatfds:",
784 ElementsAre(FdOf(primary.OatPath()), FdOf(framework_ext.OatPath()), "-1", "-1"))))))
785 .WillOnce(Return(0));
786 } else {
787 EXPECT_CALL(
788 *mock_exec_utils_,
789 DoExecAndReturnCode(AllOf(
790 Contains(Flag("--dex-file=", conscrypt_jar_)),
791 Contains(ListFlag(
792 "--boot-image=",
793 ElementsAre(framework_dir_ + "/boot.art", framework_dir_ + "/boot-framework.art"))),
794 Contains(ListFlag(
795 "-Xbootclasspathimagefds:",
796 ElementsAre(
797 FdOf(primary.ImagePath()), FdOf(framework_ext.ImagePath()), "-1", "-1"))),
798 Contains(ListFlag(
799 "-Xbootclasspathvdexfds:",
800 ElementsAre(FdOf(primary.VdexPath()), FdOf(framework_ext.VdexPath()), "-1", "-1"))),
801 Contains(ListFlag(
802 "-Xbootclasspathoatfds:",
803 ElementsAre(FdOf(primary.OatPath()), FdOf(framework_ext.OatPath()), "-1", "-1"))))))
804 .WillOnce(Return(0));
805 }
806
807 EXPECT_EQ(odrefresh_->Compile(
808 *metrics_,
809 CompilationOptions{
810 .boot_images_to_generate_for_isas{
811 {InstructionSet::kX86_64, {.boot_image_mainline_extension = true}}},
812 }),
813 ExitCode::kCompilationSuccess);
814 }
815
TEST_F(OdRefreshTest,CompileSystemServerChoosesBootImage_OnData)816 TEST_F(OdRefreshTest, CompileSystemServerChoosesBootImage_OnData) {
817 // Boot images are on /data.
818 OdrArtifacts primary = OdrArtifacts::ForBootImage(dalvik_cache_dir_ + "/x86_64/boot.art");
819 auto file1 = ScopedCreateEmptyFile(primary.ImagePath());
820 auto file2 = ScopedCreateEmptyFile(primary.VdexPath());
821 auto file3 = ScopedCreateEmptyFile(primary.OatPath());
822 OdrArtifacts mainline_ext =
823 OdrArtifacts::ForBootImage(dalvik_cache_dir_ + "/x86_64/boot-conscrypt.art");
824 auto file4 = ScopedCreateEmptyFile(mainline_ext.ImagePath());
825 auto file5 = ScopedCreateEmptyFile(mainline_ext.VdexPath());
826 auto file6 = ScopedCreateEmptyFile(mainline_ext.OatPath());
827
828 EXPECT_CALL(
829 *mock_exec_utils_,
830 DoExecAndReturnCode(AllOf(
831 Contains(ListFlag("--boot-image=",
832 ElementsAre(dalvik_cache_dir_ + "/boot.art",
833 dalvik_cache_dir_ + "/boot-conscrypt.art"))),
834 Contains(ListFlag(
835 "-Xbootclasspathimagefds:",
836 ElementsAre(FdOf(primary.ImagePath()), "-1", FdOf(mainline_ext.ImagePath()), "-1"))),
837 Contains(ListFlag(
838 "-Xbootclasspathvdexfds:",
839 ElementsAre(FdOf(primary.VdexPath()), "-1", FdOf(mainline_ext.VdexPath()), "-1"))),
840 Contains(ListFlag(
841 "-Xbootclasspathoatfds:",
842 ElementsAre(FdOf(primary.OatPath()), "-1", FdOf(mainline_ext.OatPath()), "-1"))))))
843 .Times(odrefresh_->AllSystemServerJars().size())
844 .WillRepeatedly(Return(0));
845 EXPECT_EQ(
846 odrefresh_->Compile(*metrics_,
847 CompilationOptions{
848 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
849 }),
850 ExitCode::kCompilationSuccess);
851 }
852
TEST_F(OdRefreshTest,CompileSystemServerChoosesBootImage_OnSystemAndData)853 TEST_F(OdRefreshTest, CompileSystemServerChoosesBootImage_OnSystemAndData) {
854 // The mainline extension is on /data, while others are on /system.
855 OdrArtifacts primary = OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot.art");
856 auto file1 = ScopedCreateEmptyFile(primary.ImagePath());
857 auto file2 = ScopedCreateEmptyFile(primary.VdexPath());
858 auto file3 = ScopedCreateEmptyFile(primary.OatPath());
859 OdrArtifacts framework_ext =
860 OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot-framework.art");
861 auto file4 = ScopedCreateEmptyFile(framework_ext.ImagePath());
862 auto file5 = ScopedCreateEmptyFile(framework_ext.VdexPath());
863 auto file6 = ScopedCreateEmptyFile(framework_ext.OatPath());
864 OdrArtifacts mainline_ext =
865 OdrArtifacts::ForBootImage(dalvik_cache_dir_ + "/x86_64/boot-conscrypt.art");
866 auto file7 = ScopedCreateEmptyFile(mainline_ext.ImagePath());
867 auto file8 = ScopedCreateEmptyFile(mainline_ext.VdexPath());
868 auto file9 = ScopedCreateEmptyFile(mainline_ext.OatPath());
869
870 if (IsAtLeastU()) {
871 EXPECT_CALL(*mock_exec_utils_,
872 DoExecAndReturnCode(AllOf(
873 Contains(ListFlag("--boot-image=",
874 ElementsAre(GetPrebuiltPrimaryBootImageDir() + "/boot.art",
875 dalvik_cache_dir_ + "/boot-conscrypt.art"))),
876 Contains(ListFlag("-Xbootclasspathimagefds:",
877 ElementsAre(FdOf(primary.ImagePath()),
878 FdOf(framework_ext.ImagePath()),
879 FdOf(mainline_ext.ImagePath()),
880 "-1"))),
881 Contains(ListFlag("-Xbootclasspathvdexfds:",
882 ElementsAre(FdOf(primary.VdexPath()),
883 FdOf(framework_ext.VdexPath()),
884 FdOf(mainline_ext.VdexPath()),
885 "-1"))),
886 Contains(ListFlag("-Xbootclasspathoatfds:",
887 ElementsAre(FdOf(primary.OatPath()),
888 FdOf(framework_ext.OatPath()),
889 FdOf(mainline_ext.OatPath()),
890 "-1"))))))
891 .Times(odrefresh_->AllSystemServerJars().size())
892 .WillRepeatedly(Return(0));
893 } else {
894 EXPECT_CALL(*mock_exec_utils_,
895 DoExecAndReturnCode(AllOf(
896 Contains(ListFlag("--boot-image=",
897 ElementsAre(GetPrebuiltPrimaryBootImageDir() + "/boot.art",
898 framework_dir_ + "/boot-framework.art",
899 dalvik_cache_dir_ + "/boot-conscrypt.art"))),
900 Contains(ListFlag("-Xbootclasspathimagefds:",
901 ElementsAre(FdOf(primary.ImagePath()),
902 FdOf(framework_ext.ImagePath()),
903 FdOf(mainline_ext.ImagePath()),
904 "-1"))),
905 Contains(ListFlag("-Xbootclasspathvdexfds:",
906 ElementsAre(FdOf(primary.VdexPath()),
907 FdOf(framework_ext.VdexPath()),
908 FdOf(mainline_ext.VdexPath()),
909 "-1"))),
910 Contains(ListFlag("-Xbootclasspathoatfds:",
911 ElementsAre(FdOf(primary.OatPath()),
912 FdOf(framework_ext.OatPath()),
913 FdOf(mainline_ext.OatPath()),
914 "-1"))))))
915 .Times(odrefresh_->AllSystemServerJars().size())
916 .WillRepeatedly(Return(0));
917 }
918
919 EXPECT_EQ(
920 odrefresh_->Compile(*metrics_,
921 CompilationOptions{
922 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
923 }),
924 ExitCode::kCompilationSuccess);
925 }
926
TEST_F(OdRefreshTest,CompileSystemServerChoosesBootImage_OnSystem)927 TEST_F(OdRefreshTest, CompileSystemServerChoosesBootImage_OnSystem) {
928 // Boot images are on /system.
929 OdrArtifacts primary = OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot.art");
930 auto file1 = ScopedCreateEmptyFile(primary.ImagePath());
931 auto file2 = ScopedCreateEmptyFile(primary.VdexPath());
932 auto file3 = ScopedCreateEmptyFile(primary.OatPath());
933 OdrArtifacts framework_ext =
934 OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot-framework.art");
935 auto file4 = ScopedCreateEmptyFile(framework_ext.ImagePath());
936 auto file5 = ScopedCreateEmptyFile(framework_ext.VdexPath());
937 auto file6 = ScopedCreateEmptyFile(framework_ext.OatPath());
938 OdrArtifacts mainline_ext =
939 OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot-conscrypt.art");
940 auto file7 = ScopedCreateEmptyFile(mainline_ext.ImagePath());
941 auto file8 = ScopedCreateEmptyFile(mainline_ext.VdexPath());
942 auto file9 = ScopedCreateEmptyFile(mainline_ext.OatPath());
943
944 if (IsAtLeastU()) {
945 EXPECT_CALL(*mock_exec_utils_,
946 DoExecAndReturnCode(AllOf(
947 Contains(ListFlag("--boot-image=",
948 ElementsAre(GetPrebuiltPrimaryBootImageDir() + "/boot.art",
949 framework_dir_ + "/boot-conscrypt.art"))),
950 Contains(ListFlag("-Xbootclasspathimagefds:",
951 ElementsAre(FdOf(primary.ImagePath()),
952 FdOf(framework_ext.ImagePath()),
953 FdOf(mainline_ext.ImagePath()),
954 "-1"))),
955 Contains(ListFlag("-Xbootclasspathvdexfds:",
956 ElementsAre(FdOf(primary.VdexPath()),
957 FdOf(framework_ext.VdexPath()),
958 FdOf(mainline_ext.VdexPath()),
959 "-1"))),
960 Contains(ListFlag("-Xbootclasspathoatfds:",
961 ElementsAre(FdOf(primary.OatPath()),
962 FdOf(framework_ext.OatPath()),
963 FdOf(mainline_ext.OatPath()),
964 "-1"))))))
965 .Times(odrefresh_->AllSystemServerJars().size())
966 .WillRepeatedly(Return(0));
967 } else {
968 EXPECT_CALL(*mock_exec_utils_,
969 DoExecAndReturnCode(AllOf(
970 Contains(ListFlag("--boot-image=",
971 ElementsAre(GetPrebuiltPrimaryBootImageDir() + "/boot.art",
972 framework_dir_ + "/boot-framework.art",
973 framework_dir_ + "/boot-conscrypt.art"))),
974 Contains(ListFlag("-Xbootclasspathimagefds:",
975 ElementsAre(FdOf(primary.ImagePath()),
976 FdOf(framework_ext.ImagePath()),
977 FdOf(mainline_ext.ImagePath()),
978 "-1"))),
979 Contains(ListFlag("-Xbootclasspathvdexfds:",
980 ElementsAre(FdOf(primary.VdexPath()),
981 FdOf(framework_ext.VdexPath()),
982 FdOf(mainline_ext.VdexPath()),
983 "-1"))),
984 Contains(ListFlag("-Xbootclasspathoatfds:",
985 ElementsAre(FdOf(primary.OatPath()),
986 FdOf(framework_ext.OatPath()),
987 FdOf(mainline_ext.OatPath()),
988 "-1"))))))
989 .Times(odrefresh_->AllSystemServerJars().size())
990 .WillRepeatedly(Return(0));
991 }
992
993 EXPECT_EQ(
994 odrefresh_->Compile(*metrics_,
995 CompilationOptions{
996 .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(),
997 }),
998 ExitCode::kCompilationSuccess);
999 }
1000
TEST_F(OdRefreshTest,OnlyBootImages)1001 TEST_F(OdRefreshTest, OnlyBootImages) {
1002 config_.SetOnlyBootImages(true);
1003
1004 // Primary.
1005 EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(Contains(Flag("--dex-file=", core_oj_jar_))))
1006 .Times(2)
1007 .WillRepeatedly(Return(0));
1008
1009 // Mainline extension.
1010 EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(Contains(Flag("--dex-file=", conscrypt_jar_))))
1011 .Times(2)
1012 .WillRepeatedly(Return(0));
1013
1014 EXPECT_EQ(odrefresh_->Compile(*metrics_, CompilationOptions::CompileAll(*odrefresh_)),
1015 ExitCode::kCompilationSuccess);
1016 }
1017
TEST_F(OdRefreshTest,DirtyImageObjects)1018 TEST_F(OdRefreshTest, DirtyImageObjects) {
1019 // Primary.
1020 EXPECT_CALL(*mock_exec_utils_,
1021 DoExecAndReturnCode(AllOf(
1022 Contains(Flag("--dirty-image-objects-fd=", FdOf(dirty_image_objects_file_))),
1023 Contains(Flag("--dex-file=", core_oj_jar_)))))
1024 .WillOnce(Return(0));
1025
1026 // Mainline extension.
1027 EXPECT_CALL(*mock_exec_utils_,
1028 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", conscrypt_jar_)))))
1029 .WillOnce(Return(0));
1030
1031 EXPECT_EQ(odrefresh_->Compile(
1032 *metrics_,
1033 CompilationOptions{
1034 .boot_images_to_generate_for_isas{
1035 {InstructionSet::kX86_64,
1036 {.primary_boot_image = true, .boot_image_mainline_extension = true}}},
1037 }),
1038 ExitCode::kCompilationSuccess);
1039 }
1040
TEST_F(OdRefreshTest,DirtyImageObjectsMultipleFiles)1041 TEST_F(OdRefreshTest, DirtyImageObjectsMultipleFiles) {
1042 std::string art_dirty_image_objects = art_etc_dir_ + "/dirty-image-objects";
1043 auto file = ScopedCreateEmptyFile(art_dirty_image_objects);
1044
1045 // Primary.
1046 EXPECT_CALL(*mock_exec_utils_,
1047 DoExecAndReturnCode(AllOf(
1048 Contains(Flag("--dirty-image-objects-fd=", FdOf(dirty_image_objects_file_))),
1049 Contains(Flag("--dirty-image-objects-fd=", FdOf(art_dirty_image_objects))),
1050 Contains(Flag("--dex-file=", core_oj_jar_)))))
1051 .WillOnce(Return(0));
1052
1053 // Mainline extension.
1054 EXPECT_CALL(*mock_exec_utils_,
1055 DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", conscrypt_jar_)))))
1056 .WillOnce(Return(0));
1057
1058 EXPECT_EQ(odrefresh_->Compile(
1059 *metrics_,
1060 CompilationOptions{
1061 .boot_images_to_generate_for_isas{
1062 {InstructionSet::kX86_64,
1063 {.primary_boot_image = true, .boot_image_mainline_extension = true}}},
1064 }),
1065 ExitCode::kCompilationSuccess);
1066 }
1067
1068 } // namespace odrefresh
1069 } // namespace art
1070