summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/Android.gtest.mk33
-rw-r--r--dex2oat/dex2oat.cc64
-rw-r--r--dex2oat/dex2oat_test.cc287
-rw-r--r--runtime/common_runtime_test.cc2
-rw-r--r--runtime/common_runtime_test.h2
-rw-r--r--runtime/dex2oat_environment_test.h188
-rw-r--r--runtime/oat_file_assistant_test.cc151
7 files changed, 550 insertions, 177 deletions
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index c09116ff5d..424aa7a7eb 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -65,15 +65,18 @@ $(ART_TEST_TARGET_GTEST_MainStripped_DEX): $(ART_TEST_TARGET_GTEST_Main_DEX)
$(call dexpreopt-remove-classes.dex,$@)
# Dex file dependencies for each gtest.
+ART_GTEST_dex2oat_environment_tests_DEX_DEPS := Main MainStripped MultiDex MultiDexModifiedSecondary Nested
+
ART_GTEST_class_linker_test_DEX_DEPS := Interfaces MultiDex MyClass Nested Statics StaticsFromCode
ART_GTEST_compiler_driver_test_DEX_DEPS := AbstractMethod StaticLeafMethods ProfileTestMultiDex
ART_GTEST_dex_cache_test_DEX_DEPS := Main
ART_GTEST_dex_file_test_DEX_DEPS := GetMethodSignature Main Nested
+ART_GTEST_dex2oat_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS)
ART_GTEST_exception_test_DEX_DEPS := ExceptionHandle
ART_GTEST_instrumentation_test_DEX_DEPS := Instrumentation
ART_GTEST_jni_compiler_test_DEX_DEPS := MyClassNatives
ART_GTEST_jni_internal_test_DEX_DEPS := AllFields StaticLeafMethods
-ART_GTEST_oat_file_assistant_test_DEX_DEPS := Main MainStripped MultiDex MultiDexModifiedSecondary Nested
+ART_GTEST_oat_file_assistant_test_DEX_DEPS := $(ART_GTEST_dex2oat_environment_tests_DEX_DEPS)
ART_GTEST_oat_file_test_DEX_DEPS := Main MultiDex
ART_GTEST_oat_test_DEX_DEPS := Main
ART_GTEST_object_test_DEX_DEPS := ProtoCompare ProtoCompare2 StaticsFromCode XandY
@@ -89,14 +92,25 @@ ART_GTEST_type_lookup_table_test_DEX_DEPS := Lookup
ART_GTEST_elf_writer_test_HOST_DEPS := $(HOST_CORE_IMAGE_default_no-pic_64) $(HOST_CORE_IMAGE_default_no-pic_32)
ART_GTEST_elf_writer_test_TARGET_DEPS := $(TARGET_CORE_IMAGE_default_no-pic_64) $(TARGET_CORE_IMAGE_default_no-pic_32)
-ART_GTEST_oat_file_assistant_test_HOST_DEPS := \
+ART_GTEST_dex2oat_environment_tests_HOST_DEPS := \
$(HOST_CORE_IMAGE_default_no-pic_64) \
- $(HOST_CORE_IMAGE_default_no-pic_32) \
- $(HOST_OUT_EXECUTABLES)/patchoatd
-ART_GTEST_oat_file_assistant_test_TARGET_DEPS := \
+ $(HOST_CORE_IMAGE_default_no-pic_32)
+ART_GTEST_dex2oat_environment_tests_TARGET_DEPS := \
$(TARGET_CORE_IMAGE_default_no-pic_64) \
- $(TARGET_CORE_IMAGE_default_no-pic_32) \
- $(TARGET_OUT_EXECUTABLES)/patchoatd
+ $(TARGET_CORE_IMAGE_default_no-pic_32)
+
+ART_GTEST_oat_file_assistant_test_HOST_DEPS := \
+ $(ART_GTEST_dex2oat_environment_tests_HOST_DEPS) \
+ $(HOST_OUT_EXECUTABLES)/patchoatd
+ART_GTEST_oat_file_assistant_test_TARGET_DEPS := \
+ $(ART_GTEST_dex2oat_environment_tests_TARGET_DEPS) \
+ $(TARGET_OUT_EXECUTABLES)/patchoatd
+
+
+ART_GTEST_dex2oat_test_HOST_DEPS := \
+ $(ART_GTEST_dex2oat_environment_tests_HOST_DEPS)
+ART_GTEST_dex2oat_test_TARGET_DEPS := \
+ $(ART_GTEST_dex2oat_environment_tests_TARGET_DEPS)
# TODO: document why this is needed.
ART_GTEST_proxy_test_HOST_DEPS := $(HOST_CORE_IMAGE_default_no-pic_64) $(HOST_CORE_IMAGE_default_no-pic_32)
@@ -157,6 +171,7 @@ RUNTIME_GTEST_COMMON_SRC_FILES := \
cmdline/cmdline_parser_test.cc \
dexdump/dexdump_test.cc \
dexlist/dexlist_test.cc \
+ dex2oat/dex2oat_test.cc \
imgdiag/imgdiag_test.cc \
oatdump/oatdump_test.cc \
profman/profile_assistant_test.cc \
@@ -808,11 +823,15 @@ ART_GTEST_jni_internal_test_DEX_DEPS :=
ART_GTEST_oat_file_assistant_test_DEX_DEPS :=
ART_GTEST_oat_file_assistant_test_HOST_DEPS :=
ART_GTEST_oat_file_assistant_test_TARGET_DEPS :=
+ART_GTEST_dex2oat_test_DEX_DEPS :=
+ART_GTEST_dex2oat_test_HOST_DEPS :=
+ART_GTEST_dex2oat_test_TARGET_DEPS :=
ART_GTEST_object_test_DEX_DEPS :=
ART_GTEST_proxy_test_DEX_DEPS :=
ART_GTEST_reflection_test_DEX_DEPS :=
ART_GTEST_stub_test_DEX_DEPS :=
ART_GTEST_transaction_test_DEX_DEPS :=
+ART_GTEST_dex2oat_environment_tests_DEX_DEPS :=
ART_VALGRIND_DEPENDENCIES :=
ART_VALGRIND_TARGET_DEPENDENCIES :=
$(foreach dir,$(GTEST_DEX_DIRECTORIES), $(eval ART_TEST_TARGET_GTEST_$(dir)_DEX :=))
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 24a4d586a2..437aba7ad1 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -81,6 +81,9 @@
namespace art {
+static constexpr size_t kDefaultMinDexFilesForSwap = 2;
+static constexpr size_t kDefaultMinDexFileCumulativeSizeForSwap = 20 * MB;
+
static int original_argc;
static char** original_argv;
@@ -351,6 +354,16 @@ NO_RETURN static void Usage(const char* fmt, ...) {
UsageError(" --swap-fd=<file-descriptor>: specifies a file to use for swap (by descriptor).");
UsageError(" Example: --swap-fd=10");
UsageError("");
+ UsageError(" --swap-dex-size-threshold=<size>: specifies the minimum total dex file size in");
+ UsageError(" bytes to allow the use of swap.");
+ UsageError(" Example: --swap-dex-size-threshold=1000000");
+ UsageError(" Default: %zu", kDefaultMinDexFileCumulativeSizeForSwap);
+ UsageError("");
+ UsageError(" --swap-dex-count-threshold=<count>: specifies the minimum number of dex files to");
+ UsageError(" allow the use of swap.");
+ UsageError(" Example: --swap-dex-count-threshold=10");
+ UsageError(" Default: %zu", kDefaultMinDexFilesForSwap);
+ UsageError("");
UsageError(" --app-image-fd=<file-descriptor>: specify output file descriptor for app image.");
UsageError(" Example: --app-image-fd=10");
UsageError("");
@@ -473,25 +486,6 @@ class WatchDog {
pthread_t pthread_;
};
-static constexpr size_t kMinDexFilesForSwap = 2;
-static constexpr size_t kMinDexFileCumulativeSizeForSwap = 20 * MB;
-
-static bool UseSwap(bool is_image, std::vector<const DexFile*>& dex_files) {
- if (is_image) {
- // Don't use swap, we know generation should succeed, and we don't want to slow it down.
- return false;
- }
- if (dex_files.size() < kMinDexFilesForSwap) {
- // If there are less dex files than the threshold, assume it's gonna be fine.
- return false;
- }
- size_t dex_files_size = 0;
- for (const auto* dex_file : dex_files) {
- dex_files_size += dex_file->GetHeader().file_size_;
- }
- return dex_files_size >= kMinDexFileCumulativeSizeForSwap;
-}
-
class Dex2Oat FINAL {
public:
explicit Dex2Oat(TimingLogger* timings) :
@@ -1132,6 +1126,16 @@ class Dex2Oat FINAL {
swap_file_name_ = option.substr(strlen("--swap-file=")).data();
} else if (option.starts_with("--swap-fd=")) {
ParseUintOption(option, "--swap-fd", &swap_fd_, Usage);
+ } else if (option.starts_with("--swap-dex-size-threshold=")) {
+ ParseUintOption(option,
+ "--swap-dex-size-threshold",
+ &min_dex_file_cumulative_size_for_swap_,
+ Usage);
+ } else if (option.starts_with("--swap-dex-count-threshold=")) {
+ ParseUintOption(option,
+ "--swap-dex-count-threshold",
+ &min_dex_files_for_swap_,
+ Usage);
} else if (option.starts_with("--app-image-file=")) {
app_image_file_name_ = option.substr(strlen("--app-image-file=")).data();
} else if (option.starts_with("--app-image-fd=")) {
@@ -1842,10 +1846,6 @@ class Dex2Oat FINAL {
}
}
- CompilerOptions* GetCompilerOptions() const {
- return compiler_options_.get();
- }
-
bool IsImage() const {
return IsAppImage() || IsBootImage();
}
@@ -1897,6 +1897,22 @@ class Dex2Oat FINAL {
}
private:
+ bool UseSwap(bool is_image, const std::vector<const DexFile*>& dex_files) {
+ if (is_image) {
+ // Don't use swap, we know generation should succeed, and we don't want to slow it down.
+ return false;
+ }
+ if (dex_files.size() < min_dex_files_for_swap_) {
+ // If there are less dex files than the threshold, assume it's gonna be fine.
+ return false;
+ }
+ size_t dex_files_size = 0;
+ for (const auto* dex_file : dex_files) {
+ dex_files_size += dex_file->GetHeader().file_size_;
+ }
+ return dex_files_size >= min_dex_file_cumulative_size_for_swap_;
+ }
+
template <typename T>
static std::vector<T*> MakeNonOwningPointerVector(const std::vector<std::unique_ptr<T>>& src) {
std::vector<T*> result;
@@ -2486,6 +2502,8 @@ class Dex2Oat FINAL {
bool dump_slow_timing_;
std::string swap_file_name_;
int swap_fd_;
+ size_t min_dex_files_for_swap_ = kDefaultMinDexFilesForSwap;
+ size_t min_dex_file_cumulative_size_for_swap_ = kDefaultMinDexFileCumulativeSizeForSwap;
std::string app_image_file_name_;
int app_image_fd_;
std::string profile_file_;
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
new file mode 100644
index 0000000000..de3aed9d05
--- /dev/null
+++ b/dex2oat/dex2oat_test.cc
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2016 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 <string>
+#include <vector>
+#include <sstream>
+
+#include "common_runtime_test.h"
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/stringprintf.h"
+#include "dex2oat_environment_test.h"
+#include "utils.h"
+
+#include <sys/wait.h>
+#include <unistd.h>
+
+namespace art {
+
+class Dex2oatTest : public Dex2oatEnvironmentTest {
+ public:
+ virtual void TearDown() OVERRIDE {
+ Dex2oatEnvironmentTest::TearDown();
+
+ output_ = "";
+ error_msg_ = "";
+ success_ = false;
+ }
+
+ protected:
+ void GenerateOdexForTest(const std::string& dex_location,
+ const std::string& odex_location,
+ CompilerFilter::Filter filter,
+ const std::vector<std::string>& extra_args = {},
+ bool expect_success = true) {
+ 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");
+
+ args.insert(args.end(), extra_args.begin(), extra_args.end());
+
+ std::string error_msg;
+ bool success = Dex2Oat(args, &error_msg);
+
+ if (expect_success) {
+ ASSERT_TRUE(success) << error_msg;
+
+ // 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;
+
+ CheckFilter(filter, odex_file->GetCompilerFilter());
+ } else {
+ ASSERT_FALSE(success) << output_;
+
+ error_msg_ = error_msg;
+
+ // Verify there's no loadable odex file.
+ 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);
+ }
+ }
+
+ // Check the input compiler filter against the generated oat file's filter. Mayb be overridden
+ // in subclasses when equality is not expected.
+ virtual void CheckFilter(CompilerFilter::Filter expected, CompilerFilter::Filter actual) {
+ EXPECT_EQ(expected, actual);
+ }
+
+ bool Dex2Oat(const std::vector<std::string>& dex2oat_args, std::string* error_msg) {
+ Runtime* runtime = Runtime::Current();
+
+ const std::vector<gc::space::ImageSpace*>& image_spaces =
+ runtime->GetHeap()->GetBootImageSpaces();
+ if (image_spaces.empty()) {
+ *error_msg = "No image location found for Dex2Oat.";
+ return false;
+ }
+ std::string image_location = image_spaces[0]->GetImageLocation();
+
+ std::vector<std::string> argv;
+ argv.push_back(runtime->GetCompilerExecutable());
+ argv.push_back("--runtime-arg");
+ argv.push_back("-classpath");
+ argv.push_back("--runtime-arg");
+ std::string class_path = runtime->GetClassPathString();
+ if (class_path == "") {
+ class_path = OatFile::kSpecialSharedLibrary;
+ }
+ argv.push_back(class_path);
+ if (runtime->IsDebuggable()) {
+ argv.push_back("--debuggable");
+ }
+ runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
+
+ if (!runtime->IsVerificationEnabled()) {
+ argv.push_back("--compiler-filter=verify-none");
+ }
+
+ if (runtime->MustRelocateIfPossible()) {
+ argv.push_back("--runtime-arg");
+ argv.push_back("-Xrelocate");
+ } else {
+ argv.push_back("--runtime-arg");
+ argv.push_back("-Xnorelocate");
+ }
+
+ if (!kIsTargetBuild) {
+ argv.push_back("--host");
+ }
+
+ argv.push_back("--boot-image=" + image_location);
+
+ std::vector<std::string> compiler_options = runtime->GetCompilerOptions();
+ argv.insert(argv.end(), compiler_options.begin(), compiler_options.end());
+
+ argv.insert(argv.end(), dex2oat_args.begin(), dex2oat_args.end());
+
+ // We must set --android-root.
+ const char* android_root = getenv("ANDROID_ROOT");
+ CHECK(android_root != nullptr);
+ argv.push_back("--android-root=" + std::string(android_root));
+
+ std::string command_line(Join(argv, ' '));
+
+ // We need to fix up the '&' being used for "do not check classpath."
+ size_t ampersand = command_line.find(" &");
+ CHECK_NE(ampersand, std::string::npos);
+ command_line = command_line.replace(ampersand, 2, " \\&");
+
+ command_line += " 2>&1";
+
+ // We need dex2oat to actually log things.
+ setenv("ANDROID_LOG_TAGS", "*:d", 1);
+
+ FILE* pipe = popen(command_line.c_str(), "r");
+
+ setenv("ANDROID_LOG_TAGS", "*:e", 1);
+
+ if (pipe == nullptr) {
+ success_ = false;
+ } else {
+ char buffer[128];
+
+ while (fgets(buffer, 128, pipe) != nullptr) {
+ output_ += buffer;
+ }
+
+ int result = pclose(pipe);
+ success_ = result == 0;
+ }
+ return success_;
+ }
+
+ std::string output_ = "";
+ std::string error_msg_ = "";
+ bool success_ = false;
+};
+
+class Dex2oatSwapTest : public Dex2oatTest {
+ protected:
+ void RunTest(bool use_fd, bool expect_use, const std::vector<std::string>& extra_args = {}) {
+ std::string dex_location = GetScratchDir() + "/Dex2OatSwapTest.jar";
+ std::string odex_location = GetOdexDir() + "/Dex2OatSwapTest.odex";
+
+ Copy(GetDexSrc1(), dex_location);
+
+ std::vector<std::string> copy(extra_args);
+
+ std::unique_ptr<ScratchFile> sf;
+ if (use_fd) {
+ sf.reset(new ScratchFile());
+ copy.push_back(StringPrintf("--swap-fd=%d", sf->GetFd()));
+ } else {
+ std::string swap_location = GetOdexDir() + "/Dex2OatSwapTest.odex.swap";
+ copy.push_back("--swap-file=" + swap_location);
+ }
+ GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed, copy);
+
+ CheckValidity();
+ ASSERT_TRUE(success_);
+ CheckResult(expect_use);
+ }
+
+ void CheckResult(bool expect_use) {
+ if (kIsTargetBuild) {
+ CheckTargetResult(expect_use);
+ } else {
+ CheckHostResult(expect_use);
+ }
+ }
+
+ void CheckTargetResult(bool expect_use ATTRIBUTE_UNUSED) {
+ // TODO: Ignore for now, as we won't capture any output (it goes to the logcat). We may do
+ // something for variants with file descriptor where we can control the lifetime of
+ // the swap file and thus take a look at it.
+ }
+
+ void CheckHostResult(bool expect_use) {
+ if (!kIsTargetBuild) {
+ if (expect_use) {
+ EXPECT_NE(output_.find("Large app, accepted running with swap."), std::string::npos)
+ << output_;
+ } else {
+ EXPECT_EQ(output_.find("Large app, accepted running with swap."), std::string::npos)
+ << output_;
+ }
+ }
+ }
+
+ // Check whether the dex2oat run was really successful.
+ void CheckValidity() {
+ if (kIsTargetBuild) {
+ CheckTargetValidity();
+ } else {
+ CheckHostValidity();
+ }
+ }
+
+ void CheckTargetValidity() {
+ // TODO: Ignore for now, as we won't capture any output (it goes to the logcat). We may do
+ // something for variants with file descriptor where we can control the lifetime of
+ // the swap file and thus take a look at it.
+ }
+
+ // On the host, we can get the dex2oat output. Here, look for "dex2oat took."
+ void CheckHostValidity() {
+ EXPECT_NE(output_.find("dex2oat took"), std::string::npos) << output_;
+ }
+};
+
+TEST_F(Dex2oatSwapTest, DoNotUseSwapDefaultSingleSmall) {
+ RunTest(false /* use_fd */, false /* expect_use */);
+ RunTest(true /* use_fd */, false /* expect_use */);
+}
+
+TEST_F(Dex2oatSwapTest, DoNotUseSwapSingle) {
+ RunTest(false /* use_fd */, false /* expect_use */, { "--swap-dex-size-threshold=0" });
+ RunTest(true /* use_fd */, false /* expect_use */, { "--swap-dex-size-threshold=0" });
+}
+
+TEST_F(Dex2oatSwapTest, DoNotUseSwapSmall) {
+ RunTest(false /* use_fd */, false /* expect_use */, { "--swap-dex-count-threshold=0" });
+ RunTest(true /* use_fd */, false /* expect_use */, { "--swap-dex-count-threshold=0" });
+}
+
+TEST_F(Dex2oatSwapTest, DoUseSwapSingleSmall) {
+ RunTest(false /* use_fd */,
+ true /* expect_use */,
+ { "--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0" });
+ RunTest(true /* use_fd */,
+ true /* expect_use */,
+ { "--swap-dex-size-threshold=0", "--swap-dex-count-threshold=0" });
+}
+
+} // namespace art
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 3509d9aef9..741b682996 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -463,7 +463,7 @@ std::string CommonRuntimeTestImpl::GetTestAndroidRoot() {
#define ART_TARGET_NATIVETEST_DIR_STRING ""
#endif
-std::string CommonRuntimeTestImpl::GetTestDexFileName(const char* name) {
+std::string CommonRuntimeTestImpl::GetTestDexFileName(const char* name) const {
CHECK(name != nullptr);
std::string filename;
if (IsHost()) {
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index 0ce40e8e22..b68eb19f2a 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -111,7 +111,7 @@ class CommonRuntimeTestImpl {
std::string GetTestAndroidRoot();
- std::string GetTestDexFileName(const char* name);
+ std::string GetTestDexFileName(const char* name) const;
std::vector<std::unique_ptr<const DexFile>> OpenTestDexFiles(const char* name)
SHARED_REQUIRES(Locks::mutator_lock_);
diff --git a/runtime/dex2oat_environment_test.h b/runtime/dex2oat_environment_test.h
new file mode 100644
index 0000000000..743fbb9c68
--- /dev/null
+++ b/runtime/dex2oat_environment_test.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef ART_RUNTIME_DEX2OAT_ENVIRONMENT_TEST_H_
+#define ART_RUNTIME_DEX2OAT_ENVIRONMENT_TEST_H_
+
+#include <fstream>
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "common_runtime_test.h"
+#include "compiler_callbacks.h"
+#include "gc/heap.h"
+#include "gc/space/image_space.h"
+#include "oat_file_assistant.h"
+#include "os.h"
+#include "runtime.h"
+#include "utils.h"
+
+namespace art {
+
+// Test class that provides some helpers to set a test up for compilation using dex2oat.
+class Dex2oatEnvironmentTest : public CommonRuntimeTest {
+ public:
+ virtual void SetUp() OVERRIDE {
+ CommonRuntimeTest::SetUp();
+
+ // Create a scratch directory to work from.
+ scratch_dir_ = android_data_ + "/Dex2oatEnvironmentTest";
+ ASSERT_EQ(0, mkdir(scratch_dir_.c_str(), 0700));
+
+ // Create a subdirectory in scratch for odex files.
+ odex_oat_dir_ = scratch_dir_ + "/oat";
+ ASSERT_EQ(0, mkdir(odex_oat_dir_.c_str(), 0700));
+
+ 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(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()))
+ << "Expected stripped dex file to be at: " << GetStrippedDexSrc1();
+ ASSERT_FALSE(DexFile::GetChecksum(GetStrippedDexSrc1().c_str(), &checksum, &error_msg))
+ << "Expected stripped dex file to be stripped: " << GetStrippedDexSrc1();
+ ASSERT_TRUE(OS::FileExists(GetDexSrc2().c_str()))
+ << "Expected dex file to be at: " << GetDexSrc2();
+
+ // GetMultiDexSrc2 should have the same primary dex checksum as
+ // GetMultiDexSrc1, but a different secondary dex checksum.
+ static constexpr bool kVerifyChecksum = true;
+ std::vector<std::unique_ptr<const DexFile>> multi1;
+ ASSERT_TRUE(DexFile::Open(GetMultiDexSrc1().c_str(),
+ GetMultiDexSrc1().c_str(), kVerifyChecksum, &error_msg, &multi1)) << error_msg;
+ ASSERT_GT(multi1.size(), 1u);
+
+ std::vector<std::unique_ptr<const DexFile>> multi2;
+ ASSERT_TRUE(DexFile::Open(GetMultiDexSrc2().c_str(),
+ GetMultiDexSrc2().c_str(), kVerifyChecksum, &error_msg, &multi2)) << error_msg;
+ ASSERT_GT(multi2.size(), 1u);
+
+ ASSERT_EQ(multi1[0]->GetLocationChecksum(), multi2[0]->GetLocationChecksum());
+ ASSERT_NE(multi1[1]->GetLocationChecksum(), multi2[1]->GetLocationChecksum());
+ }
+
+ virtual void SetUpRuntimeOptions(RuntimeOptions* options) OVERRIDE {
+ // options->push_back(std::make_pair("-verbose:oat", nullptr));
+
+ // Set up the image location.
+ options->push_back(std::make_pair("-Ximage:" + GetImageLocation(),
+ nullptr));
+ // Make sure compilercallbacks are not set so that relocation will be
+ // enabled.
+ callbacks_.reset();
+ }
+
+ virtual void TearDown() OVERRIDE {
+ ClearDirectory(odex_dir_.c_str());
+ ASSERT_EQ(0, rmdir(odex_dir_.c_str()));
+
+ ClearDirectory(odex_oat_dir_.c_str());
+ ASSERT_EQ(0, rmdir(odex_oat_dir_.c_str()));
+
+ ClearDirectory(scratch_dir_.c_str());
+ ASSERT_EQ(0, rmdir(scratch_dir_.c_str()));
+
+ CommonRuntimeTest::TearDown();
+ }
+
+ static void Copy(const std::string& src, const std::string& dst) {
+ std::ifstream src_stream(src, std::ios::binary);
+ std::ofstream dst_stream(dst, std::ios::binary);
+
+ dst_stream << src_stream.rdbuf();
+ }
+
+ // Returns the directory where the pre-compiled core.art can be found.
+ // TODO: We should factor out this into common tests somewhere rather than
+ // re-hardcoding it here (This was copied originally from the elf writer
+ // test).
+ std::string GetImageDirectory() const {
+ if (IsHost()) {
+ const char* host_dir = getenv("ANDROID_HOST_OUT");
+ CHECK(host_dir != nullptr);
+ return std::string(host_dir) + "/framework";
+ } else {
+ return std::string("/data/art-test");
+ }
+ }
+
+ std::string GetImageLocation() const {
+ return GetImageDirectory() + "/core.art";
+ }
+
+ std::string GetSystemImageFile() const {
+ return GetImageDirectory() + "/" + GetInstructionSetString(kRuntimeISA)
+ + "/core.art";
+ }
+
+ bool GetCachedImageFile(/*out*/std::string* image, std::string* error_msg) const {
+ std::string cache = GetDalvikCache(GetInstructionSetString(kRuntimeISA), true);
+ return GetDalvikCacheFilename(GetImageLocation().c_str(), cache.c_str(), image, error_msg);
+ }
+
+ std::string GetDexSrc1() const {
+ return GetTestDexFileName("Main");
+ }
+
+ // Returns the path to a dex file equivalent to GetDexSrc1, but with the dex
+ // file stripped.
+ std::string GetStrippedDexSrc1() const {
+ return GetTestDexFileName("MainStripped");
+ }
+
+ std::string GetMultiDexSrc1() const {
+ return GetTestDexFileName("MultiDex");
+ }
+
+ // Returns the path to a multidex file equivalent to GetMultiDexSrc2, but
+ // with the contents of the secondary dex file changed.
+ std::string GetMultiDexSrc2() const {
+ return GetTestDexFileName("MultiDexModifiedSecondary");
+ }
+
+ std::string GetDexSrc2() const {
+ return GetTestDexFileName("Nested");
+ }
+
+ // Scratch directory, for dex and odex files (oat files will go in the
+ // dalvik cache).
+ const std::string& GetScratchDir() const {
+ return scratch_dir_;
+ }
+
+ // Odex directory is the subdirectory in the scratch directory where odex
+ // files should be located.
+ const std::string& GetOdexDir() const {
+ return odex_dir_;
+ }
+
+ private:
+ std::string scratch_dir_;
+ std::string odex_oat_dir_;
+ std::string odex_dir_;
+};
+
+} // namespace art
+
+#endif // ART_RUNTIME_DEX2OAT_ENVIRONMENT_TEST_H_
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index e3cc77f2c0..a1d3ed9241 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -14,8 +14,6 @@
* limitations under the License.
*/
-#include "oat_file_assistant.h"
-
#include <algorithm>
#include <fstream>
#include <string>
@@ -29,8 +27,10 @@
#include "class_linker-inl.h"
#include "common_runtime_test.h"
#include "compiler_callbacks.h"
+#include "dex2oat_environment_test.h"
#include "gc/space/image_space.h"
#include "mem_map.h"
+#include "oat_file_assistant.h"
#include "oat_file_manager.h"
#include "os.h"
#include "scoped_thread_state_change.h"
@@ -39,52 +39,11 @@
namespace art {
-class OatFileAssistantTest : public CommonRuntimeTest {
+class OatFileAssistantTest : public Dex2oatEnvironmentTest {
public:
- virtual void SetUp() {
+ virtual void SetUp() OVERRIDE {
ReserveImageSpace();
- CommonRuntimeTest::SetUp();
-
- // Create a scratch directory to work from.
- scratch_dir_ = android_data_ + "/OatFileAssistantTest";
- ASSERT_EQ(0, mkdir(scratch_dir_.c_str(), 0700));
-
- // Create a subdirectory in scratch for odex files.
- odex_oat_dir_ = scratch_dir_ + "/oat";
- ASSERT_EQ(0, mkdir(odex_oat_dir_.c_str(), 0700));
-
- 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(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()))
- << "Expected stripped dex file to be at: " << GetStrippedDexSrc1();
- ASSERT_FALSE(DexFile::GetChecksum(GetStrippedDexSrc1().c_str(), &checksum, &error_msg))
- << "Expected stripped dex file to be stripped: " << GetStrippedDexSrc1();
- ASSERT_TRUE(OS::FileExists(GetDexSrc2().c_str()))
- << "Expected dex file to be at: " << GetDexSrc2();
-
- // GetMultiDexSrc2 should have the same primary dex checksum as
- // GetMultiDexSrc1, but a different secondary dex checksum.
- static constexpr bool kVerifyChecksum = true;
- std::vector<std::unique_ptr<const DexFile>> multi1;
- ASSERT_TRUE(DexFile::Open(GetMultiDexSrc1().c_str(),
- GetMultiDexSrc1().c_str(), kVerifyChecksum, &error_msg, &multi1)) << error_msg;
- ASSERT_GT(multi1.size(), 1u);
-
- std::vector<std::unique_ptr<const DexFile>> multi2;
- ASSERT_TRUE(DexFile::Open(GetMultiDexSrc2().c_str(),
- GetMultiDexSrc2().c_str(), kVerifyChecksum, &error_msg, &multi2)) << error_msg;
- ASSERT_GT(multi2.size(), 1u);
-
- ASSERT_EQ(multi1[0]->GetLocationChecksum(), multi2[0]->GetLocationChecksum());
- ASSERT_NE(multi1[1]->GetLocationChecksum(), multi2[1]->GetLocationChecksum());
+ Dex2oatEnvironmentTest::SetUp();
}
// Pre-Relocate the image to a known non-zero offset so we don't have to
@@ -108,17 +67,6 @@ class OatFileAssistantTest : public CommonRuntimeTest {
return Exec(argv, error_msg);
}
- virtual void SetUpRuntimeOptions(RuntimeOptions* options) {
- // options->push_back(std::make_pair("-verbose:oat", nullptr));
-
- // Set up the image location.
- options->push_back(std::make_pair("-Ximage:" + GetImageLocation(),
- nullptr));
- // Make sure compilercallbacks are not set so that relocation will be
- // enabled.
- callbacks_.reset();
- }
-
virtual void PreRuntimeCreate() {
std::string error_msg;
ASSERT_TRUE(PreRelocateImage(&error_msg)) << error_msg;
@@ -126,94 +74,10 @@ class OatFileAssistantTest : public CommonRuntimeTest {
UnreserveImageSpace();
}
- virtual void PostRuntimeCreate() {
+ virtual void PostRuntimeCreate() OVERRIDE {
ReserveImageSpace();
}
- virtual void TearDown() {
- ClearDirectory(odex_dir_.c_str());
- ASSERT_EQ(0, rmdir(odex_dir_.c_str()));
-
- ClearDirectory(odex_oat_dir_.c_str());
- ASSERT_EQ(0, rmdir(odex_oat_dir_.c_str()));
-
- ClearDirectory(scratch_dir_.c_str());
- ASSERT_EQ(0, rmdir(scratch_dir_.c_str()));
-
- CommonRuntimeTest::TearDown();
- }
-
- void Copy(std::string src, std::string dst) {
- std::ifstream src_stream(src, std::ios::binary);
- std::ofstream dst_stream(dst, std::ios::binary);
-
- dst_stream << src_stream.rdbuf();
- }
-
- // Returns the directory where the pre-compiled core.art can be found.
- // TODO: We should factor out this into common tests somewhere rather than
- // re-hardcoding it here (This was copied originally from the elf writer
- // test).
- std::string GetImageDirectory() {
- if (IsHost()) {
- const char* host_dir = getenv("ANDROID_HOST_OUT");
- CHECK(host_dir != nullptr);
- return std::string(host_dir) + "/framework";
- } else {
- return std::string("/data/art-test");
- }
- }
-
- std::string GetImageLocation() {
- return GetImageDirectory() + "/core.art";
- }
-
- 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");
- }
-
- // Returns the path to a dex file equivalent to GetDexSrc1, but with the dex
- // file stripped.
- std::string GetStrippedDexSrc1() {
- return GetTestDexFileName("MainStripped");
- }
-
- std::string GetMultiDexSrc1() {
- return GetTestDexFileName("MultiDex");
- }
-
- // Returns the path to a multidex file equivalent to GetMultiDexSrc2, but
- // with the contents of the secondary dex file changed.
- std::string GetMultiDexSrc2() {
- return GetTestDexFileName("MultiDexModifiedSecondary");
- }
-
- std::string GetDexSrc2() {
- return GetTestDexFileName("Nested");
- }
-
- // Scratch directory, for dex and odex files (oat files will go in the
- // dalvik cache).
- std::string GetScratchDir() {
- return scratch_dir_;
- }
-
- // Odex directory is the subdirectory in the scratch directory where odex
- // files should be located.
- std::string GetOdexDir() {
- return odex_dir_;
- }
-
// Generate a non-PIC odex file for the purposes of test.
// The generated odex file will be un-relocated.
void GenerateOdexForTest(const std::string& dex_location,
@@ -334,9 +198,6 @@ class OatFileAssistantTest : public CommonRuntimeTest {
image_reservation_.clear();
}
- std::string scratch_dir_;
- std::string odex_oat_dir_;
- std::string odex_dir_;
std::vector<std::unique_ptr<MemMap>> image_reservation_;
};