blob: 4689b28275cacf6aeafdb5decb67b8fc9f763edf [file] [log] [blame]
Brian Carlstrom934486c2011-07-12 23:42:50 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
Brian Carlstromb0460ea2011-07-29 10:08:05 -07003#include <dirent.h>
Elliott Hughes0af55432011-08-17 18:37:28 -07004#include <dlfcn.h>
Brian Carlstromb0460ea2011-07-29 10:08:05 -07005#include <sys/stat.h>
6#include <sys/types.h>
7
Elliott Hughes90a33692011-08-30 13:27:07 -07008#include "UniquePtr.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07009#include "base64.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070010#include "class_linker.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070011#include "class_loader.h"
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070012#include "compiler.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070013#include "dex_file.h"
Elliott Hughes90a33692011-08-30 13:27:07 -070014#include "gtest/gtest.h"
Brian Carlstrom1f870082011-08-23 16:02:11 -070015#include "heap.h"
16#include "runtime.h"
Elliott Hughes90a33692011-08-30 13:27:07 -070017#include "stringprintf.h"
18#include "thread.h"
Elliott Hughes0af55432011-08-17 18:37:28 -070019#include "unicode/uclean.h"
20#include "unicode/uvernum.h"
21
Brian Carlstrom934486c2011-07-12 23:42:50 -070022namespace art {
23
Brian Carlstrom9f30b382011-08-28 22:41:38 -070024static inline const DexFile* OpenDexFileBase64(const char* base64,
25 const std::string& location) {
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070026 CHECK(base64 != NULL);
27 size_t length;
Brian Carlstromf615a612011-07-23 12:50:34 -070028 byte* dex_bytes = DecodeBase64(base64, &length);
29 CHECK(dex_bytes != NULL);
Brian Carlstrom9f30b382011-08-28 22:41:38 -070030 const DexFile* dex_file = DexFile::OpenPtr(dex_bytes, length, location);
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070031 CHECK(dex_file != NULL);
Brian Carlstromf615a612011-07-23 12:50:34 -070032 return dex_file;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070033}
34
Brian Carlstromdb4d5402011-08-09 12:18:28 -070035class ScratchFile {
36 public:
37 ScratchFile() {
Elliott Hughes34023802011-08-30 12:06:17 -070038 filename_ = getenv("ANDROID_DATA");
39 filename_ += "/TmpFile-XXXXXX";
40 fd_ = mkstemp(&filename_[0]);
Brian Carlstromdb4d5402011-08-09 12:18:28 -070041 CHECK_NE(-1, fd_);
42 }
43
44 ~ScratchFile() {
Elliott Hughes34023802011-08-30 12:06:17 -070045 int unlink_result = unlink(filename_.c_str());
Brian Carlstromdb4d5402011-08-09 12:18:28 -070046 CHECK_EQ(0, unlink_result);
47 int close_result = close(fd_);
48 CHECK_EQ(0, close_result);
49 }
50
51 const char* GetFilename() const {
Elliott Hughes34023802011-08-30 12:06:17 -070052 return filename_.c_str();
Brian Carlstromdb4d5402011-08-09 12:18:28 -070053 }
54
55 int GetFd() const {
56 return fd_;
57 }
58
59 private:
Elliott Hughes34023802011-08-30 12:06:17 -070060 std::string filename_;
Brian Carlstromdb4d5402011-08-09 12:18:28 -070061 int fd_;
62};
63
Brian Carlstromf734cf52011-08-17 16:28:14 -070064class CommonTest : public testing::Test {
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070065 public:
66 static void LogMaps() {
67 const char* maps_file = "/proc/self/maps";
68 std::string contents;
69 CHECK(ReadFileToString(maps_file, &contents));
70 // logcat can't handle it all at once
71 std::vector<std::string> lines;
72 Split(contents, '\n', lines);
73 LOG(INFO) << maps_file << ":";
74 for (size_t i = 0; i < lines.size(); i++) {
75 LOG(INFO) << " " << lines[i];
76 }
77 }
78
79 static void MakeExecutable(const ByteArray* byte_array) {
80 uintptr_t data = reinterpret_cast<uintptr_t>(byte_array->GetData());
81 uintptr_t base = RoundDown(data, kPageSize);
82 uintptr_t limit = RoundUp(data + byte_array->GetLength(), kPageSize);
83 uintptr_t len = limit - base;
84 int result = mprotect(reinterpret_cast<void*>(base), len, PROT_READ | PROT_WRITE | PROT_EXEC);
85 CHECK_EQ(result, 0);
86 }
87
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070088 protected:
89 virtual void SetUp() {
Brian Carlstrom4a96b602011-07-26 16:40:23 -070090 is_host_ = getenv("ANDROID_BUILD_TOP") != NULL;
91
Elliott Hughes0af55432011-08-17 18:37:28 -070092 if (is_host_) {
93 // $ANDROID_ROOT is set on the device, but not on the host.
94 // We need to set this so that icu4c can find its locale data.
95 std::string root;
96 root += getenv("ANDROID_BUILD_TOP");
97 root += "/out/host/linux-x86";
98 setenv("ANDROID_ROOT", root.c_str(), 1);
99 }
100
Elliott Hughes34023802011-08-30 12:06:17 -0700101 android_data_ = (is_host_ ? "/tmp/art-data-XXXXXX" : "/sdcard/art-data-XXXXXX");
102 ASSERT_TRUE(mkdtemp(&android_data_[0]) != NULL);
103 setenv("ANDROID_DATA", android_data_.c_str(), 1);
104 art_cache_.append(android_data_.c_str());
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700105 art_cache_.append("/art-cache");
106 int mkdir_result = mkdir(art_cache_.c_str(), 0700);
107 ASSERT_EQ(mkdir_result, 0);
108
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700109 java_lang_dex_file_.reset(GetLibCoreDex());
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700110
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700111 boot_class_path_.push_back(java_lang_dex_file_.get());
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700112
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700113 runtime_.reset(Runtime::Create(boot_class_path_));
Elliott Hughes90a33692011-08-30 13:27:07 -0700114 ASSERT_TRUE(runtime_.get() != NULL);
Carl Shapiro7a909592011-07-24 19:21:59 -0700115 class_linker_ = runtime_->GetClassLinker();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700116
117 Heap::VerifyHeap(); // Check for heap corruption before the test
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700118 }
119
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700120 virtual void TearDown() {
121 const char* android_data = getenv("ANDROID_DATA");
122 ASSERT_TRUE(android_data != NULL);
123 DIR* dir = opendir(art_cache_.c_str());
124 ASSERT_TRUE(dir != NULL);
125 while (true) {
126 struct dirent entry;
127 struct dirent* entry_ptr;
128 int readdir_result = readdir_r(dir, &entry, &entry_ptr);
129 ASSERT_EQ(0, readdir_result);
130 if (entry_ptr == NULL) {
131 break;
132 }
133 if ((strcmp(entry_ptr->d_name, ".") == 0) || (strcmp(entry_ptr->d_name, "..") == 0)) {
134 continue;
135 }
136 std::string filename(art_cache_);
137 filename.push_back('/');
138 filename.append(entry_ptr->d_name);
139 int unlink_result = unlink(filename.c_str());
140 ASSERT_EQ(0, unlink_result);
Jesse Wilsonac5b9e22011-07-27 15:11:13 -0400141 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700142 closedir(dir);
143 int rmdir_cache_result = rmdir(art_cache_.c_str());
144 ASSERT_EQ(0, rmdir_cache_result);
Elliott Hughes34023802011-08-30 12:06:17 -0700145 int rmdir_data_result = rmdir(android_data_.c_str());
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700146 ASSERT_EQ(0, rmdir_data_result);
Elliott Hughes0af55432011-08-17 18:37:28 -0700147
148 // icu4c has a fixed 10-element array "gCommonICUDataArray".
149 // If we run > 10 tests, we fill that array and u_setCommonData fails.
150 // There's a function to clear the array, but it's not public...
151 typedef void (*IcuCleanupFn)();
152 void* sym = dlsym(RTLD_DEFAULT, "u_cleanup_" U_ICU_VERSION_SHORT);
153 CHECK(sym != NULL);
154 IcuCleanupFn icu_cleanup_fn = reinterpret_cast<IcuCleanupFn>(sym);
155 (*icu_cleanup_fn)();
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700156
157 Heap::VerifyHeap(); // Check for heap corruption after the test
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700158 }
Jesse Wilsonac5b9e22011-07-27 15:11:13 -0400159
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700160 std::string GetLibCoreDexFileName() {
161 if (is_host_) {
162 const char* host_dir = getenv("ANDROID_HOST_OUT");
163 CHECK(host_dir != NULL);
164 return StringPrintf("%s/framework/core-hostdex.jar", host_dir);
165 }
166 return std::string("/system/framework/core.jar");
167 }
168
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700169 const DexFile* GetLibCoreDex() {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700170 std::string libcore_dex_file_name = GetLibCoreDexFileName();
Elliott Hughes40ef99e2011-08-11 17:44:34 -0700171 return DexFile::OpenZip(libcore_dex_file_name);
Jesse Wilsonac5b9e22011-07-27 15:11:13 -0400172 }
173
Brian Carlstrom848a4b32011-09-04 11:29:27 -0700174 uint32_t FindTypeIdxByDescriptor(const DexFile& dex_file, const StringPiece& descriptor) {
175 for (size_t i = 0; i < dex_file.NumTypeIds(); i++) {
176 const DexFile::TypeId& type_id = dex_file.GetTypeId(i);
177 if (descriptor == dex_file.GetTypeDescriptor(type_id)) {
178 return i;
179 }
180 }
181 CHECK(false) << "Could not find type index for " << descriptor;
182 return 0;
183 }
184
185 uint32_t FindFieldIdxByDescriptorAndName(const DexFile& dex_file,
186 const StringPiece& class_descriptor,
187 const StringPiece& field_name) {
188 for (size_t i = 0; i < dex_file.NumFieldIds(); i++) {
189 const DexFile::FieldId& field_id = dex_file.GetFieldId(i);
190 if (class_descriptor == dex_file.GetFieldClassDescriptor(field_id)
191 && field_name == dex_file.GetFieldName(field_id)) {
192 return i;
193 }
194 }
195 CHECK(false) << "Could not find field index for " << class_descriptor << " " << field_name;
196 return 0;
197 }
198
Brian Carlstrom8a487412011-08-29 20:08:52 -0700199 const PathClassLoader* AllocPathClassLoader(const DexFile* dex_file) {
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700200 CHECK(dex_file != NULL);
201 class_linker_->RegisterDexFile(*dex_file);
Brian Carlstrom74eb46a2011-08-02 20:10:14 -0700202 std::vector<const DexFile*> dex_files;
203 dex_files.push_back(dex_file);
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700204 return PathClassLoader::Alloc(dex_files);
Brian Carlstrom74eb46a2011-08-02 20:10:14 -0700205 }
206
Brian Carlstrom9f30b382011-08-28 22:41:38 -0700207 const DexFile* OpenTestDexFile(const char* name) {
208 CHECK(name != NULL);
209 std::string filename;
210 if (is_host_) {
211 // on the host, just read target dex file
212 filename += getenv("ANDROID_PRODUCT_OUT");
213 }
214 filename += "/system/framework/art-test-dex-";
215 filename += name;
216 filename += ".jar";
217 const DexFile* dex_file = DexFile::OpenZip(filename);
218 CHECK(dex_file != NULL) << "Could not open " << filename;
219 return dex_file;
220 }
221
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700222 const ClassLoader* LoadDex(const char* dex_name) {
223 const DexFile* dex_file = OpenTestDexFile(dex_name);
224 CHECK(dex_file != NULL);
225 loaded_dex_files_.push_back(dex_file);
226 class_linker_->RegisterDexFile(*dex_file);
227 std::vector<const DexFile*> class_path;
228 class_path.push_back(dex_file);
229 const ClassLoader* class_loader = PathClassLoader::Alloc(class_path);
230 CHECK(class_loader != NULL);
231 Thread::Current()->SetClassLoaderOverride(class_loader);
232 return class_loader;
233 }
234
235 std::string ConvertClassNameToClassDescriptor(const char* class_name) {
236 std::string desc;
237 desc += "L";
238 desc += class_name;
239 desc += ";";
240 std::replace(desc.begin(), desc.end(), '.', '/');
241 return desc;
242 }
243
244 void CompileMethod(Method* method) {
245 CHECK(method != NULL);
246 Compiler compiler;
247 compiler.CompileOne(method);
248 MakeExecutable(method->GetCodeArray());
249 MakeExecutable(method->GetInvokeStubArray());
250 }
251
252 void CompileDirectMethod(const ClassLoader* class_loader,
253 const char* class_name,
254 const char* method_name,
255 const char* signature) {
256 std::string class_descriptor = ConvertClassNameToClassDescriptor(class_name);
257 Class* klass = class_linker_->FindClass(class_descriptor, class_loader);
258 CHECK(klass != NULL) << "Class not found " << class_name;
259 Method* method = klass->FindDirectMethod(method_name, signature);
260 CHECK(method != NULL) << "Method not found " << method_name;
261 CompileMethod(method);
262 }
263
264 void CompileVirtualMethod(const ClassLoader* class_loader,
265 const char* class_name,
266 const char* method_name,
267 const char* signature) {
268 std::string class_descriptor = ConvertClassNameToClassDescriptor(class_name);
269 Class* klass = class_linker_->FindClass(class_descriptor, class_loader);
270 CHECK(klass != NULL) << "Class not found " << class_name;
271 Method* method = klass->FindVirtualMethod(method_name, signature);
272 CHECK(method != NULL) << "Method not found " << method_name;
273 CompileMethod(method);
274 }
275
Brian Carlstrom4a96b602011-07-26 16:40:23 -0700276 bool is_host_;
Elliott Hughes34023802011-08-30 12:06:17 -0700277 std::string android_data_;
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700278 std::string art_cache_;
Elliott Hughes90a33692011-08-30 13:27:07 -0700279 UniquePtr<const DexFile> java_lang_dex_file_;
Brian Carlstrom9ea1cb12011-08-24 23:18:18 -0700280 std::vector<const DexFile*> boot_class_path_;
Elliott Hughes90a33692011-08-30 13:27:07 -0700281 UniquePtr<Runtime> runtime_;
Carl Shapiro7a909592011-07-24 19:21:59 -0700282 ClassLinker* class_linker_;
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -0700283
284 private:
285 std::vector<const DexFile*> loaded_dex_files_;
Brian Carlstrom578bbdc2011-07-21 14:07:47 -0700286};
287
Brian Carlstrom934486c2011-07-12 23:42:50 -0700288} // namespace art
Elliott Hughes34023802011-08-30 12:06:17 -0700289
290namespace std {
291
292// TODO: isn't gtest supposed to be able to print STL types for itself?
293template <typename T>
294std::ostream& operator<<(std::ostream& os, const std::vector<T>& rhs) {
295 os << "[";
296 for (size_t i = 0; i < rhs.size(); ++i) {
297 os << rhs[i];
298 if (i < rhs.size() - 1) {
299 os << ", ";
300 }
301 }
302 os << "]";
303 return os;
304}
305
306} // namespace std