Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "common_runtime_test.h"
     18 
     19 #include <dirent.h>
     20 #include <dlfcn.h>
     21 #include <fcntl.h>
     22 #include <ScopedLocalRef.h>
     23 
     24 #include "../../external/icu/icu4c/source/common/unicode/uvernum.h"
     25 #include "base/macros.h"
     26 #include "base/logging.h"
     27 #include "base/stl_util.h"
     28 #include "base/stringprintf.h"
     29 #include "base/unix_file/fd_file.h"
     30 #include "class_linker.h"
     31 #include "compiler_callbacks.h"
     32 #include "dex_file.h"
     33 #include "gc_root-inl.h"
     34 #include "gc/heap.h"
     35 #include "gtest/gtest.h"
     36 #include "jni_internal.h"
     37 #include "mirror/class_loader.h"
     38 #include "noop_compiler_callbacks.h"
     39 #include "os.h"
     40 #include "runtime-inl.h"
     41 #include "scoped_thread_state_change.h"
     42 #include "thread.h"
     43 #include "well_known_classes.h"
     44 
     45 int main(int argc, char **argv) {
     46   art::InitLogging(argv);
     47   LOG(INFO) << "Running main() from common_runtime_test.cc...";
     48   testing::InitGoogleTest(&argc, argv);
     49   return RUN_ALL_TESTS();
     50 }
     51 
     52 namespace art {
     53 
     54 ScratchFile::ScratchFile() {
     55   // ANDROID_DATA needs to be set
     56   CHECK_NE(static_cast<char*>(nullptr), getenv("ANDROID_DATA")) <<
     57       "Are you subclassing RuntimeTest?";
     58   filename_ = getenv("ANDROID_DATA");
     59   filename_ += "/TmpFile-XXXXXX";
     60   int fd = mkstemp(&filename_[0]);
     61   CHECK_NE(-1, fd);
     62   file_.reset(new File(fd, GetFilename(), true));
     63 }
     64 
     65 ScratchFile::ScratchFile(const ScratchFile& other, const char* suffix) {
     66   filename_ = other.GetFilename();
     67   filename_ += suffix;
     68   int fd = open(filename_.c_str(), O_RDWR | O_CREAT, 0666);
     69   CHECK_NE(-1, fd);
     70   file_.reset(new File(fd, GetFilename(), true));
     71 }
     72 
     73 ScratchFile::ScratchFile(File* file) {
     74   CHECK(file != NULL);
     75   filename_ = file->GetPath();
     76   file_.reset(file);
     77 }
     78 
     79 ScratchFile::~ScratchFile() {
     80   Unlink();
     81 }
     82 
     83 int ScratchFile::GetFd() const {
     84   return file_->Fd();
     85 }
     86 
     87 void ScratchFile::Close() {
     88   if (file_.get() != nullptr) {
     89     if (file_->FlushCloseOrErase() != 0) {
     90       PLOG(WARNING) << "Error closing scratch file.";
     91     }
     92   }
     93 }
     94 
     95 void ScratchFile::Unlink() {
     96   if (!OS::FileExists(filename_.c_str())) {
     97     return;
     98   }
     99   Close();
    100   int unlink_result = unlink(filename_.c_str());
    101   CHECK_EQ(0, unlink_result);
    102 }
    103 
    104 CommonRuntimeTest::CommonRuntimeTest() {}
    105 CommonRuntimeTest::~CommonRuntimeTest() {}
    106 
    107 void CommonRuntimeTest::SetUpAndroidRoot() {
    108   if (IsHost()) {
    109     // $ANDROID_ROOT is set on the device, but not necessarily on the host.
    110     // But it needs to be set so that icu4c can find its locale data.
    111     const char* android_root_from_env = getenv("ANDROID_ROOT");
    112     if (android_root_from_env == nullptr) {
    113       // Use ANDROID_HOST_OUT for ANDROID_ROOT if it is set.
    114       const char* android_host_out = getenv("ANDROID_HOST_OUT");
    115       if (android_host_out != nullptr) {
    116         setenv("ANDROID_ROOT", android_host_out, 1);
    117       } else {
    118         // Build it from ANDROID_BUILD_TOP or cwd
    119         std::string root;
    120         const char* android_build_top = getenv("ANDROID_BUILD_TOP");
    121         if (android_build_top != nullptr) {
    122           root += android_build_top;
    123         } else {
    124           // Not set by build server, so default to current directory
    125           char* cwd = getcwd(nullptr, 0);
    126           setenv("ANDROID_BUILD_TOP", cwd, 1);
    127           root += cwd;
    128           free(cwd);
    129         }
    130 #if defined(__linux__)
    131         root += "/out/host/linux-x86";
    132 #elif defined(__APPLE__)
    133         root += "/out/host/darwin-x86";
    134 #else
    135 #error unsupported OS
    136 #endif
    137         setenv("ANDROID_ROOT", root.c_str(), 1);
    138       }
    139     }
    140     setenv("LD_LIBRARY_PATH", ":", 0);  // Required by java.lang.System.<clinit>.
    141 
    142     // Not set by build server, so default
    143     if (getenv("ANDROID_HOST_OUT") == nullptr) {
    144       setenv("ANDROID_HOST_OUT", getenv("ANDROID_ROOT"), 1);
    145     }
    146   }
    147 }
    148 
    149 void CommonRuntimeTest::SetUpAndroidData(std::string& android_data) {
    150   // On target, Cannot use /mnt/sdcard because it is mounted noexec, so use subdir of dalvik-cache
    151   if (IsHost()) {
    152     const char* tmpdir = getenv("TMPDIR");
    153     if (tmpdir != nullptr && tmpdir[0] != 0) {
    154       android_data = tmpdir;
    155     } else {
    156       android_data = "/tmp";
    157     }
    158   } else {
    159     android_data = "/data/dalvik-cache";
    160   }
    161   android_data += "/art-data-XXXXXX";
    162   if (mkdtemp(&android_data[0]) == nullptr) {
    163     PLOG(FATAL) << "mkdtemp(\"" << &android_data[0] << "\") failed";
    164   }
    165   setenv("ANDROID_DATA", android_data.c_str(), 1);
    166 }
    167 
    168 void CommonRuntimeTest::TearDownAndroidData(const std::string& android_data, bool fail_on_error) {
    169   if (fail_on_error) {
    170     ASSERT_EQ(rmdir(android_data.c_str()), 0);
    171   } else {
    172     rmdir(android_data.c_str());
    173   }
    174 }
    175 
    176 
    177 const DexFile* CommonRuntimeTest::LoadExpectSingleDexFile(const char* location) {
    178   std::vector<const DexFile*> dex_files;
    179   std::string error_msg;
    180   if (!DexFile::Open(location, location, &error_msg, &dex_files)) {
    181     LOG(FATAL) << "Could not open .dex file '" << location << "': " << error_msg << "\n";
    182     return nullptr;
    183   } else {
    184     CHECK_EQ(1U, dex_files.size()) << "Expected only one dex file in " << location;
    185     return dex_files[0];
    186   }
    187 }
    188 
    189 void CommonRuntimeTest::SetUp() {
    190   SetUpAndroidRoot();
    191   SetUpAndroidData(android_data_);
    192   dalvik_cache_.append(android_data_.c_str());
    193   dalvik_cache_.append("/dalvik-cache");
    194   int mkdir_result = mkdir(dalvik_cache_.c_str(), 0700);
    195   ASSERT_EQ(mkdir_result, 0);
    196 
    197   MemMap::Init();  // For LoadExpectSingleDexFile
    198 
    199   std::string error_msg;
    200   java_lang_dex_file_ = LoadExpectSingleDexFile(GetLibCoreDexFileName().c_str());
    201   boot_class_path_.push_back(java_lang_dex_file_);
    202 
    203   std::string min_heap_string(StringPrintf("-Xms%zdm", gc::Heap::kDefaultInitialSize / MB));
    204   std::string max_heap_string(StringPrintf("-Xmx%zdm", gc::Heap::kDefaultMaximumSize / MB));
    205 
    206   callbacks_.reset(new NoopCompilerCallbacks());
    207 
    208   RuntimeOptions options;
    209   options.push_back(std::make_pair("bootclasspath", &boot_class_path_));
    210   options.push_back(std::make_pair("-Xcheck:jni", nullptr));
    211   options.push_back(std::make_pair(min_heap_string.c_str(), nullptr));
    212   options.push_back(std::make_pair(max_heap_string.c_str(), nullptr));
    213   options.push_back(std::make_pair("compilercallbacks", callbacks_.get()));
    214   SetUpRuntimeOptions(&options);
    215   if (!Runtime::Create(options, false)) {
    216     LOG(FATAL) << "Failed to create runtime";
    217     return;
    218   }
    219   runtime_.reset(Runtime::Current());
    220   class_linker_ = runtime_->GetClassLinker();
    221   class_linker_->FixupDexCaches(runtime_->GetResolutionMethod());
    222   class_linker_->RunRootClinits();
    223 
    224   // Runtime::Create acquired the mutator_lock_ that is normally given away when we
    225   // Runtime::Start, give it away now and then switch to a more managable ScopedObjectAccess.
    226   Thread::Current()->TransitionFromRunnableToSuspended(kNative);
    227 
    228   // We're back in native, take the opportunity to initialize well known classes.
    229   WellKnownClasses::Init(Thread::Current()->GetJniEnv());
    230 
    231   // Create the heap thread pool so that the GC runs in parallel for tests. Normally, the thread
    232   // pool is created by the runtime.
    233   runtime_->GetHeap()->CreateThreadPool();
    234   runtime_->GetHeap()->VerifyHeap();  // Check for heap corruption before the test
    235 }
    236 
    237 void CommonRuntimeTest::ClearDirectory(const char* dirpath) {
    238   ASSERT_TRUE(dirpath != nullptr);
    239   DIR* dir = opendir(dirpath);
    240   ASSERT_TRUE(dir != nullptr);
    241   dirent* e;
    242   struct stat s;
    243   while ((e = readdir(dir)) != nullptr) {
    244     if ((strcmp(e->d_name, ".") == 0) || (strcmp(e->d_name, "..") == 0)) {
    245       continue;
    246     }
    247     std::string filename(dirpath);
    248     filename.push_back('/');
    249     filename.append(e->d_name);
    250     int stat_result = lstat(filename.c_str(), &s);
    251     ASSERT_EQ(0, stat_result) << "unable to stat " << filename;
    252     if (S_ISDIR(s.st_mode)) {
    253       ClearDirectory(filename.c_str());
    254       int rmdir_result = rmdir(filename.c_str());
    255       ASSERT_EQ(0, rmdir_result) << filename;
    256     } else {
    257       int unlink_result = unlink(filename.c_str());
    258       ASSERT_EQ(0, unlink_result) << filename;
    259     }
    260   }
    261   closedir(dir);
    262 }
    263 
    264 void CommonRuntimeTest::TearDown() {
    265   const char* android_data = getenv("ANDROID_DATA");
    266   ASSERT_TRUE(android_data != nullptr);
    267   ClearDirectory(dalvik_cache_.c_str());
    268   int rmdir_cache_result = rmdir(dalvik_cache_.c_str());
    269   ASSERT_EQ(0, rmdir_cache_result);
    270   TearDownAndroidData(android_data_, true);
    271 
    272   // icu4c has a fixed 10-element array "gCommonICUDataArray".
    273   // If we run > 10 tests, we fill that array and u_setCommonData fails.
    274   // There's a function to clear the array, but it's not public...
    275   typedef void (*IcuCleanupFn)();
    276   void* sym = dlsym(RTLD_DEFAULT, "u_cleanup_" U_ICU_VERSION_SHORT);
    277   CHECK(sym != nullptr) << dlerror();
    278   IcuCleanupFn icu_cleanup_fn = reinterpret_cast<IcuCleanupFn>(sym);
    279   (*icu_cleanup_fn)();
    280 
    281   STLDeleteElements(&opened_dex_files_);
    282 
    283   Runtime::Current()->GetHeap()->VerifyHeap();  // Check for heap corruption after the test
    284 }
    285 
    286 std::string CommonRuntimeTest::GetLibCoreDexFileName() {
    287   return GetDexFileName("core-libart");
    288 }
    289 
    290 std::string CommonRuntimeTest::GetDexFileName(const std::string& jar_prefix) {
    291   if (IsHost()) {
    292     const char* host_dir = getenv("ANDROID_HOST_OUT");
    293     CHECK(host_dir != nullptr);
    294     return StringPrintf("%s/framework/%s-hostdex.jar", host_dir, jar_prefix.c_str());
    295   }
    296   return StringPrintf("%s/framework/%s.jar", GetAndroidRoot(), jar_prefix.c_str());
    297 }
    298 
    299 std::string CommonRuntimeTest::GetTestAndroidRoot() {
    300   if (IsHost()) {
    301     const char* host_dir = getenv("ANDROID_HOST_OUT");
    302     CHECK(host_dir != nullptr);
    303     return host_dir;
    304   }
    305   return GetAndroidRoot();
    306 }
    307 
    308 // Check that for target builds we have ART_TARGET_NATIVETEST_DIR set.
    309 #ifdef ART_TARGET
    310 #ifndef ART_TARGET_NATIVETEST_DIR
    311 #error "ART_TARGET_NATIVETEST_DIR not set."
    312 #endif
    313 // Wrap it as a string literal.
    314 #define ART_TARGET_NATIVETEST_DIR_STRING STRINGIFY(ART_TARGET_NATIVETEST_DIR) "/"
    315 #else
    316 #define ART_TARGET_NATIVETEST_DIR_STRING ""
    317 #endif
    318 
    319 std::vector<const DexFile*> CommonRuntimeTest::OpenTestDexFiles(const char* name) {
    320   CHECK(name != nullptr);
    321   std::string filename;
    322   if (IsHost()) {
    323     filename += getenv("ANDROID_HOST_OUT");
    324     filename += "/framework/";
    325   } else {
    326     filename += ART_TARGET_NATIVETEST_DIR_STRING;
    327   }
    328   filename += "art-gtest-";
    329   filename += name;
    330   filename += ".jar";
    331   std::string error_msg;
    332   std::vector<const DexFile*> dex_files;
    333   bool success = DexFile::Open(filename.c_str(), filename.c_str(), &error_msg, &dex_files);
    334   CHECK(success) << "Failed to open '" << filename << "': " << error_msg;
    335   for (const DexFile* dex_file : dex_files) {
    336     CHECK_EQ(PROT_READ, dex_file->GetPermissions());
    337     CHECK(dex_file->IsReadOnly());
    338   }
    339   opened_dex_files_.insert(opened_dex_files_.end(), dex_files.begin(), dex_files.end());
    340   return dex_files;
    341 }
    342 
    343 const DexFile* CommonRuntimeTest::OpenTestDexFile(const char* name) {
    344   std::vector<const DexFile*> vector = OpenTestDexFiles(name);
    345   EXPECT_EQ(1U, vector.size());
    346   return vector[0];
    347 }
    348 
    349 jobject CommonRuntimeTest::LoadDex(const char* dex_name) {
    350   std::vector<const DexFile*> dex_files = OpenTestDexFiles(dex_name);
    351   CHECK_NE(0U, dex_files.size());
    352   for (const DexFile* dex_file : dex_files) {
    353     class_linker_->RegisterDexFile(*dex_file);
    354   }
    355   ScopedObjectAccessUnchecked soa(Thread::Current());
    356   ScopedLocalRef<jobject> class_loader_local(soa.Env(),
    357       soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader));
    358   jobject class_loader = soa.Env()->NewGlobalRef(class_loader_local.get());
    359   soa.Self()->SetClassLoaderOverride(soa.Decode<mirror::ClassLoader*>(class_loader_local.get()));
    360   Runtime::Current()->SetCompileTimeClassPath(class_loader, dex_files);
    361   return class_loader;
    362 }
    363 
    364 CheckJniAbortCatcher::CheckJniAbortCatcher() : vm_(Runtime::Current()->GetJavaVM()) {
    365   vm_->check_jni_abort_hook = Hook;
    366   vm_->check_jni_abort_hook_data = &actual_;
    367 }
    368 
    369 CheckJniAbortCatcher::~CheckJniAbortCatcher() {
    370   vm_->check_jni_abort_hook = nullptr;
    371   vm_->check_jni_abort_hook_data = nullptr;
    372   EXPECT_TRUE(actual_.empty()) << actual_;
    373 }
    374 
    375 void CheckJniAbortCatcher::Check(const char* expected_text) {
    376   EXPECT_TRUE(actual_.find(expected_text) != std::string::npos) << "\n"
    377       << "Expected to find: " << expected_text << "\n"
    378       << "In the output   : " << actual_;
    379   actual_.clear();
    380 }
    381 
    382 void CheckJniAbortCatcher::Hook(void* data, const std::string& reason) {
    383   // We use += because when we're hooking the aborts like this, multiple problems can be found.
    384   *reinterpret_cast<std::string*>(data) += reason;
    385 }
    386 
    387 }  // namespace art
    388 
    389 namespace std {
    390 
    391 template <typename T>
    392 std::ostream& operator<<(std::ostream& os, const std::vector<T>& rhs) {
    393 os << ::art::ToString(rhs);
    394 return os;
    395 }
    396 
    397 }  // namespace std
    398