• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "nativehelper/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/logging.h"
31 #include "base/macros.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/heap.h"
38 #include "gc_root-inl.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 "mem_map.h"
45 #include "mirror/class-inl.h"
46 #include "mirror/class_loader.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::Abort);
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   options.push_back(std::make_pair("-XX:SlowDebug=true", nullptr));
408   static bool gSlowDebugTestFlag = false;
409   RegisterRuntimeDebugFlag(&gSlowDebugTestFlag);
410 
411   callbacks_.reset(new NoopCompilerCallbacks());
412 
413   SetUpRuntimeOptions(&options);
414 
415   // Install compiler-callbacks if SetupRuntimeOptions hasn't deleted them.
416   if (callbacks_.get() != nullptr) {
417     options.push_back(std::make_pair("compilercallbacks", callbacks_.get()));
418   }
419 
420   PreRuntimeCreate();
421   if (!Runtime::Create(options, false)) {
422     LOG(FATAL) << "Failed to create runtime";
423     return;
424   }
425   PostRuntimeCreate();
426   runtime_.reset(Runtime::Current());
427   class_linker_ = runtime_->GetClassLinker();
428 
429   // Runtime::Create acquired the mutator_lock_ that is normally given away when we
430   // Runtime::Start, give it away now and then switch to a more managable ScopedObjectAccess.
431   Thread::Current()->TransitionFromRunnableToSuspended(kNative);
432 
433   // Get the boot class path from the runtime so it can be used in tests.
434   boot_class_path_ = class_linker_->GetBootClassPath();
435   ASSERT_FALSE(boot_class_path_.empty());
436   java_lang_dex_file_ = boot_class_path_[0];
437 
438   FinalizeSetup();
439 
440   // Ensure that we're really running with debug checks enabled.
441   CHECK(gSlowDebugTestFlag);
442 }
443 
FinalizeSetup()444 void CommonRuntimeTestImpl::FinalizeSetup() {
445   // Initialize maps for unstarted runtime. This needs to be here, as running clinits needs this
446   // set up.
447   if (!unstarted_initialized_) {
448     interpreter::UnstartedRuntime::Initialize();
449     unstarted_initialized_ = true;
450   }
451 
452   {
453     ScopedObjectAccess soa(Thread::Current());
454     class_linker_->RunRootClinits();
455   }
456 
457   // We're back in native, take the opportunity to initialize well known classes.
458   WellKnownClasses::Init(Thread::Current()->GetJniEnv());
459 
460   // Create the heap thread pool so that the GC runs in parallel for tests. Normally, the thread
461   // pool is created by the runtime.
462   runtime_->GetHeap()->CreateThreadPool();
463   runtime_->GetHeap()->VerifyHeap();  // Check for heap corruption before the test
464   // Reduce timinig-dependent flakiness in OOME behavior (eg StubTest.AllocObject).
465   runtime_->GetHeap()->SetMinIntervalHomogeneousSpaceCompactionByOom(0U);
466 }
467 
ClearDirectory(const char * dirpath,bool recursive)468 void CommonRuntimeTestImpl::ClearDirectory(const char* dirpath, bool recursive) {
469   ASSERT_TRUE(dirpath != nullptr);
470   DIR* dir = opendir(dirpath);
471   ASSERT_TRUE(dir != nullptr);
472   dirent* e;
473   struct stat s;
474   while ((e = readdir(dir)) != nullptr) {
475     if ((strcmp(e->d_name, ".") == 0) || (strcmp(e->d_name, "..") == 0)) {
476       continue;
477     }
478     std::string filename(dirpath);
479     filename.push_back('/');
480     filename.append(e->d_name);
481     int stat_result = lstat(filename.c_str(), &s);
482     ASSERT_EQ(0, stat_result) << "unable to stat " << filename;
483     if (S_ISDIR(s.st_mode)) {
484       if (recursive) {
485         ClearDirectory(filename.c_str());
486         int rmdir_result = rmdir(filename.c_str());
487         ASSERT_EQ(0, rmdir_result) << filename;
488       }
489     } else {
490       int unlink_result = unlink(filename.c_str());
491       ASSERT_EQ(0, unlink_result) << filename;
492     }
493   }
494   closedir(dir);
495 }
496 
TearDown()497 void CommonRuntimeTestImpl::TearDown() {
498   const char* android_data = getenv("ANDROID_DATA");
499   ASSERT_TRUE(android_data != nullptr);
500   ClearDirectory(dalvik_cache_.c_str());
501   int rmdir_cache_result = rmdir(dalvik_cache_.c_str());
502   ASSERT_EQ(0, rmdir_cache_result);
503   TearDownAndroidData(android_data_, true);
504   dalvik_cache_.clear();
505 
506   if (runtime_ != nullptr) {
507     runtime_->GetHeap()->VerifyHeap();  // Check for heap corruption after the test
508   }
509 }
510 
GetDexFileName(const std::string & jar_prefix,bool host)511 static std::string GetDexFileName(const std::string& jar_prefix, bool host) {
512   std::string path;
513   if (host) {
514     const char* host_dir = getenv("ANDROID_HOST_OUT");
515     CHECK(host_dir != nullptr);
516     path = host_dir;
517   } else {
518     path = GetAndroidRoot();
519   }
520 
521   std::string suffix = host
522       ? "-hostdex"                 // The host version.
523       : "-testdex";                // The unstripped target version.
524 
525   return StringPrintf("%s/framework/%s%s.jar", path.c_str(), jar_prefix.c_str(), suffix.c_str());
526 }
527 
GetLibCoreDexFileNames()528 std::vector<std::string> CommonRuntimeTestImpl::GetLibCoreDexFileNames() {
529   return std::vector<std::string>({GetDexFileName("core-oj", IsHost()),
530                                    GetDexFileName("core-libart", IsHost())});
531 }
532 
GetTestAndroidRoot()533 std::string CommonRuntimeTestImpl::GetTestAndroidRoot() {
534   if (IsHost()) {
535     const char* host_dir = getenv("ANDROID_HOST_OUT");
536     CHECK(host_dir != nullptr);
537     return host_dir;
538   }
539   return GetAndroidRoot();
540 }
541 
542 // Check that for target builds we have ART_TARGET_NATIVETEST_DIR set.
543 #ifdef ART_TARGET
544 #ifndef ART_TARGET_NATIVETEST_DIR
545 #error "ART_TARGET_NATIVETEST_DIR not set."
546 #endif
547 // Wrap it as a string literal.
548 #define ART_TARGET_NATIVETEST_DIR_STRING STRINGIFY(ART_TARGET_NATIVETEST_DIR) "/"
549 #else
550 #define ART_TARGET_NATIVETEST_DIR_STRING ""
551 #endif
552 
GetTestDexFileName(const char * name) const553 std::string CommonRuntimeTestImpl::GetTestDexFileName(const char* name) const {
554   CHECK(name != nullptr);
555   std::string filename;
556   if (IsHost()) {
557     filename += getenv("ANDROID_HOST_OUT");
558     filename += "/framework/";
559   } else {
560     filename += ART_TARGET_NATIVETEST_DIR_STRING;
561   }
562   filename += "art-gtest-";
563   filename += name;
564   filename += ".jar";
565   return filename;
566 }
567 
OpenTestDexFiles(const char * name)568 std::vector<std::unique_ptr<const DexFile>> CommonRuntimeTestImpl::OpenTestDexFiles(
569     const char* name) {
570   std::string filename = GetTestDexFileName(name);
571   static constexpr bool kVerifyChecksum = true;
572   std::string error_msg;
573   std::vector<std::unique_ptr<const DexFile>> dex_files;
574   bool success = DexFile::Open(
575       filename.c_str(), filename.c_str(), kVerifyChecksum, &error_msg, &dex_files);
576   CHECK(success) << "Failed to open '" << filename << "': " << error_msg;
577   for (auto& dex_file : dex_files) {
578     CHECK_EQ(PROT_READ, dex_file->GetPermissions());
579     CHECK(dex_file->IsReadOnly());
580   }
581   return dex_files;
582 }
583 
OpenTestDexFile(const char * name)584 std::unique_ptr<const DexFile> CommonRuntimeTestImpl::OpenTestDexFile(const char* name) {
585   std::vector<std::unique_ptr<const DexFile>> vector = OpenTestDexFiles(name);
586   EXPECT_EQ(1U, vector.size());
587   return std::move(vector[0]);
588 }
589 
GetDexFiles(jobject jclass_loader)590 std::vector<const DexFile*> CommonRuntimeTestImpl::GetDexFiles(jobject jclass_loader) {
591   ScopedObjectAccess soa(Thread::Current());
592 
593   StackHandleScope<1> hs(soa.Self());
594   Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
595       soa.Decode<mirror::ClassLoader>(jclass_loader));
596   return GetDexFiles(soa, class_loader);
597 }
598 
GetDexFiles(ScopedObjectAccess & soa,Handle<mirror::ClassLoader> class_loader)599 std::vector<const DexFile*> CommonRuntimeTestImpl::GetDexFiles(
600     ScopedObjectAccess& soa,
601     Handle<mirror::ClassLoader> class_loader) {
602   std::vector<const DexFile*> ret;
603 
604   DCHECK(
605       (class_loader->GetClass() ==
606           soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader)) ||
607       (class_loader->GetClass() ==
608           soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_DelegateLastClassLoader)));
609 
610   // The class loader is a PathClassLoader which inherits from BaseDexClassLoader.
611   // We need to get the DexPathList and loop through it.
612   ArtField* cookie_field = jni::DecodeArtField(WellKnownClasses::dalvik_system_DexFile_cookie);
613   ArtField* dex_file_field =
614       jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile);
615   ObjPtr<mirror::Object> dex_path_list =
616       jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_pathList)->
617           GetObject(class_loader.Get());
618   if (dex_path_list != nullptr && dex_file_field!= nullptr && cookie_field != nullptr) {
619     // DexPathList has an array dexElements of Elements[] which each contain a dex file.
620     ObjPtr<mirror::Object> dex_elements_obj =
621         jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList_dexElements)->
622             GetObject(dex_path_list);
623     // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look
624     // at the mCookie which is a DexFile vector.
625     if (dex_elements_obj != nullptr) {
626       StackHandleScope<1> hs(soa.Self());
627       Handle<mirror::ObjectArray<mirror::Object>> dex_elements =
628           hs.NewHandle(dex_elements_obj->AsObjectArray<mirror::Object>());
629       for (int32_t i = 0; i < dex_elements->GetLength(); ++i) {
630         ObjPtr<mirror::Object> element = dex_elements->GetWithoutChecks(i);
631         if (element == nullptr) {
632           // Should never happen, fall back to java code to throw a NPE.
633           break;
634         }
635         ObjPtr<mirror::Object> dex_file = dex_file_field->GetObject(element);
636         if (dex_file != nullptr) {
637           ObjPtr<mirror::LongArray> long_array = cookie_field->GetObject(dex_file)->AsLongArray();
638           DCHECK(long_array != nullptr);
639           int32_t long_array_size = long_array->GetLength();
640           for (int32_t j = kDexFileIndexStart; j < long_array_size; ++j) {
641             const DexFile* cp_dex_file = reinterpret_cast<const DexFile*>(static_cast<uintptr_t>(
642                 long_array->GetWithoutChecks(j)));
643             if (cp_dex_file == nullptr) {
644               LOG(WARNING) << "Null DexFile";
645               continue;
646             }
647             ret.push_back(cp_dex_file);
648           }
649         }
650       }
651     }
652   }
653 
654   return ret;
655 }
656 
GetFirstDexFile(jobject jclass_loader)657 const DexFile* CommonRuntimeTestImpl::GetFirstDexFile(jobject jclass_loader) {
658   std::vector<const DexFile*> tmp(GetDexFiles(jclass_loader));
659   DCHECK(!tmp.empty());
660   const DexFile* ret = tmp[0];
661   DCHECK(ret != nullptr);
662   return ret;
663 }
664 
LoadMultiDex(const char * first_dex_name,const char * second_dex_name)665 jobject CommonRuntimeTestImpl::LoadMultiDex(const char* first_dex_name,
666                                             const char* second_dex_name) {
667   std::vector<std::unique_ptr<const DexFile>> first_dex_files = OpenTestDexFiles(first_dex_name);
668   std::vector<std::unique_ptr<const DexFile>> second_dex_files = OpenTestDexFiles(second_dex_name);
669   std::vector<const DexFile*> class_path;
670   CHECK_NE(0U, first_dex_files.size());
671   CHECK_NE(0U, second_dex_files.size());
672   for (auto& dex_file : first_dex_files) {
673     class_path.push_back(dex_file.get());
674     loaded_dex_files_.push_back(std::move(dex_file));
675   }
676   for (auto& dex_file : second_dex_files) {
677     class_path.push_back(dex_file.get());
678     loaded_dex_files_.push_back(std::move(dex_file));
679   }
680 
681   Thread* self = Thread::Current();
682   jobject class_loader = Runtime::Current()->GetClassLinker()->CreatePathClassLoader(self,
683                                                                                      class_path);
684   self->SetClassLoaderOverride(class_loader);
685   return class_loader;
686 }
687 
LoadDex(const char * dex_name)688 jobject CommonRuntimeTestImpl::LoadDex(const char* dex_name) {
689   jobject class_loader = LoadDexInPathClassLoader(dex_name, nullptr);
690   Thread::Current()->SetClassLoaderOverride(class_loader);
691   return class_loader;
692 }
693 
LoadDexInWellKnownClassLoader(const std::string & dex_name,jclass loader_class,jobject parent_loader)694 jobject CommonRuntimeTestImpl::LoadDexInWellKnownClassLoader(const std::string& dex_name,
695                                                              jclass loader_class,
696                                                              jobject parent_loader) {
697   std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(dex_name.c_str());
698   std::vector<const DexFile*> class_path;
699   CHECK_NE(0U, dex_files.size());
700   for (auto& dex_file : dex_files) {
701     class_path.push_back(dex_file.get());
702     loaded_dex_files_.push_back(std::move(dex_file));
703   }
704   Thread* self = Thread::Current();
705   ScopedObjectAccess soa(self);
706 
707   jobject result = Runtime::Current()->GetClassLinker()->CreateWellKnownClassLoader(
708       self,
709       class_path,
710       loader_class,
711       parent_loader);
712 
713   {
714     // Verify we build the correct chain.
715 
716     ObjPtr<mirror::ClassLoader> actual_class_loader = soa.Decode<mirror::ClassLoader>(result);
717     // Verify that the result has the correct class.
718     CHECK_EQ(soa.Decode<mirror::Class>(loader_class), actual_class_loader->GetClass());
719     // Verify that the parent is not null. The boot class loader will be set up as a
720     // proper object.
721     ObjPtr<mirror::ClassLoader> actual_parent(actual_class_loader->GetParent());
722     CHECK(actual_parent != nullptr);
723 
724     if (parent_loader != nullptr) {
725       // We were given a parent. Verify that it's what we expect.
726       ObjPtr<mirror::ClassLoader> expected_parent = soa.Decode<mirror::ClassLoader>(parent_loader);
727       CHECK_EQ(expected_parent, actual_parent);
728     } else {
729       // No parent given. The parent must be the BootClassLoader.
730       CHECK(Runtime::Current()->GetClassLinker()->IsBootClassLoader(soa, actual_parent));
731     }
732   }
733 
734   return result;
735 }
736 
LoadDexInPathClassLoader(const std::string & dex_name,jobject parent_loader)737 jobject CommonRuntimeTestImpl::LoadDexInPathClassLoader(const std::string& dex_name,
738                                                         jobject parent_loader) {
739   return LoadDexInWellKnownClassLoader(dex_name,
740                                        WellKnownClasses::dalvik_system_PathClassLoader,
741                                        parent_loader);
742 }
743 
LoadDexInDelegateLastClassLoader(const std::string & dex_name,jobject parent_loader)744 jobject CommonRuntimeTestImpl::LoadDexInDelegateLastClassLoader(const std::string& dex_name,
745                                                                 jobject parent_loader) {
746   return LoadDexInWellKnownClassLoader(dex_name,
747                                        WellKnownClasses::dalvik_system_DelegateLastClassLoader,
748                                        parent_loader);
749 }
750 
GetCoreFileLocation(const char * suffix)751 std::string CommonRuntimeTestImpl::GetCoreFileLocation(const char* suffix) {
752   CHECK(suffix != nullptr);
753 
754   std::string location;
755   if (IsHost()) {
756     const char* host_dir = getenv("ANDROID_HOST_OUT");
757     CHECK(host_dir != nullptr);
758     location = StringPrintf("%s/framework/core.%s", host_dir, suffix);
759   } else {
760     location = StringPrintf("/data/art-test/core.%s", suffix);
761   }
762 
763   return location;
764 }
765 
CreateClassPath(const std::vector<std::unique_ptr<const DexFile>> & dex_files)766 std::string CommonRuntimeTestImpl::CreateClassPath(
767     const std::vector<std::unique_ptr<const DexFile>>& dex_files) {
768   CHECK(!dex_files.empty());
769   std::string classpath = dex_files[0]->GetLocation();
770   for (size_t i = 1; i < dex_files.size(); i++) {
771     classpath += ":" + dex_files[i]->GetLocation();
772   }
773   return classpath;
774 }
775 
CreateClassPathWithChecksums(const std::vector<std::unique_ptr<const DexFile>> & dex_files)776 std::string CommonRuntimeTestImpl::CreateClassPathWithChecksums(
777     const std::vector<std::unique_ptr<const DexFile>>& dex_files) {
778   CHECK(!dex_files.empty());
779   std::string classpath = dex_files[0]->GetLocation() + "*" +
780       std::to_string(dex_files[0]->GetLocationChecksum());
781   for (size_t i = 1; i < dex_files.size(); i++) {
782     classpath += ":" + dex_files[i]->GetLocation() + "*" +
783         std::to_string(dex_files[i]->GetLocationChecksum());
784   }
785   return classpath;
786 }
787 
CheckJniAbortCatcher()788 CheckJniAbortCatcher::CheckJniAbortCatcher() : vm_(Runtime::Current()->GetJavaVM()) {
789   vm_->SetCheckJniAbortHook(Hook, &actual_);
790 }
791 
~CheckJniAbortCatcher()792 CheckJniAbortCatcher::~CheckJniAbortCatcher() {
793   vm_->SetCheckJniAbortHook(nullptr, nullptr);
794   EXPECT_TRUE(actual_.empty()) << actual_;
795 }
796 
Check(const std::string & expected_text)797 void CheckJniAbortCatcher::Check(const std::string& expected_text) {
798   Check(expected_text.c_str());
799 }
800 
Check(const char * expected_text)801 void CheckJniAbortCatcher::Check(const char* expected_text) {
802   EXPECT_TRUE(actual_.find(expected_text) != std::string::npos) << "\n"
803       << "Expected to find: " << expected_text << "\n"
804       << "In the output   : " << actual_;
805   actual_.clear();
806 }
807 
Hook(void * data,const std::string & reason)808 void CheckJniAbortCatcher::Hook(void* data, const std::string& reason) {
809   // We use += because when we're hooking the aborts like this, multiple problems can be found.
810   *reinterpret_cast<std::string*>(data) += reason;
811 }
812 
813 }  // namespace art
814