| /* |
| * Copyright (C) 2021 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "libdexopt.h" |
| |
| #include <string> |
| #include <vector> |
| |
| #include "android-base/result.h" |
| #include "android-base/strings.h" |
| #include "base/common_art_test.h" |
| #include "gmock/gmock.h" |
| #include "gtest/gtest.h" |
| |
| #include "aidl/com/android/art/CompilerFilter.h" |
| #include "aidl/com/android/art/DexoptBcpExtArgs.h" |
| #include "aidl/com/android/art/DexoptSystemServerArgs.h" |
| #include "aidl/com/android/art/Isa.h" |
| |
| namespace art { |
| |
| using ::testing::AllOf; |
| using ::testing::Contains; |
| using ::testing::HasSubstr; |
| using ::testing::Not; |
| using aidl::com::android::art::CompilerFilter; |
| using aidl::com::android::art::DexoptBcpExtArgs; |
| using aidl::com::android::art::DexoptSystemServerArgs; |
| using aidl::com::android::art::Isa; |
| using android::base::Result; |
| |
| std::string GetEnvironmentVariableOrDie(const char* name) { |
| const char* value = getenv(name); |
| EXPECT_NE(value, nullptr); |
| return value; |
| } |
| |
| // See art_artd_tests.xml for *CLASSPATH setup. |
| class LibDexoptTest : public CommonArtTest { |
| protected: |
| void SetUp() override { |
| CommonArtTest::SetUp(); |
| |
| default_bcp_ext_args_.dexFds = {10, 11}; |
| default_bcp_ext_args_.bootClasspaths = android::base::Split( |
| GetEnvironmentVariableOrDie("DEX2OATBOOTCLASSPATH"), ":"); // from art_artd_tests.xml |
| default_bcp_ext_args_.bootClasspathFds = {21, 22}; |
| default_bcp_ext_args_.profileFds = {30, 31}; |
| default_bcp_ext_args_.dirtyImageObjectsFd = 31; |
| default_bcp_ext_args_.imageFd = 90; |
| default_bcp_ext_args_.vdexFd = 91; |
| default_bcp_ext_args_.oatFd = 92; |
| default_bcp_ext_args_.dexPaths = {"/path/to/foo.jar", "/path/to/bar.jar"}; |
| default_bcp_ext_args_.oatLocation = "/oat/location/bar.odex"; |
| default_bcp_ext_args_.isa = Isa::X86_64; |
| default_bcp_ext_args_.cpuSet = {0, 1}; |
| default_bcp_ext_args_.threads = 42; |
| ASSERT_EQ(default_bcp_ext_args_.bootClasspaths.size(), |
| default_bcp_ext_args_.bootClasspathFds.size()); |
| |
| default_system_server_args_.dexFd = 10; |
| default_system_server_args_.profileFd = 11; |
| default_system_server_args_.bootClasspaths = android::base::Split( |
| GetEnvironmentVariableOrDie("BOOTCLASSPATH"), ":"); // from art_artd_tests.xml |
| default_system_server_args_.bootClasspathFds = {21, 22, 23}; |
| default_system_server_args_.bootClasspathImageFds = {-1, 31, -1}; |
| default_system_server_args_.bootClasspathVdexFds = {-1, 32, -1}; |
| default_system_server_args_.bootClasspathOatFds = {-1, 33, -1}; |
| default_system_server_args_.classloaderFds = {40, 41}; |
| default_system_server_args_.classloaderContext = {"/cl/abc.jar", "/cl/def.jar"}; |
| default_system_server_args_.imageFd = 90; |
| default_system_server_args_.vdexFd = 91; |
| default_system_server_args_.oatFd = 92; |
| default_system_server_args_.dexPath = "/path/to/foo.jar"; |
| default_system_server_args_.oatLocation = "/oat/location/bar.odex"; |
| default_system_server_args_.isa = Isa::X86_64; |
| default_system_server_args_.compilerFilter = CompilerFilter::SPEED_PROFILE; |
| default_system_server_args_.cpuSet = {0, 1}; |
| default_system_server_args_.threads = 42; |
| default_system_server_args_.bootImage = "/path/to/boot.art"; |
| ASSERT_EQ(default_system_server_args_.bootClasspaths.size(), |
| default_system_server_args_.bootClasspathFds.size()); |
| } |
| |
| void TearDown() override { |
| CommonArtTest::TearDown(); |
| } |
| |
| std::vector<std::string> Dex2oatArgsFromBcpExtensionArgs(const DexoptBcpExtArgs& args) { |
| std::vector<std::string> cmdline; |
| Result<void> result = AddDex2oatArgsFromBcpExtensionArgs(args, cmdline); |
| EXPECT_TRUE(result.ok()) << "Failed expectation: " << result.error().message(); |
| return cmdline; |
| } |
| |
| std::vector<std::string> Dex2oatArgsFromSystemServerArgs(const DexoptSystemServerArgs& args) { |
| std::vector<std::string> cmdline; |
| Result<void> result = AddDex2oatArgsFromSystemServerArgs(args, cmdline); |
| EXPECT_TRUE(result.ok()) << "Failed expectation: " << result.error().message(); |
| return cmdline; |
| } |
| |
| bool DexoptBcpExtArgsIsInvalid(const DexoptBcpExtArgs& args) { |
| std::vector<std::string> cmdline; |
| Result<void> result = AddDex2oatArgsFromBcpExtensionArgs(args, cmdline); |
| return result.ok(); |
| } |
| |
| bool DexoptSystemServerArgsIsInvalid(const DexoptSystemServerArgs& args) { |
| std::vector<std::string> cmdline; |
| Result<void> result = AddDex2oatArgsFromSystemServerArgs(args, cmdline); |
| return result.ok(); |
| } |
| |
| DexoptBcpExtArgs default_bcp_ext_args_; |
| DexoptSystemServerArgs default_system_server_args_; |
| }; |
| |
| TEST_F(LibDexoptTest, AddDex2oatArgsFromBcpExtensionArgs) { |
| // Test basics with default args |
| { |
| std::vector<std::string> cmdline = Dex2oatArgsFromBcpExtensionArgs(default_bcp_ext_args_); |
| |
| EXPECT_THAT(cmdline, |
| AllOf(Contains("--dex-fd=10"), |
| Contains("--dex-fd=11"), |
| Contains("--dex-file=/path/to/foo.jar"), |
| Contains("--dex-file=/path/to/bar.jar"), |
| Contains(HasSubstr("-Xbootclasspath:")), |
| Contains("-Xbootclasspathfds:21:22"), |
| |
| Contains("--profile-file-fd=30"), |
| Contains("--profile-file-fd=31"), |
| Contains("--compiler-filter=speed-profile"), |
| |
| Contains("--image-fd=90"), |
| Contains("--output-vdex-fd=91"), |
| Contains("--oat-fd=92"), |
| Contains("--oat-location=/oat/location/bar.odex"), |
| |
| Contains("--dirty-image-objects-fd=31"), |
| Contains("--instruction-set=x86_64"), |
| Contains("--cpu-set=0,1"), |
| Contains("-j42"), |
| |
| Contains(HasSubstr("--base=")))); |
| } |
| |
| // No profile |
| { |
| auto args = default_bcp_ext_args_; |
| args.profileFds = {}; |
| std::vector<std::string> cmdline = Dex2oatArgsFromBcpExtensionArgs(args); |
| |
| EXPECT_THAT(cmdline, AllOf( |
| Not(Contains(HasSubstr("--profile-file-fd="))), |
| Contains("--compiler-filter=speed"))); |
| } |
| |
| // No dirty image objects fd |
| { |
| auto args = default_bcp_ext_args_; |
| args.dirtyImageObjectsFd = -1; |
| std::vector<std::string> cmdline = Dex2oatArgsFromBcpExtensionArgs(args); |
| |
| EXPECT_THAT(cmdline, Not(Contains(HasSubstr("--dirty-image-objects-fd")))); |
| } |
| } |
| |
| TEST_F(LibDexoptTest, AddDex2oatArgsFromBcpExtensionArgs_InvalidArguments) { |
| // Mismatched dex number |
| { |
| auto args = default_bcp_ext_args_; |
| args.dexPaths = {"/path/to/foo.jar", "/path/to/bar.jar"}; |
| args.dexFds = {100, 101, 102}; |
| |
| EXPECT_FALSE(DexoptBcpExtArgsIsInvalid(args)); |
| } |
| |
| // Mismatched classpath arguments |
| { |
| auto args = default_bcp_ext_args_; |
| args.bootClasspathFds.emplace_back(200); |
| |
| EXPECT_FALSE(DexoptBcpExtArgsIsInvalid(args)); |
| } |
| |
| // Mismatched classpath arguments |
| { |
| auto args = default_bcp_ext_args_; |
| args.bootClasspaths.emplace_back("/unrecognized/jar"); |
| |
| EXPECT_FALSE(DexoptBcpExtArgsIsInvalid(args)); |
| } |
| |
| // Missing output fds |
| { |
| auto args = default_bcp_ext_args_; |
| args.imageFd = -1; |
| EXPECT_FALSE(DexoptBcpExtArgsIsInvalid(args)); |
| |
| args = default_bcp_ext_args_; |
| args.vdexFd = -1; |
| EXPECT_FALSE(DexoptBcpExtArgsIsInvalid(args)); |
| |
| args = default_bcp_ext_args_; |
| args.oatFd = -1; |
| EXPECT_FALSE(DexoptBcpExtArgsIsInvalid(args)); |
| } |
| } |
| |
| TEST_F(LibDexoptTest, AddDex2oatArgsFromSystemServerArgs) { |
| // Test basics with default args |
| { |
| std::vector<std::string> cmdline = Dex2oatArgsFromSystemServerArgs(default_system_server_args_); |
| |
| EXPECT_THAT(cmdline, |
| AllOf(Contains("--dex-fd=10"), |
| Contains("--dex-file=/path/to/foo.jar"), |
| Contains(HasSubstr("-Xbootclasspath:")), |
| Contains("-Xbootclasspathfds:21:22:23"), |
| Contains("-Xbootclasspathimagefds:-1:31:-1"), |
| Contains("-Xbootclasspathvdexfds:-1:32:-1"), |
| Contains("-Xbootclasspathoatfds:-1:33:-1"), |
| |
| Contains("--profile-file-fd=11"), |
| Contains("--compiler-filter=speed-profile"), |
| |
| Contains("--app-image-fd=90"), |
| Contains("--output-vdex-fd=91"), |
| Contains("--oat-fd=92"), |
| Contains("--oat-location=/oat/location/bar.odex"), |
| |
| Contains("--class-loader-context-fds=40:41"), |
| Contains("--class-loader-context=PCL[/cl/abc.jar:/cl/def.jar]"), |
| |
| Contains("--instruction-set=x86_64"), |
| Contains("--cpu-set=0,1"), |
| Contains("-j42"), |
| |
| Contains("--boot-image=/path/to/boot.art"))); |
| } |
| |
| // Test different compiler filters |
| { |
| // speed |
| auto args = default_system_server_args_; |
| args.compilerFilter = CompilerFilter::SPEED; |
| std::vector<std::string> cmdline = Dex2oatArgsFromSystemServerArgs(args); |
| |
| EXPECT_THAT(cmdline, AllOf( |
| Not(Contains(HasSubstr("--profile-file-fd="))), |
| Contains("--compiler-filter=speed"))); |
| |
| // verify |
| args = default_system_server_args_; |
| args.compilerFilter = CompilerFilter::VERIFY; |
| cmdline = Dex2oatArgsFromSystemServerArgs(args); |
| |
| EXPECT_THAT(cmdline, AllOf( |
| Not(Contains(HasSubstr("--profile-file-fd="))), |
| Contains("--compiler-filter=verify"))); |
| } |
| |
| // Test empty classloader context |
| { |
| auto args = default_system_server_args_; |
| args.classloaderFds = {}; |
| args.classloaderContext = {}; |
| std::vector<std::string> cmdline = Dex2oatArgsFromSystemServerArgs(args); |
| |
| EXPECT_THAT(cmdline, AllOf( |
| Not(Contains(HasSubstr("--class-loader-context-fds"))), |
| Contains("--class-loader-context=PCL[]"))); |
| } |
| |
| // Test classloader context as parent |
| { |
| auto args = default_system_server_args_; |
| args.classloaderContextAsParent = true; |
| std::vector<std::string> cmdline = Dex2oatArgsFromSystemServerArgs(args); |
| |
| EXPECT_THAT(cmdline, Contains("--class-loader-context=PCL[];PCL[/cl/abc.jar:/cl/def.jar]")); |
| } |
| } |
| |
| TEST_F(LibDexoptTest, AddDex2oatArgsFromSystemServerArgs_InvalidArguments) { |
| // Mismatched classpath arguments |
| { |
| auto args = default_system_server_args_; |
| args.bootClasspathFds.emplace_back(200); |
| |
| EXPECT_FALSE(DexoptSystemServerArgsIsInvalid(args)); |
| } |
| |
| // Unrecognized jar path |
| { |
| auto args = default_system_server_args_; |
| args.bootClasspaths.emplace_back("/unrecognized/jar"); |
| |
| EXPECT_FALSE(DexoptSystemServerArgsIsInvalid(args)); |
| } |
| |
| // speed-profile without profile fd |
| { |
| auto args = default_system_server_args_; |
| args.compilerFilter = CompilerFilter::SPEED_PROFILE; |
| args.profileFd = -1; |
| EXPECT_FALSE(DexoptSystemServerArgsIsInvalid(args)); |
| } |
| |
| // Missing output fds |
| { |
| auto args = default_system_server_args_; |
| args.imageFd = -1; |
| EXPECT_FALSE(DexoptSystemServerArgsIsInvalid(args)); |
| |
| args = default_system_server_args_; |
| args.vdexFd = -1; |
| EXPECT_FALSE(DexoptSystemServerArgsIsInvalid(args)); |
| |
| args = default_system_server_args_; |
| args.oatFd = -1; |
| EXPECT_FALSE(DexoptSystemServerArgsIsInvalid(args)); |
| } |
| } |
| |
| } // namespace art |