Clean up some image tests.
Make ImageSpaceLoadingTest<false,.,.> use a custom image
location based on ScratchFile to avoid accidentally finding
a pre-compiled boot image in default location.
Add -Xnoimage-dex2oat to Dex2oatImageTest to avoid useless
dex2oat invocations that just slow down the test. Suppress
error messages from image loading that is supposed to fail.
Compile only 3 dex files in TestModesAndFilters to make the
test faster (29s->20s on host).
Test: m test-art-host-gtest
Change-Id: Ia92e85f056027003d2fb50aa871c9fae7a5fdc01
diff --git a/dex2oat/dex2oat_image_test.cc b/dex2oat/dex2oat_image_test.cc
index 9b96494..f03f02c 100644
--- a/dex2oat/dex2oat_image_test.cc
+++ b/dex2oat/dex2oat_image_test.cc
@@ -68,6 +68,11 @@
void TearDown() override {}
protected:
+ void SetUpRuntimeOptions(RuntimeOptions* options) override {
+ // Disable implicit dex2oat invocations when loading image spaces.
+ options->emplace_back("-Xnoimage-dex2oat", nullptr);
+ }
+
// Visitors take method and type references
template <typename MethodVisitor, typename ClassVisitor>
void VisitLibcoreDexes(const MethodVisitor& method_visitor,
@@ -156,7 +161,8 @@
args.push_back(arg);
}
- ImageSizes CompileImageAndGetSizes(const std::vector<std::string>& extra_args) {
+ ImageSizes CompileImageAndGetSizes(ArrayRef<const std::string> dex_files,
+ const std::vector<std::string>& extra_args) {
ImageSizes ret;
ScratchFile scratch;
std::string scratch_dir = scratch.GetFilename();
@@ -164,8 +170,6 @@
scratch_dir.pop_back();
}
CHECK(!scratch_dir.empty()) << "No directory " << scratch.GetFilename();
- std::vector<std::string> libcore_dex_files = GetLibCoreDexFileNames();
- ArrayRef<const std::string> dex_files(libcore_dex_files);
std::vector<std::string> local_extra_args = extra_args;
local_extra_args.push_back(android::base::StringPrintf("--base=0x%08x", kBaseAddress));
std::string error_msg;
@@ -241,6 +245,38 @@
}
return res.StandardSuccess();
}
+
+ MemMap ReserveCoreImageAddressSpace(/*out*/std::string* error_msg) {
+ constexpr size_t kReservationSize = 256 * MB; // This should be enough for the compiled images.
+ // Extend to both directions for maximum relocation difference.
+ static_assert(ART_BASE_ADDRESS_MIN_DELTA < 0);
+ static_assert(ART_BASE_ADDRESS_MAX_DELTA > 0);
+ static_assert(IsAligned<kPageSize>(ART_BASE_ADDRESS_MIN_DELTA));
+ static_assert(IsAligned<kPageSize>(ART_BASE_ADDRESS_MAX_DELTA));
+ constexpr size_t kExtra = ART_BASE_ADDRESS_MAX_DELTA - ART_BASE_ADDRESS_MIN_DELTA;
+ uint32_t min_relocated_address = kBaseAddress + ART_BASE_ADDRESS_MIN_DELTA;
+ return MemMap::MapAnonymous("Reservation",
+ reinterpret_cast<uint8_t*>(min_relocated_address),
+ kReservationSize + kExtra,
+ PROT_NONE,
+ /*low_4gb=*/ true,
+ /*reuse=*/ false,
+ /*reservation=*/ nullptr,
+ error_msg);
+ }
+
+ void CopyDexFiles(const std::string& dir, /*inout*/std::vector<std::string>* dex_files) {
+ CHECK(EndsWith(dir, "/"));
+ for (std::string& dex_file : *dex_files) {
+ size_t slash_pos = dex_file.rfind('/');
+ CHECK_NE(std::string::npos, slash_pos);
+ std::string new_location = dir + dex_file.substr(slash_pos + 1u);
+ std::ifstream src_stream(dex_file, std::ios::binary);
+ std::ofstream dst_stream(new_location, std::ios::binary);
+ dst_stream << src_stream.rdbuf();
+ dex_file = new_location;
+ }
+ }
};
TEST_F(Dex2oatImageTest, TestModesAndFilters) {
@@ -253,7 +289,17 @@
// This test is too slow for target builds.
return;
}
- ImageSizes base_sizes = CompileImageAndGetSizes({});
+ // Compile only a subset of the libcore dex files to make this test shorter.
+ std::vector<std::string> libcore_dex_files = GetLibCoreDexFileNames();
+ // The primary image must contain at least core-oj and core-libart to initialize the runtime
+ // and we also need the core-icu4j if we want to compile these with full profile.
+ ASSERT_NE(std::string::npos, libcore_dex_files[0].find("core-oj"));
+ ASSERT_NE(std::string::npos, libcore_dex_files[1].find("core-libart"));
+ ASSERT_NE(std::string::npos, libcore_dex_files[2].find("core-icu4j"));
+ ArrayRef<const std::string> dex_files =
+ ArrayRef<const std::string>(libcore_dex_files).SubArray(/*pos=*/ 0u, /*length=*/ 3u);
+
+ ImageSizes base_sizes = CompileImageAndGetSizes(dex_files, {});
ImageSizes everything_sizes;
ImageSizes filter_sizes;
std::cout << "Base compile sizes " << base_sizes << std::endl;
@@ -265,6 +311,7 @@
/*method_frequency=*/ 1u,
/*type_frequency=*/ 1u);
everything_sizes = CompileImageAndGetSizes(
+ dex_files,
{"--profile-file=" + profile_file.GetFilename(),
"--compiler-filter=speed-profile"});
profile_file.Close();
@@ -284,6 +331,7 @@
kMethodFrequency,
kTypeFrequency);
filter_sizes = CompileImageAndGetSizes(
+ dex_files,
{"--profile-file=" + profile_file.GetFilename(),
"--compiler-filter=speed-profile"});
profile_file.Close();
@@ -300,6 +348,7 @@
WriteLine(classes.GetFile(), ref.dex_file->PrettyType(ref.TypeIndex()));
}, /*method_frequency=*/ 1u, /*class_frequency=*/ 1u);
ImageSizes image_classes_sizes = CompileImageAndGetSizes(
+ dex_files,
{"--dirty-image-objects=" + classes.GetFilename()});
classes.Close();
std::cout << "Dirty image object sizes " << image_classes_sizes << std::endl;
@@ -307,24 +356,9 @@
}
TEST_F(Dex2oatImageTest, TestExtension) {
- constexpr size_t kReservationSize = 256 * MB; // This should be enough for the compiled images.
- // Extend to both directions for maximum relocation difference.
- static_assert(ART_BASE_ADDRESS_MIN_DELTA < 0);
- static_assert(ART_BASE_ADDRESS_MAX_DELTA > 0);
- static_assert(IsAligned<kPageSize>(ART_BASE_ADDRESS_MIN_DELTA));
- static_assert(IsAligned<kPageSize>(ART_BASE_ADDRESS_MAX_DELTA));
- constexpr size_t kExtra = ART_BASE_ADDRESS_MAX_DELTA - ART_BASE_ADDRESS_MIN_DELTA;
- uint32_t min_relocated_address = kBaseAddress + ART_BASE_ADDRESS_MIN_DELTA;
std::string error_msg;
- MemMap reservation = MemMap::MapAnonymous("Reservation",
- reinterpret_cast<uint8_t*>(min_relocated_address),
- kReservationSize + kExtra,
- PROT_NONE,
- /*low_4gb=*/ true,
- /*reuse=*/ false,
- /*reservation=*/ nullptr,
- &error_msg);
- ASSERT_TRUE(reservation.IsValid());
+ MemMap reservation = ReserveCoreImageAddressSpace(&error_msg);
+ ASSERT_TRUE(reservation.IsValid()) << error_msg;
ScratchFile scratch;
std::string scratch_dir = scratch.GetFilename() + "-d";
@@ -343,15 +377,7 @@
ASSERT_EQ(0, mkdir_result);
jar_dir += '/';
std::vector<std::string> libcore_dex_files = GetLibCoreDexFileNames();
- for (std::string& dex_file : libcore_dex_files) {
- size_t slash_pos = dex_file.rfind('/');
- ASSERT_NE(std::string::npos, slash_pos);
- std::string new_location = jar_dir + dex_file.substr(slash_pos + 1u);
- std::ifstream src_stream(dex_file, std::ios::binary);
- std::ofstream dst_stream(new_location, std::ios::binary);
- dst_stream << src_stream.rdbuf();
- dex_file = new_location;
- }
+ CopyDexFiles(jar_dir, &libcore_dex_files);
// Create a profile.
ScratchFile profile_file;
@@ -415,10 +441,10 @@
extra_args.push_back("--boot-image=" + base_location);
bool mid_ok = CompileBootImage(extra_args, filename_prefix, mid_dex_files, &error_msg);
ASSERT_TRUE(mid_ok) << error_msg;
+ extra_args.resize(extra_args.size() - 3u);
// Try to compile the "tail" without specifying the "mid" extension. This shall fail.
std::string full_bcp_string = android::base::Join(full_bcp, ':');
- extra_args.clear();
AddRuntimeArg(extra_args, "-Xbootclasspath:" + full_bcp_string);
AddRuntimeArg(extra_args, "-Xbootclasspath-locations:" + full_bcp_string);
extra_args.push_back("--boot-image=" + base_location);
@@ -454,8 +480,12 @@
&boot_image_spaces,
&extra_reservation);
};
+ auto silent_load = [&](const std::string& image_location) {
+ ScopedLogSeverity quiet(LogSeverity::FATAL);
+ return load(image_location);
+ };
- for (bool r : { false, true}) {
+ for (bool r : { false, true }) {
relocate = r;
// Load primary image with full path.
@@ -465,13 +495,13 @@
ASSERT_EQ(head_dex_files.size(), boot_image_spaces.size());
// Fail to load primary image with just the name.
- load_ok = load(base_name);
+ load_ok = silent_load(base_name);
ASSERT_FALSE(load_ok);
// Fail to load primary image with a search path.
- load_ok = load("*");
+ load_ok = silent_load("*");
ASSERT_FALSE(load_ok);
- load_ok = load(scratch_dir + "*");
+ load_ok = silent_load(scratch_dir + "*");
ASSERT_FALSE(load_ok);
// Load the primary and first extension with full path.
@@ -513,17 +543,9 @@
// Now copy the libcore dex files to the `scratch_dir` and retry loading the boot image
// with BCP in the scratch_dir so that the images can be found based on BCP paths.
- for (std::string& bcp_component : boot_class_path) {
- size_t slash_pos = bcp_component.rfind('/');
- ASSERT_NE(std::string::npos, slash_pos);
- std::string new_location = scratch_dir + bcp_component.substr(slash_pos + 1u);
- std::ifstream src_stream(bcp_component, std::ios::binary);
- std::ofstream dst_stream(new_location, std::ios::binary);
- dst_stream << src_stream.rdbuf();
- bcp_component = new_location;
- }
+ CopyDexFiles(scratch_dir, &boot_class_path);
- for (bool r : { false, true}) {
+ for (bool r : { false, true }) {
relocate = r;
// Loading the primary image with just the name now succeeds.
@@ -531,9 +553,9 @@
ASSERT_TRUE(load_ok) << error_msg;
// Loading the primary image with a search path still fails.
- load_ok = load("*");
+ load_ok = silent_load("*");
ASSERT_FALSE(load_ok);
- load_ok = load(scratch_dir + "*");
+ load_ok = silent_load(scratch_dir + "*");
ASSERT_FALSE(load_ok);
// Load the primary and first extension without paths.
@@ -568,9 +590,9 @@
ASSERT_EQ(full_bcp.size(), boot_image_spaces.size());
// Fail to load any images with invalid image locations (named component after search paths).
- load_ok = load(base_location + ":*:" + tail_location);
+ load_ok = silent_load(base_location + ":*:" + tail_location);
ASSERT_FALSE(load_ok);
- load_ok = load(base_location + ':' + scratch_dir + "*:" + tail_location);
+ load_ok = silent_load(base_location + ':' + scratch_dir + "*:" + tail_location);
ASSERT_FALSE(load_ok);
}
diff --git a/runtime/gc/space/image_space_test.cc b/runtime/gc/space/image_space_test.cc
index f3398e9..008793b 100644
--- a/runtime/gc/space/image_space_test.cc
+++ b/runtime/gc/space/image_space_test.cc
@@ -166,10 +166,13 @@
class ImageSpaceLoadingTest : public CommonRuntimeTest {
protected:
void SetUpRuntimeOptions(RuntimeOptions* options) override {
- if (kImage) {
- options->emplace_back(android::base::StringPrintf("-Ximage:%s", GetCoreArtLocation().c_str()),
- nullptr);
+ std::string image_location = GetCoreArtLocation();
+ if (!kImage) {
+ missing_image_base_ = std::make_unique<ScratchFile>();
+ image_location = missing_image_base_->GetFilename() + ".art";
}
+ options->emplace_back(android::base::StringPrintf("-Ximage:%s", image_location.c_str()),
+ nullptr);
options->emplace_back(kRelocate ? "-Xrelocate" : "-Xnorelocate", nullptr);
options->emplace_back(kImageDex2oat ? "-Ximage-dex2oat" : "-Xnoimage-dex2oat", nullptr);
@@ -194,9 +197,11 @@
CHECK_EQ(result, 0);
old_dex2oat_bcp_.reset();
}
+ missing_image_base_.reset();
}
private:
+ std::unique_ptr<ScratchFile> missing_image_base_;
UniqueCPtr<const char[]> old_dex2oat_bcp_;
};
@@ -238,13 +243,13 @@
}
void TearDown() override {
+ ImageSpaceLoadingTest<false, true, true>::TearDown();
int result = unlink(bad_dalvik_cache_.c_str());
CHECK_EQ(result, 0) << strerror(errno);
result = rmdir(bad_android_data_.c_str());
CHECK_EQ(result, 0) << strerror(errno);
result = setenv("ANDROID_DATA", old_android_data_.c_str(), /* replace */ 1);
CHECK_EQ(result, 0) << strerror(errno);
- ImageSpaceLoadingTest<false, true, true>::TearDown();
}
private: