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