blob: add300bdf3325df77dd2472c095542a14d43d3c0 [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
19#include <dirent.h>
20#include <dlfcn.h>
21#include <fcntl.h>
Andreas Gampe369810a2015-01-14 19:53:31 -080022#include <stdlib.h>
Andreas Gampe8cf9cb32017-07-19 09:28:38 -070023#include <cstdio>
Andreas Gampe373a9b52017-10-18 09:01:57 -070024#include "nativehelper/scoped_local_ref.h"
Ian Rogerse63db272014-07-15 15:36:11 -070025
Andreas Gampe46ee31b2016-12-14 10:11:49 -080026#include "android-base/stringprintf.h"
Andreas Gampefdb7a612017-11-01 15:11:13 -070027#include <unicode/uvernum.h>
Andreas Gampe46ee31b2016-12-14 10:11:49 -080028
Mathieu Chartiere401d142015-04-22 13:56:20 -070029#include "art_field-inl.h"
David Sehr891a50e2017-10-27 17:01:07 -070030#include "base/file_utils.h"
Elliott Hughes07ed66b2012-12-12 18:34:25 -080031#include "base/logging.h"
Steven Morelande431e272017-07-18 16:53:49 -070032#include "base/macros.h"
David Sehrc431b9d2018-03-02 12:01:51 -080033#include "base/mutex.h"
34#include "base/os.h"
Andreas Gampedcc528d2017-12-07 13:37:10 -080035#include "base/runtime_debug.h"
Ian Rogerse63db272014-07-15 15:36:11 -070036#include "base/stl_util.h"
Ian Rogerse63db272014-07-15 15:36:11 -070037#include "base/unix_file/fd_file.h"
38#include "class_linker.h"
39#include "compiler_callbacks.h"
David Sehr013fd802018-01-11 22:55:24 -080040#include "dex/art_dex_file_loader.h"
David Sehr9e734c72018-01-04 17:56:19 -080041#include "dex/dex_file-inl.h"
42#include "dex/dex_file_loader.h"
David Sehr67bf42e2018-02-26 16:43:04 -080043#include "dex/primitive.h"
Ian Rogerse63db272014-07-15 15:36:11 -070044#include "gc/heap.h"
Steven Morelande431e272017-07-18 16:53:49 -070045#include "gc_root-inl.h"
Elliott Hugheseb02a122012-06-12 11:35:40 -070046#include "gtest/gtest.h"
Andreas Gampe81c6f8d2015-03-25 17:19:53 -070047#include "handle_scope-inl.h"
Andreas Gampe9b5cba42015-03-11 09:53:50 -070048#include "interpreter/unstarted_runtime.h"
Andreas Gampec15a2f42017-04-21 12:09:39 -070049#include "java_vm_ext.h"
Ian Rogerse63db272014-07-15 15:36:11 -070050#include "jni_internal.h"
Steven Morelande431e272017-07-18 16:53:49 -070051#include "mem_map.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070052#include "mirror/class-inl.h"
Ian Rogerse63db272014-07-15 15:36:11 -070053#include "mirror/class_loader.h"
Mathieu Chartiere58991b2015-10-13 07:59:34 -070054#include "native/dalvik_system_DexFile.h"
Ian Rogerse63db272014-07-15 15:36:11 -070055#include "noop_compiler_callbacks.h"
Ian Rogerse63db272014-07-15 15:36:11 -070056#include "runtime-inl.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070057#include "scoped_thread_state_change-inl.h"
Ian Rogerse63db272014-07-15 15:36:11 -070058#include "thread.h"
59#include "well_known_classes.h"
Elliott Hugheseb02a122012-06-12 11:35:40 -070060
61int main(int argc, char **argv) {
Andreas Gampe369810a2015-01-14 19:53:31 -080062 // Gtests can be very noisy. For example, an executable with multiple tests will trigger native
63 // bridge warnings. The following line reduces the minimum log severity to ERROR and suppresses
64 // everything else. In case you want to see all messages, comment out the line.
Nicolas Geoffraya7a47592015-11-24 09:17:30 +000065 setenv("ANDROID_LOG_TAGS", "*:e", 1);
Andreas Gampe369810a2015-01-14 19:53:31 -080066
David Sehrc431b9d2018-03-02 12:01:51 -080067 art::Locks::Init();
Andreas Gampe51d80cc2017-06-21 21:05:13 -070068 art::InitLogging(argv, art::Runtime::Abort);
Andreas Gampe3fec9ac2016-09-13 10:47:28 -070069 LOG(INFO) << "Running main() from common_runtime_test.cc...";
Elliott Hugheseb02a122012-06-12 11:35:40 -070070 testing::InitGoogleTest(&argc, argv);
71 return RUN_ALL_TESTS();
72}
Ian Rogerse63db272014-07-15 15:36:11 -070073
74namespace art {
75
Andreas Gampe46ee31b2016-12-14 10:11:49 -080076using android::base::StringPrintf;
77
Ian Rogerse63db272014-07-15 15:36:11 -070078ScratchFile::ScratchFile() {
79 // ANDROID_DATA needs to be set
80 CHECK_NE(static_cast<char*>(nullptr), getenv("ANDROID_DATA")) <<
81 "Are you subclassing RuntimeTest?";
82 filename_ = getenv("ANDROID_DATA");
83 filename_ += "/TmpFile-XXXXXX";
84 int fd = mkstemp(&filename_[0]);
Andreas Gampe29d38e72016-03-23 15:31:51 +000085 CHECK_NE(-1, fd) << strerror(errno) << " for " << filename_;
Andreas Gampe4303ba92014-11-06 01:00:46 -080086 file_.reset(new File(fd, GetFilename(), true));
Ian Rogerse63db272014-07-15 15:36:11 -070087}
88
Mathieu Chartier866d8742016-09-21 15:24:18 -070089ScratchFile::ScratchFile(const ScratchFile& other, const char* suffix)
90 : ScratchFile(other.GetFilename() + suffix) {}
91
92ScratchFile::ScratchFile(const std::string& filename) : filename_(filename) {
Ian Rogerse63db272014-07-15 15:36:11 -070093 int fd = open(filename_.c_str(), O_RDWR | O_CREAT, 0666);
94 CHECK_NE(-1, fd);
Andreas Gampe4303ba92014-11-06 01:00:46 -080095 file_.reset(new File(fd, GetFilename(), true));
Ian Rogerse63db272014-07-15 15:36:11 -070096}
97
98ScratchFile::ScratchFile(File* file) {
Mathieu Chartier2cebb242015-04-21 16:50:40 -070099 CHECK(file != nullptr);
Ian Rogerse63db272014-07-15 15:36:11 -0700100 filename_ = file->GetPath();
101 file_.reset(file);
102}
103
Mathieu Chartier866d8742016-09-21 15:24:18 -0700104ScratchFile::ScratchFile(ScratchFile&& other) {
105 *this = std::move(other);
106}
107
108ScratchFile& ScratchFile::operator=(ScratchFile&& other) {
109 if (GetFile() != other.GetFile()) {
110 std::swap(filename_, other.filename_);
111 std::swap(file_, other.file_);
112 }
113 return *this;
114}
115
Ian Rogerse63db272014-07-15 15:36:11 -0700116ScratchFile::~ScratchFile() {
117 Unlink();
118}
119
120int ScratchFile::GetFd() const {
121 return file_->Fd();
122}
123
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800124void ScratchFile::Close() {
Andreas Gampe4303ba92014-11-06 01:00:46 -0800125 if (file_.get() != nullptr) {
126 if (file_->FlushCloseOrErase() != 0) {
127 PLOG(WARNING) << "Error closing scratch file.";
128 }
129 }
Andreas Gampee21dc3d2014-12-08 16:59:43 -0800130}
131
132void ScratchFile::Unlink() {
133 if (!OS::FileExists(filename_.c_str())) {
134 return;
135 }
136 Close();
Ian Rogerse63db272014-07-15 15:36:11 -0700137 int unlink_result = unlink(filename_.c_str());
138 CHECK_EQ(0, unlink_result);
139}
140
Andreas Gampe9b5cba42015-03-11 09:53:50 -0700141static bool unstarted_initialized_ = false;
142
Andreas Gampe48864112017-01-19 17:23:17 -0800143CommonRuntimeTestImpl::CommonRuntimeTestImpl()
144 : class_linker_(nullptr), java_lang_dex_file_(nullptr) {
145}
Mathieu Chartier91c91162016-01-15 09:48:15 -0800146
147CommonRuntimeTestImpl::~CommonRuntimeTestImpl() {
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800148 // Ensure the dex files are cleaned up before the runtime.
149 loaded_dex_files_.clear();
150 runtime_.reset();
151}
Ian Rogerse63db272014-07-15 15:36:11 -0700152
Mathieu Chartier91c91162016-01-15 09:48:15 -0800153void CommonRuntimeTestImpl::SetUpAndroidRoot() {
Ian Rogerse63db272014-07-15 15:36:11 -0700154 if (IsHost()) {
155 // $ANDROID_ROOT is set on the device, but not necessarily on the host.
156 // But it needs to be set so that icu4c can find its locale data.
157 const char* android_root_from_env = getenv("ANDROID_ROOT");
158 if (android_root_from_env == nullptr) {
159 // Use ANDROID_HOST_OUT for ANDROID_ROOT if it is set.
160 const char* android_host_out = getenv("ANDROID_HOST_OUT");
161 if (android_host_out != nullptr) {
162 setenv("ANDROID_ROOT", android_host_out, 1);
163 } else {
164 // Build it from ANDROID_BUILD_TOP or cwd
165 std::string root;
166 const char* android_build_top = getenv("ANDROID_BUILD_TOP");
167 if (android_build_top != nullptr) {
168 root += android_build_top;
169 } else {
170 // Not set by build server, so default to current directory
171 char* cwd = getcwd(nullptr, 0);
172 setenv("ANDROID_BUILD_TOP", cwd, 1);
173 root += cwd;
174 free(cwd);
175 }
176#if defined(__linux__)
177 root += "/out/host/linux-x86";
178#elif defined(__APPLE__)
179 root += "/out/host/darwin-x86";
180#else
181#error unsupported OS
182#endif
183 setenv("ANDROID_ROOT", root.c_str(), 1);
184 }
185 }
186 setenv("LD_LIBRARY_PATH", ":", 0); // Required by java.lang.System.<clinit>.
187
188 // Not set by build server, so default
189 if (getenv("ANDROID_HOST_OUT") == nullptr) {
190 setenv("ANDROID_HOST_OUT", getenv("ANDROID_ROOT"), 1);
191 }
192 }
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700193}
Ian Rogerse63db272014-07-15 15:36:11 -0700194
Mathieu Chartier91c91162016-01-15 09:48:15 -0800195void CommonRuntimeTestImpl::SetUpAndroidData(std::string& android_data) {
Ian Rogerse63db272014-07-15 15:36:11 -0700196 // On target, Cannot use /mnt/sdcard because it is mounted noexec, so use subdir of dalvik-cache
Andreas Gampe5a79fde2014-08-06 13:12:26 -0700197 if (IsHost()) {
198 const char* tmpdir = getenv("TMPDIR");
199 if (tmpdir != nullptr && tmpdir[0] != 0) {
200 android_data = tmpdir;
201 } else {
202 android_data = "/tmp";
203 }
204 } else {
205 android_data = "/data/dalvik-cache";
206 }
207 android_data += "/art-data-XXXXXX";
Ian Rogerse63db272014-07-15 15:36:11 -0700208 if (mkdtemp(&android_data[0]) == nullptr) {
209 PLOG(FATAL) << "mkdtemp(\"" << &android_data[0] << "\") failed";
210 }
211 setenv("ANDROID_DATA", android_data.c_str(), 1);
212}
213
Mathieu Chartier91c91162016-01-15 09:48:15 -0800214void CommonRuntimeTestImpl::TearDownAndroidData(const std::string& android_data,
215 bool fail_on_error) {
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700216 if (fail_on_error) {
217 ASSERT_EQ(rmdir(android_data.c_str()), 0);
218 } else {
219 rmdir(android_data.c_str());
220 }
221}
222
David Srbecky3e52aa42015-04-12 07:45:18 +0100223// Helper - find directory with the following format:
224// ${ANDROID_BUILD_TOP}/${subdir1}/${subdir2}-${version}/${subdir3}/bin/
225static std::string GetAndroidToolsDir(const std::string& subdir1,
226 const std::string& subdir2,
227 const std::string& subdir3) {
228 std::string root;
229 const char* android_build_top = getenv("ANDROID_BUILD_TOP");
230 if (android_build_top != nullptr) {
231 root = android_build_top;
232 } else {
233 // Not set by build server, so default to current directory
234 char* cwd = getcwd(nullptr, 0);
235 setenv("ANDROID_BUILD_TOP", cwd, 1);
236 root = cwd;
237 free(cwd);
238 }
239
240 std::string toolsdir = root + "/" + subdir1;
241 std::string founddir;
242 DIR* dir;
243 if ((dir = opendir(toolsdir.c_str())) != nullptr) {
244 float maxversion = 0;
245 struct dirent* entry;
246 while ((entry = readdir(dir)) != nullptr) {
247 std::string format = subdir2 + "-%f";
248 float version;
249 if (std::sscanf(entry->d_name, format.c_str(), &version) == 1) {
250 if (version > maxversion) {
251 maxversion = version;
252 founddir = toolsdir + "/" + entry->d_name + "/" + subdir3 + "/bin/";
253 }
254 }
255 }
256 closedir(dir);
257 }
258
259 if (founddir.empty()) {
Roland Levillain91d65e02016-01-19 15:59:16 +0000260 ADD_FAILURE() << "Cannot find Android tools directory.";
David Srbecky3e52aa42015-04-12 07:45:18 +0100261 }
262 return founddir;
263}
264
Mathieu Chartier91c91162016-01-15 09:48:15 -0800265std::string CommonRuntimeTestImpl::GetAndroidHostToolsDir() {
David Srbecky3e52aa42015-04-12 07:45:18 +0100266 return GetAndroidToolsDir("prebuilts/gcc/linux-x86/host",
267 "x86_64-linux-glibc2.15",
268 "x86_64-linux");
269}
270
Mathieu Chartier91c91162016-01-15 09:48:15 -0800271std::string CommonRuntimeTestImpl::GetAndroidTargetToolsDir(InstructionSet isa) {
David Srbecky3e52aa42015-04-12 07:45:18 +0100272 switch (isa) {
Vladimir Marko33bff252017-11-01 14:35:42 +0000273 case InstructionSet::kArm:
274 case InstructionSet::kThumb2:
David Srbecky3e52aa42015-04-12 07:45:18 +0100275 return GetAndroidToolsDir("prebuilts/gcc/linux-x86/arm",
276 "arm-linux-androideabi",
277 "arm-linux-androideabi");
Vladimir Marko33bff252017-11-01 14:35:42 +0000278 case InstructionSet::kArm64:
David Srbecky3e52aa42015-04-12 07:45:18 +0100279 return GetAndroidToolsDir("prebuilts/gcc/linux-x86/aarch64",
280 "aarch64-linux-android",
281 "aarch64-linux-android");
Vladimir Marko33bff252017-11-01 14:35:42 +0000282 case InstructionSet::kX86:
283 case InstructionSet::kX86_64:
David Srbecky3e52aa42015-04-12 07:45:18 +0100284 return GetAndroidToolsDir("prebuilts/gcc/linux-x86/x86",
285 "x86_64-linux-android",
286 "x86_64-linux-android");
Vladimir Marko33bff252017-11-01 14:35:42 +0000287 case InstructionSet::kMips:
288 case InstructionSet::kMips64:
David Srbecky3e52aa42015-04-12 07:45:18 +0100289 return GetAndroidToolsDir("prebuilts/gcc/linux-x86/mips",
290 "mips64el-linux-android",
291 "mips64el-linux-android");
Vladimir Marko33bff252017-11-01 14:35:42 +0000292 case InstructionSet::kNone:
David Srbecky3e52aa42015-04-12 07:45:18 +0100293 break;
294 }
295 ADD_FAILURE() << "Invalid isa " << isa;
296 return "";
297}
298
Mathieu Chartier91c91162016-01-15 09:48:15 -0800299std::string CommonRuntimeTestImpl::GetCoreArtLocation() {
Igor Murashkin37743352014-11-13 14:38:00 -0800300 return GetCoreFileLocation("art");
301}
302
Mathieu Chartier91c91162016-01-15 09:48:15 -0800303std::string CommonRuntimeTestImpl::GetCoreOatLocation() {
Igor Murashkin37743352014-11-13 14:38:00 -0800304 return GetCoreFileLocation("oat");
305}
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700306
Mathieu Chartier91c91162016-01-15 09:48:15 -0800307std::unique_ptr<const DexFile> CommonRuntimeTestImpl::LoadExpectSingleDexFile(
308 const char* location) {
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800309 std::vector<std::unique_ptr<const DexFile>> dex_files;
Ian Rogerse63db272014-07-15 15:36:11 -0700310 std::string error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800311 MemMap::Init();
Aart Bik37d6a3b2016-06-21 18:30:10 -0700312 static constexpr bool kVerifyChecksum = true;
David Sehr013fd802018-01-11 22:55:24 -0800313 const ArtDexFileLoader dex_file_loader;
314 if (!dex_file_loader.Open(
Nicolas Geoffray095c6c92017-10-19 13:59:55 +0100315 location, location, /* verify */ true, kVerifyChecksum, &error_msg, &dex_files)) {
Ian Rogerse63db272014-07-15 15:36:11 -0700316 LOG(FATAL) << "Could not open .dex file '" << location << "': " << error_msg << "\n";
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800317 UNREACHABLE();
Ian Rogerse63db272014-07-15 15:36:11 -0700318 } else {
319 CHECK_EQ(1U, dex_files.size()) << "Expected only one dex file in " << location;
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800320 return std::move(dex_files[0]);
Ian Rogerse63db272014-07-15 15:36:11 -0700321 }
322}
323
Mathieu Chartier91c91162016-01-15 09:48:15 -0800324void CommonRuntimeTestImpl::SetUp() {
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700325 SetUpAndroidRoot();
326 SetUpAndroidData(android_data_);
Ian Rogerse63db272014-07-15 15:36:11 -0700327 dalvik_cache_.append(android_data_.c_str());
328 dalvik_cache_.append("/dalvik-cache");
329 int mkdir_result = mkdir(dalvik_cache_.c_str(), 0700);
330 ASSERT_EQ(mkdir_result, 0);
331
Ian Rogerse63db272014-07-15 15:36:11 -0700332 std::string min_heap_string(StringPrintf("-Xms%zdm", gc::Heap::kDefaultInitialSize / MB));
333 std::string max_heap_string(StringPrintf("-Xmx%zdm", gc::Heap::kDefaultMaximumSize / MB));
334
Ian Rogerse63db272014-07-15 15:36:11 -0700335
336 RuntimeOptions options;
Narayan Kamathd1ef4362015-11-12 11:49:06 +0000337 std::string boot_class_path_string = "-Xbootclasspath";
338 for (const std::string &core_dex_file_name : GetLibCoreDexFileNames()) {
339 boot_class_path_string += ":";
340 boot_class_path_string += core_dex_file_name;
341 }
342
Richard Uhlerc2752592015-01-02 13:28:22 -0800343 options.push_back(std::make_pair(boot_class_path_string, nullptr));
Ian Rogerse63db272014-07-15 15:36:11 -0700344 options.push_back(std::make_pair("-Xcheck:jni", nullptr));
Richard Uhlerc2752592015-01-02 13:28:22 -0800345 options.push_back(std::make_pair(min_heap_string, nullptr));
346 options.push_back(std::make_pair(max_heap_string, nullptr));
Andreas Gampe1c5b42f2017-06-15 18:20:45 -0700347 options.push_back(std::make_pair("-XX:SlowDebug=true", nullptr));
Andreas Gampe46c4c852017-06-21 19:49:08 -0700348 static bool gSlowDebugTestFlag = false;
349 RegisterRuntimeDebugFlag(&gSlowDebugTestFlag);
Andreas Gampebb9c6b12015-03-29 13:56:36 -0700350
351 callbacks_.reset(new NoopCompilerCallbacks());
352
Ian Rogerse63db272014-07-15 15:36:11 -0700353 SetUpRuntimeOptions(&options);
Igor Murashkinaaebaa02015-01-26 10:55:53 -0800354
Andreas Gampebb9c6b12015-03-29 13:56:36 -0700355 // Install compiler-callbacks if SetupRuntimeOptions hasn't deleted them.
356 if (callbacks_.get() != nullptr) {
357 options.push_back(std::make_pair("compilercallbacks", callbacks_.get()));
358 }
359
Richard Uhler66d874d2015-01-15 09:37:19 -0800360 PreRuntimeCreate();
Ian Rogerse63db272014-07-15 15:36:11 -0700361 if (!Runtime::Create(options, false)) {
362 LOG(FATAL) << "Failed to create runtime";
363 return;
364 }
Richard Uhler66d874d2015-01-15 09:37:19 -0800365 PostRuntimeCreate();
Ian Rogerse63db272014-07-15 15:36:11 -0700366 runtime_.reset(Runtime::Current());
367 class_linker_ = runtime_->GetClassLinker();
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700368
Andreas Gampea00f0122015-12-16 16:54:35 -0800369 // Runtime::Create acquired the mutator_lock_ that is normally given away when we
370 // Runtime::Start, give it away now and then switch to a more managable ScopedObjectAccess.
371 Thread::Current()->TransitionFromRunnableToSuspended(kNative);
372
373 // Get the boot class path from the runtime so it can be used in tests.
374 boot_class_path_ = class_linker_->GetBootClassPath();
375 ASSERT_FALSE(boot_class_path_.empty());
376 java_lang_dex_file_ = boot_class_path_[0];
377
378 FinalizeSetup();
Andreas Gampe46c4c852017-06-21 19:49:08 -0700379
380 // Ensure that we're really running with debug checks enabled.
381 CHECK(gSlowDebugTestFlag);
Andreas Gampea00f0122015-12-16 16:54:35 -0800382}
383
Mathieu Chartier91c91162016-01-15 09:48:15 -0800384void CommonRuntimeTestImpl::FinalizeSetup() {
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700385 // Initialize maps for unstarted runtime. This needs to be here, as running clinits needs this
386 // set up.
Andreas Gampe9b5cba42015-03-11 09:53:50 -0700387 if (!unstarted_initialized_) {
Andreas Gampe799681b2015-05-15 19:24:12 -0700388 interpreter::UnstartedRuntime::Initialize();
Andreas Gampe9b5cba42015-03-11 09:53:50 -0700389 unstarted_initialized_ = true;
390 }
Andreas Gampe2969bcd2015-03-09 12:57:41 -0700391
Andreas Gampea00f0122015-12-16 16:54:35 -0800392 {
393 ScopedObjectAccess soa(Thread::Current());
394 class_linker_->RunRootClinits();
395 }
Ian Rogerse63db272014-07-15 15:36:11 -0700396
397 // We're back in native, take the opportunity to initialize well known classes.
398 WellKnownClasses::Init(Thread::Current()->GetJniEnv());
399
400 // Create the heap thread pool so that the GC runs in parallel for tests. Normally, the thread
401 // pool is created by the runtime.
402 runtime_->GetHeap()->CreateThreadPool();
403 runtime_->GetHeap()->VerifyHeap(); // Check for heap corruption before the test
Hiroshi Yamauchi4460a842015-03-09 11:57:48 -0700404 // Reduce timinig-dependent flakiness in OOME behavior (eg StubTest.AllocObject).
405 runtime_->GetHeap()->SetMinIntervalHomogeneousSpaceCompactionByOom(0U);
Ian Rogerse63db272014-07-15 15:36:11 -0700406}
407
Mathieu Chartierf70fe3d2017-06-21 15:24:02 -0700408void CommonRuntimeTestImpl::ClearDirectory(const char* dirpath, bool recursive) {
Alex Lighta59dd802014-07-02 16:28:08 -0700409 ASSERT_TRUE(dirpath != nullptr);
410 DIR* dir = opendir(dirpath);
Ian Rogerse63db272014-07-15 15:36:11 -0700411 ASSERT_TRUE(dir != nullptr);
412 dirent* e;
Alex Lighta59dd802014-07-02 16:28:08 -0700413 struct stat s;
Ian Rogerse63db272014-07-15 15:36:11 -0700414 while ((e = readdir(dir)) != nullptr) {
415 if ((strcmp(e->d_name, ".") == 0) || (strcmp(e->d_name, "..") == 0)) {
416 continue;
417 }
Jeff Haof0a3f092014-07-24 16:26:09 -0700418 std::string filename(dirpath);
Ian Rogerse63db272014-07-15 15:36:11 -0700419 filename.push_back('/');
420 filename.append(e->d_name);
Alex Lighta59dd802014-07-02 16:28:08 -0700421 int stat_result = lstat(filename.c_str(), &s);
422 ASSERT_EQ(0, stat_result) << "unable to stat " << filename;
423 if (S_ISDIR(s.st_mode)) {
Mathieu Chartierf70fe3d2017-06-21 15:24:02 -0700424 if (recursive) {
425 ClearDirectory(filename.c_str());
426 int rmdir_result = rmdir(filename.c_str());
427 ASSERT_EQ(0, rmdir_result) << filename;
428 }
Alex Lighta59dd802014-07-02 16:28:08 -0700429 } else {
430 int unlink_result = unlink(filename.c_str());
431 ASSERT_EQ(0, unlink_result) << filename;
432 }
Ian Rogerse63db272014-07-15 15:36:11 -0700433 }
434 closedir(dir);
Alex Lighta59dd802014-07-02 16:28:08 -0700435}
436
Mathieu Chartier91c91162016-01-15 09:48:15 -0800437void CommonRuntimeTestImpl::TearDown() {
Alex Lighta59dd802014-07-02 16:28:08 -0700438 const char* android_data = getenv("ANDROID_DATA");
439 ASSERT_TRUE(android_data != nullptr);
440 ClearDirectory(dalvik_cache_.c_str());
Ian Rogerse63db272014-07-15 15:36:11 -0700441 int rmdir_cache_result = rmdir(dalvik_cache_.c_str());
442 ASSERT_EQ(0, rmdir_cache_result);
Andreas Gampe7747c8d2014-08-06 14:53:03 -0700443 TearDownAndroidData(android_data_, true);
Andreas Gampe3f41a012016-02-18 16:53:41 -0800444 dalvik_cache_.clear();
Ian Rogerse63db272014-07-15 15:36:11 -0700445
Andreas Gampe48864112017-01-19 17:23:17 -0800446 if (runtime_ != nullptr) {
447 runtime_->GetHeap()->VerifyHeap(); // Check for heap corruption after the test
448 }
Ian Rogerse63db272014-07-15 15:36:11 -0700449}
450
Andreas Gampec7d4a582015-09-30 11:52:02 -0700451static std::string GetDexFileName(const std::string& jar_prefix, bool host) {
452 std::string path;
453 if (host) {
Ian Rogerse63db272014-07-15 15:36:11 -0700454 const char* host_dir = getenv("ANDROID_HOST_OUT");
455 CHECK(host_dir != nullptr);
Andreas Gampec7d4a582015-09-30 11:52:02 -0700456 path = host_dir;
457 } else {
458 path = GetAndroidRoot();
Ian Rogerse63db272014-07-15 15:36:11 -0700459 }
Andreas Gampec7d4a582015-09-30 11:52:02 -0700460
461 std::string suffix = host
462 ? "-hostdex" // The host version.
463 : "-testdex"; // The unstripped target version.
464
465 return StringPrintf("%s/framework/%s%s.jar", path.c_str(), jar_prefix.c_str(), suffix.c_str());
466}
467
Mathieu Chartier91c91162016-01-15 09:48:15 -0800468std::vector<std::string> CommonRuntimeTestImpl::GetLibCoreDexFileNames() {
Andreas Gampec7d4a582015-09-30 11:52:02 -0700469 return std::vector<std::string>({GetDexFileName("core-oj", IsHost()),
470 GetDexFileName("core-libart", IsHost())});
Ian Rogerse63db272014-07-15 15:36:11 -0700471}
472
Mathieu Chartier91c91162016-01-15 09:48:15 -0800473std::string CommonRuntimeTestImpl::GetTestAndroidRoot() {
Ian Rogerse63db272014-07-15 15:36:11 -0700474 if (IsHost()) {
475 const char* host_dir = getenv("ANDROID_HOST_OUT");
476 CHECK(host_dir != nullptr);
477 return host_dir;
478 }
479 return GetAndroidRoot();
480}
481
Andreas Gampe1fe5e5c2014-07-11 21:14:35 -0700482// Check that for target builds we have ART_TARGET_NATIVETEST_DIR set.
483#ifdef ART_TARGET
484#ifndef ART_TARGET_NATIVETEST_DIR
485#error "ART_TARGET_NATIVETEST_DIR not set."
486#endif
487// Wrap it as a string literal.
488#define ART_TARGET_NATIVETEST_DIR_STRING STRINGIFY(ART_TARGET_NATIVETEST_DIR) "/"
489#else
490#define ART_TARGET_NATIVETEST_DIR_STRING ""
491#endif
492
Andreas Gampee1459ae2016-06-29 09:36:30 -0700493std::string CommonRuntimeTestImpl::GetTestDexFileName(const char* name) const {
Ian Rogerse63db272014-07-15 15:36:11 -0700494 CHECK(name != nullptr);
495 std::string filename;
496 if (IsHost()) {
497 filename += getenv("ANDROID_HOST_OUT");
498 filename += "/framework/";
499 } else {
Andreas Gampe1fe5e5c2014-07-11 21:14:35 -0700500 filename += ART_TARGET_NATIVETEST_DIR_STRING;
Ian Rogerse63db272014-07-15 15:36:11 -0700501 }
502 filename += "art-gtest-";
503 filename += name;
504 filename += ".jar";
Richard Uhler66d874d2015-01-15 09:37:19 -0800505 return filename;
506}
507
Mathieu Chartier91c91162016-01-15 09:48:15 -0800508std::vector<std::unique_ptr<const DexFile>> CommonRuntimeTestImpl::OpenTestDexFiles(
509 const char* name) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800510 std::string filename = GetTestDexFileName(name);
Aart Bik37d6a3b2016-06-21 18:30:10 -0700511 static constexpr bool kVerifyChecksum = true;
Ian Rogerse63db272014-07-15 15:36:11 -0700512 std::string error_msg;
David Sehr013fd802018-01-11 22:55:24 -0800513 const ArtDexFileLoader dex_file_loader;
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800514 std::vector<std::unique_ptr<const DexFile>> dex_files;
David Sehr013fd802018-01-11 22:55:24 -0800515 bool success = dex_file_loader.Open(filename.c_str(),
516 filename.c_str(),
517 /* verify */ true,
518 kVerifyChecksum,
519 &error_msg, &dex_files);
Ian Rogerse63db272014-07-15 15:36:11 -0700520 CHECK(success) << "Failed to open '" << filename << "': " << error_msg;
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800521 for (auto& dex_file : dex_files) {
Ian Rogerse63db272014-07-15 15:36:11 -0700522 CHECK_EQ(PROT_READ, dex_file->GetPermissions());
523 CHECK(dex_file->IsReadOnly());
524 }
Ian Rogerse63db272014-07-15 15:36:11 -0700525 return dex_files;
526}
527
Mathieu Chartier91c91162016-01-15 09:48:15 -0800528std::unique_ptr<const DexFile> CommonRuntimeTestImpl::OpenTestDexFile(const char* name) {
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800529 std::vector<std::unique_ptr<const DexFile>> vector = OpenTestDexFiles(name);
Ian Rogerse63db272014-07-15 15:36:11 -0700530 EXPECT_EQ(1U, vector.size());
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800531 return std::move(vector[0]);
Ian Rogerse63db272014-07-15 15:36:11 -0700532}
533
Mathieu Chartier91c91162016-01-15 09:48:15 -0800534std::vector<const DexFile*> CommonRuntimeTestImpl::GetDexFiles(jobject jclass_loader) {
Andreas Gampe81c6f8d2015-03-25 17:19:53 -0700535 ScopedObjectAccess soa(Thread::Current());
536
Calin Juravlec79470d2017-07-12 17:37:42 -0700537 StackHandleScope<1> hs(soa.Self());
Andreas Gampe81c6f8d2015-03-25 17:19:53 -0700538 Handle<mirror::ClassLoader> class_loader = hs.NewHandle(
Mathieu Chartier0795f232016-09-27 18:43:30 -0700539 soa.Decode<mirror::ClassLoader>(jclass_loader));
Calin Juravlec79470d2017-07-12 17:37:42 -0700540 return GetDexFiles(soa, class_loader);
541}
Andreas Gampe81c6f8d2015-03-25 17:19:53 -0700542
Calin Juravlec79470d2017-07-12 17:37:42 -0700543std::vector<const DexFile*> CommonRuntimeTestImpl::GetDexFiles(
544 ScopedObjectAccess& soa,
545 Handle<mirror::ClassLoader> class_loader) {
546 std::vector<const DexFile*> ret;
547
548 DCHECK(
549 (class_loader->GetClass() ==
550 soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_PathClassLoader)) ||
551 (class_loader->GetClass() ==
552 soa.Decode<mirror::Class>(WellKnownClasses::dalvik_system_DelegateLastClassLoader)));
Andreas Gampe81c6f8d2015-03-25 17:19:53 -0700553
554 // The class loader is a PathClassLoader which inherits from BaseDexClassLoader.
555 // We need to get the DexPathList and loop through it.
Andreas Gampe08883de2016-11-08 13:20:52 -0800556 ArtField* cookie_field = jni::DecodeArtField(WellKnownClasses::dalvik_system_DexFile_cookie);
Mathieu Chartierc7853442015-03-27 14:35:38 -0700557 ArtField* dex_file_field =
Andreas Gampe08883de2016-11-08 13:20:52 -0800558 jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList__Element_dexFile);
Mathieu Chartier3398c782016-09-30 10:27:43 -0700559 ObjPtr<mirror::Object> dex_path_list =
Andreas Gampe08883de2016-11-08 13:20:52 -0800560 jni::DecodeArtField(WellKnownClasses::dalvik_system_BaseDexClassLoader_pathList)->
561 GetObject(class_loader.Get());
Mathieu Chartierc7853442015-03-27 14:35:38 -0700562 if (dex_path_list != nullptr && dex_file_field!= nullptr && cookie_field != nullptr) {
Andreas Gampe81c6f8d2015-03-25 17:19:53 -0700563 // DexPathList has an array dexElements of Elements[] which each contain a dex file.
Mathieu Chartier3398c782016-09-30 10:27:43 -0700564 ObjPtr<mirror::Object> dex_elements_obj =
Andreas Gampe08883de2016-11-08 13:20:52 -0800565 jni::DecodeArtField(WellKnownClasses::dalvik_system_DexPathList_dexElements)->
566 GetObject(dex_path_list);
Andreas Gampe81c6f8d2015-03-25 17:19:53 -0700567 // Loop through each dalvik.system.DexPathList$Element's dalvik.system.DexFile and look
568 // at the mCookie which is a DexFile vector.
569 if (dex_elements_obj != nullptr) {
Calin Juravlec79470d2017-07-12 17:37:42 -0700570 StackHandleScope<1> hs(soa.Self());
Andreas Gampe81c6f8d2015-03-25 17:19:53 -0700571 Handle<mirror::ObjectArray<mirror::Object>> dex_elements =
572 hs.NewHandle(dex_elements_obj->AsObjectArray<mirror::Object>());
573 for (int32_t i = 0; i < dex_elements->GetLength(); ++i) {
Mathieu Chartier3398c782016-09-30 10:27:43 -0700574 ObjPtr<mirror::Object> element = dex_elements->GetWithoutChecks(i);
Andreas Gampe81c6f8d2015-03-25 17:19:53 -0700575 if (element == nullptr) {
576 // Should never happen, fall back to java code to throw a NPE.
577 break;
578 }
Mathieu Chartier3398c782016-09-30 10:27:43 -0700579 ObjPtr<mirror::Object> dex_file = dex_file_field->GetObject(element);
Andreas Gampe81c6f8d2015-03-25 17:19:53 -0700580 if (dex_file != nullptr) {
Mathieu Chartier3398c782016-09-30 10:27:43 -0700581 ObjPtr<mirror::LongArray> long_array = cookie_field->GetObject(dex_file)->AsLongArray();
Andreas Gampe81c6f8d2015-03-25 17:19:53 -0700582 DCHECK(long_array != nullptr);
583 int32_t long_array_size = long_array->GetLength();
Mathieu Chartiere58991b2015-10-13 07:59:34 -0700584 for (int32_t j = kDexFileIndexStart; j < long_array_size; ++j) {
Andreas Gampe81c6f8d2015-03-25 17:19:53 -0700585 const DexFile* cp_dex_file = reinterpret_cast<const DexFile*>(static_cast<uintptr_t>(
586 long_array->GetWithoutChecks(j)));
587 if (cp_dex_file == nullptr) {
588 LOG(WARNING) << "Null DexFile";
589 continue;
590 }
591 ret.push_back(cp_dex_file);
592 }
593 }
594 }
595 }
596 }
597
598 return ret;
599}
600
Mathieu Chartier91c91162016-01-15 09:48:15 -0800601const DexFile* CommonRuntimeTestImpl::GetFirstDexFile(jobject jclass_loader) {
Andreas Gampe81c6f8d2015-03-25 17:19:53 -0700602 std::vector<const DexFile*> tmp(GetDexFiles(jclass_loader));
603 DCHECK(!tmp.empty());
604 const DexFile* ret = tmp[0];
605 DCHECK(ret != nullptr);
606 return ret;
607}
608
Nicolas Geoffrayd01f60c2016-10-28 14:45:48 +0100609jobject CommonRuntimeTestImpl::LoadMultiDex(const char* first_dex_name,
610 const char* second_dex_name) {
611 std::vector<std::unique_ptr<const DexFile>> first_dex_files = OpenTestDexFiles(first_dex_name);
612 std::vector<std::unique_ptr<const DexFile>> second_dex_files = OpenTestDexFiles(second_dex_name);
613 std::vector<const DexFile*> class_path;
614 CHECK_NE(0U, first_dex_files.size());
615 CHECK_NE(0U, second_dex_files.size());
616 for (auto& dex_file : first_dex_files) {
617 class_path.push_back(dex_file.get());
618 loaded_dex_files_.push_back(std::move(dex_file));
619 }
620 for (auto& dex_file : second_dex_files) {
621 class_path.push_back(dex_file.get());
622 loaded_dex_files_.push_back(std::move(dex_file));
623 }
624
625 Thread* self = Thread::Current();
626 jobject class_loader = Runtime::Current()->GetClassLinker()->CreatePathClassLoader(self,
627 class_path);
628 self->SetClassLoaderOverride(class_loader);
629 return class_loader;
630}
631
Mathieu Chartier91c91162016-01-15 09:48:15 -0800632jobject CommonRuntimeTestImpl::LoadDex(const char* dex_name) {
Calin Juravle7865ac72017-06-28 11:03:12 -0700633 jobject class_loader = LoadDexInPathClassLoader(dex_name, nullptr);
634 Thread::Current()->SetClassLoaderOverride(class_loader);
635 return class_loader;
636}
637
638jobject CommonRuntimeTestImpl::LoadDexInWellKnownClassLoader(const std::string& dex_name,
639 jclass loader_class,
640 jobject parent_loader) {
641 std::vector<std::unique_ptr<const DexFile>> dex_files = OpenTestDexFiles(dex_name.c_str());
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800642 std::vector<const DexFile*> class_path;
Ian Rogerse63db272014-07-15 15:36:11 -0700643 CHECK_NE(0U, dex_files.size());
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800644 for (auto& dex_file : dex_files) {
645 class_path.push_back(dex_file.get());
Richard Uhlerfbef44d2014-12-23 09:48:51 -0800646 loaded_dex_files_.push_back(std::move(dex_file));
Ian Rogerse63db272014-07-15 15:36:11 -0700647 }
Ian Rogers68d8b422014-07-17 11:09:10 -0700648 Thread* self = Thread::Current();
Calin Juravle7865ac72017-06-28 11:03:12 -0700649 ScopedObjectAccess soa(self);
650
651 jobject result = Runtime::Current()->GetClassLinker()->CreateWellKnownClassLoader(
652 self,
653 class_path,
654 loader_class,
655 parent_loader);
656
657 {
658 // Verify we build the correct chain.
659
660 ObjPtr<mirror::ClassLoader> actual_class_loader = soa.Decode<mirror::ClassLoader>(result);
661 // Verify that the result has the correct class.
662 CHECK_EQ(soa.Decode<mirror::Class>(loader_class), actual_class_loader->GetClass());
663 // Verify that the parent is not null. The boot class loader will be set up as a
664 // proper object.
665 ObjPtr<mirror::ClassLoader> actual_parent(actual_class_loader->GetParent());
666 CHECK(actual_parent != nullptr);
667
668 if (parent_loader != nullptr) {
669 // We were given a parent. Verify that it's what we expect.
670 ObjPtr<mirror::ClassLoader> expected_parent = soa.Decode<mirror::ClassLoader>(parent_loader);
671 CHECK_EQ(expected_parent, actual_parent);
672 } else {
673 // No parent given. The parent must be the BootClassLoader.
674 CHECK(Runtime::Current()->GetClassLinker()->IsBootClassLoader(soa, actual_parent));
675 }
676 }
677
678 return result;
679}
680
681jobject CommonRuntimeTestImpl::LoadDexInPathClassLoader(const std::string& dex_name,
682 jobject parent_loader) {
683 return LoadDexInWellKnownClassLoader(dex_name,
684 WellKnownClasses::dalvik_system_PathClassLoader,
685 parent_loader);
686}
687
688jobject CommonRuntimeTestImpl::LoadDexInDelegateLastClassLoader(const std::string& dex_name,
689 jobject parent_loader) {
690 return LoadDexInWellKnownClassLoader(dex_name,
691 WellKnownClasses::dalvik_system_DelegateLastClassLoader,
692 parent_loader);
Ian Rogerse63db272014-07-15 15:36:11 -0700693}
694
Mathieu Chartier91c91162016-01-15 09:48:15 -0800695std::string CommonRuntimeTestImpl::GetCoreFileLocation(const char* suffix) {
Igor Murashkin37743352014-11-13 14:38:00 -0800696 CHECK(suffix != nullptr);
697
698 std::string location;
699 if (IsHost()) {
700 const char* host_dir = getenv("ANDROID_HOST_OUT");
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700701 CHECK(host_dir != nullptr);
Richard Uhler67e1dc52017-02-06 16:50:17 +0000702 location = StringPrintf("%s/framework/core.%s", host_dir, suffix);
Igor Murashkin37743352014-11-13 14:38:00 -0800703 } else {
Richard Uhler67e1dc52017-02-06 16:50:17 +0000704 location = StringPrintf("/data/art-test/core.%s", suffix);
Igor Murashkin37743352014-11-13 14:38:00 -0800705 }
706
707 return location;
708}
709
Calin Juravlec79470d2017-07-12 17:37:42 -0700710std::string CommonRuntimeTestImpl::CreateClassPath(
711 const std::vector<std::unique_ptr<const DexFile>>& dex_files) {
712 CHECK(!dex_files.empty());
713 std::string classpath = dex_files[0]->GetLocation();
714 for (size_t i = 1; i < dex_files.size(); i++) {
715 classpath += ":" + dex_files[i]->GetLocation();
716 }
717 return classpath;
718}
719
720std::string CommonRuntimeTestImpl::CreateClassPathWithChecksums(
721 const std::vector<std::unique_ptr<const DexFile>>& dex_files) {
722 CHECK(!dex_files.empty());
723 std::string classpath = dex_files[0]->GetLocation() + "*" +
724 std::to_string(dex_files[0]->GetLocationChecksum());
725 for (size_t i = 1; i < dex_files.size(); i++) {
726 classpath += ":" + dex_files[i]->GetLocation() + "*" +
727 std::to_string(dex_files[i]->GetLocationChecksum());
728 }
729 return classpath;
730}
731
Andreas Gampe26761f72017-07-20 18:00:39 -0700732void CommonRuntimeTestImpl::FillHeap(Thread* self,
733 ClassLinker* class_linker,
734 VariableSizedHandleScope* handle_scope) {
735 DCHECK(handle_scope != nullptr);
736
737 Runtime::Current()->GetHeap()->SetIdealFootprint(1 * GB);
738
739 // Class java.lang.Object.
740 Handle<mirror::Class> c(handle_scope->NewHandle(
741 class_linker->FindSystemClass(self, "Ljava/lang/Object;")));
742 // Array helps to fill memory faster.
743 Handle<mirror::Class> ca(handle_scope->NewHandle(
744 class_linker->FindSystemClass(self, "[Ljava/lang/Object;")));
745
746 // Start allocating with ~128K
747 size_t length = 128 * KB;
748 while (length > 40) {
749 const int32_t array_length = length / 4; // Object[] has elements of size 4.
750 MutableHandle<mirror::Object> h(handle_scope->NewHandle<mirror::Object>(
751 mirror::ObjectArray<mirror::Object>::Alloc(self, ca.Get(), array_length)));
752 if (self->IsExceptionPending() || h == nullptr) {
753 self->ClearException();
754
755 // Try a smaller length
756 length = length / 2;
757 // Use at most a quarter the reported free space.
758 size_t mem = Runtime::Current()->GetHeap()->GetFreeMemory();
759 if (length * 4 > mem) {
760 length = mem / 4;
761 }
762 }
763 }
764
765 // Allocate simple objects till it fails.
766 while (!self->IsExceptionPending()) {
767 handle_scope->NewHandle<mirror::Object>(c->AllocObject(self));
768 }
769 self->ClearException();
770}
771
772void CommonRuntimeTestImpl::SetUpRuntimeOptionsForFillHeap(RuntimeOptions *options) {
773 // Use a smaller heap
774 bool found = false;
775 for (std::pair<std::string, const void*>& pair : *options) {
776 if (pair.first.find("-Xmx") == 0) {
777 pair.first = "-Xmx4M"; // Smallest we can go.
778 found = true;
779 }
780 }
781 if (!found) {
782 options->emplace_back("-Xmx4M", nullptr);
783 }
784}
785
Ian Rogerse63db272014-07-15 15:36:11 -0700786CheckJniAbortCatcher::CheckJniAbortCatcher() : vm_(Runtime::Current()->GetJavaVM()) {
Ian Rogers68d8b422014-07-17 11:09:10 -0700787 vm_->SetCheckJniAbortHook(Hook, &actual_);
Ian Rogerse63db272014-07-15 15:36:11 -0700788}
789
790CheckJniAbortCatcher::~CheckJniAbortCatcher() {
Ian Rogers68d8b422014-07-17 11:09:10 -0700791 vm_->SetCheckJniAbortHook(nullptr, nullptr);
Ian Rogerse63db272014-07-15 15:36:11 -0700792 EXPECT_TRUE(actual_.empty()) << actual_;
793}
794
Igor Murashkin367f3dd2016-09-01 17:00:24 -0700795void CheckJniAbortCatcher::Check(const std::string& expected_text) {
796 Check(expected_text.c_str());
797}
798
Ian Rogerse63db272014-07-15 15:36:11 -0700799void CheckJniAbortCatcher::Check(const char* expected_text) {
800 EXPECT_TRUE(actual_.find(expected_text) != std::string::npos) << "\n"
801 << "Expected to find: " << expected_text << "\n"
802 << "In the output : " << actual_;
803 actual_.clear();
804}
805
806void CheckJniAbortCatcher::Hook(void* data, const std::string& reason) {
807 // We use += because when we're hooking the aborts like this, multiple problems can be found.
808 *reinterpret_cast<std::string*>(data) += reason;
809}
810
811} // namespace art