OatFileAssistantTest: do not relocate image randomly.
Manually relocate the boot image to a known location before starting
the runtime so that the image won't be randomly relocated. This fixes
flaky test failures due to the image randomly being relocated by 0.
Bug: 28294887
Change-Id: I05a7961f1237a05e89d3f631c959e260ccfe0b70
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index c79a9a6..23ba4d8 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -56,12 +56,11 @@
odex_dir_ = odex_oat_dir_ + "/" + std::string(GetInstructionSetString(kRuntimeISA));
ASSERT_EQ(0, mkdir(odex_dir_.c_str(), 0700));
-
// Verify the environment is as we expect
uint32_t checksum;
std::string error_msg;
- ASSERT_TRUE(OS::FileExists(GetImageFile().c_str()))
- << "Expected pre-compiled boot image to be at: " << GetImageFile();
+ ASSERT_TRUE(OS::FileExists(GetSystemImageFile().c_str()))
+ << "Expected pre-compiled boot image to be at: " << GetSystemImageFile();
ASSERT_TRUE(OS::FileExists(GetDexSrc1().c_str()))
<< "Expected dex file to be at: " << GetDexSrc1();
ASSERT_TRUE(OS::FileExists(GetStrippedDexSrc1().c_str()))
@@ -87,6 +86,27 @@
ASSERT_NE(multi1[1]->GetLocationChecksum(), multi2[1]->GetLocationChecksum());
}
+ // Pre-Relocate the image to a known non-zero offset so we don't have to
+ // deal with the runtime randomly relocating the image by 0 and messing up
+ // the expected results of the tests.
+ bool PreRelocateImage(std::string* error_msg) {
+ std::string image;
+ if (!GetCachedImageFile(&image, error_msg)) {
+ return false;
+ }
+
+ std::string patchoat = GetAndroidRoot();
+ patchoat += kIsDebugBuild ? "/bin/patchoatd" : "/bin/patchoat";
+
+ std::vector<std::string> argv;
+ argv.push_back(patchoat);
+ argv.push_back("--input-image-location=" + GetImageLocation());
+ argv.push_back("--output-image-file=" + image);
+ argv.push_back("--instruction-set=" + std::string(GetInstructionSetString(kRuntimeISA)));
+ argv.push_back("--base-offset-delta=0x00008000");
+ return Exec(argv, error_msg);
+ }
+
virtual void SetUpRuntimeOptions(RuntimeOptions* options) {
// options->push_back(std::make_pair("-verbose:oat", nullptr));
@@ -99,6 +119,9 @@
}
virtual void PreRuntimeCreate() {
+ std::string error_msg;
+ ASSERT_TRUE(PreRelocateImage(&error_msg)) << error_msg;
+
UnreserveImageSpace();
}
@@ -144,11 +167,16 @@
return GetImageDirectory() + "/core.art";
}
- std::string GetImageFile() {
+ std::string GetSystemImageFile() {
return GetImageDirectory() + "/" + GetInstructionSetString(kRuntimeISA)
+ "/core.art";
}
+ bool GetCachedImageFile(/*out*/std::string* image, std::string* error_msg) {
+ std::string cache = GetDalvikCache(GetInstructionSetString(kRuntimeISA), true);
+ return GetDalvikCacheFilename(GetImageLocation().c_str(), cache.c_str(), image, error_msg);
+ }
+
std::string GetDexSrc1() {
return GetTestDexFileName("Main");
}
@@ -189,34 +217,31 @@
// The generated odex file will be un-relocated.
void GenerateOdexForTest(const std::string& dex_location,
const std::string& odex_location,
- CompilerFilter::Filter filter) {
- // To generate an un-relocated odex file, we first compile a relocated
- // version of the file, then manually call patchoat to make it look as if
- // it is unrelocated.
- std::string relocated_odex_location = odex_location + ".relocated";
+ CompilerFilter::Filter filter,
+ bool pic = false,
+ bool with_patch_info = true) {
+ // Temporarily redirect the dalvik cache so dex2oat doesn't find the
+ // relocated image file.
+ std::string android_data_tmp = GetScratchDir() + "AndroidDataTmp";
+ setenv("ANDROID_DATA", android_data_tmp.c_str(), 1);
std::vector<std::string> args;
args.push_back("--dex-file=" + dex_location);
- args.push_back("--oat-file=" + relocated_odex_location);
+ args.push_back("--oat-file=" + odex_location);
args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(filter));
+ args.push_back("--runtime-arg");
+ args.push_back("-Xnorelocate");
- // We need to use the quick compiler to generate non-PIC code, because
- // the optimizing compiler always generates PIC.
- args.push_back("--compiler-backend=Quick");
- args.push_back("--include-patch-information");
+ if (pic) {
+ args.push_back("--compile-pic");
+ }
+
+ if (with_patch_info) {
+ args.push_back("--include-patch-information");
+ }
std::string error_msg;
ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
-
- // Use patchoat to unrelocate the relocated odex file.
- Runtime* runtime = Runtime::Current();
- std::vector<std::string> argv;
- argv.push_back(runtime->GetPatchoatExecutable());
- argv.push_back("--instruction-set=" + std::string(GetInstructionSetString(kRuntimeISA)));
- argv.push_back("--input-oat-file=" + relocated_odex_location);
- argv.push_back("--output-oat-file=" + odex_location);
- argv.push_back("--base-offset-delta=0x00008000");
- std::string command_line(Join(argv, ' '));
- ASSERT_TRUE(Exec(argv, &error_msg)) << error_msg;
+ setenv("ANDROID_DATA", android_data_.c_str(), 1);
// Verify the odex file was generated as expected and really is
// unrelocated.
@@ -229,13 +254,13 @@
dex_location.c_str(),
&error_msg));
ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
- EXPECT_FALSE(odex_file->IsPic());
- EXPECT_TRUE(odex_file->HasPatchInfo());
+ EXPECT_EQ(pic, odex_file->IsPic());
+ EXPECT_EQ(with_patch_info, odex_file->HasPatchInfo());
EXPECT_EQ(filter, odex_file->GetCompilerFilter());
if (CompilerFilter::IsBytecodeCompilationEnabled(filter)) {
const std::vector<gc::space::ImageSpace*> image_spaces =
- runtime->GetHeap()->GetBootImageSpaces();
+ Runtime::Current()->GetHeap()->GetBootImageSpaces();
ASSERT_TRUE(!image_spaces.empty() && image_spaces[0] != nullptr);
const ImageHeader& image_header = image_spaces[0]->GetImageHeader();
const OatHeader& oat_header = odex_file->GetOatHeader();
@@ -250,71 +275,15 @@
void GeneratePicOdexForTest(const std::string& dex_location,
const std::string& odex_location,
CompilerFilter::Filter filter) {
- // Temporarily redirect the dalvik cache so dex2oat doesn't find the
- // relocated image file.
- std::string android_data_tmp = GetScratchDir() + "AndroidDataTmp";
- setenv("ANDROID_DATA", android_data_tmp.c_str(), 1);
- std::vector<std::string> args;
- args.push_back("--dex-file=" + dex_location);
- args.push_back("--oat-file=" + odex_location);
- args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(filter));
- args.push_back("--compile-pic");
- args.push_back("--runtime-arg");
- args.push_back("-Xnorelocate");
- std::string error_msg;
- ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
- setenv("ANDROID_DATA", android_data_.c_str(), 1);
-
- // Verify the odex file was generated as expected.
- std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
- odex_location.c_str(),
- nullptr,
- nullptr,
- false,
- /*low_4gb*/false,
- dex_location.c_str(),
- &error_msg));
- ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
- EXPECT_TRUE(odex_file->IsPic());
- EXPECT_EQ(filter, odex_file->GetCompilerFilter());
+ GenerateOdexForTest(dex_location, odex_location, filter, true, false);
}
// Generate a non-PIC odex file without patch information for the purposes
// of test. The generated odex file will be un-relocated.
- // TODO: This won't work correctly if we depend on the boot image being
- // randomly relocated by a non-zero amount. We should have a better solution
- // for avoiding that flakiness and duplicating code to generate odex and oat
- // files for test.
void GenerateNoPatchOdexForTest(const std::string& dex_location,
const std::string& odex_location,
CompilerFilter::Filter filter) {
- // Temporarily redirect the dalvik cache so dex2oat doesn't find the
- // relocated image file.
- std::string android_data_tmp = GetScratchDir() + "AndroidDataTmp";
- setenv("ANDROID_DATA", android_data_tmp.c_str(), 1);
- std::vector<std::string> args;
- args.push_back("--dex-file=" + dex_location);
- args.push_back("--oat-file=" + odex_location);
- args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(filter));
- args.push_back("--runtime-arg");
- args.push_back("-Xnorelocate");
- std::string error_msg;
- ASSERT_TRUE(OatFileAssistant::Dex2Oat(args, &error_msg)) << error_msg;
- setenv("ANDROID_DATA", android_data_.c_str(), 1);
-
- // Verify the odex file was generated as expected.
- std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
- odex_location.c_str(),
- nullptr,
- nullptr,
- false,
- /*low_4gb*/false,
- dex_location.c_str(),
- &error_msg));
- ASSERT_TRUE(odex_file.get() != nullptr) << error_msg;
- EXPECT_FALSE(odex_file->IsPic());
- EXPECT_FALSE(odex_file->HasPatchInfo());
- EXPECT_EQ(filter, odex_file->GetCompilerFilter());
+ GenerateOdexForTest(dex_location, odex_location, filter, false, false);
}
private:
@@ -326,11 +295,10 @@
MemMap::Init();
// Ensure a chunk of memory is reserved for the image space.
- uintptr_t reservation_start = ART_BASE_ADDRESS + ART_BASE_ADDRESS_MIN_DELTA;
- uintptr_t reservation_end = ART_BASE_ADDRESS + ART_BASE_ADDRESS_MAX_DELTA
- // Include the main space that has to come right after the
- // image in case of the GSS collector.
- + 384 * MB;
+ // The reservation_end includes room for the main space that has to come
+ // right after the image in case of the GSS collector.
+ uintptr_t reservation_start = ART_BASE_ADDRESS;
+ uintptr_t reservation_end = ART_BASE_ADDRESS + 384 * MB;
std::unique_ptr<BacktraceMap> map(BacktraceMap::Create(getpid(), true));
ASSERT_TRUE(map.get() != nullptr) << "Failed to build process map";