common_test.h revision 7655f29fabc0a12765de828914a18314382e5a35
12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/*
22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project
32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License.
62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at
72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software
112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and
142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License.
152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */
16934486cf07c578b6494417ca5dcbae89cf04b019Brian Carlstrom
17fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#ifndef ART_RUNTIME_COMMON_TEST_H_
18fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#define ART_RUNTIME_COMMON_TEST_H_
19fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom
20b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom#include <dirent.h>
210af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes#include <dlfcn.h>
2227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom#include <sys/mman.h>
23b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom#include <sys/stat.h>
24b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom#include <sys/types.h>
25b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
26f66330a747eff155eb571b634fc9d901c55a78a7Elliott Hughes#include "../../external/icu4c/common/unicode/uvernum.h"
27761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/macros.h"
281aa246dec5abe212f699de1413a0c4a191ca364aElliott Hughes#include "base/stl_util.h"
29e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes#include "base/stringprintf.h"
30761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/unix_file/fd_file.h"
31578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "class_linker.h"
321212a022fa5f8ef9585d765b1809521812af882cIan Rogers#include "compiler/driver/compiler_driver.h"
334f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h"
347655f29fabc0a12765de828914a18314382e5a35Ian Rogers#include "entrypoints/entrypoint_utils.h"
351d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/heap.h"
3690a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes#include "gtest/gtest.h"
370f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes#include "instruction_set.h"
382dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class_loader.h"
393320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom#include "oat_file.h"
406d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "object_utils.h"
4133f741eefef8f8012f6c190b39355f2e0430d535Brian Carlstrom#include "os.h"
421f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom#include "runtime.h"
4300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h"
44e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes#include "ScopedLocalRef.h"
4590a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes#include "thread.h"
460f3c55331439970e01af67f80ac117c473bc04cfElliott Hughes#include "UniquePtr.h"
4700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "well_known_classes.h"
480af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes
49934486cf07c578b6494417ca5dcbae89cf04b019Brian Carlstromnamespace art {
50934486cf07c578b6494417ca5dcbae89cf04b019Brian Carlstrom
51b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstromstatic const byte kBase64Map[256] = {
52b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
53b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
54b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
55b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  255, 255, 255, 255, 255, 255, 255,  62, 255, 255, 255,  63,
56b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  52,  53,  54,  55,  56,  57,  58,  59,  60,  61, 255, 255,
57b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  255, 254, 255, 255, 255,   0,   1,   2,   3,   4,   5,   6,
587934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18,  // NOLINT
597934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom   19,  20,  21,  22,  23,  24,  25, 255, 255, 255, 255, 255,  // NOLINT
60b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  255,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,
617934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom   37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48,  // NOLINT
627934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom   49,  50,  51, 255, 255, 255, 255, 255, 255, 255, 255, 255,  // NOLINT
63b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
64b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
65b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
66b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
67b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
68b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
69b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
70b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
71b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
72b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
73b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  255, 255, 255, 255
74b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom};
75b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom
76b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrombyte* DecodeBase64(const char* src, size_t* dst_size) {
77b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  std::vector<byte> tmp;
78a21039c3ae2b20e44ceb2735251c04d0aac89afdElliott Hughes  uint32_t t = 0, y = 0;
79b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  int g = 3;
80b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  for (size_t i = 0; src[i] != '\0'; ++i) {
81b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom    byte c = kBase64Map[src[i] & 0xFF];
82b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom    if (c == 255) continue;
83b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom    // the final = symbols are read and used to trim the remaining bytes
84b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom    if (c == 254) {
85b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom      c = 0;
86b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom      // prevent g < 0 which would potentially allow an overflow later
87b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom      if (--g < 0) {
885147733292cd0b80ca7da3099e43cc549d67526bBrian Carlstrom        *dst_size = 0;
89b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom        return NULL;
90b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom      }
91b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom    } else if (g != 3) {
92b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom      // we only allow = to be at the end
935147733292cd0b80ca7da3099e43cc549d67526bBrian Carlstrom      *dst_size = 0;
94b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom      return NULL;
95b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom    }
96b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom    t = (t << 6) | c;
97b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom    if (++y == 4) {
98b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom      tmp.push_back((t >> 16) & 255);
99b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom      if (g > 1) {
100b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom        tmp.push_back((t >> 8) & 255);
101b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom      }
102b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom      if (g > 2) {
103b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom        tmp.push_back(t & 255);
104b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom      }
105b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom      y = t = 0;
106b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom    }
107b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  }
108b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  if (y != 0) {
1095147733292cd0b80ca7da3099e43cc549d67526bBrian Carlstrom    *dst_size = 0;
110b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom    return NULL;
111b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  }
112b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  UniquePtr<byte[]> dst(new byte[tmp.size()]);
113b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  if (dst_size != NULL) {
114b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom    *dst_size = tmp.size();
1155147733292cd0b80ca7da3099e43cc549d67526bBrian Carlstrom  } else {
1165147733292cd0b80ca7da3099e43cc549d67526bBrian Carlstrom    *dst_size = 0;
117b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  }
118b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  std::copy(tmp.begin(), tmp.end(), dst.get());
119b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom  return dst.release();
120b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom}
121b9cc1ca34adec5e9254f78e9ee40d57348aa2fd0Brian Carlstrom
122db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstromclass ScratchFile {
123db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom public:
124db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  ScratchFile() {
12534023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes    filename_ = getenv("ANDROID_DATA");
12634023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes    filename_ += "/TmpFile-XXXXXX";
127761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    int fd = mkstemp(&filename_[0]);
128761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    CHECK_NE(-1, fd);
129761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    file_.reset(new File(fd, GetFilename()));
130db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  }
131db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
132db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  ~ScratchFile() {
13334023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes    int unlink_result = unlink(filename_.c_str());
134db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom    CHECK_EQ(0, unlink_result);
135db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  }
136db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
137a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  const std::string& GetFilename() const {
138a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    return filename_;
139db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  }
140db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
141234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes  File* GetFile() const {
142234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes    return file_.get();
143234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes  }
144234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes
145db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  int GetFd() const {
146761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    return file_->Fd();
147db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  }
148db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
149db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom private:
15034023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes  std::string filename_;
151234da578a2d91ed7f2ef47b2ec23fb0033e2746bElliott Hughes  UniquePtr<File> file_;
152db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom};
153db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
154f734cf55d510976f4862b15e35fc86eae2a3daf8Brian Carlstromclass CommonTest : public testing::Test {
1559baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom public:
1562dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  static void MakeExecutable(const mirror::ByteArray* code_array) {
1573320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    CHECK(code_array != NULL);
1583320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    MakeExecutable(code_array->GetData(), code_array->GetLength());
1593320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  }
1603320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
1611cb0ae742072b5ea2c7f677e6ad220ba01255daeShih-wei Liao  static void MakeExecutable(const std::vector<uint8_t>& code) {
1623320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    CHECK_NE(code.size(), 0U);
1633320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    MakeExecutable(&code[0], code.size());
1643320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  }
1653320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
166ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  // Create an OatMethod based on pointers (for unit tests)
167ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  OatFile::OatMethod CreateOatMethod(const void* code,
168ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                     const size_t frame_size_in_bytes,
169ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                     const uint32_t core_spill_mask,
170ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                     const uint32_t fp_spill_mask,
171ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                     const uint32_t* mapping_table,
172ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                     const uint16_t* vmap_table,
17374180cad94848107cf297d37e72437c5a6eecf1bJeff Hao                                     const uint8_t* gc_map) {
174ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      return OatFile::OatMethod(NULL,
175ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                reinterpret_cast<uint32_t>(code),
176ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                frame_size_in_bytes,
177ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                core_spill_mask,
178ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                fp_spill_mask,
179ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                reinterpret_cast<uint32_t>(mapping_table),
180ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                reinterpret_cast<uint32_t>(vmap_table),
181df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom                                reinterpret_cast<uint32_t>(gc_map));
182ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
183ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
1842dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  void MakeExecutable(mirror::AbstractMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1853320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    CHECK(method != NULL);
18674180cad94848107cf297d37e72437c5a6eecf1bJeff Hao    LOG(INFO) << "MakeExecutable " << PrettyMethod(method);
1873320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
188f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers    const CompiledMethod* compiled_method = NULL;
1893320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    if (!method->IsAbstract()) {
1902dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      const mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
1914445a7e3398a6143939168097a3aa275b734504dIan Rogers      const DexFile& dex_file = *dex_cache->GetDexFile();
192f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers      compiled_method =
19351c2467e8771b56e25ae4f17f66522f979f57a7eBrian Carlstrom          compiler_driver_->GetCompiledMethod(MethodReference(&dex_file,
19451c2467e8771b56e25ae4f17f66522f979f57a7eBrian Carlstrom                                                              method->GetDexMethodIndex()));
195f7015fd55a8dc969ac2440ffc829a6b4d942fb5aLogan Chien
196c4f105d75cd0cbc5145620068bbb8a819148e535Anwar Ghuloum#ifndef ART_LIGHT_MODE
197f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers      CHECK(compiled_method != NULL) << PrettyMethod(method);
198f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers#endif
199f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers    }
200f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers    if (compiled_method != NULL) {
201971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien      const std::vector<uint8_t>& code = compiled_method->GetCode();
202971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien      MakeExecutable(code);
203971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien      const void* method_code = CompiledMethod::CodePointer(&code[0],
204971bf3f9184010d68b9a3ad30b396fa401af91a3Logan Chien                                                            compiled_method->GetInstructionSet());
2053320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom      LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
206ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      OatFile::OatMethod oat_method = CreateOatMethod(method_code,
207ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                                      compiled_method->GetFrameSizeInBytes(),
208ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                                      compiled_method->GetCoreSpillMask(),
209ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                                      compiled_method->GetFpSpillMask(),
210ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                                      &compiled_method->GetMappingTable()[0],
211ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                                      &compiled_method->GetVmapTable()[0],
21274180cad94848107cf297d37e72437c5a6eecf1bJeff Hao                                                      NULL);
213265091e581c9f643b37e7966890911f09e223269Brian Carlstrom      oat_method.LinkMethod(method);
2143320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    } else {
215f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers      const void* method_code;
216f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers      if (method->IsAbstract()) {
21779fe539587d4c09244172d0168eeed0ec9770466Jeff Hao        method_code = GetAbstractMethodErrorStub();
218f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers      } else {
219f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers        // No code? You must mean to go into the interpreter.
220f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers        method_code = GetInterpreterEntryPoint();
221f3e9855ee2000106b54fd479f7a46da2dc2ad079Ian Rogers      }
2223320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom      LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
223ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      OatFile::OatMethod oat_method = CreateOatMethod(method_code,
224ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                                      kStackAlignment,
225ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                                      0,
226ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                                      0,
227ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                                      NULL,
228ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                                      NULL,
22974180cad94848107cf297d37e72437c5a6eecf1bJeff Hao                                                      NULL);
230265091e581c9f643b37e7966890911f09e223269Brian Carlstrom      oat_method.LinkMethod(method);
2313320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    }
2323320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  }
2333320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
2343320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  static void MakeExecutable(const void* code_start, size_t code_length) {
2353320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    CHECK(code_start != NULL);
2363320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    CHECK_NE(code_length, 0U);
2373320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    uintptr_t data = reinterpret_cast<uintptr_t>(code_start);
2389baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom    uintptr_t base = RoundDown(data, kPageSize);
2393320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    uintptr_t limit = RoundUp(data + code_length, kPageSize);
2409baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom    uintptr_t len = limit - base;
2419baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom    int result = mprotect(reinterpret_cast<void*>(base), len, PROT_READ | PROT_WRITE | PROT_EXEC);
2427a00a3c6c9a3425ba8331ee8e479040731db651bBrian Carlstrom    CHECK_EQ(result, 0);
24324782c6aa7abf396de057d7eb15035b4c594a3b4Shih-wei Liao
2441634155a231665f16867cbecab9332a8b1cf3b1eIan Rogers    // Flush instruction cache
24524782c6aa7abf396de057d7eb15035b4c594a3b4Shih-wei Liao    // Only uses __builtin___clear_cache if GCC >= 4.3.3
24624782c6aa7abf396de057d7eb15035b4c594a3b4Shih-wei Liao#if GCC_VERSION >= 40303
2471634155a231665f16867cbecab9332a8b1cf3b1eIan Rogers    __builtin___clear_cache(reinterpret_cast<void*>(base), reinterpret_cast<void*>(base + len));
2487a00a3c6c9a3425ba8331ee8e479040731db651bBrian Carlstrom#else
2496f485c62b9cfce3ab71020c646ab9f48d9d29d6dBrian Carlstrom    LOG(FATAL) << "UNIMPLEMENTED: cache flush";
25024782c6aa7abf396de057d7eb15035b4c594a3b4Shih-wei Liao#endif
2519baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom  }
2529baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom
253761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  static void SetEnvironmentVariables(std::string& android_data) {
254761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    if (IsHost()) {
2550af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      // $ANDROID_ROOT is set on the device, but not on the host.
2560af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      // We need to set this so that icu4c can find its locale data.
2570af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      std::string root;
2580af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      root += getenv("ANDROID_BUILD_TOP");
259a0cb1204543934b1f4975025cd6047eb71dc6429Elliott Hughes#if defined(__linux__)
2600af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      root += "/out/host/linux-x86";
261a0cb1204543934b1f4975025cd6047eb71dc6429Elliott Hughes#elif defined(__APPLE__)
262a0cb1204543934b1f4975025cd6047eb71dc6429Elliott Hughes      root += "/out/host/darwin-x86";
263a0cb1204543934b1f4975025cd6047eb71dc6429Elliott Hughes#else
264a0cb1204543934b1f4975025cd6047eb71dc6429Elliott Hughes#error unsupported OS
265a0cb1204543934b1f4975025cd6047eb71dc6429Elliott Hughes#endif
2660af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes      setenv("ANDROID_ROOT", root.c_str(), 1);
2672fa6b2e2fc3d2a2fc27808ce518dc76b80ce369aIan Rogers      setenv("LD_LIBRARY_PATH", ":", 0);  // Required by java.lang.System.<clinit>.
2680af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes    }
2690af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes
2707675e16bcae06c0fe258aad89b3d511037dec399Brian Carlstrom    // On target, Cannot use /mnt/sdcard because it is mounted noexec, so use subdir of dalvik-cache
2717675e16bcae06c0fe258aad89b3d511037dec399Brian Carlstrom    android_data = (IsHost() ? "/tmp/art-data-XXXXXX" : "/data/dalvik-cache/art-data-XXXXXX");
272761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    if (mkdtemp(&android_data[0]) == NULL) {
273761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes      PLOG(FATAL) << "mkdtemp(\"" << &android_data[0] << "\") failed";
2740f4c41d75c821162184501cd4b510a93f6eb580fElliott Hughes    }
275761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    setenv("ANDROID_DATA", android_data.c_str(), 1);
276761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  }
277761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
278761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes protected:
279761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  static bool IsHost() {
280761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    return (getenv("ANDROID_BUILD_TOP") != NULL);
281761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  }
282761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes
283761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes  virtual void SetUp() {
284761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    SetEnvironmentVariables(android_data_);
2857675e16bcae06c0fe258aad89b3d511037dec399Brian Carlstrom    dalvik_cache_.append(android_data_.c_str());
2867675e16bcae06c0fe258aad89b3d511037dec399Brian Carlstrom    dalvik_cache_.append("/dalvik-cache");
2877675e16bcae06c0fe258aad89b3d511037dec399Brian Carlstrom    int mkdir_result = mkdir(dalvik_cache_.c_str(), 0700);
288b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom    ASSERT_EQ(mkdir_result, 0);
289b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
290a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    java_lang_dex_file_ = DexFile::Open(GetLibCoreDexFileName(), GetLibCoreDexFileName());
29133e9566255c426e7a2c8fca5b8a1b6a94a5d352cIan Rogers    if (java_lang_dex_file_ == NULL) {
29233e9566255c426e7a2c8fca5b8a1b6a94a5d352cIan Rogers      LOG(FATAL) << "Could not open .dex file '" << GetLibCoreDexFileName() << "'\n";
29333e9566255c426e7a2c8fca5b8a1b6a94a5d352cIan Rogers    }
294654d91957edb4d1f7534ed5d743cf914db763448Brian Carlstrom    conscrypt_file_ = DexFile::Open(GetConscryptFileName(), GetConscryptFileName());
29533e9566255c426e7a2c8fca5b8a1b6a94a5d352cIan Rogers    if (conscrypt_file_  == NULL) {
29633e9566255c426e7a2c8fca5b8a1b6a94a5d352cIan Rogers      LOG(FATAL) << "Could not open .dex file '" << GetConscryptFileName() << "'\n";
29733e9566255c426e7a2c8fca5b8a1b6a94a5d352cIan Rogers    }
298a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    boot_class_path_.push_back(java_lang_dex_file_);
299654d91957edb4d1f7534ed5d743cf914db763448Brian Carlstrom    boot_class_path_.push_back(conscrypt_file_);
300578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom
3011d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    std::string min_heap_string(StringPrintf("-Xms%zdm", gc::Heap::kDefaultInitialSize / MB));
3021d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    std::string max_heap_string(StringPrintf("-Xmx%zdm", gc::Heap::kDefaultMaximumSize / MB));
30330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers
30469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    Runtime::Options options;
305a4a7b48c813ad73ac795d0b405de69755b36dd6bBrian Carlstrom    options.push_back(std::make_pair("compiler", reinterpret_cast<void*>(NULL)));
306a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    options.push_back(std::make_pair("bootclasspath", &boot_class_path_));
30769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    options.push_back(std::make_pair("-Xcheck:jni", reinterpret_cast<void*>(NULL)));
30830fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    options.push_back(std::make_pair(min_heap_string.c_str(), reinterpret_cast<void*>(NULL)));
30930fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    options.push_back(std::make_pair(max_heap_string.c_str(), reinterpret_cast<void*>(NULL)));
310df62950e7a32031b82360c407d46a37b94188fbbBrian Carlstrom    if (!Runtime::Create(options, false)) {
31100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      LOG(FATAL) << "Failed to create runtime";
31200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers      return;
31300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    }
31400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    runtime_.reset(Runtime::Current());
31500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
31600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    // give it away now and then switch to a more managable ScopedObjectAccess.
31700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    Thread::Current()->TransitionFromRunnableToSuspended(kNative);
3181d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    {
3191d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      ScopedObjectAccess soa(Thread::Current());
3201d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      ASSERT_TRUE(runtime_.get() != NULL);
3211d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      class_linker_ = runtime_->GetClassLinker();
3220cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers
3231d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      InstructionSet instruction_set = kNone;
324c0228b8f02c05ed58bea58490e0d8bdcaf8c5bb8jeffhao#if defined(__arm__)
3251d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      instruction_set = kThumb2;
326c0228b8f02c05ed58bea58490e0d8bdcaf8c5bb8jeffhao#elif defined(__mips__)
3271d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      instruction_set = kMips;
328c0228b8f02c05ed58bea58490e0d8bdcaf8c5bb8jeffhao#elif defined(__i386__)
3291d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      instruction_set = kX86;
3302c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers#endif
331c531cefbfb5394413122e9f57d211ba436cff012buzbee
3321d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      // TODO: make selectable
333c531cefbfb5394413122e9f57d211ba436cff012buzbee#if defined(ART_USE_PORTABLE_COMPILER)
3341d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      CompilerBackend compiler_backend = kPortable;
335c531cefbfb5394413122e9f57d211ba436cff012buzbee#else
3361d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      CompilerBackend compiler_backend = kQuick;
337c531cefbfb5394413122e9f57d211ba436cff012buzbee#endif
338c531cefbfb5394413122e9f57d211ba436cff012buzbee
3391d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      if (!runtime_->HasResolutionMethod()) {
3401d54e73444e017d3a65234e0f193846f3e27472bIan Rogers        runtime_->SetResolutionMethod(runtime_->CreateResolutionMethod());
3411d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      }
3421d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
3431d54e73444e017d3a65234e0f193846f3e27472bIan Rogers        Runtime::CalleeSaveType type = Runtime::CalleeSaveType(i);
3441d54e73444e017d3a65234e0f193846f3e27472bIan Rogers        if (!runtime_->HasCalleeSaveMethod(type)) {
3451d54e73444e017d3a65234e0f193846f3e27472bIan Rogers          runtime_->SetCalleeSaveMethod(
3461d54e73444e017d3a65234e0f193846f3e27472bIan Rogers              runtime_->CreateCalleeSaveMethod(instruction_set, type), type);
3471d54e73444e017d3a65234e0f193846f3e27472bIan Rogers        }
3484f0d07c783afef89703dce32c94440fc8621a29bIan Rogers      }
3491d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      class_linker_->FixupDexCaches(runtime_->GetResolutionMethod());
3501d54e73444e017d3a65234e0f193846f3e27472bIan Rogers      compiler_driver_.reset(new CompilerDriver(compiler_backend, instruction_set,
3511d54e73444e017d3a65234e0f193846f3e27472bIan Rogers                                                true, new CompilerDriver::DescriptorSet,
3524560248d4c85cade7f4fc7b30c3fb41b95a04a7fBrian Carlstrom                                                2, true));
3534f0d07c783afef89703dce32c94440fc8621a29bIan Rogers    }
35496391606d8adfc661e1c21703ded1e7a39377a76Brian Carlstrom    // We typically don't generate an image in unit tests, disable this optimization by default.
35596391606d8adfc661e1c21703ded1e7a39377a76Brian Carlstrom    compiler_driver_->SetSupportBootImageFixup(false);
3562c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
3571d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    // We're back in native, take the opportunity to initialize well known classes.
3581d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    WellKnownClasses::InitClasses(Thread::Current()->GetJniEnv());
35902b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier    // Create the heap thread pool so that the GC runs in parallel for tests. Normally, the thread
36002b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier    // pool is created by the runtime.
36102b6a78038f12c109f95eb31713cfc747f5512f1Mathieu Chartier    runtime_->GetHeap()->CreateThreadPool();
36200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    runtime_->GetHeap()->VerifyHeap();  // Check for heap corruption before the test
363578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom  }
364578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom
365b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  virtual void TearDown() {
366b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom    const char* android_data = getenv("ANDROID_DATA");
367b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom    ASSERT_TRUE(android_data != NULL);
3687675e16bcae06c0fe258aad89b3d511037dec399Brian Carlstrom    DIR* dir = opendir(dalvik_cache_.c_str());
369b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom    ASSERT_TRUE(dir != NULL);
3704696b5b20be2f51f4ada5f3771a205d90bff351dElliott Hughes    dirent* e;
3714696b5b20be2f51f4ada5f3771a205d90bff351dElliott Hughes    while ((e = readdir(dir)) != NULL) {
3724696b5b20be2f51f4ada5f3771a205d90bff351dElliott Hughes      if ((strcmp(e->d_name, ".") == 0) || (strcmp(e->d_name, "..") == 0)) {
373b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom        continue;
374b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom      }
3757675e16bcae06c0fe258aad89b3d511037dec399Brian Carlstrom      std::string filename(dalvik_cache_);
376b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom      filename.push_back('/');
3774696b5b20be2f51f4ada5f3771a205d90bff351dElliott Hughes      filename.append(e->d_name);
378b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom      int unlink_result = unlink(filename.c_str());
379b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom      ASSERT_EQ(0, unlink_result);
380b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom    }
381b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom    closedir(dir);
3827675e16bcae06c0fe258aad89b3d511037dec399Brian Carlstrom    int rmdir_cache_result = rmdir(dalvik_cache_.c_str());
383b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom    ASSERT_EQ(0, rmdir_cache_result);
38434023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes    int rmdir_data_result = rmdir(android_data_.c_str());
385b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom    ASSERT_EQ(0, rmdir_data_result);
3860af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes
3870af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes    // icu4c has a fixed 10-element array "gCommonICUDataArray".
3880af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes    // If we run > 10 tests, we fill that array and u_setCommonData fails.
3890af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes    // There's a function to clear the array, but it's not public...
3900af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes    typedef void (*IcuCleanupFn)();
3910af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes    void* sym = dlsym(RTLD_DEFAULT, "u_cleanup_" U_ICU_VERSION_SHORT);
3920af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes    CHECK(sym != NULL);
3930af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes    IcuCleanupFn icu_cleanup_fn = reinterpret_cast<IcuCleanupFn>(sym);
3940af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes    (*icu_cleanup_fn)();
3950cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers
3961212a022fa5f8ef9585d765b1809521812af882cIan Rogers    compiler_driver_.reset();
3974d6850c47515fe2a4f9de923befb6287bb863c8cElliott Hughes    STLDeleteElements(&opened_dex_files_);
3982c8f653c98d658419f464b6147c10e11a664d2e6Ian Rogers
399b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes    Runtime::Current()->GetHeap()->VerifyHeap();  // Check for heap corruption after the test
400b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  }
401b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom
402b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  std::string GetLibCoreDexFileName() {
4033b010aa88cec548a9a4213c7cbdc416f73ea5c3cBrian Carlstrom    return GetDexFileName("core-libart");
404265091e581c9f643b37e7966890911f09e223269Brian Carlstrom  }
405265091e581c9f643b37e7966890911f09e223269Brian Carlstrom
406654d91957edb4d1f7534ed5d743cf914db763448Brian Carlstrom  std::string GetConscryptFileName() {
407654d91957edb4d1f7534ed5d743cf914db763448Brian Carlstrom    return GetDexFileName("conscrypt");
408654d91957edb4d1f7534ed5d743cf914db763448Brian Carlstrom  }
409654d91957edb4d1f7534ed5d743cf914db763448Brian Carlstrom
410265091e581c9f643b37e7966890911f09e223269Brian Carlstrom  std::string GetDexFileName(const std::string& jar_prefix) {
411761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    if (IsHost()) {
412b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom      const char* host_dir = getenv("ANDROID_HOST_OUT");
413b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom      CHECK(host_dir != NULL);
414265091e581c9f643b37e7966890911f09e223269Brian Carlstrom      return StringPrintf("%s/framework/%s-hostdex.jar", host_dir, jar_prefix.c_str());
415ac5b9e22d32c4f986783a2207b08ade769619f6fJesse Wilson    }
416265091e581c9f643b37e7966890911f09e223269Brian Carlstrom    return StringPrintf("%s/framework/%s.jar", GetAndroidRoot(), jar_prefix.c_str());
417b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom  }
418ac5b9e22d32c4f986783a2207b08ade769619f6fJesse Wilson
4193f47c12487250f61f3be95e9f275e3b08e2c49fbBrian Carlstrom  std::string GetTestAndroidRoot() {
4203f47c12487250f61f3be95e9f275e3b08e2c49fbBrian Carlstrom    if (IsHost()) {
4213f47c12487250f61f3be95e9f275e3b08e2c49fbBrian Carlstrom      const char* host_dir = getenv("ANDROID_HOST_OUT");
4223f47c12487250f61f3be95e9f275e3b08e2c49fbBrian Carlstrom      CHECK(host_dir != NULL);
4233f47c12487250f61f3be95e9f275e3b08e2c49fbBrian Carlstrom      return host_dir;
4243f47c12487250f61f3be95e9f275e3b08e2c49fbBrian Carlstrom    }
4253f47c12487250f61f3be95e9f275e3b08e2c49fbBrian Carlstrom    return GetAndroidRoot();
4263f47c12487250f61f3be95e9f275e3b08e2c49fbBrian Carlstrom  }
4273f47c12487250f61f3be95e9f275e3b08e2c49fbBrian Carlstrom
42833e9566255c426e7a2c8fca5b8a1b6a94a5d352cIan Rogers  const DexFile* OpenTestDexFile(const char* name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
4299f30b38d74990286ce27c3a45368f73dbe3638f0Brian Carlstrom    CHECK(name != NULL);
4309f30b38d74990286ce27c3a45368f73dbe3638f0Brian Carlstrom    std::string filename;
431761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes    if (IsHost()) {
432b2793375d42b5d90d9a0111581c4314abe11ca4cBrian Carlstrom      filename += getenv("ANDROID_HOST_OUT");
433b2793375d42b5d90d9a0111581c4314abe11ca4cBrian Carlstrom      filename += "/framework/";
434b2793375d42b5d90d9a0111581c4314abe11ca4cBrian Carlstrom    } else {
435b2793375d42b5d90d9a0111581c4314abe11ca4cBrian Carlstrom      filename += "/data/nativetest/art/";
4369f30b38d74990286ce27c3a45368f73dbe3638f0Brian Carlstrom    }
437b2793375d42b5d90d9a0111581c4314abe11ca4cBrian Carlstrom    filename += "art-test-dex-";
4389f30b38d74990286ce27c3a45368f73dbe3638f0Brian Carlstrom    filename += name;
4399f30b38d74990286ce27c3a45368f73dbe3638f0Brian Carlstrom    filename += ".jar";
440a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    const DexFile* dex_file = DexFile::Open(filename, filename);
44169b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    CHECK(dex_file != NULL) << "Failed to open " << filename;
4424d6850c47515fe2a4f9de923befb6287bb863c8cElliott Hughes    opened_dex_files_.push_back(dex_file);
4439f30b38d74990286ce27c3a45368f73dbe3638f0Brian Carlstrom    return dex_file;
4449f30b38d74990286ce27c3a45368f73dbe3638f0Brian Carlstrom  }
4459f30b38d74990286ce27c3a45368f73dbe3638f0Brian Carlstrom
44633e9566255c426e7a2c8fca5b8a1b6a94a5d352cIan Rogers  jobject LoadDex(const char* dex_name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
4479baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom    const DexFile* dex_file = OpenTestDexFile(dex_name);
4489baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom    CHECK(dex_file != NULL);
4499baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom    class_linker_->RegisterDexFile(*dex_file);
4509baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom    std::vector<const DexFile*> class_path;
4519baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom    class_path.push_back(dex_file);
45200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    ScopedObjectAccessUnchecked soa(Thread::Current());
45300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    ScopedLocalRef<jobject> class_loader_local(soa.Env(),
45400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers        soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader));
45500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    jobject class_loader = soa.Env()->NewGlobalRef(class_loader_local.get());
4562dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    soa.Self()->SetClassLoaderOverride(soa.Decode<mirror::ClassLoader*>(class_loader_local.get()));
45700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    Runtime::Current()->SetCompileTimeClassPath(class_loader, class_path);
45800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return class_loader;
4599baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom  }
4609baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom
46133e9566255c426e7a2c8fca5b8a1b6a94a5d352cIan Rogers  void CompileClass(mirror::ClassLoader* class_loader, const char* class_name)
46233e9566255c426e7a2c8fca5b8a1b6a94a5d352cIan Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
463955724179c6c739524f610023287f56b24dc31deElliott Hughes    std::string class_descriptor(DotToDescriptor(class_name));
4642dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader);
465aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    CHECK(klass != NULL) << "Class not found " << class_name;
466aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
467aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      CompileMethod(klass->GetDirectMethod(i));
468aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
469aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
470aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      CompileMethod(klass->GetVirtualMethod(i));
471aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
472aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
473aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
4742dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  void CompileMethod(mirror::AbstractMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
4759baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom    CHECK(method != NULL);
4766f28d91aab952e3244fbb4e707fa38f85538f374Anwar Ghuloum    base::TimingLogger timings("CommonTest::CompileMethod", false, false);
477be576f48e4bf5c2afcaadd6e3a6d0f6a3153f031Anwar Ghuloum    timings.StartSplit("CompileOne");
4784560248d4c85cade7f4fc7b30c3fb41b95a04a7fBrian Carlstrom    compiler_driver_->CompileOne(method, timings);
4793320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    MakeExecutable(method);
4809baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom  }
4819baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom
4822dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  void CompileDirectMethod(mirror::ClassLoader* class_loader,
4839baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom                           const char* class_name,
4849baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom                           const char* method_name,
48500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                           const char* signature)
486b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
487955724179c6c739524f610023287f56b24dc31deElliott Hughes    std::string class_descriptor(DotToDescriptor(class_name));
4882dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader);
4899baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom    CHECK(klass != NULL) << "Class not found " << class_name;
4902dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::AbstractMethod* method = klass->FindDirectMethod(method_name, signature);
4910f4c41d75c821162184501cd4b510a93f6eb580fElliott Hughes    CHECK(method != NULL) << "Direct method not found: "
4920f4c41d75c821162184501cd4b510a93f6eb580fElliott Hughes                          << class_name << "." << method_name << signature;
4939baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom    CompileMethod(method);
4949baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom  }
4959baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom
4962dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  void CompileVirtualMethod(mirror::ClassLoader* class_loader,
4979baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom                            const char* class_name,
4989baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom                            const char* method_name,
49900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers                            const char* signature)
500b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
501955724179c6c739524f610023287f56b24dc31deElliott Hughes    std::string class_descriptor(DotToDescriptor(class_name));
5022dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader);
5039baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom    CHECK(klass != NULL) << "Class not found " << class_name;
5042dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::AbstractMethod* method = klass->FindVirtualMethod(method_name, signature);
5050f4c41d75c821162184501cd4b510a93f6eb580fElliott Hughes    CHECK(method != NULL) << "Virtual method not found: "
5060f4c41d75c821162184501cd4b510a93f6eb580fElliott Hughes                          << class_name << "." << method_name << signature;
5079baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom    CompileMethod(method);
5089baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom  }
5099baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom
510700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  void ReserveImageSpace() {
511700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    // Reserve where the image will be loaded up front so that other parts of test set up don't
512700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    // accidentally end up colliding with the fixed memory address when we need to load the image.
5132d88862f0752a7a0e65145b088f49dabd49d4284Brian Carlstrom    image_reservation_.reset(MemMap::MapAnonymous("image reservation",
5142d88862f0752a7a0e65145b088f49dabd49d4284Brian Carlstrom                                                  reinterpret_cast<byte*>(ART_BASE_ADDRESS),
515700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom                                                  (size_t)100 * 1024 * 1024,  // 100MB
516700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom                                                  PROT_NONE));
517700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  }
518700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom
519700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  void UnreserveImageSpace() {
520700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    image_reservation_.reset();
521700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  }
522700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom
52334023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes  std::string android_data_;
5247675e16bcae06c0fe258aad89b3d511037dec399Brian Carlstrom  std::string dalvik_cache_;
525a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  const DexFile* java_lang_dex_file_;  // owned by runtime_
526654d91957edb4d1f7534ed5d743cf914db763448Brian Carlstrom  const DexFile* conscrypt_file_;  // owned by runtime_
5279ea1cb1a22be5b85dc2622e3836c46a1c48e3f25Brian Carlstrom  std::vector<const DexFile*> boot_class_path_;
52890a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes  UniquePtr<Runtime> runtime_;
5290e073f7b9386a461b470d30415a96480ab1b76afIan Rogers  // Owned by the runtime
5307a90959d4ef7a69f3bcb7b8763f646e12d9267d3Carl Shapiro  ClassLinker* class_linker_;
5311212a022fa5f8ef9585d765b1809521812af882cIan Rogers  UniquePtr<CompilerDriver> compiler_driver_;
5329baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom
5339baa4aefc370f48774b6104680193d9a7e4fb631Brian Carlstrom private:
5344d6850c47515fe2a4f9de923befb6287bb863c8cElliott Hughes  std::vector<const DexFile*> opened_dex_files_;
535700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  UniquePtr<MemMap> image_reservation_;
536578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom};
537578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom
538b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes// Sets a CheckJni abort hook to catch failures. Note that this will cause CheckJNI to carry on
539b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes// rather than aborting, so be careful!
540b264f081424642b06b0bbe7102781895d41faa9dElliott Hughesclass CheckJniAbortCatcher {
541b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes public:
542b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes  CheckJniAbortCatcher() : vm_(Runtime::Current()->GetJavaVM()) {
543b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes    vm_->check_jni_abort_hook = Hook;
544b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes    vm_->check_jni_abort_hook_data = &actual_;
545b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes  }
546b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes
547b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes  ~CheckJniAbortCatcher() {
548b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes    vm_->check_jni_abort_hook = NULL;
549b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes    vm_->check_jni_abort_hook_data = NULL;
55056ef042065ce282f8f01a0f31f5cce868a60ede8Elliott Hughes    EXPECT_TRUE(actual_.empty()) << actual_;
551b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes  }
552b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes
553b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes  void Check(const char* expected_text) {
554b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes    EXPECT_TRUE(actual_.find(expected_text) != std::string::npos) << "\n"
555b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes        << "Expected to find: " << expected_text << "\n"
556b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes        << "In the output   : " << actual_;
5573f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    actual_.clear();
558b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes  }
559b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes
560b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes private:
561b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes  static void Hook(void* data, const std::string& reason) {
5623f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    // We use += because when we're hooking the aborts like this, multiple problems can be found.
5633f6635a2c84d645002f651c312d53f8348646c1fElliott Hughes    *reinterpret_cast<std::string*>(data) += reason;
564b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes  }
565b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes
566b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes  JavaVMExt* vm_;
567b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes  std::string actual_;
568b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes
569b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes  DISALLOW_COPY_AND_ASSIGN(CheckJniAbortCatcher);
570b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes};
571b264f081424642b06b0bbe7102781895d41faa9dElliott Hughes
572265091e581c9f643b37e7966890911f09e223269Brian Carlstrom// TODO: These tests were disabled for portable when we went to having
573265091e581c9f643b37e7966890911f09e223269Brian Carlstrom// MCLinker link LLVM ELF output because we no longer just have code
574265091e581c9f643b37e7966890911f09e223269Brian Carlstrom// blobs in memory. We'll need to dlopen to load and relocate
575265091e581c9f643b37e7966890911f09e223269Brian Carlstrom// temporary output to resurrect these tests.
576265091e581c9f643b37e7966890911f09e223269Brian Carlstrom#if defined(ART_USE_PORTABLE_COMPILER)
577265091e581c9f643b37e7966890911f09e223269Brian Carlstrom#define TEST_DISABLED_FOR_PORTABLE() printf("WARNING: TEST DISABLED FOR PORTABLE\n"); return
578265091e581c9f643b37e7966890911f09e223269Brian Carlstrom#else
579265091e581c9f643b37e7966890911f09e223269Brian Carlstrom#define TEST_DISABLED_FOR_PORTABLE()
580265091e581c9f643b37e7966890911f09e223269Brian Carlstrom#endif
581265091e581c9f643b37e7966890911f09e223269Brian Carlstrom
582934486cf07c578b6494417ca5dcbae89cf04b019Brian Carlstrom}  // namespace art
58334023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes
58434023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughesnamespace std {
58534023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes
58634023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes// TODO: isn't gtest supposed to be able to print STL types for itself?
58734023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughestemplate <typename T>
58834023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughesstd::ostream& operator<<(std::ostream& os, const std::vector<T>& rhs) {
58914134a10e9bbaff0faf314dc00c1a1aeef8ef86bElliott Hughes  os << ::art::ToString(rhs);
59034023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes  return os;
59134023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes}
59234023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes
59334023801bd544e613d6e85c9a5b2e743f3710e8fElliott Hughes}  // namespace std
594fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom
595fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#endif  // ART_RUNTIME_COMMON_TEST_H_
596