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