1/*
2 * Copyright (C) 2011 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#ifndef ART_RUNTIME_COMMON_TEST_H_
18#define ART_RUNTIME_COMMON_TEST_H_
19
20#include <dirent.h>
21#include <dlfcn.h>
22#include <sys/mman.h>
23#include <sys/stat.h>
24#include <sys/types.h>
25
26#include "../../external/icu4c/common/unicode/uvernum.h"
27#include "base/macros.h"
28#include "base/stl_util.h"
29#include "base/stringprintf.h"
30#include "base/unix_file/fd_file.h"
31#include "class_linker.h"
32#include "compiler/driver/compiler_driver.h"
33#include "dex_file-inl.h"
34#include "entrypoints/entrypoint_utils.h"
35#include "gc/heap.h"
36#include "gtest/gtest.h"
37#include "instruction_set.h"
38#include "interpreter/interpreter.h"
39#include "mirror/class_loader.h"
40#include "oat_file.h"
41#include "object_utils.h"
42#include "os.h"
43#include "runtime.h"
44#include "scoped_thread_state_change.h"
45#include "ScopedLocalRef.h"
46#include "thread.h"
47#include "UniquePtr.h"
48#include "well_known_classes.h"
49
50namespace art {
51
52static const byte kBase64Map[256] = {
53  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
54  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
55  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
56  255, 255, 255, 255, 255, 255, 255,  62, 255, 255, 255,  63,
57  52,  53,  54,  55,  56,  57,  58,  59,  60,  61, 255, 255,
58  255, 254, 255, 255, 255,   0,   1,   2,   3,   4,   5,   6,
59    7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18,  // NOLINT
60   19,  20,  21,  22,  23,  24,  25, 255, 255, 255, 255, 255,  // NOLINT
61  255,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,
62   37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  // NOLINT
63   49,  50,  51, 255, 255, 255, 255, 255, 255, 255, 255, 255,  // NOLINT
64  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
65  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
66  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
67  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
68  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
69  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
70  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
71  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
72  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
73  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
74  255, 255, 255, 255
75};
76
77byte* DecodeBase64(const char* src, size_t* dst_size) {
78  std::vector<byte> tmp;
79  uint32_t t = 0, y = 0;
80  int g = 3;
81  for (size_t i = 0; src[i] != '\0'; ++i) {
82    byte c = kBase64Map[src[i] & 0xFF];
83    if (c == 255) continue;
84    // the final = symbols are read and used to trim the remaining bytes
85    if (c == 254) {
86      c = 0;
87      // prevent g < 0 which would potentially allow an overflow later
88      if (--g < 0) {
89        *dst_size = 0;
90        return NULL;
91      }
92    } else if (g != 3) {
93      // we only allow = to be at the end
94      *dst_size = 0;
95      return NULL;
96    }
97    t = (t << 6) | c;
98    if (++y == 4) {
99      tmp.push_back((t >> 16) & 255);
100      if (g > 1) {
101        tmp.push_back((t >> 8) & 255);
102      }
103      if (g > 2) {
104        tmp.push_back(t & 255);
105      }
106      y = t = 0;
107    }
108  }
109  if (y != 0) {
110    *dst_size = 0;
111    return NULL;
112  }
113  UniquePtr<byte[]> dst(new byte[tmp.size()]);
114  if (dst_size != NULL) {
115    *dst_size = tmp.size();
116  } else {
117    *dst_size = 0;
118  }
119  std::copy(tmp.begin(), tmp.end(), dst.get());
120  return dst.release();
121}
122
123class ScratchFile {
124 public:
125  ScratchFile() {
126    filename_ = getenv("ANDROID_DATA");
127    filename_ += "/TmpFile-XXXXXX";
128    int fd = mkstemp(&filename_[0]);
129    CHECK_NE(-1, fd);
130    file_.reset(new File(fd, GetFilename()));
131  }
132
133  ~ScratchFile() {
134    int unlink_result = unlink(filename_.c_str());
135    CHECK_EQ(0, unlink_result);
136  }
137
138  const std::string& GetFilename() const {
139    return filename_;
140  }
141
142  File* GetFile() const {
143    return file_.get();
144  }
145
146  int GetFd() const {
147    return file_->Fd();
148  }
149
150 private:
151  std::string filename_;
152  UniquePtr<File> file_;
153};
154
155class CommonTest : public testing::Test {
156 public:
157  static void MakeExecutable(const mirror::ByteArray* code_array) {
158    CHECK(code_array != NULL);
159    MakeExecutable(code_array->GetData(), code_array->GetLength());
160  }
161
162  static void MakeExecutable(const std::vector<uint8_t>& code) {
163    CHECK_NE(code.size(), 0U);
164    MakeExecutable(&code[0], code.size());
165  }
166
167  // Create an OatMethod based on pointers (for unit tests)
168  OatFile::OatMethod CreateOatMethod(const void* code,
169                                     const size_t frame_size_in_bytes,
170                                     const uint32_t core_spill_mask,
171                                     const uint32_t fp_spill_mask,
172                                     const uint8_t* mapping_table,
173                                     const uint8_t* vmap_table,
174                                     const uint8_t* gc_map) {
175      return OatFile::OatMethod(NULL,
176                                reinterpret_cast<uint32_t>(code),
177                                frame_size_in_bytes,
178                                core_spill_mask,
179                                fp_spill_mask,
180                                reinterpret_cast<uint32_t>(mapping_table),
181                                reinterpret_cast<uint32_t>(vmap_table),
182                                reinterpret_cast<uint32_t>(gc_map));
183  }
184
185  void MakeExecutable(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
186    CHECK(method != NULL);
187    LOG(INFO) << "MakeExecutable " << PrettyMethod(method);
188
189    const CompiledMethod* compiled_method = NULL;
190    if (!method->IsAbstract()) {
191      const mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
192      const DexFile& dex_file = *dex_cache->GetDexFile();
193      compiled_method =
194          compiler_driver_->GetCompiledMethod(MethodReference(&dex_file,
195                                                              method->GetDexMethodIndex()));
196    }
197    if (compiled_method != NULL) {
198      const std::vector<uint8_t>& code = compiled_method->GetCode();
199      MakeExecutable(code);
200      const void* method_code = CompiledMethod::CodePointer(&code[0],
201                                                            compiled_method->GetInstructionSet());
202      LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
203      OatFile::OatMethod oat_method = CreateOatMethod(method_code,
204                                                      compiled_method->GetFrameSizeInBytes(),
205                                                      compiled_method->GetCoreSpillMask(),
206                                                      compiled_method->GetFpSpillMask(),
207                                                      &compiled_method->GetMappingTable()[0],
208                                                      &compiled_method->GetVmapTable()[0],
209                                                      NULL);
210      oat_method.LinkMethod(method);
211      method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
212    } else {
213      const void* method_code;
214      // No code? You must mean to go into the interpreter.
215      method_code = GetCompiledCodeToInterpreterBridge();
216      LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
217      OatFile::OatMethod oat_method = CreateOatMethod(method_code,
218                                                      kStackAlignment,
219                                                      0,
220                                                      0,
221                                                      NULL,
222                                                      NULL,
223                                                      NULL);
224      oat_method.LinkMethod(method);
225      method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge);
226    }
227  }
228
229  static void MakeExecutable(const void* code_start, size_t code_length) {
230    CHECK(code_start != NULL);
231    CHECK_NE(code_length, 0U);
232    uintptr_t data = reinterpret_cast<uintptr_t>(code_start);
233    uintptr_t base = RoundDown(data, kPageSize);
234    uintptr_t limit = RoundUp(data + code_length, kPageSize);
235    uintptr_t len = limit - base;
236    int result = mprotect(reinterpret_cast<void*>(base), len, PROT_READ | PROT_WRITE | PROT_EXEC);
237    CHECK_EQ(result, 0);
238
239    // Flush instruction cache
240    // Only uses __builtin___clear_cache if GCC >= 4.3.3
241#if GCC_VERSION >= 40303
242    __builtin___clear_cache(reinterpret_cast<void*>(base), reinterpret_cast<void*>(base + len));
243#else
244    LOG(FATAL) << "UNIMPLEMENTED: cache flush";
245#endif
246  }
247
248  static void SetEnvironmentVariables(std::string& android_data) {
249    if (IsHost()) {
250      // $ANDROID_ROOT is set on the device, but not on the host.
251      // We need to set this so that icu4c can find its locale data.
252      std::string root;
253      root += getenv("ANDROID_BUILD_TOP");
254#if defined(__linux__)
255      root += "/out/host/linux-x86";
256#elif defined(__APPLE__)
257      root += "/out/host/darwin-x86";
258#else
259#error unsupported OS
260#endif
261      setenv("ANDROID_ROOT", root.c_str(), 1);
262      setenv("LD_LIBRARY_PATH", ":", 0);  // Required by java.lang.System.<clinit>.
263    }
264
265    // On target, Cannot use /mnt/sdcard because it is mounted noexec, so use subdir of dalvik-cache
266    android_data = (IsHost() ? "/tmp/art-data-XXXXXX" : "/data/dalvik-cache/art-data-XXXXXX");
267    if (mkdtemp(&android_data[0]) == NULL) {
268      PLOG(FATAL) << "mkdtemp(\"" << &android_data[0] << "\") failed";
269    }
270    setenv("ANDROID_DATA", android_data.c_str(), 1);
271  }
272
273 protected:
274  static bool IsHost() {
275    return (getenv("ANDROID_BUILD_TOP") != NULL);
276  }
277
278  virtual void SetUp() {
279    SetEnvironmentVariables(android_data_);
280    dalvik_cache_.append(android_data_.c_str());
281    dalvik_cache_.append("/dalvik-cache");
282    int mkdir_result = mkdir(dalvik_cache_.c_str(), 0700);
283    ASSERT_EQ(mkdir_result, 0);
284
285    java_lang_dex_file_ = DexFile::Open(GetLibCoreDexFileName(), GetLibCoreDexFileName());
286    if (java_lang_dex_file_ == NULL) {
287      LOG(FATAL) << "Could not open .dex file '" << GetLibCoreDexFileName() << "'\n";
288    }
289    conscrypt_file_ = DexFile::Open(GetConscryptFileName(), GetConscryptFileName());
290    if (conscrypt_file_  == NULL) {
291      LOG(FATAL) << "Could not open .dex file '" << GetConscryptFileName() << "'\n";
292    }
293    boot_class_path_.push_back(java_lang_dex_file_);
294    boot_class_path_.push_back(conscrypt_file_);
295
296    std::string min_heap_string(StringPrintf("-Xms%zdm", gc::Heap::kDefaultInitialSize / MB));
297    std::string max_heap_string(StringPrintf("-Xmx%zdm", gc::Heap::kDefaultMaximumSize / MB));
298
299    Runtime::Options options;
300    options.push_back(std::make_pair("compiler", reinterpret_cast<void*>(NULL)));
301    options.push_back(std::make_pair("bootclasspath", &boot_class_path_));
302    options.push_back(std::make_pair("-Xcheck:jni", reinterpret_cast<void*>(NULL)));
303    options.push_back(std::make_pair(min_heap_string.c_str(), reinterpret_cast<void*>(NULL)));
304    options.push_back(std::make_pair(max_heap_string.c_str(), reinterpret_cast<void*>(NULL)));
305    if (!Runtime::Create(options, false)) {
306      LOG(FATAL) << "Failed to create runtime";
307      return;
308    }
309    runtime_.reset(Runtime::Current());
310    // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
311    // give it away now and then switch to a more managable ScopedObjectAccess.
312    Thread::Current()->TransitionFromRunnableToSuspended(kNative);
313    {
314      ScopedObjectAccess soa(Thread::Current());
315      ASSERT_TRUE(runtime_.get() != NULL);
316      class_linker_ = runtime_->GetClassLinker();
317
318      InstructionSet instruction_set = kNone;
319#if defined(__arm__)
320      instruction_set = kThumb2;
321#elif defined(__mips__)
322      instruction_set = kMips;
323#elif defined(__i386__)
324      instruction_set = kX86;
325#endif
326
327      // TODO: make selectable
328#if defined(ART_USE_PORTABLE_COMPILER)
329      CompilerBackend compiler_backend = kPortable;
330#else
331      CompilerBackend compiler_backend = kQuick;
332#endif
333
334      if (!runtime_->HasResolutionMethod()) {
335        runtime_->SetResolutionMethod(runtime_->CreateResolutionMethod());
336      }
337      for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
338        Runtime::CalleeSaveType type = Runtime::CalleeSaveType(i);
339        if (!runtime_->HasCalleeSaveMethod(type)) {
340          runtime_->SetCalleeSaveMethod(
341              runtime_->CreateCalleeSaveMethod(instruction_set, type), type);
342        }
343      }
344      class_linker_->FixupDexCaches(runtime_->GetResolutionMethod());
345      compiler_driver_.reset(new CompilerDriver(compiler_backend, instruction_set,
346                                                true, new CompilerDriver::DescriptorSet,
347                                                2, true));
348    }
349    // We typically don't generate an image in unit tests, disable this optimization by default.
350    compiler_driver_->SetSupportBootImageFixup(false);
351
352    // We're back in native, take the opportunity to initialize well known classes.
353    WellKnownClasses::Init(Thread::Current()->GetJniEnv());
354    // Create the heap thread pool so that the GC runs in parallel for tests. Normally, the thread
355    // pool is created by the runtime.
356    runtime_->GetHeap()->CreateThreadPool();
357    runtime_->GetHeap()->VerifyHeap();  // Check for heap corruption before the test
358  }
359
360  virtual void TearDown() {
361    const char* android_data = getenv("ANDROID_DATA");
362    ASSERT_TRUE(android_data != NULL);
363    DIR* dir = opendir(dalvik_cache_.c_str());
364    ASSERT_TRUE(dir != NULL);
365    dirent* e;
366    while ((e = readdir(dir)) != NULL) {
367      if ((strcmp(e->d_name, ".") == 0) || (strcmp(e->d_name, "..") == 0)) {
368        continue;
369      }
370      std::string filename(dalvik_cache_);
371      filename.push_back('/');
372      filename.append(e->d_name);
373      int unlink_result = unlink(filename.c_str());
374      ASSERT_EQ(0, unlink_result);
375    }
376    closedir(dir);
377    int rmdir_cache_result = rmdir(dalvik_cache_.c_str());
378    ASSERT_EQ(0, rmdir_cache_result);
379    int rmdir_data_result = rmdir(android_data_.c_str());
380    ASSERT_EQ(0, rmdir_data_result);
381
382    // icu4c has a fixed 10-element array "gCommonICUDataArray".
383    // If we run > 10 tests, we fill that array and u_setCommonData fails.
384    // There's a function to clear the array, but it's not public...
385    typedef void (*IcuCleanupFn)();
386    void* sym = dlsym(RTLD_DEFAULT, "u_cleanup_" U_ICU_VERSION_SHORT);
387    CHECK(sym != NULL);
388    IcuCleanupFn icu_cleanup_fn = reinterpret_cast<IcuCleanupFn>(sym);
389    (*icu_cleanup_fn)();
390
391    compiler_driver_.reset();
392    STLDeleteElements(&opened_dex_files_);
393
394    Runtime::Current()->GetHeap()->VerifyHeap();  // Check for heap corruption after the test
395  }
396
397  std::string GetLibCoreDexFileName() {
398    return GetDexFileName("core-libart");
399  }
400
401  std::string GetConscryptFileName() {
402    return GetDexFileName("conscrypt");
403  }
404
405  std::string GetDexFileName(const std::string& jar_prefix) {
406    if (IsHost()) {
407      const char* host_dir = getenv("ANDROID_HOST_OUT");
408      CHECK(host_dir != NULL);
409      return StringPrintf("%s/framework/%s-hostdex.jar", host_dir, jar_prefix.c_str());
410    }
411    return StringPrintf("%s/framework/%s.jar", GetAndroidRoot(), jar_prefix.c_str());
412  }
413
414  std::string GetTestAndroidRoot() {
415    if (IsHost()) {
416      const char* host_dir = getenv("ANDROID_HOST_OUT");
417      CHECK(host_dir != NULL);
418      return host_dir;
419    }
420    return GetAndroidRoot();
421  }
422
423  const DexFile* OpenTestDexFile(const char* name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
424    CHECK(name != NULL);
425    std::string filename;
426    if (IsHost()) {
427      filename += getenv("ANDROID_HOST_OUT");
428      filename += "/framework/";
429    } else {
430      filename += "/data/nativetest/art/";
431    }
432    filename += "art-test-dex-";
433    filename += name;
434    filename += ".jar";
435    const DexFile* dex_file = DexFile::Open(filename, filename);
436    CHECK(dex_file != NULL) << "Failed to open " << filename;
437    CHECK_EQ(PROT_READ, dex_file->GetPermissions());
438    CHECK(dex_file->IsReadOnly());
439    opened_dex_files_.push_back(dex_file);
440    return dex_file;
441  }
442
443  jobject LoadDex(const char* dex_name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
444    const DexFile* dex_file = OpenTestDexFile(dex_name);
445    CHECK(dex_file != NULL);
446    class_linker_->RegisterDexFile(*dex_file);
447    std::vector<const DexFile*> class_path;
448    class_path.push_back(dex_file);
449    ScopedObjectAccessUnchecked soa(Thread::Current());
450    ScopedLocalRef<jobject> class_loader_local(soa.Env(),
451        soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader));
452    jobject class_loader = soa.Env()->NewGlobalRef(class_loader_local.get());
453    soa.Self()->SetClassLoaderOverride(soa.Decode<mirror::ClassLoader*>(class_loader_local.get()));
454    Runtime::Current()->SetCompileTimeClassPath(class_loader, class_path);
455    return class_loader;
456  }
457
458  void CompileClass(mirror::ClassLoader* class_loader, const char* class_name)
459      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
460    std::string class_descriptor(DotToDescriptor(class_name));
461    mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader);
462    CHECK(klass != NULL) << "Class not found " << class_name;
463    for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
464      CompileMethod(klass->GetDirectMethod(i));
465    }
466    for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
467      CompileMethod(klass->GetVirtualMethod(i));
468    }
469  }
470
471  void CompileMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
472    CHECK(method != NULL);
473    base::TimingLogger timings("CommonTest::CompileMethod", false, false);
474    timings.StartSplit("CompileOne");
475    compiler_driver_->CompileOne(method, timings);
476    MakeExecutable(method);
477  }
478
479  void CompileDirectMethod(mirror::ClassLoader* class_loader,
480                           const char* class_name,
481                           const char* method_name,
482                           const char* signature)
483      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
484    std::string class_descriptor(DotToDescriptor(class_name));
485    mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader);
486    CHECK(klass != NULL) << "Class not found " << class_name;
487    mirror::ArtMethod* method = klass->FindDirectMethod(method_name, signature);
488    CHECK(method != NULL) << "Direct method not found: "
489                          << class_name << "." << method_name << signature;
490    CompileMethod(method);
491  }
492
493  void CompileVirtualMethod(mirror::ClassLoader* class_loader,
494                            const char* class_name,
495                            const char* method_name,
496                            const char* signature)
497      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
498    std::string class_descriptor(DotToDescriptor(class_name));
499    mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader);
500    CHECK(klass != NULL) << "Class not found " << class_name;
501    mirror::ArtMethod* method = klass->FindVirtualMethod(method_name, signature);
502    CHECK(method != NULL) << "Virtual method not found: "
503                          << class_name << "." << method_name << signature;
504    CompileMethod(method);
505  }
506
507  void ReserveImageSpace() {
508    // Reserve where the image will be loaded up front so that other parts of test set up don't
509    // accidentally end up colliding with the fixed memory address when we need to load the image.
510    image_reservation_.reset(MemMap::MapAnonymous("image reservation",
511                                                  reinterpret_cast<byte*>(ART_BASE_ADDRESS),
512                                                  (size_t)100 * 1024 * 1024,  // 100MB
513                                                  PROT_NONE));
514  }
515
516  void UnreserveImageSpace() {
517    image_reservation_.reset();
518  }
519
520  std::string android_data_;
521  std::string dalvik_cache_;
522  const DexFile* java_lang_dex_file_;  // owned by runtime_
523  const DexFile* conscrypt_file_;  // owned by runtime_
524  std::vector<const DexFile*> boot_class_path_;
525  UniquePtr<Runtime> runtime_;
526  // Owned by the runtime
527  ClassLinker* class_linker_;
528  UniquePtr<CompilerDriver> compiler_driver_;
529
530 private:
531  std::vector<const DexFile*> opened_dex_files_;
532  UniquePtr<MemMap> image_reservation_;
533};
534
535// Sets a CheckJni abort hook to catch failures. Note that this will cause CheckJNI to carry on
536// rather than aborting, so be careful!
537class CheckJniAbortCatcher {
538 public:
539  CheckJniAbortCatcher() : vm_(Runtime::Current()->GetJavaVM()) {
540    vm_->check_jni_abort_hook = Hook;
541    vm_->check_jni_abort_hook_data = &actual_;
542  }
543
544  ~CheckJniAbortCatcher() {
545    vm_->check_jni_abort_hook = NULL;
546    vm_->check_jni_abort_hook_data = NULL;
547    EXPECT_TRUE(actual_.empty()) << actual_;
548  }
549
550  void Check(const char* expected_text) {
551    EXPECT_TRUE(actual_.find(expected_text) != std::string::npos) << "\n"
552        << "Expected to find: " << expected_text << "\n"
553        << "In the output   : " << actual_;
554    actual_.clear();
555  }
556
557 private:
558  static void Hook(void* data, const std::string& reason) {
559    // We use += because when we're hooking the aborts like this, multiple problems can be found.
560    *reinterpret_cast<std::string*>(data) += reason;
561  }
562
563  JavaVMExt* vm_;
564  std::string actual_;
565
566  DISALLOW_COPY_AND_ASSIGN(CheckJniAbortCatcher);
567};
568
569// TODO: These tests were disabled for portable when we went to having
570// MCLinker link LLVM ELF output because we no longer just have code
571// blobs in memory. We'll need to dlopen to load and relocate
572// temporary output to resurrect these tests.
573#if defined(ART_USE_PORTABLE_COMPILER)
574#define TEST_DISABLED_FOR_PORTABLE() printf("WARNING: TEST DISABLED FOR PORTABLE\n"); return
575#else
576#define TEST_DISABLED_FOR_PORTABLE()
577#endif
578
579}  // namespace art
580
581namespace std {
582
583// TODO: isn't gtest supposed to be able to print STL types for itself?
584template <typename T>
585std::ostream& operator<<(std::ostream& os, const std::vector<T>& rhs) {
586  os << ::art::ToString(rhs);
587  return os;
588}
589
590}  // namespace std
591
592#endif  // ART_RUNTIME_COMMON_TEST_H_
593