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