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