diff options
Diffstat (limited to 'odrefresh/odrefresh_test.cc')
| -rw-r--r-- | odrefresh/odrefresh_test.cc | 799 |
1 files changed, 604 insertions, 195 deletions
diff --git a/odrefresh/odrefresh_test.cc b/odrefresh/odrefresh_test.cc index ae7cc78594..8ebeeab6bb 100644 --- a/odrefresh/odrefresh_test.cc +++ b/odrefresh/odrefresh_test.cc @@ -29,11 +29,13 @@ #include "android-base/scopeguard.h" #include "android-base/stringprintf.h" #include "android-base/strings.h" +#include "android-modules-utils/sdk_level.h" #include "arch/instruction_set.h" #include "base/common_art_test.h" #include "base/file_utils.h" #include "base/stl_util.h" #include "exec_utils.h" +#include "fmt/format.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "odr_artifacts.h" @@ -46,13 +48,18 @@ namespace art { namespace odrefresh { +using ::android::base::Split; +using ::android::modules::sdklevel::IsAtLeastU; using ::testing::_; using ::testing::AllOf; using ::testing::Contains; -using ::testing::HasSubstr; +using ::testing::ElementsAre; using ::testing::Not; +using ::testing::ResultOf; using ::testing::Return; +using ::fmt::literals::operator""_format; // NOLINT + constexpr int kReplace = 1; void CreateEmptyFile(const std::string& name) { @@ -71,29 +78,31 @@ class MockExecUtils : public ExecUtils { public: // A workaround to avoid MOCK_METHOD on a method with an `std::string*` parameter, which will lead // to a conflict between gmock and android-base/logging.h (b/132668253). - int ExecAndReturnCode(std::vector<std::string>& arg_vector, - time_t, - bool*, - std::string*) const override { - return DoExecAndReturnCode(arg_vector); + ExecResult ExecAndReturnResult(const std::vector<std::string>& arg_vector, + int, + std::string*) const override { + return {.status = ExecResult::kExited, .exit_code = DoExecAndReturnCode(arg_vector)}; } - MOCK_METHOD(int, DoExecAndReturnCode, (std::vector<std::string> & arg_vector), (const)); + MOCK_METHOD(int, DoExecAndReturnCode, (const std::vector<std::string>& arg_vector), (const)); }; -// Matches a flag that starts with `flag` and is a colon-separated list that contains an element -// that matches `matcher`. -MATCHER_P2(FlagContains, flag, matcher, "") { - std::string_view value = arg; +// Matches a flag that starts with `flag` and whose value matches `matcher`. +MATCHER_P2(Flag, flag, matcher, "") { + std::string_view value(arg); if (!android::base::ConsumePrefix(&value, flag)) { return false; } - for (std::string_view s : SplitString(value, ':')) { - if (ExplainMatchResult(matcher, s, result_listener)) { - return true; - } - } - return false; + return ExplainMatchResult(matcher, std::string(value), result_listener); +} + +// Matches a flag that starts with `flag` and whose value is a colon-separated list that matches +// `matcher`. The matcher acts on an `std::vector<std::string>` of the split list argument. +MATCHER_P2(ListFlag, flag, matcher, "") { + return ExplainMatchResult( + Flag(flag, ResultOf(std::bind(Split, std::placeholders::_1, ":"), matcher)), + arg, + result_listener); } // Matches an FD of a file whose path matches `matcher`. @@ -140,20 +149,21 @@ class OdRefreshTest : public CommonArtTest { CommonArtTest::SetUp(); temp_dir_ = std::make_unique<ScratchDir>(); - std::string_view temp_dir_path = temp_dir_->GetPath(); - android::base::ConsumeSuffix(&temp_dir_path, "/"); + std::string temp_dir_path = temp_dir_->GetPath(); + // Remove the trailing '/'; + temp_dir_path.resize(temp_dir_path.length() - 1); - std::string android_root_path = Concatenate({temp_dir_path, "/system"}); + std::string android_root_path = temp_dir_path + "/system"; ASSERT_TRUE(EnsureDirectoryExists(android_root_path)); android_root_env_ = std::make_unique<ScopedUnsetEnvironmentVariable>("ANDROID_ROOT"); setenv("ANDROID_ROOT", android_root_path.c_str(), kReplace); - std::string android_art_root_path = Concatenate({temp_dir_path, "/apex/com.android.art"}); + std::string android_art_root_path = temp_dir_path + "/apex/com.android.art"; ASSERT_TRUE(EnsureDirectoryExists(android_art_root_path)); android_art_root_env_ = std::make_unique<ScopedUnsetEnvironmentVariable>("ANDROID_ART_ROOT"); setenv("ANDROID_ART_ROOT", android_art_root_path.c_str(), kReplace); - std::string art_apex_data_path = Concatenate({temp_dir_path, kArtApexDataDefaultPath}); + std::string art_apex_data_path = temp_dir_path + kArtApexDataDefaultPath; ASSERT_TRUE(EnsureDirectoryExists(art_apex_data_path)); art_apex_data_env_ = std::make_unique<ScopedUnsetEnvironmentVariable>("ART_APEX_DATA"); setenv("ART_APEX_DATA", art_apex_data_path.c_str(), kReplace); @@ -161,11 +171,15 @@ class OdRefreshTest : public CommonArtTest { dalvik_cache_dir_ = art_apex_data_path + "/dalvik-cache"; ASSERT_TRUE(EnsureDirectoryExists(dalvik_cache_dir_ + "/x86_64")); - std::string system_etc_dir = Concatenate({android_root_path, "/etc"}); + std::string system_etc_dir = android_root_path + "/etc"; ASSERT_TRUE(EnsureDirectoryExists(system_etc_dir)); framework_profile_ = system_etc_dir + "/boot-image.prof"; CreateEmptyFile(framework_profile_); - std::string art_etc_dir = Concatenate({android_art_root_path, "/etc"}); + dirty_image_objects_file_ = system_etc_dir + "/dirty-image-objects"; + CreateEmptyFile(dirty_image_objects_file_); + preloaded_classes_file_ = system_etc_dir + "/preloaded-classes"; + CreateEmptyFile(preloaded_classes_file_); + std::string art_etc_dir = android_art_root_path + "/etc"; ASSERT_TRUE(EnsureDirectoryExists(art_etc_dir)); art_profile_ = art_etc_dir + "/boot-image.prof"; CreateEmptyFile(art_profile_); @@ -176,9 +190,13 @@ class OdRefreshTest : public CommonArtTest { services_jar_ = framework_dir_ + "/services.jar"; services_foo_jar_ = framework_dir_ + "/services-foo.jar"; services_bar_jar_ = framework_dir_ + "/services-bar.jar"; - std::string services_jar_prof = framework_dir_ + "/services.jar.prof"; - art_javalib_dir_ = android_art_root_path + "/javalib"; - core_oj_jar_ = art_javalib_dir_ + "/core-oj.jar"; + services_jar_profile_ = framework_dir_ + "/services.jar.prof"; + std::string art_javalib_dir = android_art_root_path + "/javalib"; + core_oj_jar_ = art_javalib_dir + "/core-oj.jar"; + std::string conscrypt_javalib_dir = temp_dir_path + "/apex/com.android.conscrypt/javalib"; + conscrypt_jar_ = conscrypt_javalib_dir + "/conscrypt.jar"; + std::string wifi_javalib_dir = temp_dir_path + "/apex/com.android.wifi/javalib"; + framework_wifi_jar_ = wifi_javalib_dir + "/framework-wifi.jar"; // Create placeholder files. ASSERT_TRUE(EnsureDirectoryExists(framework_dir_ + "/x86_64")); @@ -187,22 +205,27 @@ class OdRefreshTest : public CommonArtTest { CreateEmptyFile(services_jar_); CreateEmptyFile(services_foo_jar_); CreateEmptyFile(services_bar_jar_); - CreateEmptyFile(services_jar_prof); - ASSERT_TRUE(EnsureDirectoryExists(art_javalib_dir_)); + CreateEmptyFile(services_jar_profile_); + ASSERT_TRUE(EnsureDirectoryExists(art_javalib_dir)); CreateEmptyFile(core_oj_jar_); + ASSERT_TRUE(EnsureDirectoryExists(conscrypt_javalib_dir)); + CreateEmptyFile(conscrypt_jar_); + ASSERT_TRUE(EnsureDirectoryExists(wifi_javalib_dir)); + CreateEmptyFile(framework_wifi_jar_); - std::string apex_info_filename = Concatenate({temp_dir_path, "/apex-info-list.xml"}); + std::string apex_info_filename = temp_dir_path + "/apex-info-list.xml"; WriteFakeApexInfoList(apex_info_filename); config_.SetApexInfoListFile(apex_info_filename); - config_.SetArtBinDir(Concatenate({temp_dir_path, "/bin"})); - config_.SetBootClasspath(Concatenate({core_oj_jar_, ":", framework_jar_})); - config_.SetDex2oatBootclasspath(Concatenate({core_oj_jar_, ":", framework_jar_})); - config_.SetSystemServerClasspath(Concatenate({location_provider_jar_, ":", services_jar_})); - config_.SetStandaloneSystemServerJars(Concatenate({services_foo_jar_, ":", services_bar_jar_})); + config_.SetArtBinDir(temp_dir_path + "/bin"); + config_.SetBootClasspath(core_oj_jar_ + ":" + framework_jar_ + ":" + conscrypt_jar_ + ":" + + framework_wifi_jar_); + config_.SetDex2oatBootclasspath(core_oj_jar_ + ":" + framework_jar_); + config_.SetSystemServerClasspath(location_provider_jar_ + ":" + services_jar_); + config_.SetStandaloneSystemServerJars(services_foo_jar_ + ":" + services_bar_jar_); config_.SetIsa(InstructionSet::kX86_64); config_.SetZygoteKind(ZygoteKind::kZygote64_32); - config_.SetSystemServerCompilerFilter("speed"); // specify a default + config_.SetSystemServerCompilerFilter(""); config_.SetArtifactDirectory(dalvik_cache_dir_); std::string staging_dir = dalvik_cache_dir_ + "/staging"; @@ -213,8 +236,9 @@ class OdRefreshTest : public CommonArtTest { mock_exec_utils_ = mock_exec_utils.get(); metrics_ = std::make_unique<OdrMetrics>(dalvik_cache_dir_); + cache_info_xml_ = dalvik_cache_dir_ + "/cache-info.xml"; odrefresh_ = std::make_unique<OnDeviceRefresh>( - config_, dalvik_cache_dir_ + "/cache-info.xml", std::move(mock_exec_utils)); + config_, cache_info_xml_, std::move(mock_exec_utils)); } void TearDown() override { @@ -237,87 +261,208 @@ class OdRefreshTest : public CommonArtTest { std::unique_ptr<OdrMetrics> metrics_; std::string core_oj_jar_; std::string framework_jar_; + std::string conscrypt_jar_; + std::string framework_wifi_jar_; std::string location_provider_jar_; std::string services_jar_; std::string services_foo_jar_; std::string services_bar_jar_; std::string dalvik_cache_dir_; std::string framework_dir_; - std::string art_javalib_dir_; std::string framework_profile_; std::string art_profile_; + std::string services_jar_profile_; + std::string dirty_image_objects_file_; + std::string preloaded_classes_file_; + std::string cache_info_xml_; }; -TEST_F(OdRefreshTest, BootClasspathJars) { +TEST_F(OdRefreshTest, PrimaryBootImage) { EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(AllOf( - Contains(Concatenate({"--dex-file=", core_oj_jar_})), - Contains(Concatenate({"--dex-file=", framework_jar_})), - Contains(FlagContains("--dex-fd=", FdOf(core_oj_jar_))), - Contains(FlagContains("--dex-fd=", FdOf(framework_jar_))), - Contains(FlagContains("--profile-file-fd=", FdOf(art_profile_))), - Contains(FlagContains("--profile-file-fd=", FdOf(framework_profile_))), - Contains(Concatenate({"--oat-location=", dalvik_cache_dir_, "/x86_64/boot.oat"})), - Contains(HasSubstr("--base=")), - Contains("--compiler-filter=speed-profile")))) + Contains(Flag("--dex-file=", core_oj_jar_)), + Contains(Flag("--dex-file=", framework_jar_)), + Not(Contains(Flag("--dex-file=", conscrypt_jar_))), + Not(Contains(Flag("--dex-file=", framework_wifi_jar_))), + Contains(Flag("--dex-fd=", FdOf(core_oj_jar_))), + Contains(Flag("--dex-fd=", FdOf(framework_jar_))), + Not(Contains(Flag("--dex-fd=", FdOf(conscrypt_jar_)))), + Not(Contains(Flag("--dex-fd=", FdOf(framework_wifi_jar_)))), + Contains(ListFlag("-Xbootclasspath:", ElementsAre(core_oj_jar_, framework_jar_))), + Contains(ListFlag("-Xbootclasspathfds:", + ElementsAre(FdOf(core_oj_jar_), FdOf(framework_jar_)))), + Contains(Flag("--oat-location=", dalvik_cache_dir_ + "/x86_64/boot.oat")), + Contains(Flag("--base=", _)), + Not(Contains(Flag("--boot-image=", _))), + Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_)))))) + .WillOnce(Return(0)); + + // Ignore the invocation for the mainline extension. + EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(Contains(Flag("--dex-file=", conscrypt_jar_)))) .WillOnce(Return(0)); - EXPECT_EQ(odrefresh_->Compile(*metrics_, - CompilationOptions{ - .compile_boot_classpath_for_isas = {InstructionSet::kX86_64}, - }), + EXPECT_EQ(odrefresh_->Compile( + *metrics_, + CompilationOptions{ + .boot_images_to_generate_for_isas{ + {InstructionSet::kX86_64, + {.primary_boot_image = true, .boot_image_mainline_extension = true}}}, + }), + ExitCode::kCompilationSuccess); +} + +TEST_F(OdRefreshTest, BootImageMainlineExtension) { + EXPECT_CALL( + *mock_exec_utils_, + DoExecAndReturnCode(AllOf( + Not(Contains(Flag("--dex-file=", core_oj_jar_))), + Not(Contains(Flag("--dex-file=", framework_jar_))), + Contains(Flag("--dex-file=", conscrypt_jar_)), + Contains(Flag("--dex-file=", framework_wifi_jar_)), + Not(Contains(Flag("--dex-fd=", FdOf(core_oj_jar_)))), + Not(Contains(Flag("--dex-fd=", FdOf(framework_jar_)))), + Contains(Flag("--dex-fd=", FdOf(conscrypt_jar_))), + Contains(Flag("--dex-fd=", FdOf(framework_wifi_jar_))), + Contains(ListFlag( + "-Xbootclasspath:", + ElementsAre(core_oj_jar_, framework_jar_, conscrypt_jar_, framework_wifi_jar_))), + Contains(ListFlag("-Xbootclasspathfds:", + ElementsAre(FdOf(core_oj_jar_), + FdOf(framework_jar_), + FdOf(conscrypt_jar_), + FdOf(framework_wifi_jar_)))), + Contains(Flag("--oat-location=", dalvik_cache_dir_ + "/x86_64/boot-conscrypt.oat")), + Not(Contains(Flag("--base=", _))), + Contains(Flag("--boot-image=", _)), + Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_)))))) + .WillOnce(Return(0)); + + EXPECT_EQ(odrefresh_->Compile( + *metrics_, + CompilationOptions{ + .boot_images_to_generate_for_isas{ + {InstructionSet::kX86_64, {.boot_image_mainline_extension = true}}}, + }), + ExitCode::kCompilationSuccess); +} + +TEST_F(OdRefreshTest, BootClasspathJarsWithExplicitCompilerFilter) { + config_.SetBootImageCompilerFilter("speed"); + + // Profiles should still be passed for primary boot image. + EXPECT_CALL( + *mock_exec_utils_, + DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", core_oj_jar_)), + Contains(Flag("--profile-file-fd=", FdOf(art_profile_))), + Contains(Flag("--profile-file-fd=", FdOf(framework_profile_))), + Contains("--compiler-filter=speed")))) + .WillOnce(Return(0)); + + // "verify" should always be used for boot image mainline extension. + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", conscrypt_jar_)), + Not(Contains(Flag("--profile-file-fd=", _))), + Contains("--compiler-filter=verify")))) + .WillOnce(Return(0)); + + EXPECT_EQ(odrefresh_->Compile( + *metrics_, + CompilationOptions{ + .boot_images_to_generate_for_isas{ + {InstructionSet::kX86_64, + {.primary_boot_image = true, .boot_image_mainline_extension = true}}}, + }), + ExitCode::kCompilationSuccess); +} + +TEST_F(OdRefreshTest, BootClasspathJarsWithDefaultCompilerFilter) { + EXPECT_CALL( + *mock_exec_utils_, + DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", core_oj_jar_)), + Contains(Flag("--profile-file-fd=", FdOf(art_profile_))), + Contains(Flag("--profile-file-fd=", FdOf(framework_profile_))), + Contains("--compiler-filter=speed-profile")))) + .WillOnce(Return(0)); + + // "verify" should always be used for boot image mainline extension. + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", conscrypt_jar_)), + Not(Contains(Flag("--profile-file-fd=", _))), + Contains("--compiler-filter=verify")))) + .WillOnce(Return(0)); + + EXPECT_EQ(odrefresh_->Compile( + *metrics_, + CompilationOptions{ + .boot_images_to_generate_for_isas{ + {InstructionSet::kX86_64, + {.primary_boot_image = true, .boot_image_mainline_extension = true}}}, + }), ExitCode::kCompilationSuccess); } TEST_F(OdRefreshTest, BootClasspathJarsFallback) { // Simulate the case where dex2oat fails when generating the full boot image. EXPECT_CALL(*mock_exec_utils_, - DoExecAndReturnCode(AllOf(Contains(Concatenate({"--dex-file=", core_oj_jar_})), - Contains(Concatenate({"--dex-file=", framework_jar_}))))) + DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", core_oj_jar_)), + Contains(Flag("--dex-file=", framework_jar_))))) .Times(2) .WillRepeatedly(Return(1)); // It should fall back to generating a minimal boot image. - EXPECT_CALL( - *mock_exec_utils_, - DoExecAndReturnCode(AllOf(Contains(Concatenate({"--dex-file=", core_oj_jar_})), - Not(Contains(Concatenate({"--dex-file=", framework_jar_})))))) + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", core_oj_jar_)), + Not(Contains(Flag("--dex-file=", framework_jar_)))))) .Times(2) .WillOnce(Return(0)); - EXPECT_EQ( - odrefresh_->Compile( - *metrics_, - CompilationOptions{ - .compile_boot_classpath_for_isas = {InstructionSet::kX86, InstructionSet::kX86_64}, - .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(), - }), - ExitCode::kCompilationFailed); + EXPECT_EQ(odrefresh_->Compile( + *metrics_, + CompilationOptions{ + .boot_images_to_generate_for_isas{ + {InstructionSet::kX86_64, + {.primary_boot_image = true, .boot_image_mainline_extension = true}}, + {InstructionSet::kX86, + {.primary_boot_image = true, .boot_image_mainline_extension = true}}}, + .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(), + }), + ExitCode::kCompilationFailed); } TEST_F(OdRefreshTest, AllSystemServerJars) { EXPECT_CALL(*mock_exec_utils_, - DoExecAndReturnCode(AllOf( - Contains(Concatenate({"--dex-file=", location_provider_jar_})), - Contains("--class-loader-context=PCL[]")))) + DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", location_provider_jar_)), + Contains("--class-loader-context=PCL[]"), + Not(Contains(Flag("--class-loader-context-fds=", _))), + Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_)))))) .WillOnce(Return(0)); - EXPECT_CALL(*mock_exec_utils_, - DoExecAndReturnCode(AllOf( - Contains(Concatenate({"--dex-file=", services_jar_})), - Contains(Concatenate({"--class-loader-context=PCL[", location_provider_jar_, - "]"}))))) + EXPECT_CALL( + *mock_exec_utils_, + DoExecAndReturnCode( + AllOf(Contains(Flag("--dex-file=", services_jar_)), + Contains(Flag("--class-loader-context=", "PCL[{}]"_format(location_provider_jar_))), + Contains(Flag("--class-loader-context-fds=", FdOf(location_provider_jar_))), + Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_)))))) .WillOnce(Return(0)); - EXPECT_CALL(*mock_exec_utils_, - DoExecAndReturnCode(AllOf( - Contains(Concatenate({"--dex-file=", services_foo_jar_})), - Contains(Concatenate({"--class-loader-context=PCL[];PCL[", location_provider_jar_, - ":", services_jar_, "]"}))))) + EXPECT_CALL( + *mock_exec_utils_, + DoExecAndReturnCode(AllOf( + Contains(Flag("--dex-file=", services_foo_jar_)), + Contains(Flag("--class-loader-context=", + "PCL[];PCL[{}:{}]"_format(location_provider_jar_, services_jar_))), + Contains(ListFlag("--class-loader-context-fds=", + ElementsAre(FdOf(location_provider_jar_), FdOf(services_jar_)))), + Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_)))))) .WillOnce(Return(0)); - EXPECT_CALL(*mock_exec_utils_, - DoExecAndReturnCode(AllOf( - Contains(Concatenate({"--dex-file=", services_bar_jar_})), - Contains(Concatenate({"--class-loader-context=PCL[];PCL[", location_provider_jar_, - ":", services_jar_, "]"}))))) + EXPECT_CALL( + *mock_exec_utils_, + DoExecAndReturnCode(AllOf( + Contains(Flag("--dex-file=", services_bar_jar_)), + Contains(Flag("--class-loader-context=", + "PCL[];PCL[{}:{}]"_format(location_provider_jar_, services_jar_))), + Contains(ListFlag("--class-loader-context-fds=", + ElementsAre(FdOf(location_provider_jar_), FdOf(services_jar_)))), + Contains(Flag("--cache-info-fd=", FdOf(cache_info_xml_)))))) .WillOnce(Return(0)); EXPECT_EQ( @@ -329,16 +474,21 @@ TEST_F(OdRefreshTest, AllSystemServerJars) { } TEST_F(OdRefreshTest, PartialSystemServerJars) { - EXPECT_CALL(*mock_exec_utils_, - DoExecAndReturnCode(AllOf( - Contains(Concatenate({"--dex-file=", services_jar_})), - Contains(Concatenate({"--class-loader-context=PCL[", location_provider_jar_, "]"}))))) + EXPECT_CALL( + *mock_exec_utils_, + DoExecAndReturnCode( + AllOf(Contains(Flag("--dex-file=", services_jar_)), + Contains(Flag("--class-loader-context=", "PCL[{}]"_format(location_provider_jar_))), + Contains(Flag("--class-loader-context-fds=", FdOf(location_provider_jar_)))))) .WillOnce(Return(0)); - EXPECT_CALL(*mock_exec_utils_, - DoExecAndReturnCode(AllOf( - Contains(Concatenate({"--dex-file=", services_bar_jar_})), - Contains(Concatenate({"--class-loader-context=PCL[];PCL[", location_provider_jar_, - ":", services_jar_, "]"}))))) + EXPECT_CALL( + *mock_exec_utils_, + DoExecAndReturnCode(AllOf( + Contains(Flag("--dex-file=", services_bar_jar_)), + Contains(Flag("--class-loader-context=", + "PCL[];PCL[{}:{}]"_format(location_provider_jar_, services_jar_))), + Contains(ListFlag("--class-loader-context-fds=", + ElementsAre(FdOf(location_provider_jar_), FdOf(services_jar_))))))) .WillOnce(Return(0)); EXPECT_EQ( @@ -362,90 +512,131 @@ TEST_F(OdRefreshTest, MissingStandaloneSystemServerJars) { ExitCode::kCompilationSuccess); } -TEST_F(OdRefreshTest, CompileSetsCompilerFilterToSpeed) { - // Test setup: use "speed" compiler filter. - config_.SetSystemServerCompilerFilter("speed"); +TEST_F(OdRefreshTest, ContinueWhenBcpCompilationFailed) { + // Simulate that the compilation of BCP for the system server ISA succeeds. + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(AllOf(Contains("--instruction-set=x86_64"), + Contains(Flag("--dex-file=", core_oj_jar_))))) + .WillOnce(Return(0)); + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(AllOf(Contains("--instruction-set=x86_64"), + Contains(Flag("--dex-file=", conscrypt_jar_))))) + .WillOnce(Return(0)); - // Uninteresting calls. - EXPECT_CALL( - *mock_exec_utils_, DoExecAndReturnCode(_)) - .Times(odrefresh_->AllSystemServerJars().size() - 2) - .WillRepeatedly(Return(0)); + // Simulate that the compilation of BCP for the other ISA fails. + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(AllOf(Contains("--instruction-set=x86"), + Contains(Flag("--dex-file=", core_oj_jar_))))) + .Times(2) + .WillRepeatedly(Return(1)); - EXPECT_CALL( - *mock_exec_utils_, - DoExecAndReturnCode(AllOf(Contains(Concatenate({"--dex-file=", location_provider_jar_})), - Not(Contains(HasSubstr("--profile-file-fd="))), - Contains("--compiler-filter=speed")))) + // It should still compile system server. + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(Contains(Flag("--dex-file=", location_provider_jar_)))) .WillOnce(Return(0)); - EXPECT_CALL( - *mock_exec_utils_, - DoExecAndReturnCode(AllOf(Contains(Concatenate({"--dex-file=", services_jar_})), - Not(Contains(HasSubstr("--profile-file-fd="))), - Contains("--compiler-filter=speed")))) + EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(Contains(Flag("--dex-file=", services_jar_)))) + .WillOnce(Return(0)); + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(Contains(Flag("--dex-file=", services_foo_jar_)))) + .WillOnce(Return(0)); + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(Contains(Flag("--dex-file=", services_bar_jar_)))) + .WillOnce(Return(0)); + + EXPECT_EQ(odrefresh_->Compile( + *metrics_, + CompilationOptions{ + .boot_images_to_generate_for_isas{ + {InstructionSet::kX86_64, + {.primary_boot_image = true, .boot_image_mainline_extension = true}}, + {InstructionSet::kX86, + {.primary_boot_image = true, .boot_image_mainline_extension = true}}}, + .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(), + }), + ExitCode::kCompilationFailed); +} + +TEST_F(OdRefreshTest, ContinueWhenSystemServerCompilationFailed) { + // Simulate that the compilation of "services.jar" fails, while others still succeed. + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(Contains(Flag("--dex-file=", location_provider_jar_)))) .WillOnce(Return(0)); + EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(Contains(Flag("--dex-file=", services_jar_)))) + .WillOnce(Return(1)); + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(Contains(Flag("--dex-file=", services_foo_jar_)))) + .WillOnce(Return(0)); + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(Contains(Flag("--dex-file=", services_bar_jar_)))) + .WillOnce(Return(0)); + EXPECT_EQ( odrefresh_->Compile(*metrics_, CompilationOptions{ - .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(), + .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(), }), - ExitCode::kCompilationSuccess); + ExitCode::kCompilationFailed); } -TEST_F(OdRefreshTest, CompileSetsCompilerFilterToSpeedProfile) { - // Test setup: with "speed-profile" compiler filter in the request, only apply if there is a - // profile, otherwise fallback to speed. +// Test setup: The compiler filter is explicitly set to "speed-profile". Use it regardless of +// whether the profile exists or not. Dex2oat will fall back to "verify" if the profile doesn't +// exist. +TEST_F(OdRefreshTest, CompileSetsCompilerFilterWithExplicitValue) { config_.SetSystemServerCompilerFilter("speed-profile"); // Uninteresting calls. - EXPECT_CALL( - *mock_exec_utils_, DoExecAndReturnCode(_)) + EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_)) .Times(odrefresh_->AllSystemServerJars().size() - 2) .WillRepeatedly(Return(0)); - // services.jar has a profile, while location.provider.jar does not. - EXPECT_CALL( - *mock_exec_utils_, - DoExecAndReturnCode(AllOf(Contains(Concatenate({"--dex-file=", location_provider_jar_})), - Not(Contains(HasSubstr("--profile-file-fd="))), - Contains("--compiler-filter=speed")))) + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", location_provider_jar_)), + Not(Contains(Flag("--profile-file-fd=", _))), + Contains("--compiler-filter=speed-profile")))) .WillOnce(Return(0)); EXPECT_CALL( *mock_exec_utils_, - DoExecAndReturnCode(AllOf(Contains(Concatenate({"--dex-file=", services_jar_})), - Contains(HasSubstr("--profile-file-fd=")), + DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", services_jar_)), + Contains(Flag("--profile-file-fd=", FdOf(services_jar_profile_))), Contains("--compiler-filter=speed-profile")))) .WillOnce(Return(0)); EXPECT_EQ( odrefresh_->Compile(*metrics_, CompilationOptions{ - .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(), + .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(), }), ExitCode::kCompilationSuccess); } -TEST_F(OdRefreshTest, CompileSetsCompilerFilterToVerify) { - // Test setup: use "speed" compiler filter. - config_.SetSystemServerCompilerFilter("verify"); - +// Test setup: The compiler filter is not explicitly set. Use "speed-profile" if there is a vetted +// profile (on U+), otherwise fall back to "speed". +TEST_F(OdRefreshTest, CompileSetsCompilerFilterWithDefaultValue) { // Uninteresting calls. - EXPECT_CALL( - *mock_exec_utils_, DoExecAndReturnCode(_)) + EXPECT_CALL(*mock_exec_utils_, DoExecAndReturnCode(_)) .Times(odrefresh_->AllSystemServerJars().size() - 2) .WillRepeatedly(Return(0)); - EXPECT_CALL( - *mock_exec_utils_, - DoExecAndReturnCode(AllOf(Contains(Concatenate({"--dex-file=", location_provider_jar_})), - Not(Contains(HasSubstr("--profile-file-fd="))), - Contains("--compiler-filter=verify")))) - .WillOnce(Return(0)); - EXPECT_CALL( - *mock_exec_utils_, - DoExecAndReturnCode(AllOf(Contains(Concatenate({"--dex-file=", services_jar_})), - Not(Contains(HasSubstr("--profile-file-fd="))), - Contains("--compiler-filter=verify")))) + // services.jar has a profile, while location.provider.jar does not. + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", location_provider_jar_)), + Not(Contains(Flag("--profile-file-fd=", _))), + Contains("--compiler-filter=speed")))) .WillOnce(Return(0)); + // Only on U+ should we use the profile by default if available. + if (IsAtLeastU()) { + EXPECT_CALL( + *mock_exec_utils_, + DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", services_jar_)), + Contains(Flag("--profile-file-fd=", FdOf(services_jar_profile_))), + Contains("--compiler-filter=speed-profile")))) + .WillOnce(Return(0)); + } else { + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(AllOf(Contains(Flag("--dex-file=", services_jar_)), + Not(Contains(Flag("--profile-file-fd=", _))), + Contains("--compiler-filter=speed")))) + .WillOnce(Return(0)); + } EXPECT_EQ( odrefresh_->Compile(*metrics_, CompilationOptions{ @@ -455,83 +646,301 @@ TEST_F(OdRefreshTest, CompileSetsCompilerFilterToVerify) { } TEST_F(OdRefreshTest, OutputFilesAndIsa) { - EXPECT_CALL( - *mock_exec_utils_, - DoExecAndReturnCode(AllOf(Contains("--instruction-set=x86_64"), - Contains(HasSubstr("--image-fd=")), - Contains(HasSubstr("--output-vdex-fd=")), - Contains(HasSubstr("--oat-fd="))))) + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(AllOf(Contains("--instruction-set=x86_64"), + Contains(Flag("--image-fd=", FdOf(_))), + Contains(Flag("--output-vdex-fd=", FdOf(_))), + Contains(Flag("--oat-fd=", FdOf(_)))))) + .Times(2) + .WillOnce(Return(0)); + + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(AllOf(Contains("--instruction-set=x86_64"), + Contains(Flag("--app-image-fd=", FdOf(_))), + Contains(Flag("--output-vdex-fd=", FdOf(_))), + Contains(Flag("--oat-fd=", FdOf(_)))))) + .Times(odrefresh_->AllSystemServerJars().size()) + .WillRepeatedly(Return(0)); + + EXPECT_EQ(odrefresh_->Compile( + *metrics_, + CompilationOptions{ + .boot_images_to_generate_for_isas{ + {InstructionSet::kX86_64, + {.primary_boot_image = true, .boot_image_mainline_extension = true}}}, + .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(), + }), + ExitCode::kCompilationSuccess); +} + +TEST_F(OdRefreshTest, GenerateBootImageMainlineExtensionChoosesBootImage_OnData) { + // Primary boot image is on /data. + OdrArtifacts primary = OdrArtifacts::ForBootImage(dalvik_cache_dir_ + "/x86_64/boot.art"); + auto file1 = ScopedCreateEmptyFile(primary.ImagePath()); + auto file2 = ScopedCreateEmptyFile(primary.VdexPath()); + auto file3 = ScopedCreateEmptyFile(primary.OatPath()); + + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(AllOf( + Contains(Flag("--dex-file=", conscrypt_jar_)), + Contains(Flag("--boot-image=", dalvik_cache_dir_ + "/boot.art")), + Contains(ListFlag("-Xbootclasspathimagefds:", + ElementsAre(FdOf(primary.ImagePath()), "-1", "-1", "-1"))), + Contains(ListFlag("-Xbootclasspathvdexfds:", + ElementsAre(FdOf(primary.VdexPath()), "-1", "-1", "-1"))), + Contains(ListFlag("-Xbootclasspathoatfds:", + ElementsAre(FdOf(primary.OatPath()), "-1", "-1", "-1")))))) .WillOnce(Return(0)); + EXPECT_EQ(odrefresh_->Compile( + *metrics_, + CompilationOptions{ + .boot_images_to_generate_for_isas{ + {InstructionSet::kX86_64, {.boot_image_mainline_extension = true}}}, + }), + ExitCode::kCompilationSuccess); +} + +TEST_F(OdRefreshTest, GenerateBootImageMainlineExtensionChoosesBootImage_OnSystem) { + // Primary boot image and framework extension are on /system. + OdrArtifacts primary = OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot.art"); + auto file1 = ScopedCreateEmptyFile(primary.ImagePath()); + auto file2 = ScopedCreateEmptyFile(primary.VdexPath()); + auto file3 = ScopedCreateEmptyFile(primary.OatPath()); + OdrArtifacts framework_ext = + OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot-framework.art"); + auto file4 = ScopedCreateEmptyFile(framework_ext.ImagePath()); + auto file5 = ScopedCreateEmptyFile(framework_ext.VdexPath()); + auto file6 = ScopedCreateEmptyFile(framework_ext.OatPath()); + + if (IsAtLeastU()) { + EXPECT_CALL( + *mock_exec_utils_, + DoExecAndReturnCode(AllOf( + Contains(Flag("--dex-file=", conscrypt_jar_)), + Contains(ListFlag("--boot-image=", ElementsAre(framework_dir_ + "/boot.art"))), + Contains(ListFlag( + "-Xbootclasspathimagefds:", + ElementsAre( + FdOf(primary.ImagePath()), FdOf(framework_ext.ImagePath()), "-1", "-1"))), + Contains(ListFlag( + "-Xbootclasspathvdexfds:", + ElementsAre(FdOf(primary.VdexPath()), FdOf(framework_ext.VdexPath()), "-1", "-1"))), + Contains(ListFlag( + "-Xbootclasspathoatfds:", + ElementsAre(FdOf(primary.OatPath()), FdOf(framework_ext.OatPath()), "-1", "-1")))))) + .WillOnce(Return(0)); + } else { + EXPECT_CALL( + *mock_exec_utils_, + DoExecAndReturnCode(AllOf( + Contains(Flag("--dex-file=", conscrypt_jar_)), + Contains(ListFlag( + "--boot-image=", + ElementsAre(framework_dir_ + "/boot.art", framework_dir_ + "/boot-framework.art"))), + Contains(ListFlag( + "-Xbootclasspathimagefds:", + ElementsAre( + FdOf(primary.ImagePath()), FdOf(framework_ext.ImagePath()), "-1", "-1"))), + Contains(ListFlag( + "-Xbootclasspathvdexfds:", + ElementsAre(FdOf(primary.VdexPath()), FdOf(framework_ext.VdexPath()), "-1", "-1"))), + Contains(ListFlag( + "-Xbootclasspathoatfds:", + ElementsAre(FdOf(primary.OatPath()), FdOf(framework_ext.OatPath()), "-1", "-1")))))) + .WillOnce(Return(0)); + } + + EXPECT_EQ(odrefresh_->Compile( + *metrics_, + CompilationOptions{ + .boot_images_to_generate_for_isas{ + {InstructionSet::kX86_64, {.boot_image_mainline_extension = true}}}, + }), + ExitCode::kCompilationSuccess); +} + +TEST_F(OdRefreshTest, CompileSystemServerChoosesBootImage_OnData) { + // Boot images are on /data. + OdrArtifacts primary = OdrArtifacts::ForBootImage(dalvik_cache_dir_ + "/x86_64/boot.art"); + auto file1 = ScopedCreateEmptyFile(primary.ImagePath()); + auto file2 = ScopedCreateEmptyFile(primary.VdexPath()); + auto file3 = ScopedCreateEmptyFile(primary.OatPath()); + OdrArtifacts mainline_ext = + OdrArtifacts::ForBootImage(dalvik_cache_dir_ + "/x86_64/boot-conscrypt.art"); + auto file4 = ScopedCreateEmptyFile(mainline_ext.ImagePath()); + auto file5 = ScopedCreateEmptyFile(mainline_ext.VdexPath()); + auto file6 = ScopedCreateEmptyFile(mainline_ext.OatPath()); + EXPECT_CALL( *mock_exec_utils_, - DoExecAndReturnCode(AllOf(Contains("--instruction-set=x86_64"), - Contains(HasSubstr("--app-image-fd=")), - Contains(HasSubstr("--output-vdex-fd=")), - Contains(HasSubstr("--oat-fd="))))) + DoExecAndReturnCode(AllOf( + Contains(ListFlag("--boot-image=", + ElementsAre(dalvik_cache_dir_ + "/boot.art", + dalvik_cache_dir_ + "/boot-conscrypt.art"))), + Contains(ListFlag( + "-Xbootclasspathimagefds:", + ElementsAre(FdOf(primary.ImagePath()), "-1", FdOf(mainline_ext.ImagePath()), "-1"))), + Contains(ListFlag( + "-Xbootclasspathvdexfds:", + ElementsAre(FdOf(primary.VdexPath()), "-1", FdOf(mainline_ext.VdexPath()), "-1"))), + Contains(ListFlag( + "-Xbootclasspathoatfds:", + ElementsAre(FdOf(primary.OatPath()), "-1", FdOf(mainline_ext.OatPath()), "-1")))))) .Times(odrefresh_->AllSystemServerJars().size()) .WillRepeatedly(Return(0)); - EXPECT_EQ( odrefresh_->Compile(*metrics_, CompilationOptions{ - .compile_boot_classpath_for_isas = {InstructionSet::kX86_64}, - .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(), + .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(), }), ExitCode::kCompilationSuccess); } -TEST_F(OdRefreshTest, CompileChoosesBootImage_OnData) { - // Boot image is on /data. - OdrArtifacts artifacts = OdrArtifacts::ForBootImage(dalvik_cache_dir_ + "/x86_64/boot.art"); - auto file1 = ScopedCreateEmptyFile(artifacts.ImagePath()); - auto file2 = ScopedCreateEmptyFile(artifacts.VdexPath()); - auto file3 = ScopedCreateEmptyFile(artifacts.OatPath()); +TEST_F(OdRefreshTest, CompileSystemServerChoosesBootImage_OnSystemAndData) { + // The mainline extension is on /data, while others are on /system. + OdrArtifacts primary = OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot.art"); + auto file1 = ScopedCreateEmptyFile(primary.ImagePath()); + auto file2 = ScopedCreateEmptyFile(primary.VdexPath()); + auto file3 = ScopedCreateEmptyFile(primary.OatPath()); + OdrArtifacts framework_ext = + OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot-framework.art"); + auto file4 = ScopedCreateEmptyFile(framework_ext.ImagePath()); + auto file5 = ScopedCreateEmptyFile(framework_ext.VdexPath()); + auto file6 = ScopedCreateEmptyFile(framework_ext.OatPath()); + OdrArtifacts mainline_ext = + OdrArtifacts::ForBootImage(dalvik_cache_dir_ + "/x86_64/boot-conscrypt.art"); + auto file7 = ScopedCreateEmptyFile(mainline_ext.ImagePath()); + auto file8 = ScopedCreateEmptyFile(mainline_ext.VdexPath()); + auto file9 = ScopedCreateEmptyFile(mainline_ext.OatPath()); + + if (IsAtLeastU()) { + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(AllOf( + Contains(ListFlag("--boot-image=", + ElementsAre(GetPrebuiltPrimaryBootImageDir() + "/boot.art", + dalvik_cache_dir_ + "/boot-conscrypt.art"))), + Contains(ListFlag("-Xbootclasspathimagefds:", + ElementsAre(FdOf(primary.ImagePath()), + FdOf(framework_ext.ImagePath()), + FdOf(mainline_ext.ImagePath()), + "-1"))), + Contains(ListFlag("-Xbootclasspathvdexfds:", + ElementsAre(FdOf(primary.VdexPath()), + FdOf(framework_ext.VdexPath()), + FdOf(mainline_ext.VdexPath()), + "-1"))), + Contains(ListFlag("-Xbootclasspathoatfds:", + ElementsAre(FdOf(primary.OatPath()), + FdOf(framework_ext.OatPath()), + FdOf(mainline_ext.OatPath()), + "-1")))))) + .Times(odrefresh_->AllSystemServerJars().size()) + .WillRepeatedly(Return(0)); + } else { + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(AllOf( + Contains(ListFlag("--boot-image=", + ElementsAre(GetPrebuiltPrimaryBootImageDir() + "/boot.art", + framework_dir_ + "/boot-framework.art", + dalvik_cache_dir_ + "/boot-conscrypt.art"))), + Contains(ListFlag("-Xbootclasspathimagefds:", + ElementsAre(FdOf(primary.ImagePath()), + FdOf(framework_ext.ImagePath()), + FdOf(mainline_ext.ImagePath()), + "-1"))), + Contains(ListFlag("-Xbootclasspathvdexfds:", + ElementsAre(FdOf(primary.VdexPath()), + FdOf(framework_ext.VdexPath()), + FdOf(mainline_ext.VdexPath()), + "-1"))), + Contains(ListFlag("-Xbootclasspathoatfds:", + ElementsAre(FdOf(primary.OatPath()), + FdOf(framework_ext.OatPath()), + FdOf(mainline_ext.OatPath()), + "-1")))))) + .Times(odrefresh_->AllSystemServerJars().size()) + .WillRepeatedly(Return(0)); + } - EXPECT_CALL( - *mock_exec_utils_, - DoExecAndReturnCode(AllOf( - Contains(Concatenate({"--boot-image=", dalvik_cache_dir_, "/boot.art"})), - Contains(FlagContains("-Xbootclasspathimagefds:", FdOf(artifacts.ImagePath()))), - Contains(FlagContains("-Xbootclasspathvdexfds:", FdOf(artifacts.VdexPath()))), - Contains(FlagContains("-Xbootclasspathoatfds:", FdOf(artifacts.OatPath())))))) - .Times(odrefresh_->AllSystemServerJars().size()) - .WillRepeatedly(Return(0)); EXPECT_EQ( odrefresh_->Compile(*metrics_, CompilationOptions{ - .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(), + .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(), }), ExitCode::kCompilationSuccess); } -TEST_F(OdRefreshTest, CompileChoosesBootImage_OnSystem) { - // Boot image is on /system. - OdrArtifacts artifacts = +TEST_F(OdRefreshTest, CompileSystemServerChoosesBootImage_OnSystem) { + // Boot images are on /system. + OdrArtifacts primary = OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot.art"); + auto file1 = ScopedCreateEmptyFile(primary.ImagePath()); + auto file2 = ScopedCreateEmptyFile(primary.VdexPath()); + auto file3 = ScopedCreateEmptyFile(primary.OatPath()); + OdrArtifacts framework_ext = OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot-framework.art"); - auto file1 = ScopedCreateEmptyFile(artifacts.ImagePath()); - auto file2 = ScopedCreateEmptyFile(artifacts.VdexPath()); - auto file3 = ScopedCreateEmptyFile(artifacts.OatPath()); + auto file4 = ScopedCreateEmptyFile(framework_ext.ImagePath()); + auto file5 = ScopedCreateEmptyFile(framework_ext.VdexPath()); + auto file6 = ScopedCreateEmptyFile(framework_ext.OatPath()); + OdrArtifacts mainline_ext = + OdrArtifacts::ForBootImage(framework_dir_ + "/x86_64/boot-conscrypt.art"); + auto file7 = ScopedCreateEmptyFile(mainline_ext.ImagePath()); + auto file8 = ScopedCreateEmptyFile(mainline_ext.VdexPath()); + auto file9 = ScopedCreateEmptyFile(mainline_ext.OatPath()); + + if (IsAtLeastU()) { + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(AllOf( + Contains(ListFlag("--boot-image=", + ElementsAre(GetPrebuiltPrimaryBootImageDir() + "/boot.art", + framework_dir_ + "/boot-conscrypt.art"))), + Contains(ListFlag("-Xbootclasspathimagefds:", + ElementsAre(FdOf(primary.ImagePath()), + FdOf(framework_ext.ImagePath()), + FdOf(mainline_ext.ImagePath()), + "-1"))), + Contains(ListFlag("-Xbootclasspathvdexfds:", + ElementsAre(FdOf(primary.VdexPath()), + FdOf(framework_ext.VdexPath()), + FdOf(mainline_ext.VdexPath()), + "-1"))), + Contains(ListFlag("-Xbootclasspathoatfds:", + ElementsAre(FdOf(primary.OatPath()), + FdOf(framework_ext.OatPath()), + FdOf(mainline_ext.OatPath()), + "-1")))))) + .Times(odrefresh_->AllSystemServerJars().size()) + .WillRepeatedly(Return(0)); + } else { + EXPECT_CALL(*mock_exec_utils_, + DoExecAndReturnCode(AllOf( + Contains(ListFlag("--boot-image=", + ElementsAre(GetPrebuiltPrimaryBootImageDir() + "/boot.art", + framework_dir_ + "/boot-framework.art", + framework_dir_ + "/boot-conscrypt.art"))), + Contains(ListFlag("-Xbootclasspathimagefds:", + ElementsAre(FdOf(primary.ImagePath()), + FdOf(framework_ext.ImagePath()), + FdOf(mainline_ext.ImagePath()), + "-1"))), + Contains(ListFlag("-Xbootclasspathvdexfds:", + ElementsAre(FdOf(primary.VdexPath()), + FdOf(framework_ext.VdexPath()), + FdOf(mainline_ext.VdexPath()), + "-1"))), + Contains(ListFlag("-Xbootclasspathoatfds:", + ElementsAre(FdOf(primary.OatPath()), + FdOf(framework_ext.OatPath()), + FdOf(mainline_ext.OatPath()), + "-1")))))) + .Times(odrefresh_->AllSystemServerJars().size()) + .WillRepeatedly(Return(0)); + } - // Ignore the execution for compiling the boot classpath. - EXPECT_CALL( - *mock_exec_utils_, DoExecAndReturnCode(Contains(HasSubstr("--image-fd=")))) - .WillRepeatedly(Return(0)); - EXPECT_CALL( - *mock_exec_utils_, - DoExecAndReturnCode(AllOf( - Contains(Concatenate({"--boot-image=", - GetPrebuiltPrimaryBootImageDir(), "/boot.art:", - framework_dir_, "/boot-framework.art"})), - Contains(FlagContains("-Xbootclasspathimagefds:", FdOf(artifacts.ImagePath()))), - Contains(FlagContains("-Xbootclasspathvdexfds:", FdOf(artifacts.VdexPath()))), - Contains(FlagContains("-Xbootclasspathoatfds:", FdOf(artifacts.OatPath())))))) - .Times(odrefresh_->AllSystemServerJars().size()) - .WillRepeatedly(Return(0)); EXPECT_EQ( odrefresh_->Compile(*metrics_, CompilationOptions{ - .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(), + .system_server_jars_to_compile = odrefresh_->AllSystemServerJars(), }), ExitCode::kCompilationSuccess); } |