blob: e2ecf4b0b9a7b19708bd56d900be962ff0509511 [file] [log] [blame]
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_RUNTIME_COMMON_RUNTIME_TEST_H_
18#define ART_RUNTIME_COMMON_RUNTIME_TEST_H_
19
20#include <dirent.h>
21#include <dlfcn.h>
22#include <sys/mman.h>
23#include <sys/stat.h>
24#include <sys/types.h>
25#include <fstream>
26
27#include "../../external/icu4c/common/unicode/uvernum.h"
28#include "base/macros.h"
29#include "base/stl_util.h"
30#include "base/stringprintf.h"
31#include "base/unix_file/fd_file.h"
32#include "class_linker.h"
33#include "compiler_callbacks.h"
34#include "dex_file-inl.h"
35#include "entrypoints/entrypoint_utils.h"
36#include "gc/heap.h"
37#include "gtest/gtest.h"
38#include "instruction_set.h"
39#include "interpreter/interpreter.h"
40#include "mirror/class_loader.h"
41#include "oat_file.h"
42#include "object_utils.h"
43#include "os.h"
44#include "runtime.h"
45#include "scoped_thread_state_change.h"
46#include "ScopedLocalRef.h"
47#include "thread.h"
48#include "utils.h"
49#include "UniquePtr.h"
50#include "verifier/method_verifier.h"
51#include "verifier/method_verifier-inl.h"
52#include "well_known_classes.h"
53
54namespace art {
55
56class ScratchFile {
57 public:
58 ScratchFile() {
59 filename_ = getenv("ANDROID_DATA");
60 filename_ += "/TmpFile-XXXXXX";
61 int fd = mkstemp(&filename_[0]);
62 CHECK_NE(-1, fd);
63 file_.reset(new File(fd, GetFilename()));
64 }
65
66 ~ScratchFile() {
67 int unlink_result = unlink(filename_.c_str());
68 CHECK_EQ(0, unlink_result);
69 }
70
71 const std::string& GetFilename() const {
72 return filename_;
73 }
74
75 File* GetFile() const {
76 return file_.get();
77 }
78
79 int GetFd() const {
80 return file_->Fd();
81 }
82
83 private:
84 std::string filename_;
85 UniquePtr<File> file_;
86};
87
88class NoopCompilerCallbacks : public CompilerCallbacks {
89 public:
90 NoopCompilerCallbacks() {}
91 virtual ~NoopCompilerCallbacks() {}
92 virtual bool MethodVerified(verifier::MethodVerifier* verifier) {
93 return true;
94 }
95 virtual void ClassRejected(ClassReference ref) {}
96};
97
98class CommonRuntimeTest : public testing::Test {
99 public:
100 static void SetEnvironmentVariables(std::string& android_data) {
101 if (IsHost()) {
102 // $ANDROID_ROOT is set on the device, but not on the host.
103 // We need to set this so that icu4c can find its locale data.
104 std::string root;
105 const char* android_build_top = getenv("ANDROID_BUILD_TOP");
106 if (android_build_top != nullptr) {
107 root += android_build_top;
108 } else {
109 // Not set by build server, so default to current directory
110 char* cwd = getcwd(nullptr, 0);
111 setenv("ANDROID_BUILD_TOP", cwd, 1);
112 root += cwd;
113 free(cwd);
114 }
115#if defined(__linux__)
116 root += "/out/host/linux-x86";
117#elif defined(__APPLE__)
118 root += "/out/host/darwin-x86";
119#else
120#error unsupported OS
121#endif
122 setenv("ANDROID_ROOT", root.c_str(), 1);
123 setenv("LD_LIBRARY_PATH", ":", 0); // Required by java.lang.System.<clinit>.
124
125 // Not set by build server, so default
126 if (getenv("ANDROID_HOST_OUT") == nullptr) {
127 setenv("ANDROID_HOST_OUT", root.c_str(), 1);
128 }
129 }
130
131 // On target, Cannot use /mnt/sdcard because it is mounted noexec, so use subdir of dalvik-cache
132 android_data = (IsHost() ? "/tmp/art-data-XXXXXX" : "/data/dalvik-cache/art-data-XXXXXX");
133 if (mkdtemp(&android_data[0]) == nullptr) {
134 PLOG(FATAL) << "mkdtemp(\"" << &android_data[0] << "\") failed";
135 }
136 setenv("ANDROID_DATA", android_data.c_str(), 1);
137 }
138
139 protected:
140 static bool IsHost() {
141 return !kIsTargetBuild;
142 }
143
144 virtual void SetUp() {
145 SetEnvironmentVariables(android_data_);
146 dalvik_cache_.append(android_data_.c_str());
147 dalvik_cache_.append("/dalvik-cache");
148 int mkdir_result = mkdir(dalvik_cache_.c_str(), 0700);
149 ASSERT_EQ(mkdir_result, 0);
150
151 std::string error_msg;
152 java_lang_dex_file_ = DexFile::Open(GetLibCoreDexFileName().c_str(),
153 GetLibCoreDexFileName().c_str(), &error_msg);
154 if (java_lang_dex_file_ == nullptr) {
155 LOG(FATAL) << "Could not open .dex file '" << GetLibCoreDexFileName() << "': "
156 << error_msg << "\n";
157 }
158 boot_class_path_.push_back(java_lang_dex_file_);
159
160 std::string min_heap_string(StringPrintf("-Xms%zdm", gc::Heap::kDefaultInitialSize / MB));
161 std::string max_heap_string(StringPrintf("-Xmx%zdm", gc::Heap::kDefaultMaximumSize / MB));
162
163 Runtime::Options options;
164 options.push_back(std::make_pair("bootclasspath", &boot_class_path_));
165 options.push_back(std::make_pair("-Xcheck:jni", nullptr));
166 options.push_back(std::make_pair(min_heap_string.c_str(), nullptr));
167 options.push_back(std::make_pair(max_heap_string.c_str(), nullptr));
168 options.push_back(std::make_pair("compilercallbacks", &callbacks_));
169 SetUpRuntimeOptions(&options);
170 if (!Runtime::Create(options, false)) {
171 LOG(FATAL) << "Failed to create runtime";
172 return;
173 }
174 runtime_.reset(Runtime::Current());
175 class_linker_ = runtime_->GetClassLinker();
176 class_linker_->FixupDexCaches(runtime_->GetResolutionMethod());
177
178 // Runtime::Create acquired the mutator_lock_ that is normally given away when we
179 // Runtime::Start, give it away now and then switch to a more managable ScopedObjectAccess.
180 Thread::Current()->TransitionFromRunnableToSuspended(kNative);
181
182 // We're back in native, take the opportunity to initialize well known classes.
183 WellKnownClasses::Init(Thread::Current()->GetJniEnv());
184
185 // Create the heap thread pool so that the GC runs in parallel for tests. Normally, the thread
186 // pool is created by the runtime.
187 runtime_->GetHeap()->CreateThreadPool();
188 runtime_->GetHeap()->VerifyHeap(); // Check for heap corruption before the test
189 }
190
191 // Allow subclases such as CommonCompilerTest to add extra options.
192 virtual void SetUpRuntimeOptions(Runtime::Options *options) {}
193
194 virtual void TearDown() {
195 const char* android_data = getenv("ANDROID_DATA");
196 ASSERT_TRUE(android_data != nullptr);
197 DIR* dir = opendir(dalvik_cache_.c_str());
198 ASSERT_TRUE(dir != nullptr);
199 dirent* e;
200 while ((e = readdir(dir)) != nullptr) {
201 if ((strcmp(e->d_name, ".") == 0) || (strcmp(e->d_name, "..") == 0)) {
202 continue;
203 }
204 std::string filename(dalvik_cache_);
205 filename.push_back('/');
206 filename.append(e->d_name);
207 int unlink_result = unlink(filename.c_str());
208 ASSERT_EQ(0, unlink_result);
209 }
210 closedir(dir);
211 int rmdir_cache_result = rmdir(dalvik_cache_.c_str());
212 ASSERT_EQ(0, rmdir_cache_result);
213 int rmdir_data_result = rmdir(android_data_.c_str());
214 ASSERT_EQ(0, rmdir_data_result);
215
216 // icu4c has a fixed 10-element array "gCommonICUDataArray".
217 // If we run > 10 tests, we fill that array and u_setCommonData fails.
218 // There's a function to clear the array, but it's not public...
219 typedef void (*IcuCleanupFn)();
220 void* sym = dlsym(RTLD_DEFAULT, "u_cleanup_" U_ICU_VERSION_SHORT);
221 CHECK(sym != nullptr);
222 IcuCleanupFn icu_cleanup_fn = reinterpret_cast<IcuCleanupFn>(sym);
223 (*icu_cleanup_fn)();
224
225 STLDeleteElements(&opened_dex_files_);
226
227 Runtime::Current()->GetHeap()->VerifyHeap(); // Check for heap corruption after the test
228 }
229
230 std::string GetLibCoreDexFileName() {
231 return GetDexFileName("core-libart");
232 }
233
234 std::string GetDexFileName(const std::string& jar_prefix) {
235 if (IsHost()) {
236 const char* host_dir = getenv("ANDROID_HOST_OUT");
237 CHECK(host_dir != nullptr);
238 return StringPrintf("%s/framework/%s-hostdex.jar", host_dir, jar_prefix.c_str());
239 }
240 return StringPrintf("%s/framework/%s.jar", GetAndroidRoot(), jar_prefix.c_str());
241 }
242
243 std::string GetTestAndroidRoot() {
244 if (IsHost()) {
245 const char* host_dir = getenv("ANDROID_HOST_OUT");
246 CHECK(host_dir != nullptr);
247 return host_dir;
248 }
249 return GetAndroidRoot();
250 }
251
252 const DexFile* OpenTestDexFile(const char* name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
253 CHECK(name != nullptr);
254 std::string filename;
255 if (IsHost()) {
256 filename += getenv("ANDROID_HOST_OUT");
257 filename += "/framework/";
258 } else {
259 filename += "/data/nativetest/art/";
260 }
261 filename += "art-test-dex-";
262 filename += name;
263 filename += ".jar";
264 std::string error_msg;
265 const DexFile* dex_file = DexFile::Open(filename.c_str(), filename.c_str(), &error_msg);
266 CHECK(dex_file != nullptr) << "Failed to open '" << filename << "': " << error_msg;
267 CHECK_EQ(PROT_READ, dex_file->GetPermissions());
268 CHECK(dex_file->IsReadOnly());
269 opened_dex_files_.push_back(dex_file);
270 return dex_file;
271 }
272
273 jobject LoadDex(const char* dex_name) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
274 const DexFile* dex_file = OpenTestDexFile(dex_name);
275 CHECK(dex_file != nullptr);
276 class_linker_->RegisterDexFile(*dex_file);
277 std::vector<const DexFile*> class_path;
278 class_path.push_back(dex_file);
279 ScopedObjectAccessUnchecked soa(Thread::Current());
280 ScopedLocalRef<jobject> class_loader_local(soa.Env(),
281 soa.Env()->AllocObject(WellKnownClasses::dalvik_system_PathClassLoader));
282 jobject class_loader = soa.Env()->NewGlobalRef(class_loader_local.get());
283 soa.Self()->SetClassLoaderOverride(soa.Decode<mirror::ClassLoader*>(class_loader_local.get()));
284 Runtime::Current()->SetCompileTimeClassPath(class_loader, class_path);
285 return class_loader;
286 }
287
288 std::string android_data_;
289 std::string dalvik_cache_;
290 const DexFile* java_lang_dex_file_; // owned by runtime_
291 std::vector<const DexFile*> boot_class_path_;
292 UniquePtr<Runtime> runtime_;
293 // Owned by the runtime
294 ClassLinker* class_linker_;
295
296 private:
297 NoopCompilerCallbacks callbacks_;
298 std::vector<const DexFile*> opened_dex_files_;
299};
300
301// Sets a CheckJni abort hook to catch failures. Note that this will cause CheckJNI to carry on
302// rather than aborting, so be careful!
303class CheckJniAbortCatcher {
304 public:
305 CheckJniAbortCatcher() : vm_(Runtime::Current()->GetJavaVM()) {
306 vm_->check_jni_abort_hook = Hook;
307 vm_->check_jni_abort_hook_data = &actual_;
308 }
309
310 ~CheckJniAbortCatcher() {
311 vm_->check_jni_abort_hook = nullptr;
312 vm_->check_jni_abort_hook_data = nullptr;
313 EXPECT_TRUE(actual_.empty()) << actual_;
314 }
315
316 void Check(const char* expected_text) {
317 EXPECT_TRUE(actual_.find(expected_text) != std::string::npos) << "\n"
318 << "Expected to find: " << expected_text << "\n"
319 << "In the output : " << actual_;
320 actual_.clear();
321 }
322
323 private:
324 static void Hook(void* data, const std::string& reason) {
325 // We use += because when we're hooking the aborts like this, multiple problems can be found.
326 *reinterpret_cast<std::string*>(data) += reason;
327 }
328
329 JavaVMExt* vm_;
330 std::string actual_;
331
332 DISALLOW_COPY_AND_ASSIGN(CheckJniAbortCatcher);
333};
334
335// TODO: These tests were disabled for portable when we went to having
336// MCLinker link LLVM ELF output because we no longer just have code
337// blobs in memory. We'll need to dlopen to load and relocate
338// temporary output to resurrect these tests.
339#define TEST_DISABLED_FOR_PORTABLE() \
340 if (kUsePortableCompiler) { \
341 printf("WARNING: TEST DISABLED FOR PORTABLE\n"); \
342 return; \
343 }
344
345} // namespace art
346
347namespace std {
348
349// TODO: isn't gtest supposed to be able to print STL types for itself?
350template <typename T>
351std::ostream& operator<<(std::ostream& os, const std::vector<T>& rhs) {
352 os << ::art::ToString(rhs);
353 return os;
354}
355
356} // namespace std
357
358#endif // ART_RUNTIME_COMMON_RUNTIME_TEST_H_