blob: de3a29b0d457cad7026ae358869374ca7a72d16e [file] [log] [blame]
Elliott Hugheseb02a122012-06-12 11:35:40 -07001/*
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
Ian Rogerse63db272014-07-15 15:36:11 -070017#include "common_runtime_test.h"
18
David Srbecky3e52aa42015-04-12 07:45:18 +010019#include <cstdio>
Ian Rogerse63db272014-07-15 15:36:11 -070020#include <dirent.h>
21#include <dlfcn.h>
22#include <fcntl.h>
23#include <ScopedLocalRef.h>
Andreas Gampe369810a2015-01-14 19:53:31 -080024#include <stdlib.h>
Ian Rogerse63db272014-07-15 15:36:11 -070025
26#include "../../external/icu/icu4c/source/common/unicode/uvernum.h"
Andreas Gampe1fe5e5c2014-07-11 21:14:35 -070027#include "base/macros.h"
Elliott Hughes07ed66b2012-12-12 18:34:25 -080028#include "base/logging.h"
Ian Rogerse63db272014-07-15 15:36:11 -070029#include "base/stl_util.h"
30#include "base/stringprintf.h"
31#include "base/unix_file/fd_file.h"
32#include "class_linker.h"
33#include "compiler_callbacks.h"
34#include "dex_file.h"
Hiroshi Yamauchi94f7b492014-07-22 18:08:23 -070035#include "gc_root-inl.h"
Ian Rogerse63db272014-07-15 15:36:11 -070036#include "gc/heap.h"
Elliott Hugheseb02a122012-06-12 11:35:40 -070037#include "gtest/gtest.h"
Andreas Gampe81c6f8d2015-03-25 17:19:53 -070038#include "handle_scope-inl.h"
Andreas Gampe9b5cba42015-03-11 09:53:50 -070039#include "interpreter/unstarted_runtime.h"
Ian Rogerse63db272014-07-15 15:36:11 -070040#include "jni_internal.h"
41#include "mirror/class_loader.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080042#include "mem_map.h"
Ian Rogerse63db272014-07-15 15:36:11 -070043#include "noop_compiler_callbacks.h"
44#include "os.h"
45#include "runtime-inl.h"
46#include "scoped_thread_state_change.h"
47#include "thread.h"
48#include "well_known_classes.h"
Elliott Hugheseb02a122012-06-12 11:35:40 -070049
50int main(int argc, char **argv) {
Andreas Gampe369810a2015-01-14 19:53:31 -080051 // Gtests can be very noisy. For example, an executable with multiple tests will trigger native
52 // bridge warnings. The following line reduces the minimum log severity to ERROR and suppresses
53 // everything else. In case you want to see all messages, comment out the line.
Richard Uhler892fc962015-03-10 16:57:05 +000054 setenv("ANDROID_LOG_TAGS", "*:e", 1);
Andreas Gampe369810a2015-01-14 19:53:31 -080055
Elliott Hugheseb02a122012-06-12 11:35:40 -070056 art::InitLogging(argv);
Ian Rogersc7dd2952014-10-21 23:31:19 -070057 LOG(::art::INFO) << "Running main() from common_runtime_test.cc...";
Elliott Hugheseb02a122012-06-12 11:35:40 -070058 testing::InitGoogleTest(&argc, argv);
59 return RUN_ALL_TESTS();
60}
Ian Rogerse63db272014-07-15 15:36:11 -070061
62namespace art {
63
64ScratchFile::ScratchFile() {
65 // ANDROID_DATA needs to be set
66 CHECK_NE(static_cast<char*>(nullptr), getenv("ANDROID_DATA")) <<
67 "Are you subclassing RuntimeTest?";
68 filename_ = getenv("ANDROID_DATA");
69 filename_ += "/TmpFile-XXXXXX";
70 int fd = mkstemp(&filename_[0]);
71 CHECK_NE(-1, fd);
Andreas Gampe4303ba92014-11-06 01:00:46 -080072 file_.reset(new File(fd, GetFilename(), true));
Ian Rogerse63db272014-07-15 15:36:11 -070073}
74
75ScratchFile::ScratchFile(const ScratchFile& other, const char* suffix) {
76 filename_ = other.GetFilename();
77 filename_ += suffix;
78 int fd = open(filename_.c_str(), O_RDWR | O_CREAT, 0666);
79 CHECK_NE(-1, fd);
Andreas Gampe4303ba92014-11-06 01:00:46 -080080 file_.reset(new File(fd, GetFilename(), true));
Ian Rogerse63db272014-07-15 15:36:11 -070081}
82
83ScratchFile::ScratchFile(File* file) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -070084 CHECK(file != nullptr);
Ian Rogerse63db272014-07-15 15:36:11 -070085 filename_ = file->GetPath();
86 file_.reset(file);
87}
88
89ScratchFile::~ScratchFile() {
90 Unlink();
91}
92
93int ScratchFile::GetFd() const {
94 return file_->Fd();
95}
96
Andreas Gampee21dc3d2014-12-08 16:59:43 -080097void ScratchFile::Close() {
Andreas Gampe4303ba92014-11-06 01:00:46 -080098 if (file_.get() != nullptr) {
99 if (file_->FlushCloseOrErase() != 0) {
100 PLOG(WARNING) << "Error closing scratch file.";
101 }
102 }
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800103}
104
105void ScratchFile::Unlink() {
106 if (!OS::FileExists(filename_.c_str())) {
107 return;
108 }
109 Close();
Ian Rogerse63db272014-07-15 15:36:11 -0700110 int unlink_result = unlink(filename_.c_str());
111 CHECK_EQ(0, unlink_result);
112}
113
Andreas Gampe9b5cba42015-03-11 09:53:50 -0700114static bool unstarted_initialized_ = false;
115
Ian Rogerse63db272014-07-15 15:36:11 -0700116CommonRuntimeTest::CommonRuntimeTest() {}
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800117CommonRuntimeTest::~CommonRuntimeTest() {
118 // Ensure the dex files are cleaned up before the runtime.
119 loaded_dex_files_.clear();
120 runtime_.reset();
121}
Ian Rogerse63db272014-07-15 15:36:11 -0700122
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700123void CommonRuntimeTest::SetUpAndroidRoot() {
Ian Rogerse63db272014-07-15 15:36:11 -0700124 if (IsHost()) {
125 // $ANDROID_ROOT is set on the device, but not necessarily on the host.
126 // But it needs to be set so that icu4c can find its locale data.
127 const char* android_root_from_env = getenv("ANDROID_ROOT");
128 if (android_root_from_env == nullptr) {
129 // Use ANDROID_HOST_OUT for ANDROID_ROOT if it is set.
130 const char* android_host_out = getenv("ANDROID_HOST_OUT");
131 if (android_host_out != nullptr) {
132 setenv("ANDROID_ROOT", android_host_out, 1);
133 } else {
134 // Build it from ANDROID_BUILD_TOP or cwd
135 std::string root;
136 const char* android_build_top = getenv("ANDROID_BUILD_TOP");
137 if (android_build_top != nullptr) {
138 root += android_build_top;
139 } else {
140 // Not set by build server, so default to current directory
141 char* cwd = getcwd(nullptr, 0);
142 setenv("ANDROID_BUILD_TOP", cwd, 1);
143 root += cwd;
144 free(cwd);
145 }
146#if defined(__linux__)
147 root += "/out/host/linux-x86";
148#elif defined(__APPLE__)
149 root += "/out/host/darwin-x86";
150#else
151#error unsupported OS
152#endif
153 setenv("ANDROID_ROOT", root.c_str(), 1);
154 }
155 }
156 setenv("LD_LIBRARY_PATH", ":", 0); // Required by java.lang.System.<clinit>.
157
158 // Not set by build server, so default
159 if (getenv("ANDROID_HOST_OUT") == nullptr) {
160 setenv("ANDROID_HOST_OUT", getenv("ANDROID_ROOT"), 1);
161 }
162 }
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700163}
Ian Rogerse63db272014-07-15 15:36:11 -0700164
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700165void CommonRuntimeTest::SetUpAndroidData(std::string& android_data) {
Ian Rogerse63db272014-07-15 15:36:11 -0700166 // On target, Cannot use /mnt/sdcard because it is mounted noexec, so use subdir of dalvik-cache
Andreas Gampe5a79fde2014-08-06 13:12:26 -0700167 if (IsHost()) {
168 const char* tmpdir = getenv("TMPDIR");
169 if (tmpdir != nullptr && tmpdir[0] != 0) {
170 android_data = tmpdir;
171 } else {
172 android_data = "/tmp";
173 }
174 } else {
175 android_data = "/data/dalvik-cache";
176 }
177 android_data += "/art-data-XXXXXX";
Ian Rogerse63db272014-07-15 15:36:11 -0700178 if (mkdtemp(&android_data[0]) == nullptr) {
179 PLOG(FATAL) << "mkdtemp(\"" << &android_data[0] << "\") failed";
180 }
181 setenv("ANDROID_DATA", android_data.c_str(), 1);
182}
183
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700184void CommonRuntimeTest::TearDownAndroidData(const std::string& android_data, bool fail_on_error) {
185 if (fail_on_error) {
186 ASSERT_EQ(rmdir(android_data.c_str()), 0);
187 } else {
188 rmdir(android_data.c_str());
189 }
190}
191
David Srbecky3e52aa42015-04-12 07:45:18 +0100192// Helper - find directory with the following format:
193// ${ANDROID_BUILD_TOP}/${subdir1}/${subdir2}-${version}/${subdir3}/bin/
194static std::string GetAndroidToolsDir(const std::string& subdir1,
195 const std::string& subdir2,
196 const std::string& subdir3) {
197 std::string root;
198 const char* android_build_top = getenv("ANDROID_BUILD_TOP");
199 if (android_build_top != nullptr) {
200 root = android_build_top;
201 } else {
202 // Not set by build server, so default to current directory
203 char* cwd = getcwd(nullptr, 0);
204 setenv("ANDROID_BUILD_TOP", cwd, 1);
205 root = cwd;
206 free(cwd);
207 }
208
209 std::string toolsdir = root + "/" + subdir1;
210 std::string founddir;
211 DIR* dir;
212 if ((dir = opendir(toolsdir.c_str())) != nullptr) {
213 float maxversion = 0;
214 struct dirent* entry;
215 while ((entry = readdir(dir)) != nullptr) {
216 std::string format = subdir2 + "-%f";
217 float version;
218 if (std::sscanf(entry->d_name, format.c_str(), &version) == 1) {
219 if (version > maxversion) {
220 maxversion = version;
221 founddir = toolsdir + "/" + entry->d_name + "/" + subdir3 + "/bin/";
222 }
223 }
224 }
225 closedir(dir);
226 }
227
228 if (founddir.empty()) {
229 ADD_FAILURE() << "Can not find Android tools directory.";
230 }
231 return founddir;
232}
233
234std::string CommonRuntimeTest::GetAndroidHostToolsDir() {
235 return GetAndroidToolsDir("prebuilts/gcc/linux-x86/host",
236 "x86_64-linux-glibc2.15",
237 "x86_64-linux");
238}
239
240std::string CommonRuntimeTest::GetAndroidTargetToolsDir(InstructionSet isa) {
241 switch (isa) {
242 case kArm:
243 case kThumb2:
244 return GetAndroidToolsDir("prebuilts/gcc/linux-x86/arm",
245 "arm-linux-androideabi",
246 "arm-linux-androideabi");
247 case kArm64:
248 return GetAndroidToolsDir("prebuilts/gcc/linux-x86/aarch64",
249 "aarch64-linux-android",
250 "aarch64-linux-android");
251 case kX86:
252 case kX86_64:
253 return GetAndroidToolsDir("prebuilts/gcc/linux-x86/x86",
254 "x86_64-linux-android",
255 "x86_64-linux-android");
256 case kMips:
257 case kMips64:
258 return GetAndroidToolsDir("prebuilts/gcc/linux-x86/mips",
259 "mips64el-linux-android",
260 "mips64el-linux-android");
261 case kNone:
262 break;
263 }
264 ADD_FAILURE() << "Invalid isa " << isa;
265 return "";
266}
267
Igor Murashkin37743352014-11-13 14:38:00 -0800268std::string CommonRuntimeTest::GetCoreArtLocation() {
269 return GetCoreFileLocation("art");
270}
271
272std::string CommonRuntimeTest::GetCoreOatLocation() {
273 return GetCoreFileLocation("oat");
274}
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700275
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800276std::unique_ptr<const DexFile> CommonRuntimeTest::LoadExpectSingleDexFile(const char* location) {
277 std::vector<std::unique_ptr<const DexFile>> dex_files;
Ian Rogerse63db272014-07-15 15:36:11 -0700278 std::string error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800279 MemMap::Init();
Ian Rogerse63db272014-07-15 15:36:11 -0700280 if (!DexFile::Open(location, location, &error_msg, &dex_files)) {
281 LOG(FATAL) << "Could not open .dex file '" << location << "': " << error_msg << "\n";
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800282 UNREACHABLE();
Ian Rogerse63db272014-07-15 15:36:11 -0700283 } else {
284 CHECK_EQ(1U, dex_files.size()) << "Expected only one dex file in " << location;
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800285 return std::move(dex_files[0]);
Ian Rogerse63db272014-07-15 15:36:11 -0700286 }
287}
288
289void CommonRuntimeTest::SetUp() {
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700290 SetUpAndroidRoot();
291 SetUpAndroidData(android_data_);
Ian Rogerse63db272014-07-15 15:36:11 -0700292 dalvik_cache_.append(android_data_.c_str());
293 dalvik_cache_.append("/dalvik-cache");
294 int mkdir_result = mkdir(dalvik_cache_.c_str(), 0700);
295 ASSERT_EQ(mkdir_result, 0);
296
Ian Rogerse63db272014-07-15 15:36:11 -0700297 std::string min_heap_string(StringPrintf("-Xms%zdm", gc::Heap::kDefaultInitialSize / MB));
298 std::string max_heap_string(StringPrintf("-Xmx%zdm", gc::Heap::kDefaultMaximumSize / MB));
299
Ian Rogerse63db272014-07-15 15:36:11 -0700300
301 RuntimeOptions options;
Richard Uhlerc2752592015-01-02 13:28:22 -0800302 std::string boot_class_path_string = "-Xbootclasspath:" + GetLibCoreDexFileName();
303 options.push_back(std::make_pair(boot_class_path_string, nullptr));
Ian Rogerse63db272014-07-15 15:36:11 -0700304 options.push_back(std::make_pair("-Xcheck:jni", nullptr));
Richard Uhlerc2752592015-01-02 13:28:22 -0800305 options.push_back(std::make_pair(min_heap_string, nullptr));
306 options.push_back(std::make_pair(max_heap_string, nullptr));
Andreas Gampebb9c6b12015-03-29 13:56:36 -0700307
308 callbacks_.reset(new NoopCompilerCallbacks());
309
Ian Rogerse63db272014-07-15 15:36:11 -0700310 SetUpRuntimeOptions(&options);
Igor Murashkinaaebaa02015-01-26 10:55:53 -0800311
Andreas Gampebb9c6b12015-03-29 13:56:36 -0700312 // Install compiler-callbacks if SetupRuntimeOptions hasn't deleted them.
313 if (callbacks_.get() != nullptr) {
314 options.push_back(std::make_pair("compilercallbacks", callbacks_.get()));
315 }
316
Richard Uhler66d874d2015-01-15 09:37:19 -0800317 PreRuntimeCreate();
Ian Rogerse63db272014-07-15 15:36:11 -0700318 if (!Runtime::Create(options, false)) {
319 LOG(FATAL) << "Failed to create runtime";
320 return;
321 }
Richard Uhler66d874d2015-01-15 09:37:19 -0800322 PostRuntimeCreate();
Ian Rogerse63db272014-07-15 15:36:11 -0700323 runtime_.reset(Runtime::Current());
324 class_linker_ = runtime_->GetClassLinker();
325 class_linker_->FixupDexCaches(runtime_->GetResolutionMethod());
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700326
327 // Initialize maps for unstarted runtime. This needs to be here, as running clinits needs this
328 // set up.
Andreas Gampe9b5cba42015-03-11 09:53:50 -0700329 if (!unstarted_initialized_) {
Andreas Gampe799681b2015-05-15 19:24:12 -0700330 interpreter::UnstartedRuntime::Initialize();
Andreas Gampe9b5cba42015-03-11 09:53:50 -0700331 unstarted_initialized_ = true;
332 }
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700333
Ian Rogerse63db272014-07-15 15:36:11 -0700334 class_linker_->RunRootClinits();
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800335 boot_class_path_ = class_linker_->GetBootClassPath();
336 java_lang_dex_file_ = boot_class_path_[0];
337
Ian Rogerse63db272014-07-15 15:36:11 -0700338
339 // Runtime::Create acquired the mutator_lock_ that is normally given away when we
340 // Runtime::Start, give it away now and then switch to a more managable ScopedObjectAccess.
341 Thread::Current()->TransitionFromRunnableToSuspended(kNative);
342
343 // We're back in native, take the opportunity to initialize well known classes.
344 WellKnownClasses::Init(Thread::Current()->GetJniEnv());
345
346 // Create the heap thread pool so that the GC runs in parallel for tests. Normally, the thread
347 // pool is created by the runtime.
348 runtime_->GetHeap()->CreateThreadPool();
349 runtime_->GetHeap()->VerifyHeap(); // Check for heap corruption before the test
Hiroshi Yamauchi4460a842015-03-09 11:57:48 -0700350 // Reduce timinig-dependent flakiness in OOME behavior (eg StubTest.AllocObject).
351 runtime_->GetHeap()->SetMinIntervalHomogeneousSpaceCompactionByOom(0U);
Richard Uhlerc2752592015-01-02 13:28:22 -0800352
353 // Get the boot class path from the runtime so it can be used in tests.
354 boot_class_path_ = class_linker_->GetBootClassPath();
355 ASSERT_FALSE(boot_class_path_.empty());
356 java_lang_dex_file_ = boot_class_path_[0];
Ian Rogerse63db272014-07-15 15:36:11 -0700357}
358
Alex Lighta59dd802014-07-02 16:28:08 -0700359void CommonRuntimeTest::ClearDirectory(const char* dirpath) {
360 ASSERT_TRUE(dirpath != nullptr);
361 DIR* dir = opendir(dirpath);
Ian Rogerse63db272014-07-15 15:36:11 -0700362 ASSERT_TRUE(dir != nullptr);
363 dirent* e;
Alex Lighta59dd802014-07-02 16:28:08 -0700364 struct stat s;
Ian Rogerse63db272014-07-15 15:36:11 -0700365 while ((e = readdir(dir)) != nullptr) {
366 if ((strcmp(e->d_name, ".") == 0) || (strcmp(e->d_name, "..") == 0)) {
367 continue;
368 }
Jeff Haof0a3f092014-07-24 16:26:09 -0700369 std::string filename(dirpath);
Ian Rogerse63db272014-07-15 15:36:11 -0700370 filename.push_back('/');
371 filename.append(e->d_name);
Alex Lighta59dd802014-07-02 16:28:08 -0700372 int stat_result = lstat(filename.c_str(), &s);
373 ASSERT_EQ(0, stat_result) << "unable to stat " << filename;
374 if (S_ISDIR(s.st_mode)) {
375 ClearDirectory(filename.c_str());
376 int rmdir_result = rmdir(filename.c_str());
377 ASSERT_EQ(0, rmdir_result) << filename;
378 } else {
379 int unlink_result = unlink(filename.c_str());
380 ASSERT_EQ(0, unlink_result) << filename;
381 }
Ian Rogerse63db272014-07-15 15:36:11 -0700382 }
383 closedir(dir);
Alex Lighta59dd802014-07-02 16:28:08 -0700384}
385
386void CommonRuntimeTest::TearDown() {
387 const char* android_data = getenv("ANDROID_DATA");
388 ASSERT_TRUE(android_data != nullptr);
389 ClearDirectory(dalvik_cache_.c_str());
Ian Rogerse63db272014-07-15 15:36:11 -0700390 int rmdir_cache_result = rmdir(dalvik_cache_.c_str());
391 ASSERT_EQ(0, rmdir_cache_result);
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700392 TearDownAndroidData(android_data_, true);
Ian Rogerse63db272014-07-15 15:36:11 -0700393
394 // icu4c has a fixed 10-element array "gCommonICUDataArray".
395 // If we run > 10 tests, we fill that array and u_setCommonData fails.
396 // There's a function to clear the array, but it's not public...
397 typedef void (*IcuCleanupFn)();
398 void* sym = dlsym(RTLD_DEFAULT, "u_cleanup_" U_ICU_VERSION_SHORT);
399 CHECK(sym != nullptr) << dlerror();
400 IcuCleanupFn icu_cleanup_fn = reinterpret_cast<IcuCleanupFn>(sym);
401 (*icu_cleanup_fn)();
402
Ian Rogerse63db272014-07-15 15:36:11 -0700403 Runtime::Current()->GetHeap()->VerifyHeap(); // Check for heap corruption after the test
404}
405
406std::string CommonRuntimeTest::GetLibCoreDexFileName() {
407 return GetDexFileName("core-libart");
408}
409
410std::string CommonRuntimeTest::GetDexFileName(const std::string& jar_prefix) {
411 if (IsHost()) {
412 const char* host_dir = getenv("ANDROID_HOST_OUT");
413 CHECK(host_dir != nullptr);
414 return StringPrintf("%s/framework/%s-hostdex.jar", host_dir, jar_prefix.c_str());
415 }
416 return StringPrintf("%s/framework/%s.jar", GetAndroidRoot(), jar_prefix.c_str());
417}
418
419std::string CommonRuntimeTest::GetTestAndroidRoot() {
420 if (IsHost()) {
421 const char* host_dir = getenv("ANDROID_HOST_OUT");
422 CHECK(host_dir != nullptr);
423 return host_dir;
424 }
425 return GetAndroidRoot();
426}
427
Andreas Gampe1fe5e5c2014-07-11 21:14:35 -0700428// Check that for target builds we have ART_TARGET_NATIVETEST_DIR set.
429#ifdef ART_TARGET
430#ifndef ART_TARGET_NATIVETEST_DIR
431#error "ART_TARGET_NATIVETEST_DIR not set."
432#endif
433// Wrap it as a string literal.
434#define ART_TARGET_NATIVETEST_DIR_STRING STRINGIFY(ART_TARGET_NATIVETEST_DIR) "/"
435#else
436#define ART_TARGET_NATIVETEST_DIR_STRING ""
437#endif
438
Richard Uhler66d874d2015-01-15 09:37:19 -0800439std::string CommonRuntimeTest::GetTestDexFileName(const char* name) {
Ian Rogerse63db272014-07-15 15:36:11 -0700440 CHECK(name != nullptr);
441 std::string filename;
442 if (IsHost()) {
443 filename += getenv("ANDROID_HOST_OUT");
444 filename += "/framework/";
445 } else {
Andreas Gampe1fe5e5c2014-07-11 21:14:35 -0700446 filename += ART_TARGET_NATIVETEST_DIR_STRING;
Ian Rogerse63db272014-07-15 15:36:11 -0700447 }
448 filename += "art-gtest-";
449 filename += name;
450 filename += ".jar";
Richard Uhler66d874d2015-01-15 09:37:19 -0800451 return filename;
452}
453
454std::vector<std::unique_ptr<const DexFile>> CommonRuntimeTest::OpenTestDexFiles(const char* name) {
455 std::string filename = GetTestDexFileName(name);
Ian Rogerse63db272014-07-15 15:36:11 -0700456 std::string error_msg;
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800457 std::vector<std::unique_ptr<const DexFile>> dex_files;
Ian Rogerse63db272014-07-15 15:36:11 -0700458 bool success = DexFile::Open(filename.c_str(), filename.c_str(), &error_msg, &dex_files);
459 CHECK(success) << "Failed to open '" << filename << "': " << error_msg;
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800460 for (auto& dex_file : dex_files) {
Ian Rogerse63db272014-07-15 15:36:11 -0700461 CHECK_EQ(PROT_READ, dex_file->GetPermissions());
462 CHECK(dex_file->IsReadOnly());
463 }
Ian Rogerse63db272014-07-15 15:36:11 -0700464 return dex_files;
465}
466
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800467std::unique_ptr<const DexFile> CommonRuntimeTest::OpenTestDexFile(const char* name) {
468 std::vector<std::unique_ptr<const DexFile>> vector = OpenTestDexFiles(name);
Ian Rogerse63db272014-07-15 15:36:11 -0700469 EXPECT_EQ(1U, vector.size());
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800470 return std::move(vector[0]);
Ian Rogerse63db272014-07-15 15:36:11 -0700471}
472
Andreas Gampe81c6f8d2015-03-25 17:19:53 -0700473std::vector<const DexFile*> CommonRuntimeTest::GetDexFiles(jobject jclass_loader) {
474 std::vector<const DexFile*> ret;
475
476 ScopedObjectAccess soa(Thread::Current());
477
Mathieu Chartierc7853442015-03-27 14:35:38 -0700478 StackHandleScope<2> hs(soa.Self());
Andreas Gampe81c6f8d2015-03-25 17:19:53 -0700479 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
480 soa.Decode<mirror::ClassLoader*>(jclass_loader));
481
482 DCHECK_EQ(class_loader->GetClass(),
483 soa.Decode<mirror::Class*>(WellKnownClasses::dalvik_system_PathClassLoader));
484 DCHECK_EQ(class_loader->GetParent()->GetClass(),
485 soa.Decode<mirror::Class*>(WellKnownClasses::java_lang_BootClassLoader));
486
487 // The class loader is a PathClassLoader which inherits from BaseDexClassLoader.
488 // We need to get the DexPathList and loop through it.
Mathieu Chartierc7853442015-03-27 14:35:38 -0700489 ArtField* cookie_field = soa.DecodeField(WellKnownClasses::dalvik_system_DexFile_cookie);
490 ArtField* dex_file_field =
491 soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile);
Andreas Gampe81c6f8d2015-03-25 17:19:53 -0700492 mirror::Object* dex_path_list =
493 soa.DecodeField(WellKnownClasses::dalvik_system_PathClassLoader_pathList)->
494 GetObject(class_loader.Get());
Mathieu Chartierc7853442015-03-27 14:35:38 -0700495 if (dex_path_list != nullptr && dex_file_field!= nullptr && cookie_field != nullptr) {
Andreas Gampe81c6f8d2015-03-25 17:19:53 -0700496 // DexPathList has an array dexElements of Elements[] which each contain a dex file.
497 mirror::Object* dex_elements_obj =
498 soa.DecodeField(WellKnownClasses::dalvik_system_DexPathList_dexElements)->
499 GetObject(dex_path_list);
500 // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look
501 // at the mCookie which is a DexFile vector.
502 if (dex_elements_obj != nullptr) {
503 Handle<mirror::ObjectArray<mirror::Object>> dex_elements =
504 hs.NewHandle(dex_elements_obj->AsObjectArray<mirror::Object>());
505 for (int32_t i = 0; i < dex_elements->GetLength(); ++i) {
506 mirror::Object* element = dex_elements->GetWithoutChecks(i);
507 if (element == nullptr) {
508 // Should never happen, fall back to java code to throw a NPE.
509 break;
510 }
511 mirror::Object* dex_file = dex_file_field->GetObject(element);
512 if (dex_file != nullptr) {
513 mirror::LongArray* long_array = cookie_field->GetObject(dex_file)->AsLongArray();
514 DCHECK(long_array != nullptr);
515 int32_t long_array_size = long_array->GetLength();
516 for (int32_t j = 0; j < long_array_size; ++j) {
517 const DexFile* cp_dex_file = reinterpret_cast<const DexFile*>(static_cast<uintptr_t>(
518 long_array->GetWithoutChecks(j)));
519 if (cp_dex_file == nullptr) {
520 LOG(WARNING) << "Null DexFile";
521 continue;
522 }
523 ret.push_back(cp_dex_file);
524 }
525 }
526 }
527 }
528 }
529
530 return ret;
531}
532
533const DexFile* CommonRuntimeTest::GetFirstDexFile(jobject jclass_loader) {
534 std::vector<const DexFile*> tmp(GetDexFiles(jclass_loader));
535 DCHECK(!tmp.empty());
536 const DexFile* ret = tmp[0];
537 DCHECK(ret != nullptr);
538 return ret;
539}
540
Ian Rogerse63db272014-07-15 15:36:11 -0700541jobject CommonRuntimeTest::LoadDex(const char* dex_name) {
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800542 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(dex_name);
543 std::vector<const DexFile*> class_path;
Ian Rogerse63db272014-07-15 15:36:11 -0700544 CHECK_NE(0U, dex_files.size());
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800545 for (auto& dex_file : dex_files) {
546 class_path.push_back(dex_file.get());
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800547 loaded_dex_files_.push_back(std::move(dex_file));
Ian Rogerse63db272014-07-15 15:36:11 -0700548 }
Andreas Gampe81c6f8d2015-03-25 17:19:53 -0700549
Ian Rogers68d8b422014-07-17 11:09:10 -0700550 Thread* self = Thread::Current();
Andreas Gampe81c6f8d2015-03-25 17:19:53 -0700551 jobject class_loader = Runtime::Current()->GetClassLinker()->CreatePathClassLoader(self, class_path);
552 self->SetClassLoaderOverride(class_loader);
Ian Rogerse63db272014-07-15 15:36:11 -0700553 return class_loader;
554}
555
Igor Murashkin37743352014-11-13 14:38:00 -0800556std::string CommonRuntimeTest::GetCoreFileLocation(const char* suffix) {
557 CHECK(suffix != nullptr);
558
559 std::string location;
560 if (IsHost()) {
561 const char* host_dir = getenv("ANDROID_HOST_OUT");
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700562 CHECK(host_dir != nullptr);
Igor Murashkin37743352014-11-13 14:38:00 -0800563 location = StringPrintf("%s/framework/core.%s", host_dir, suffix);
564 } else {
565 location = StringPrintf("/data/art-test/core.%s", suffix);
566 }
567
568 return location;
569}
570
Ian Rogerse63db272014-07-15 15:36:11 -0700571CheckJniAbortCatcher::CheckJniAbortCatcher() : vm_(Runtime::Current()->GetJavaVM()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700572 vm_->SetCheckJniAbortHook(Hook, &actual_);
Ian Rogerse63db272014-07-15 15:36:11 -0700573}
574
575CheckJniAbortCatcher::~CheckJniAbortCatcher() {
Ian Rogers68d8b422014-07-17 11:09:10 -0700576 vm_->SetCheckJniAbortHook(nullptr, nullptr);
Ian Rogerse63db272014-07-15 15:36:11 -0700577 EXPECT_TRUE(actual_.empty()) << actual_;
578}
579
580void CheckJniAbortCatcher::Check(const char* expected_text) {
581 EXPECT_TRUE(actual_.find(expected_text) != std::string::npos) << "\n"
582 << "Expected to find: " << expected_text << "\n"
583 << "In the output : " << actual_;
584 actual_.clear();
585}
586
587void CheckJniAbortCatcher::Hook(void* data, const std::string& reason) {
588 // We use += because when we're hooking the aborts like this, multiple problems can be found.
589 *reinterpret_cast<std::string*>(data) += reason;
590}
591
592} // namespace art
593
594namespace std {
595
596template <typename T>
597std::ostream& operator<<(std::ostream& os, const std::vector<T>& rhs) {
598os << ::art::ToString(rhs);
599return os;
600}
601
602} // namespace std