common_test.h revision 971bf3f9184010d68b9a3ad30b396fa401af91a3
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#include <dirent.h>
18#include <dlfcn.h>
19#include <sys/mman.h>
20#include <sys/stat.h>
21#include <sys/types.h>
22
23#include "class_linker.h"
24#include "class_loader.h"
25#include "compiler.h"
26#include "dex_file.h"
27#include "file.h"
28#include "gtest/gtest.h"
29#include "heap.h"
30#include "instruction_set.h"
31#include "macros.h"
32#include "oat_file.h"
33#include "object_utils.h"
34#include "os.h"
35#include "runtime.h"
36#include "stl_util.h"
37#include "stringprintf.h"
38#include "thread.h"
39#include "unicode/uclean.h"
40#include "unicode/uvernum.h"
41#include "UniquePtr.h"
42
43namespace art {
44
45static const byte kBase64Map[256] = {
46  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
47  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
48  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
49  255, 255, 255, 255, 255, 255, 255,  62, 255, 255, 255,  63,
50  52,  53,  54,  55,  56,  57,  58,  59,  60,  61, 255, 255,
51  255, 254, 255, 255, 255,   0,   1,   2,   3,   4,   5,   6,
52    7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18, // NOLINT
53   19,  20,  21,  22,  23,  24,  25, 255, 255, 255, 255, 255, // NOLINT
54  255,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,
55   37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47,  48, // NOLINT
56   49,  50,  51, 255, 255, 255, 255, 255, 255, 255, 255, 255, // NOLINT
57  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
58  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
59  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
60  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
61  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
62  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
63  255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
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
68};
69
70byte* DecodeBase64(const char* src, size_t* dst_size) {
71  std::vector<byte> tmp;
72  uint32_t t = 0, y = 0;
73  int g = 3;
74  for (size_t i = 0; src[i] != '\0'; ++i) {
75    byte c = kBase64Map[src[i] & 0xFF];
76    if (c == 255) continue;
77    // the final = symbols are read and used to trim the remaining bytes
78    if (c == 254) {
79      c = 0;
80      // prevent g < 0 which would potentially allow an overflow later
81      if (--g < 0) {
82        *dst_size = 0;
83        return NULL;
84      }
85    } else if (g != 3) {
86      // we only allow = to be at the end
87      *dst_size = 0;
88      return NULL;
89    }
90    t = (t << 6) | c;
91    if (++y == 4) {
92      tmp.push_back((t >> 16) & 255);
93      if (g > 1) {
94        tmp.push_back((t >> 8) & 255);
95      }
96      if (g > 2) {
97        tmp.push_back(t & 255);
98      }
99      y = t = 0;
100    }
101  }
102  if (y != 0) {
103    *dst_size = 0;
104    return NULL;
105  }
106  UniquePtr<byte[]> dst(new byte[tmp.size()]);
107  if (dst_size != NULL) {
108    *dst_size = tmp.size();
109  } else {
110    *dst_size = 0;
111  }
112  std::copy(tmp.begin(), tmp.end(), dst.get());
113  return dst.release();
114}
115
116static inline const DexFile* OpenDexFileBase64(const char* base64,
117                                               const std::string& location) {
118  // decode base64
119  CHECK(base64 != NULL);
120  size_t length;
121  UniquePtr<byte[]> dex_bytes(DecodeBase64(base64, &length));
122  CHECK(dex_bytes.get() != NULL);
123
124  // write to provided file
125  UniquePtr<File> file(OS::OpenFile(location.c_str(), true));
126  CHECK(file.get() != NULL);
127  if (!file->WriteFully(dex_bytes.get(), length)) {
128    PLOG(FATAL) << "Failed to write base64 as dex file";
129  }
130  file.reset();
131
132  // read dex file
133  const DexFile* dex_file = DexFile::Open(location, location);
134  CHECK(dex_file != NULL);
135  return dex_file;
136}
137
138class ScratchFile {
139 public:
140  ScratchFile() {
141    filename_ = getenv("ANDROID_DATA");
142    filename_ += "/TmpFile-XXXXXX";
143    fd_ = mkstemp(&filename_[0]);
144    CHECK_NE(-1, fd_);
145    file_.reset(OS::FileFromFd(GetFilename().c_str(), fd_));
146  }
147
148  ~ScratchFile() {
149    int unlink_result = unlink(filename_.c_str());
150    CHECK_EQ(0, unlink_result);
151    int close_result = close(fd_);
152    CHECK_EQ(0, close_result);
153  }
154
155  const std::string& GetFilename() const {
156    return filename_;
157  }
158
159  File* GetFile() const {
160    return file_.get();
161  }
162
163  int GetFd() const {
164    return fd_;
165  }
166
167 private:
168  std::string filename_;
169  int fd_;
170  UniquePtr<File> file_;
171};
172
173class CommonTest : public testing::Test {
174 public:
175  static void MakeExecutable(const ByteArray* code_array) {
176    CHECK(code_array != NULL);
177    MakeExecutable(code_array->GetData(), code_array->GetLength());
178  }
179
180  static void MakeExecutable(const std::vector<uint8_t>& code) {
181    CHECK_NE(code.size(), 0U);
182    MakeExecutable(&code[0], code.size());
183  }
184
185  // Create an OatMethod based on pointers (for unit tests)
186  OatFile::OatMethod CreateOatMethod(const void* code,
187                                     const size_t frame_size_in_bytes,
188                                     const uint32_t core_spill_mask,
189                                     const uint32_t fp_spill_mask,
190                                     const uint32_t* mapping_table,
191                                     const uint16_t* vmap_table,
192                                     const uint8_t* gc_map,
193                                     const Method::InvokeStub* invoke_stub) {
194      return OatFile::OatMethod(NULL,
195                                reinterpret_cast<uint32_t>(code),
196                                frame_size_in_bytes,
197                                core_spill_mask,
198                                fp_spill_mask,
199                                reinterpret_cast<uint32_t>(mapping_table),
200                                reinterpret_cast<uint32_t>(vmap_table),
201                                reinterpret_cast<uint32_t>(gc_map),
202                                reinterpret_cast<uint32_t>(invoke_stub)
203#if defined(ART_USE_LLVM_COMPILER)
204                              , 0
205#endif
206                                );
207  }
208
209  void MakeExecutable(Method* method) {
210    CHECK(method != NULL);
211
212    MethodHelper mh(method);
213    const CompiledInvokeStub* compiled_invoke_stub =
214        compiler_->FindInvokeStub(mh.IsStatic(), mh.GetShorty());
215    CHECK(compiled_invoke_stub != NULL) << PrettyMethod(method);
216
217    const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
218    MakeExecutable(invoke_stub);
219    const Method::InvokeStub* method_invoke_stub =
220        reinterpret_cast<const Method::InvokeStub*>(
221          CompiledCode::CodePointer(&invoke_stub[0],
222                                    compiled_invoke_stub->GetInstructionSet()));
223
224    LOG(INFO) << "MakeExecutable " << PrettyMethod(method)
225              << " invoke_stub=" << reinterpret_cast<void*>(method_invoke_stub);
226
227    if (!method->IsAbstract()) {
228      const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
229      const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache);
230      const CompiledMethod* compiled_method =
231          compiler_->GetCompiledMethod(Compiler::MethodReference(&dex_file,
232                                                                 method->GetDexMethodIndex()));
233      CHECK(compiled_method != NULL) << PrettyMethod(method);
234
235      const std::vector<uint8_t>& code = compiled_method->GetCode();
236      MakeExecutable(code);
237      const void* method_code = CompiledMethod::CodePointer(&code[0],
238                                                            compiled_method->GetInstructionSet());
239
240      LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
241
242      OatFile::OatMethod oat_method = CreateOatMethod(method_code,
243                                                      compiled_method->GetFrameSizeInBytes(),
244                                                      compiled_method->GetCoreSpillMask(),
245                                                      compiled_method->GetFpSpillMask(),
246                                                      &compiled_method->GetMappingTable()[0],
247                                                      &compiled_method->GetVmapTable()[0],
248                                                      NULL,
249                                                      method_invoke_stub);
250      oat_method.LinkMethodPointers(method);
251    } else {
252      MakeExecutable(runtime_->GetAbstractMethodErrorStubArray());
253      const void* method_code = runtime_->GetAbstractMethodErrorStubArray()->GetData();
254      LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
255      OatFile::OatMethod oat_method = CreateOatMethod(method_code,
256                                                      kStackAlignment,
257                                                      0,
258                                                      0,
259                                                      NULL,
260                                                      NULL,
261                                                      NULL,
262                                                      method_invoke_stub);
263      oat_method.LinkMethodPointers(method);
264    }
265  }
266
267  static void MakeExecutable(const void* code_start, size_t code_length) {
268    CHECK(code_start != NULL);
269    CHECK_NE(code_length, 0U);
270    uintptr_t data = reinterpret_cast<uintptr_t>(code_start);
271    uintptr_t base = RoundDown(data, kPageSize);
272    uintptr_t limit = RoundUp(data + code_length, kPageSize);
273    uintptr_t len = limit - base;
274    int result = mprotect(reinterpret_cast<void*>(base), len, PROT_READ | PROT_WRITE | PROT_EXEC);
275    CHECK_EQ(result, 0);
276
277    // Flush instruction cache
278    // Only uses __builtin___clear_cache if GCC >= 4.3.3
279#if GCC_VERSION >= 40303
280    __builtin___clear_cache(reinterpret_cast<void*>(base), reinterpret_cast<void*>(base + len));
281#elif defined(__APPLE__)
282    // Currently, only Mac OS builds use GCC 4.2.*. Those host builds do not
283    // need to generate clear_cache on x86.
284#else
285#error unsupported
286#endif
287  }
288
289 protected:
290  virtual void SetUp() {
291    is_host_ = getenv("ANDROID_BUILD_TOP") != NULL;
292
293    if (is_host_) {
294      // $ANDROID_ROOT is set on the device, but not on the host.
295      // We need to set this so that icu4c can find its locale data.
296      std::string root;
297      root += getenv("ANDROID_BUILD_TOP");
298#if defined(__linux__)
299      root += "/out/host/linux-x86";
300#elif defined(__APPLE__)
301      root += "/out/host/darwin-x86";
302#else
303#error unsupported OS
304#endif
305      setenv("ANDROID_ROOT", root.c_str(), 1);
306    }
307
308    // On target, Cannot use /mnt/sdcard because it is mounted noexec, so use subdir of art-cache
309    android_data_ = (is_host_ ? "/tmp/art-data-XXXXXX" : "/data/art-cache/art-data-XXXXXX");
310    if (mkdtemp(&android_data_[0]) == NULL) {
311      PLOG(FATAL) << "mkdtemp(\"" << &android_data_[0] << "\") failed";
312    }
313    setenv("ANDROID_DATA", android_data_.c_str(), 1);
314    art_cache_.append(android_data_.c_str());
315    art_cache_.append("/art-cache");
316    int mkdir_result = mkdir(art_cache_.c_str(), 0700);
317    ASSERT_EQ(mkdir_result, 0);
318
319    java_lang_dex_file_ = DexFile::Open(GetLibCoreDexFileName(), GetLibCoreDexFileName());
320    boot_class_path_.push_back(java_lang_dex_file_);
321
322    std::string min_heap_string(StringPrintf("-Xms%zdm", Heap::kInitialSize / MB));
323    std::string max_heap_string(StringPrintf("-Xmx%zdm", Heap::kMaximumSize / MB));
324
325    Runtime::Options options;
326    options.push_back(std::make_pair("compiler", reinterpret_cast<void*>(NULL)));
327    options.push_back(std::make_pair("bootclasspath", &boot_class_path_));
328    options.push_back(std::make_pair("-Xcheck:jni", reinterpret_cast<void*>(NULL)));
329    options.push_back(std::make_pair(min_heap_string.c_str(), reinterpret_cast<void*>(NULL)));
330    options.push_back(std::make_pair(max_heap_string.c_str(), reinterpret_cast<void*>(NULL)));
331    runtime_.reset(Runtime::Create(options, false));
332    ASSERT_TRUE(runtime_.get() != NULL);
333    class_linker_ = runtime_->GetClassLinker();
334
335    InstructionSet instruction_set = kNone;
336#if defined(__i386__)
337    instruction_set = kX86;
338#elif defined(__arm__)
339    instruction_set = kThumb2;
340#endif
341    runtime_->SetJniDlsymLookupStub(Compiler::CreateJniDlsymLookupStub(instruction_set));
342    runtime_->SetAbstractMethodErrorStubArray(Compiler::CreateAbstractMethodErrorStub(instruction_set));
343    for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
344      Runtime::TrampolineType type = Runtime::TrampolineType(i);
345      if (!runtime_->HasResolutionStubArray(type)) {
346        runtime_->SetResolutionStubArray(
347            Compiler::CreateResolutionStub(instruction_set, type), type);
348      }
349    }
350    if (!runtime_->HasResolutionMethod()) {
351      runtime_->SetResolutionMethod(runtime_->CreateResolutionMethod());
352    }
353    for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
354      Runtime::CalleeSaveType type = Runtime::CalleeSaveType(i);
355      if (!runtime_->HasCalleeSaveMethod(type)) {
356        runtime_->SetCalleeSaveMethod(
357            runtime_->CreateCalleeSaveMethod(instruction_set, type), type);
358      }
359    }
360    class_linker_->FixupDexCaches(runtime_->GetResolutionMethod());
361    image_classes_.reset(new std::set<std::string>);
362    compiler_.reset(new Compiler(instruction_set, true, 2, false, image_classes_.get(),
363                                 true, true));
364
365    Runtime::Current()->GetHeap()->VerifyHeap();  // Check for heap corruption before the test
366  }
367
368  virtual void TearDown() {
369    const char* android_data = getenv("ANDROID_DATA");
370    ASSERT_TRUE(android_data != NULL);
371    DIR* dir = opendir(art_cache_.c_str());
372    ASSERT_TRUE(dir != NULL);
373    while (true) {
374      dirent entry;
375      dirent* entry_ptr;
376      int readdir_result = readdir_r(dir, &entry, &entry_ptr);
377      ASSERT_EQ(0, readdir_result);
378      if (entry_ptr == NULL) {
379        break;
380      }
381      if ((strcmp(entry_ptr->d_name, ".") == 0) || (strcmp(entry_ptr->d_name, "..") == 0)) {
382        continue;
383      }
384      std::string filename(art_cache_);
385      filename.push_back('/');
386      filename.append(entry_ptr->d_name);
387      int unlink_result = unlink(filename.c_str());
388      ASSERT_EQ(0, unlink_result);
389    }
390    closedir(dir);
391    int rmdir_cache_result = rmdir(art_cache_.c_str());
392    ASSERT_EQ(0, rmdir_cache_result);
393    int rmdir_data_result = rmdir(android_data_.c_str());
394    ASSERT_EQ(0, rmdir_data_result);
395
396    // icu4c has a fixed 10-element array "gCommonICUDataArray".
397    // If we run > 10 tests, we fill that array and u_setCommonData fails.
398    // There's a function to clear the array, but it's not public...
399    typedef void (*IcuCleanupFn)();
400    void* sym = dlsym(RTLD_DEFAULT, "u_cleanup_" U_ICU_VERSION_SHORT);
401    CHECK(sym != NULL);
402    IcuCleanupFn icu_cleanup_fn = reinterpret_cast<IcuCleanupFn>(sym);
403    (*icu_cleanup_fn)();
404
405    compiler_.reset();
406    image_classes_.reset();
407    STLDeleteElements(&opened_dex_files_);
408
409    Runtime::Current()->GetHeap()->VerifyHeap();  // Check for heap corruption after the test
410  }
411
412  std::string GetLibCoreDexFileName() {
413    if (is_host_) {
414      const char* host_dir = getenv("ANDROID_HOST_OUT");
415      CHECK(host_dir != NULL);
416      return StringPrintf("%s/framework/core-hostdex.jar", host_dir);
417    }
418    return StringPrintf("%s/framework/core.jar", GetAndroidRoot());
419  }
420
421  const DexFile* OpenTestDexFile(const char* name) {
422    CHECK(name != NULL);
423    std::string filename;
424    if (is_host_) {
425      filename += getenv("ANDROID_HOST_OUT");
426      filename += "/framework/";
427    } else {
428      filename += "/data/nativetest/art/";
429    }
430    filename += "art-test-dex-";
431    filename += name;
432    filename += ".jar";
433    const DexFile* dex_file = DexFile::Open(filename, filename);
434    CHECK(dex_file != NULL) << "Failed to open " << filename;
435    opened_dex_files_.push_back(dex_file);
436    return dex_file;
437  }
438
439  ClassLoader* LoadDex(const char* dex_name) {
440    const DexFile* dex_file = OpenTestDexFile(dex_name);
441    CHECK(dex_file != NULL);
442    class_linker_->RegisterDexFile(*dex_file);
443    std::vector<const DexFile*> class_path;
444    class_path.push_back(dex_file);
445    SirtRef<ClassLoader> class_loader(PathClassLoader::AllocCompileTime(class_path));
446    CHECK(class_loader.get() != NULL);
447    Thread::Current()->SetClassLoaderOverride(class_loader.get());
448    return class_loader.get();
449  }
450
451  void CompileClass(ClassLoader* class_loader, const char* class_name) {
452    std::string class_descriptor(DotToDescriptor(class_name));
453    Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader);
454    CHECK(klass != NULL) << "Class not found " << class_name;
455    for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
456      CompileMethod(klass->GetDirectMethod(i));
457    }
458    for (size_t i = 0; i < klass->NumVirtualMethods(); i++) {
459      CompileMethod(klass->GetVirtualMethod(i));
460    }
461  }
462
463  void CompileMethod(Method* method) {
464    CHECK(method != NULL);
465    compiler_->CompileOne(method);
466    MakeExecutable(method);
467
468    MakeExecutable(runtime_->GetJniDlsymLookupStub());
469  }
470
471  void CompileDirectMethod(ClassLoader* class_loader,
472                           const char* class_name,
473                           const char* method_name,
474                           const char* signature) {
475    std::string class_descriptor(DotToDescriptor(class_name));
476    Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader);
477    CHECK(klass != NULL) << "Class not found " << class_name;
478    Method* method = klass->FindDirectMethod(method_name, signature);
479    CHECK(method != NULL) << "Direct method not found: "
480                          << class_name << "." << method_name << signature;
481    CompileMethod(method);
482  }
483
484  void CompileVirtualMethod(ClassLoader* class_loader,
485                            const char* class_name,
486                            const char* method_name,
487                            const char* signature) {
488    std::string class_descriptor(DotToDescriptor(class_name));
489    Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader);
490    CHECK(klass != NULL) << "Class not found " << class_name;
491    Method* method = klass->FindVirtualMethod(method_name, signature);
492    CHECK(method != NULL) << "Virtual method not found: "
493                          << class_name << "." << method_name << signature;
494    CompileMethod(method);
495  }
496
497  bool is_host_;
498  std::string android_data_;
499  std::string art_cache_;
500  const DexFile* java_lang_dex_file_;  // owned by runtime_
501  std::vector<const DexFile*> boot_class_path_;
502  UniquePtr<Runtime> runtime_;
503  // Owned by the runtime
504  ClassLinker* class_linker_;
505  UniquePtr<Compiler> compiler_;
506  UniquePtr<std::set<std::string> > image_classes_;
507
508 private:
509  std::vector<const DexFile*> opened_dex_files_;
510};
511
512// Sets a CheckJni abort hook to catch failures. Note that this will cause CheckJNI to carry on
513// rather than aborting, so be careful!
514class CheckJniAbortCatcher {
515 public:
516  CheckJniAbortCatcher() : vm_(Runtime::Current()->GetJavaVM()) {
517    vm_->check_jni_abort_hook = Hook;
518    vm_->check_jni_abort_hook_data = &actual_;
519  }
520
521  ~CheckJniAbortCatcher() {
522    vm_->check_jni_abort_hook = NULL;
523    vm_->check_jni_abort_hook_data = NULL;
524    EXPECT_TRUE(actual_.empty()) << actual_;
525  }
526
527  void Check(const char* expected_text) {
528    EXPECT_TRUE(actual_.find(expected_text) != std::string::npos) << "\n"
529        << "Expected to find: " << expected_text << "\n"
530        << "In the output   : " << actual_;
531    actual_.clear();
532  }
533
534 private:
535  static void Hook(void* data, const std::string& reason) {
536    // We use += because when we're hooking the aborts like this, multiple problems can be found.
537    *reinterpret_cast<std::string*>(data) += reason;
538  }
539
540  JavaVMExt* vm_;
541  std::string actual_;
542
543  DISALLOW_COPY_AND_ASSIGN(CheckJniAbortCatcher);
544};
545
546}  // namespace art
547
548namespace std {
549
550// TODO: isn't gtest supposed to be able to print STL types for itself?
551template <typename T>
552std::ostream& operator<<(std::ostream& os, const std::vector<T>& rhs) {
553  os << ::art::ToString(rhs);
554  return os;
555}
556
557}  // namespace std
558