Break apart header files.
Create libart-gtest for common runtime and compiler gtest routines.
Rename CompilerCallbacksImpl that is quick compiler specific.
Rename trace clock source constants to not use the overloaded profiler term.
Change-Id: I4aac4bdc7e7850c68335f81e59a390133b54e933
diff --git a/runtime/common_runtime_test.h b/runtime/common_runtime_test.h
index ac6d44b..d045031 100644
--- a/runtime/common_runtime_test.h
+++ b/runtime/common_runtime_test.h
@@ -17,73 +17,33 @@
#ifndef ART_RUNTIME_COMMON_RUNTIME_TEST_H_
#define ART_RUNTIME_COMMON_RUNTIME_TEST_H_
-#include <dirent.h>
-#include <dlfcn.h>
-#include <stdlib.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <fstream>
-#include <memory>
+#include <gtest/gtest.h>
+#include <jni.h>
-#include "../../external/icu/icu4c/source/common/unicode/uvernum.h"
-#include "base/macros.h"
-#include "base/stl_util.h"
-#include "base/stringprintf.h"
-#include "base/unix_file/fd_file.h"
-#include "class_linker.h"
-#include "dex_file-inl.h"
-#include "entrypoints/entrypoint_utils.h"
-#include "gc/heap.h"
-#include "gtest/gtest.h"
-#include "instruction_set.h"
-#include "interpreter/interpreter.h"
-#include "mirror/class_loader.h"
-#include "noop_compiler_callbacks.h"
-#include "oat_file.h"
-#include "object_utils.h"
+#include <string>
+
+#include "base/mutex.h"
+#include "globals.h"
#include "os.h"
-#include "runtime.h"
-#include "scoped_thread_state_change.h"
-#include "ScopedLocalRef.h"
-#include "thread.h"
-#include "utils.h"
-#include "verifier/method_verifier.h"
-#include "verifier/method_verifier-inl.h"
-#include "well_known_classes.h"
namespace art {
+class ClassLinker;
+class CompilerCallbacks;
+class DexFile;
+class JavaVMExt;
+class Runtime;
+typedef std::vector<std::pair<std::string, const void*>> RuntimeOptions;
+
class ScratchFile {
public:
- ScratchFile() {
- // ANDROID_DATA needs to be set
- CHECK_NE(static_cast<char*>(nullptr), getenv("ANDROID_DATA")) <<
- "Are you subclassing RuntimeTest?";
- filename_ = getenv("ANDROID_DATA");
- filename_ += "/TmpFile-XXXXXX";
- int fd = mkstemp(&filename_[0]);
- CHECK_NE(-1, fd);
- file_.reset(new File(fd, GetFilename()));
- }
+ ScratchFile();
- ScratchFile(const ScratchFile& other, const char* suffix) {
- filename_ = other.GetFilename();
- filename_ += suffix;
- int fd = open(filename_.c_str(), O_RDWR | O_CREAT, 0666);
- CHECK_NE(-1, fd);
- file_.reset(new File(fd, GetFilename()));
- }
+ ScratchFile(const ScratchFile& other, const char* suffix);
- explicit ScratchFile(File* file) {
- CHECK(file != NULL);
- filename_ = file->GetPath();
- file_.reset(file);
- }
+ explicit ScratchFile(File* file);
- ~ScratchFile() {
- Unlink();
- }
+ ~ScratchFile();
const std::string& GetFilename() const {
return filename_;
@@ -93,17 +53,9 @@
return file_.get();
}
- int GetFd() const {
- return file_->Fd();
- }
+ int GetFd() const;
- void Unlink() {
- if (!OS::FileExists(filename_.c_str())) {
- return;
- }
- int unlink_result = unlink(filename_.c_str());
- CHECK_EQ(0, unlink_result);
- }
+ void Unlink();
private:
std::string filename_;
@@ -112,222 +64,37 @@
class CommonRuntimeTest : public testing::Test {
public:
- static void SetEnvironmentVariables(std::string& android_data) {
- if (IsHost()) {
- // $ANDROID_ROOT is set on the device, but not necessarily on the host.
- // But it needs to be set so that icu4c can find its locale data.
- const char* android_root_from_env = getenv("ANDROID_ROOT");
- if (android_root_from_env == nullptr) {
- // Use ANDROID_HOST_OUT for ANDROID_ROOT if it is set.
- const char* android_host_out = getenv("ANDROID_HOST_OUT");
- if (android_host_out != nullptr) {
- setenv("ANDROID_ROOT", android_host_out, 1);
- } else {
- // Build it from ANDROID_BUILD_TOP or cwd
- std::string root;
- const char* android_build_top = getenv("ANDROID_BUILD_TOP");
- if (android_build_top != nullptr) {
- root += android_build_top;
- } else {
- // Not set by build server, so default to current directory
- char* cwd = getcwd(nullptr, 0);
- setenv("ANDROID_BUILD_TOP", cwd, 1);
- root += cwd;
- free(cwd);
- }
-#if defined(__linux__)
- root += "/out/host/linux-x86";
-#elif defined(__APPLE__)
- root += "/out/host/darwin-x86";
-#else
-#error unsupported OS
-#endif
- setenv("ANDROID_ROOT", root.c_str(), 1);
- }
- }
- setenv("LD_LIBRARY_PATH", ":", 0); // Required by java.lang.System.<clinit>.
+ static void SetEnvironmentVariables(std::string& android_data);
- // Not set by build server, so default
- if (getenv("ANDROID_HOST_OUT") == nullptr) {
- setenv("ANDROID_HOST_OUT", getenv("ANDROID_ROOT"), 1);
- }
- }
-
- // On target, Cannot use /mnt/sdcard because it is mounted noexec, so use subdir of dalvik-cache
- android_data = (IsHost() ? "/tmp/art-data-XXXXXX" : "/data/dalvik-cache/art-data-XXXXXX");
- if (mkdtemp(&android_data[0]) == nullptr) {
- PLOG(FATAL) << "mkdtemp(\"" << &android_data[0] << "\") failed";
- }
- setenv("ANDROID_DATA", android_data.c_str(), 1);
- }
+ CommonRuntimeTest();
+ ~CommonRuntimeTest();
protected:
static bool IsHost() {
return !kIsTargetBuild;
}
- const DexFile* LoadExpectSingleDexFile(const char* location) {
- std::vector<const DexFile*> dex_files;
- std::string error_msg;
- if (!DexFile::Open(location, location, &error_msg, &dex_files)) {
- LOG(FATAL) << "Could not open .dex file '" << location << "': " << error_msg << "\n";
- return nullptr;
- } else {
- CHECK_EQ(1U, dex_files.size()) << "Expected only one dex file in " << location;
- return dex_files[0];
- }
- }
+ const DexFile* LoadExpectSingleDexFile(const char* location);
- virtual void SetUp() {
- SetEnvironmentVariables(android_data_);
- dalvik_cache_.append(android_data_.c_str());
- dalvik_cache_.append("/dalvik-cache");
- int mkdir_result = mkdir(dalvik_cache_.c_str(), 0700);
- ASSERT_EQ(mkdir_result, 0);
-
- std::string error_msg;
- java_lang_dex_file_ = LoadExpectSingleDexFile(GetLibCoreDexFileName().c_str());
- boot_class_path_.push_back(java_lang_dex_file_);
-
- std::string min_heap_string(StringPrintf("-Xms%zdm", gc::Heap::kDefaultInitialSize / MB));
- std::string max_heap_string(StringPrintf("-Xmx%zdm", gc::Heap::kDefaultMaximumSize / MB));
-
- Runtime::Options options;
- options.push_back(std::make_pair("bootclasspath", &boot_class_path_));
- options.push_back(std::make_pair("-Xcheck:jni", nullptr));
- options.push_back(std::make_pair(min_heap_string.c_str(), nullptr));
- options.push_back(std::make_pair(max_heap_string.c_str(), nullptr));
- options.push_back(std::make_pair("compilercallbacks", &callbacks_));
- SetUpRuntimeOptions(&options);
- if (!Runtime::Create(options, false)) {
- LOG(FATAL) << "Failed to create runtime";
- return;
- }
- runtime_.reset(Runtime::Current());
- class_linker_ = runtime_->GetClassLinker();
- class_linker_->FixupDexCaches(runtime_->GetResolutionMethod());
- class_linker_->RunRootClinits();
-
- // Runtime::Create acquired the mutator_lock_ that is normally given away when we
- // Runtime::Start, give it away now and then switch to a more managable ScopedObjectAccess.
- Thread::Current()->TransitionFromRunnableToSuspended(kNative);
-
- // We're back in native, take the opportunity to initialize well known classes.
- WellKnownClasses::Init(Thread::Current()->GetJniEnv());
-
- // Create the heap thread pool so that the GC runs in parallel for tests. Normally, the thread
- // pool is created by the runtime.
- runtime_->GetHeap()->CreateThreadPool();
- runtime_->GetHeap()->VerifyHeap(); // Check for heap corruption before the test
- }
+ virtual void SetUp();
// Allow subclases such as CommonCompilerTest to add extra options.
- virtual void SetUpRuntimeOptions(Runtime::Options *options) {}
+ virtual void SetUpRuntimeOptions(RuntimeOptions* options) {}
- virtual void TearDown() {
- const char* android_data = getenv("ANDROID_DATA");
- ASSERT_TRUE(android_data != nullptr);
- DIR* dir = opendir(dalvik_cache_.c_str());
- ASSERT_TRUE(dir != nullptr);
- dirent* e;
- while ((e = readdir(dir)) != nullptr) {
- if ((strcmp(e->d_name, ".") == 0) || (strcmp(e->d_name, "..") == 0)) {
- continue;
- }
- std::string filename(dalvik_cache_);
- filename.push_back('/');
- filename.append(e->d_name);
- int unlink_result = unlink(filename.c_str());
- ASSERT_EQ(0, unlink_result);
- }
- closedir(dir);
- int rmdir_cache_result = rmdir(dalvik_cache_.c_str());
- ASSERT_EQ(0, rmdir_cache_result);
- int rmdir_data_result = rmdir(android_data_.c_str());
- ASSERT_EQ(0, rmdir_data_result);
+ virtual void TearDown();
- // icu4c has a fixed 10-element array "gCommonICUDataArray".
- // If we run > 10 tests, we fill that array and u_setCommonData fails.
- // There's a function to clear the array, but it's not public...
- typedef void (*IcuCleanupFn)();
- void* sym = dlsym(RTLD_DEFAULT, "u_cleanup_" U_ICU_VERSION_SHORT);
- CHECK(sym != nullptr) << dlerror();
- IcuCleanupFn icu_cleanup_fn = reinterpret_cast<IcuCleanupFn>(sym);
- (*icu_cleanup_fn)();
+ std::string GetLibCoreDexFileName();
- STLDeleteElements(&opened_dex_files_);
+ std::string GetDexFileName(const std::string& jar_prefix);
- Runtime::Current()->GetHeap()->VerifyHeap(); // Check for heap corruption after the test
- }
-
- std::string GetLibCoreDexFileName() {
- return GetDexFileName("core-libart");
- }
-
- std::string GetDexFileName(const std::string& jar_prefix) {
- if (IsHost()) {
- const char* host_dir = getenv("ANDROID_HOST_OUT");
- CHECK(host_dir != nullptr);
- return StringPrintf("%s/framework/%s-hostdex.jar", host_dir, jar_prefix.c_str());
- }
- return StringPrintf("%s/framework/%s.jar", GetAndroidRoot(), jar_prefix.c_str());
- }
-
- std::string GetTestAndroidRoot() {
- if (IsHost()) {
- const char* host_dir = getenv("ANDROID_HOST_OUT");
- CHECK(host_dir != nullptr);
- return host_dir;
- }
- return GetAndroidRoot();
- }
+ std::string GetTestAndroidRoot();
std::vector<const DexFile*> OpenTestDexFiles(const char* name)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- CHECK(name != nullptr);
- std::string filename;
- if (IsHost()) {
- filename += getenv("ANDROID_HOST_OUT");
- filename += "/framework/";
- } else {
- filename += "/data/nativetest/art/";
- }
- filename += "art-gtest-";
- filename += name;
- filename += ".jar";
- std::string error_msg;
- std::vector<const DexFile*> dex_files;
- bool success = DexFile::Open(filename.c_str(), filename.c_str(), &error_msg, &dex_files);
- CHECK(success) << "Failed to open '" << filename << "': " << error_msg;
- for (const DexFile* dex_file : dex_files) {
- CHECK_EQ(PROT_READ, dex_file->GetPermissions());
- CHECK(dex_file->IsReadOnly());
- }
- opened_dex_files_.insert(opened_dex_files_.end(), dex_files.begin(), dex_files.end());
- return dex_files;
- }
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- const DexFile* OpenTestDexFile(const char* name)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- std::vector<const DexFile*> vector = OpenTestDexFiles(name);
- EXPECT_EQ(1U, vector.size());
- return vector[0];
- }
+ const DexFile* OpenTestDexFile(const char* name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- jobject LoadDex(const char* dex_name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- std::vector<const DexFile*> dex_files = OpenTestDexFiles(dex_name);
- CHECK_NE(0U, dex_files.size());
- for (const DexFile* dex_file : dex_files) {
- class_linker_->RegisterDexFile(*dex_file);
- }
- ScopedObjectAccessUnchecked soa(Thread::Current());
- ScopedLocalRef<jobject> class_loader_local(soa.Env(),
- soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader));
- jobject class_loader = soa.Env()->NewGlobalRef(class_loader_local.get());
- soa.Self()->SetClassLoaderOverride(soa.Decode<mirror::ClassLoader*>(class_loader_local.get()));
- Runtime::Current()->SetCompileTimeClassPath(class_loader, dex_files);
- return class_loader;
- }
+ jobject LoadDex(const char* dex_name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
std::string android_data_;
std::string dalvik_cache_;
@@ -338,7 +105,7 @@
ClassLinker* class_linker_;
private:
- NoopCompilerCallbacks callbacks_;
+ std::unique_ptr<CompilerCallbacks> callbacks_;
std::vector<const DexFile*> opened_dex_files_;
};
@@ -346,29 +113,14 @@
// rather than aborting, so be careful!
class CheckJniAbortCatcher {
public:
- CheckJniAbortCatcher() : vm_(Runtime::Current()->GetJavaVM()) {
- vm_->check_jni_abort_hook = Hook;
- vm_->check_jni_abort_hook_data = &actual_;
- }
+ CheckJniAbortCatcher();
- ~CheckJniAbortCatcher() {
- vm_->check_jni_abort_hook = nullptr;
- vm_->check_jni_abort_hook_data = nullptr;
- EXPECT_TRUE(actual_.empty()) << actual_;
- }
+ ~CheckJniAbortCatcher();
- void Check(const char* expected_text) {
- EXPECT_TRUE(actual_.find(expected_text) != std::string::npos) << "\n"
- << "Expected to find: " << expected_text << "\n"
- << "In the output : " << actual_;
- actual_.clear();
- }
+ void Check(const char* expected_text);
private:
- static void Hook(void* data, const std::string& reason) {
- // We use += because when we're hooking the aborts like this, multiple problems can be found.
- *reinterpret_cast<std::string*>(data) += reason;
- }
+ static void Hook(void* data, const std::string& reason);
JavaVMExt* vm_;
std::string actual_;
@@ -399,10 +151,7 @@
// TODO: isn't gtest supposed to be able to print STL types for itself?
template <typename T>
-std::ostream& operator<<(std::ostream& os, const std::vector<T>& rhs) {
- os << ::art::ToString(rhs);
- return os;
-}
+std::ostream& operator<<(std::ostream& os, const std::vector<T>& rhs);
} // namespace std