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 <cstdio>
20 #include <dirent.h>
21 #include <dlfcn.h>
22 #include <fcntl.h>
23 #include <ScopedLocalRef.h>
24 #include <stdlib.h>
25 
26 #include "../../external/icu/icu4c/source/common/unicode/uvernum.h"
27 #include "android-base/stringprintf.h"
28 
29 #include "art_field-inl.h"
30 #include "base/macros.h"
31 #include "base/logging.h"
32 #include "base/stl_util.h"
33 #include "base/unix_file/fd_file.h"
34 #include "class_linker.h"
35 #include "compiler_callbacks.h"
36 #include "dex_file-inl.h"
37 #include "gc_root-inl.h"
38 #include "gc/heap.h"
39 #include "gtest/gtest.h"
40 #include "handle_scope-inl.h"
41 #include "interpreter/unstarted_runtime.h"
42 #include "java_vm_ext.h"
43 #include "jni_internal.h"
44 #include "mirror/class-inl.h"
45 #include "mirror/class_loader.h"
46 #include "mem_map.h"
47 #include "native/dalvik_system_DexFile.h"
48 #include "noop_compiler_callbacks.h"
49 #include "os.h"
50 #include "primitive.h"
51 #include "runtime-inl.h"
52 #include "scoped_thread_state_change-inl.h"
53 #include "thread.h"
54 #include "well_known_classes.h"
55 
main(int argc,char ** argv)56 int main(int argc, char **argv) {
57   // Gtests can be very noisy. For example, an executable with multiple tests will trigger native
58   // bridge warnings. The following line reduces the minimum log severity to ERROR and suppresses
59   // everything else. In case you want to see all messages, comment out the line.
60   setenv("ANDROID_LOG_TAGS", "*:e", 1);
61 
62   art::InitLogging(argv, art::Runtime::Aborter);
63   LOG(INFO) << "Running main() from common_runtime_test.cc...";
64   testing::InitGoogleTest(&argc, argv);
65   return RUN_ALL_TESTS();
66 }
67 
68 namespace art {
69 
70 using android::base::StringPrintf;
71 
72 static const uint8_t kBase64Map[256] = {
73   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
74   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
75   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
76   255, 255, 255, 255, 255, 255, 255,  62, 255, 255, 255,  63,
77   52,  53,  54,  55,  56,  57,  58,  59,  60,  61, 255, 255,
78   255, 254, 255, 255, 255,   0,   1,   2,   3,   4,   5,   6,
79     7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18,  // NOLINT
80    19,  20,  21,  22,  23,  24,  25, 255, 255, 255, 255, 255,  // NOLINT
81   255,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,
82    37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  // NOLINT
83    49,  50,  51, 255, 255, 255, 255, 255, 255, 255, 255, 255,  // NOLINT
84   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
85   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
86   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
87   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
88   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
89   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
90   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
91   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
92   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
93   255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
94   255, 255, 255, 255
95 };
96 
DecodeBase64(const char * src,size_t * dst_size)97 uint8_t* DecodeBase64(const char* src, size_t* dst_size) {
98   CHECK(dst_size != nullptr);
99   std::vector<uint8_t> tmp;
100   uint32_t t = 0, y = 0;
101   int g = 3;
102   for (size_t i = 0; src[i] != '\0'; ++i) {
103     uint8_t c = kBase64Map[src[i] & 0xFF];
104     if (c == 255) continue;
105     // the final = symbols are read and used to trim the remaining bytes
106     if (c == 254) {
107       c = 0;
108       // prevent g < 0 which would potentially allow an overflow later
109       if (--g < 0) {
110         *dst_size = 0;
111         return nullptr;
112       }
113     } else if (g != 3) {
114       // we only allow = to be at the end
115       *dst_size = 0;
116       return nullptr;
117     }
118     t = (t << 6) | c;
119     if (++y == 4) {
120       tmp.push_back((t >> 16) & 255);
121       if (g > 1) {
122         tmp.push_back((t >> 8) & 255);
123       }
124       if (g > 2) {
125         tmp.push_back(t & 255);
126       }
127       y = t = 0;
128     }
129   }
130   if (y != 0) {
131     *dst_size = 0;
132     return nullptr;
133   }
134   std::unique_ptr<uint8_t[]> dst(new uint8_t[tmp.size()]);
135   *dst_size = tmp.size();
136   std::copy(tmp.begin(), tmp.end(), dst.get());
137   return dst.release();
138 }
139 
ScratchFile()140 ScratchFile::ScratchFile() {
141   // ANDROID_DATA needs to be set
142   CHECK_NE(static_cast<char*>(nullptr), getenv("ANDROID_DATA")) <<
143       "Are you subclassing RuntimeTest?";
144   filename_ = getenv("ANDROID_DATA");
145   filename_ += "/TmpFile-XXXXXX";
146   int fd = mkstemp(&filename_[0]);
147   CHECK_NE(-1, fd) << strerror(errno) << " for " << filename_;
148   file_.reset(new File(fd, GetFilename(), true));
149 }
150 
ScratchFile(const ScratchFile & other,const char * suffix)151 ScratchFile::ScratchFile(const ScratchFile& other, const char* suffix)
152     : ScratchFile(other.GetFilename() + suffix) {}
153 
ScratchFile(const std::string & filename)154 ScratchFile::ScratchFile(const std::string& filename) : filename_(filename) {
155   int fd = open(filename_.c_str(), O_RDWR | O_CREAT, 0666);
156   CHECK_NE(-1, fd);
157   file_.reset(new File(fd, GetFilename(), true));
158 }
159 
ScratchFile(File * file)160 ScratchFile::ScratchFile(File* file) {
161   CHECK(file != nullptr);
162   filename_ = file->GetPath();
163   file_.reset(file);
164 }
165 
ScratchFile(ScratchFile && other)166 ScratchFile::ScratchFile(ScratchFile&& other) {
167   *this = std::move(other);
168 }
169 
operator =(ScratchFile && other)170 ScratchFile& ScratchFile::operator=(ScratchFile&& other) {
171   if (GetFile() != other.GetFile()) {
172     std::swap(filename_, other.filename_);
173     std::swap(file_, other.file_);
174   }
175   return *this;
176 }
177 
~ScratchFile()178 ScratchFile::~ScratchFile() {
179   Unlink();
180 }
181 
GetFd() const182 int ScratchFile::GetFd() const {
183   return file_->Fd();
184 }
185 
Close()186 void ScratchFile::Close() {
187   if (file_.get() != nullptr) {
188     if (file_->FlushCloseOrErase() != 0) {
189       PLOG(WARNING) << "Error closing scratch file.";
190     }
191   }
192 }
193 
Unlink()194 void ScratchFile::Unlink() {
195   if (!OS::FileExists(filename_.c_str())) {
196     return;
197   }
198   Close();
199   int unlink_result = unlink(filename_.c_str());
200   CHECK_EQ(0, unlink_result);
201 }
202 
203 static bool unstarted_initialized_ = false;
204 
CommonRuntimeTestImpl()205 CommonRuntimeTestImpl::CommonRuntimeTestImpl()
206     : class_linker_(nullptr), java_lang_dex_file_(nullptr) {
207 }
208 
~CommonRuntimeTestImpl()209 CommonRuntimeTestImpl::~CommonRuntimeTestImpl() {
210   // Ensure the dex files are cleaned up before the runtime.
211   loaded_dex_files_.clear();
212   runtime_.reset();
213 }
214 
SetUpAndroidRoot()215 void CommonRuntimeTestImpl::SetUpAndroidRoot() {
216   if (IsHost()) {
217     // $ANDROID_ROOT is set on the device, but not necessarily on the host.
218     // But it needs to be set so that icu4c can find its locale data.
219     const char* android_root_from_env = getenv("ANDROID_ROOT");
220     if (android_root_from_env == nullptr) {
221       // Use ANDROID_HOST_OUT for ANDROID_ROOT if it is set.
222       const char* android_host_out = getenv("ANDROID_HOST_OUT");
223       if (android_host_out != nullptr) {
224         setenv("ANDROID_ROOT", android_host_out, 1);
225       } else {
226         // Build it from ANDROID_BUILD_TOP or cwd
227         std::string root;
228         const char* android_build_top = getenv("ANDROID_BUILD_TOP");
229         if (android_build_top != nullptr) {
230           root += android_build_top;
231         } else {
232           // Not set by build server, so default to current directory
233           char* cwd = getcwd(nullptr, 0);
234           setenv("ANDROID_BUILD_TOP", cwd, 1);
235           root += cwd;
236           free(cwd);
237         }
238 #if defined(__linux__)
239         root += "/out/host/linux-x86";
240 #elif defined(__APPLE__)
241         root += "/out/host/darwin-x86";
242 #else
243 #error unsupported OS
244 #endif
245         setenv("ANDROID_ROOT", root.c_str(), 1);
246       }
247     }
248     setenv("LD_LIBRARY_PATH", ":", 0);  // Required by java.lang.System.<clinit>.
249 
250     // Not set by build server, so default
251     if (getenv("ANDROID_HOST_OUT") == nullptr) {
252       setenv("ANDROID_HOST_OUT", getenv("ANDROID_ROOT"), 1);
253     }
254   }
255 }
256 
SetUpAndroidData(std::string & android_data)257 void CommonRuntimeTestImpl::SetUpAndroidData(std::string& android_data) {
258   // On target, Cannot use /mnt/sdcard because it is mounted noexec, so use subdir of dalvik-cache
259   if (IsHost()) {
260     const char* tmpdir = getenv("TMPDIR");
261     if (tmpdir != nullptr && tmpdir[0] != 0) {
262       android_data = tmpdir;
263     } else {
264       android_data = "/tmp";
265     }
266   } else {
267     android_data = "/data/dalvik-cache";
268   }
269   android_data += "/art-data-XXXXXX";
270   if (mkdtemp(&android_data[0]) == nullptr) {
271     PLOG(FATAL) << "mkdtemp(\"" << &android_data[0] << "\") failed";
272   }
273   setenv("ANDROID_DATA", android_data.c_str(), 1);
274 }
275 
TearDownAndroidData(const std::string & android_data,bool fail_on_error)276 void CommonRuntimeTestImpl::TearDownAndroidData(const std::string& android_data,
277                                                 bool fail_on_error) {
278   if (fail_on_error) {
279     ASSERT_EQ(rmdir(android_data.c_str()), 0);
280   } else {
281     rmdir(android_data.c_str());
282   }
283 }
284 
285 // Helper - find directory with the following format:
286 // ${ANDROID_BUILD_TOP}/${subdir1}/${subdir2}-${version}/${subdir3}/bin/
GetAndroidToolsDir(const std::string & subdir1,const std::string & subdir2,const std::string & subdir3)287 static std::string GetAndroidToolsDir(const std::string& subdir1,
288                                       const std::string& subdir2,
289                                       const std::string& subdir3) {
290   std::string root;
291   const char* android_build_top = getenv("ANDROID_BUILD_TOP");
292   if (android_build_top != nullptr) {
293     root = android_build_top;
294   } else {
295     // Not set by build server, so default to current directory
296     char* cwd = getcwd(nullptr, 0);
297     setenv("ANDROID_BUILD_TOP", cwd, 1);
298     root = cwd;
299     free(cwd);
300   }
301 
302   std::string toolsdir = root + "/" + subdir1;
303   std::string founddir;
304   DIR* dir;
305   if ((dir = opendir(toolsdir.c_str())) != nullptr) {
306     float maxversion = 0;
307     struct dirent* entry;
308     while ((entry = readdir(dir)) != nullptr) {
309       std::string format = subdir2 + "-%f";
310       float version;
311       if (std::sscanf(entry->d_name, format.c_str(), &version) == 1) {
312         if (version > maxversion) {
313           maxversion = version;
314           founddir = toolsdir + "/" + entry->d_name + "/" + subdir3 + "/bin/";
315         }
316       }
317     }
318     closedir(dir);
319   }
320 
321   if (founddir.empty()) {
322     ADD_FAILURE() << "Cannot find Android tools directory.";
323   }
324   return founddir;
325 }
326 
GetAndroidHostToolsDir()327 std::string CommonRuntimeTestImpl::GetAndroidHostToolsDir() {
328   return GetAndroidToolsDir("prebuilts/gcc/linux-x86/host",
329                             "x86_64-linux-glibc2.15",
330                             "x86_64-linux");
331 }
332 
GetAndroidTargetToolsDir(InstructionSet isa)333 std::string CommonRuntimeTestImpl::GetAndroidTargetToolsDir(InstructionSet isa) {
334   switch (isa) {
335     case kArm:
336     case kThumb2:
337       return GetAndroidToolsDir("prebuilts/gcc/linux-x86/arm",
338                                 "arm-linux-androideabi",
339                                 "arm-linux-androideabi");
340     case kArm64:
341       return GetAndroidToolsDir("prebuilts/gcc/linux-x86/aarch64",
342                                 "aarch64-linux-android",
343                                 "aarch64-linux-android");
344     case kX86:
345     case kX86_64:
346       return GetAndroidToolsDir("prebuilts/gcc/linux-x86/x86",
347                                 "x86_64-linux-android",
348                                 "x86_64-linux-android");
349     case kMips:
350     case kMips64:
351       return GetAndroidToolsDir("prebuilts/gcc/linux-x86/mips",
352                                 "mips64el-linux-android",
353                                 "mips64el-linux-android");
354     case kNone:
355       break;
356   }
357   ADD_FAILURE() << "Invalid isa " << isa;
358   return "";
359 }
360 
GetCoreArtLocation()361 std::string CommonRuntimeTestImpl::GetCoreArtLocation() {
362   return GetCoreFileLocation("art");
363 }
364 
GetCoreOatLocation()365 std::string CommonRuntimeTestImpl::GetCoreOatLocation() {
366   return GetCoreFileLocation("oat");
367 }
368 
LoadExpectSingleDexFile(const char * location)369 std::unique_ptr<const DexFile> CommonRuntimeTestImpl::LoadExpectSingleDexFile(
370     const char* location) {
371   std::vector<std::unique_ptr<const DexFile>> dex_files;
372   std::string error_msg;
373   MemMap::Init();
374   static constexpr bool kVerifyChecksum = true;
375   if (!DexFile::Open(location, location, kVerifyChecksum, &error_msg, &dex_files)) {
376     LOG(FATAL) << "Could not open .dex file '" << location << "': " << error_msg << "\n";
377     UNREACHABLE();
378   } else {
379     CHECK_EQ(1U, dex_files.size()) << "Expected only one dex file in " << location;
380     return std::move(dex_files[0]);
381   }
382 }
383 
SetUp()384 void CommonRuntimeTestImpl::SetUp() {
385   SetUpAndroidRoot();
386   SetUpAndroidData(android_data_);
387   dalvik_cache_.append(android_data_.c_str());
388   dalvik_cache_.append("/dalvik-cache");
389   int mkdir_result = mkdir(dalvik_cache_.c_str(), 0700);
390   ASSERT_EQ(mkdir_result, 0);
391 
392   std::string min_heap_string(StringPrintf("-Xms%zdm", gc::Heap::kDefaultInitialSize / MB));
393   std::string max_heap_string(StringPrintf("-Xmx%zdm", gc::Heap::kDefaultMaximumSize / MB));
394 
395 
396   RuntimeOptions options;
397   std::string boot_class_path_string = "-Xbootclasspath";
398   for (const std::string &core_dex_file_name : GetLibCoreDexFileNames()) {
399     boot_class_path_string += ":";
400     boot_class_path_string += core_dex_file_name;
401   }
402 
403   options.push_back(std::make_pair(boot_class_path_string, nullptr));
404   options.push_back(std::make_pair("-Xcheck:jni", nullptr));
405   options.push_back(std::make_pair(min_heap_string, nullptr));
406   options.push_back(std::make_pair(max_heap_string, nullptr));
407 
408   callbacks_.reset(new NoopCompilerCallbacks());
409 
410   SetUpRuntimeOptions(&options);
411 
412   // Install compiler-callbacks if SetupRuntimeOptions hasn't deleted them.
413   if (callbacks_.get() != nullptr) {
414     options.push_back(std::make_pair("compilercallbacks", callbacks_.get()));
415   }
416 
417   PreRuntimeCreate();
418   if (!Runtime::Create(options, false)) {
419     LOG(FATAL) << "Failed to create runtime";
420     return;
421   }
422   PostRuntimeCreate();
423   runtime_.reset(Runtime::Current());
424   class_linker_ = runtime_->GetClassLinker();
425   class_linker_->FixupDexCaches(runtime_->GetResolutionMethod());
426 
427   // Runtime::Create acquired the mutator_lock_ that is normally given away when we
428   // Runtime::Start, give it away now and then switch to a more managable ScopedObjectAccess.
429   Thread::Current()->TransitionFromRunnableToSuspended(kNative);
430 
431   // Get the boot class path from the runtime so it can be used in tests.
432   boot_class_path_ = class_linker_->GetBootClassPath();
433   ASSERT_FALSE(boot_class_path_.empty());
434   java_lang_dex_file_ = boot_class_path_[0];
435 
436   FinalizeSetup();
437 }
438 
FinalizeSetup()439 void CommonRuntimeTestImpl::FinalizeSetup() {
440   // Initialize maps for unstarted runtime. This needs to be here, as running clinits needs this
441   // set up.
442   if (!unstarted_initialized_) {
443     interpreter::UnstartedRuntime::Initialize();
444     unstarted_initialized_ = true;
445   }
446 
447   {
448     ScopedObjectAccess soa(Thread::Current());
449     class_linker_->RunRootClinits();
450   }
451 
452   // We're back in native, take the opportunity to initialize well known classes.
453   WellKnownClasses::Init(Thread::Current()->GetJniEnv());
454 
455   // Create the heap thread pool so that the GC runs in parallel for tests. Normally, the thread
456   // pool is created by the runtime.
457   runtime_->GetHeap()->CreateThreadPool();
458   runtime_->GetHeap()->VerifyHeap();  // Check for heap corruption before the test
459   // Reduce timinig-dependent flakiness in OOME behavior (eg StubTest.AllocObject).
460   runtime_->GetHeap()->SetMinIntervalHomogeneousSpaceCompactionByOom(0U);
461 }
462 
ClearDirectory(const char * dirpath)463 void CommonRuntimeTestImpl::ClearDirectory(const char* dirpath) {
464   ASSERT_TRUE(dirpath != nullptr);
465   DIR* dir = opendir(dirpath);
466   ASSERT_TRUE(dir != nullptr);
467   dirent* e;
468   struct stat s;
469   while ((e = readdir(dir)) != nullptr) {
470     if ((strcmp(e->d_name, ".") == 0) || (strcmp(e->d_name, "..") == 0)) {
471       continue;
472     }
473     std::string filename(dirpath);
474     filename.push_back('/');
475     filename.append(e->d_name);
476     int stat_result = lstat(filename.c_str(), &s);
477     ASSERT_EQ(0, stat_result) << "unable to stat " << filename;
478     if (S_ISDIR(s.st_mode)) {
479       ClearDirectory(filename.c_str());
480       int rmdir_result = rmdir(filename.c_str());
481       ASSERT_EQ(0, rmdir_result) << filename;
482     } else {
483       int unlink_result = unlink(filename.c_str());
484       ASSERT_EQ(0, unlink_result) << filename;
485     }
486   }
487   closedir(dir);
488 }
489 
TearDown()490 void CommonRuntimeTestImpl::TearDown() {
491   const char* android_data = getenv("ANDROID_DATA");
492   ASSERT_TRUE(android_data != nullptr);
493   ClearDirectory(dalvik_cache_.c_str());
494   int rmdir_cache_result = rmdir(dalvik_cache_.c_str());
495   ASSERT_EQ(0, rmdir_cache_result);
496   TearDownAndroidData(android_data_, true);
497   dalvik_cache_.clear();
498 
499   if (runtime_ != nullptr) {
500     runtime_->GetHeap()->VerifyHeap();  // Check for heap corruption after the test
501   }
502 }
503 
GetDexFileName(const std::string & jar_prefix,bool host)504 static std::string GetDexFileName(const std::string& jar_prefix, bool host) {
505   std::string path;
506   if (host) {
507     const char* host_dir = getenv("ANDROID_HOST_OUT");
508     CHECK(host_dir != nullptr);
509     path = host_dir;
510   } else {
511     path = GetAndroidRoot();
512   }
513 
514   std::string suffix = host
515       ? "-hostdex"                 // The host version.
516       : "-testdex";                // The unstripped target version.
517 
518   return StringPrintf("%s/framework/%s%s.jar", path.c_str(), jar_prefix.c_str(), suffix.c_str());
519 }
520 
GetLibCoreDexFileNames()521 std::vector<std::string> CommonRuntimeTestImpl::GetLibCoreDexFileNames() {
522   return std::vector<std::string>({GetDexFileName("core-oj", IsHost()),
523                                    GetDexFileName("core-libart", IsHost())});
524 }
525 
GetTestAndroidRoot()526 std::string CommonRuntimeTestImpl::GetTestAndroidRoot() {
527   if (IsHost()) {
528     const char* host_dir = getenv("ANDROID_HOST_OUT");
529     CHECK(host_dir != nullptr);
530     return host_dir;
531   }
532   return GetAndroidRoot();
533 }
534 
535 // Check that for target builds we have ART_TARGET_NATIVETEST_DIR set.
536 #ifdef ART_TARGET
537 #ifndef ART_TARGET_NATIVETEST_DIR
538 #error "ART_TARGET_NATIVETEST_DIR not set."
539 #endif
540 // Wrap it as a string literal.
541 #define ART_TARGET_NATIVETEST_DIR_STRING STRINGIFY(ART_TARGET_NATIVETEST_DIR) "/"
542 #else
543 #define ART_TARGET_NATIVETEST_DIR_STRING ""
544 #endif
545 
GetTestDexFileName(const char * name) const546 std::string CommonRuntimeTestImpl::GetTestDexFileName(const char* name) const {
547   CHECK(name != nullptr);
548   std::string filename;
549   if (IsHost()) {
550     filename += getenv("ANDROID_HOST_OUT");
551     filename += "/framework/";
552   } else {
553     filename += ART_TARGET_NATIVETEST_DIR_STRING;
554   }
555   filename += "art-gtest-";
556   filename += name;
557   filename += ".jar";
558   return filename;
559 }
560 
OpenTestDexFiles(const char * name)561 std::vector<std::unique_ptr<const DexFile>> CommonRuntimeTestImpl::OpenTestDexFiles(
562     const char* name) {
563   std::string filename = GetTestDexFileName(name);
564   static constexpr bool kVerifyChecksum = true;
565   std::string error_msg;
566   std::vector<std::unique_ptr<const DexFile>> dex_files;
567   bool success = DexFile::Open(
568       filename.c_str(), filename.c_str(), kVerifyChecksum, &error_msg, &dex_files);
569   CHECK(success) << "Failed to open '" << filename << "': " << error_msg;
570   for (auto& dex_file : dex_files) {
571     CHECK_EQ(PROT_READ, dex_file->GetPermissions());
572     CHECK(dex_file->IsReadOnly());
573   }
574   return dex_files;
575 }
576 
OpenTestDexFile(const char * name)577 std::unique_ptr<const DexFile> CommonRuntimeTestImpl::OpenTestDexFile(const char* name) {
578   std::vector<std::unique_ptr<const DexFile>> vector = OpenTestDexFiles(name);
579   EXPECT_EQ(1U, vector.size());
580   return std::move(vector[0]);
581 }
582 
GetDexFiles(jobject jclass_loader)583 std::vector<const DexFile*> CommonRuntimeTestImpl::GetDexFiles(jobject jclass_loader) {
584   std::vector<const DexFile*> ret;
585 
586   ScopedObjectAccess soa(Thread::Current());
587 
588   StackHandleScope<2> hs(soa.Self());
589   Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
590       soa.Decode<mirror::ClassLoader>(jclass_loader));
591 
592   DCHECK_EQ(class_loader->GetClass(),
593             soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader));
594   DCHECK_EQ(class_loader->GetParent()->GetClass(),
595             soa.Decode<mirror::Class>(WellKnownClasses::java_lang_BootClassLoader));
596 
597   // The class loader is a PathClassLoader which inherits from BaseDexClassLoader.
598   // We need to get the DexPathList and loop through it.
599   ArtField* cookie_field = jni::DecodeArtField(WellKnownClasses::dalvik_system_DexFile_cookie);
600   ArtField* dex_file_field =
601       jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile);
602   ObjPtr<mirror::Object> dex_path_list =
603       jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_pathList)->
604           GetObject(class_loader.Get());
605   if (dex_path_list != nullptr && dex_file_field!= nullptr && cookie_field != nullptr) {
606     // DexPathList has an array dexElements of Elements[] which each contain a dex file.
607     ObjPtr<mirror::Object> dex_elements_obj =
608         jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList_dexElements)->
609             GetObject(dex_path_list);
610     // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look
611     // at the mCookie which is a DexFile vector.
612     if (dex_elements_obj != nullptr) {
613       Handle<mirror::ObjectArray<mirror::Object>> dex_elements =
614           hs.NewHandle(dex_elements_obj->AsObjectArray<mirror::Object>());
615       for (int32_t i = 0; i < dex_elements->GetLength(); ++i) {
616         ObjPtr<mirror::Object> element = dex_elements->GetWithoutChecks(i);
617         if (element == nullptr) {
618           // Should never happen, fall back to java code to throw a NPE.
619           break;
620         }
621         ObjPtr<mirror::Object> dex_file = dex_file_field->GetObject(element);
622         if (dex_file != nullptr) {
623           ObjPtr<mirror::LongArray> long_array = cookie_field->GetObject(dex_file)->AsLongArray();
624           DCHECK(long_array != nullptr);
625           int32_t long_array_size = long_array->GetLength();
626           for (int32_t j = kDexFileIndexStart; j < long_array_size; ++j) {
627             const DexFile* cp_dex_file = reinterpret_cast<const DexFile*>(static_cast<uintptr_t>(
628                 long_array->GetWithoutChecks(j)));
629             if (cp_dex_file == nullptr) {
630               LOG(WARNING) << "Null DexFile";
631               continue;
632             }
633             ret.push_back(cp_dex_file);
634           }
635         }
636       }
637     }
638   }
639 
640   return ret;
641 }
642 
GetFirstDexFile(jobject jclass_loader)643 const DexFile* CommonRuntimeTestImpl::GetFirstDexFile(jobject jclass_loader) {
644   std::vector<const DexFile*> tmp(GetDexFiles(jclass_loader));
645   DCHECK(!tmp.empty());
646   const DexFile* ret = tmp[0];
647   DCHECK(ret != nullptr);
648   return ret;
649 }
650 
LoadMultiDex(const char * first_dex_name,const char * second_dex_name)651 jobject CommonRuntimeTestImpl::LoadMultiDex(const char* first_dex_name,
652                                             const char* second_dex_name) {
653   std::vector<std::unique_ptr<const DexFile>> first_dex_files = OpenTestDexFiles(first_dex_name);
654   std::vector<std::unique_ptr<const DexFile>> second_dex_files = OpenTestDexFiles(second_dex_name);
655   std::vector<const DexFile*> class_path;
656   CHECK_NE(0U, first_dex_files.size());
657   CHECK_NE(0U, second_dex_files.size());
658   for (auto& dex_file : first_dex_files) {
659     class_path.push_back(dex_file.get());
660     loaded_dex_files_.push_back(std::move(dex_file));
661   }
662   for (auto& dex_file : second_dex_files) {
663     class_path.push_back(dex_file.get());
664     loaded_dex_files_.push_back(std::move(dex_file));
665   }
666 
667   Thread* self = Thread::Current();
668   jobject class_loader = Runtime::Current()->GetClassLinker()->CreatePathClassLoader(self,
669                                                                                      class_path);
670   self->SetClassLoaderOverride(class_loader);
671   return class_loader;
672 }
673 
LoadDex(const char * dex_name)674 jobject CommonRuntimeTestImpl::LoadDex(const char* dex_name) {
675   std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(dex_name);
676   std::vector<const DexFile*> class_path;
677   CHECK_NE(0U, dex_files.size());
678   for (auto& dex_file : dex_files) {
679     class_path.push_back(dex_file.get());
680     loaded_dex_files_.push_back(std::move(dex_file));
681   }
682 
683   Thread* self = Thread::Current();
684   jobject class_loader = Runtime::Current()->GetClassLinker()->CreatePathClassLoader(self,
685                                                                                      class_path);
686   self->SetClassLoaderOverride(class_loader);
687   return class_loader;
688 }
689 
GetCoreFileLocation(const char * suffix)690 std::string CommonRuntimeTestImpl::GetCoreFileLocation(const char* suffix) {
691   CHECK(suffix != nullptr);
692 
693   std::string location;
694   if (IsHost()) {
695     const char* host_dir = getenv("ANDROID_HOST_OUT");
696     CHECK(host_dir != nullptr);
697     location = StringPrintf("%s/framework/core.%s", host_dir, suffix);
698   } else {
699     location = StringPrintf("/data/art-test/core.%s", suffix);
700   }
701 
702   return location;
703 }
704 
CheckJniAbortCatcher()705 CheckJniAbortCatcher::CheckJniAbortCatcher() : vm_(Runtime::Current()->GetJavaVM()) {
706   vm_->SetCheckJniAbortHook(Hook, &actual_);
707 }
708 
~CheckJniAbortCatcher()709 CheckJniAbortCatcher::~CheckJniAbortCatcher() {
710   vm_->SetCheckJniAbortHook(nullptr, nullptr);
711   EXPECT_TRUE(actual_.empty()) << actual_;
712 }
713 
Check(const std::string & expected_text)714 void CheckJniAbortCatcher::Check(const std::string& expected_text) {
715   Check(expected_text.c_str());
716 }
717 
Check(const char * expected_text)718 void CheckJniAbortCatcher::Check(const char* expected_text) {
719   EXPECT_TRUE(actual_.find(expected_text) != std::string::npos) << "\n"
720       << "Expected to find: " << expected_text << "\n"
721       << "In the output   : " << actual_;
722   actual_.clear();
723 }
724 
Hook(void * data,const std::string & reason)725 void CheckJniAbortCatcher::Hook(void* data, const std::string& reason) {
726   // We use += because when we're hooking the aborts like this, multiple problems can be found.
727   *reinterpret_cast<std::string*>(data) += reason;
728 }
729 
730 }  // namespace art
731 
732 namespace std {
733 
734 template <typename T>
operator <<(std::ostream & os,const std::vector<T> & rhs)735 std::ostream& operator<<(std::ostream& os, const std::vector<T>& rhs) {
736 os << ::art::ToString(rhs);
737 return os;
738 }
739 
740 }  // namespace std
741