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