blob: d94da1ef65ebf04b12c64e1fb45454e555493cad [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -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 */
Elliott Hughes0c9cd562011-08-12 10:59:29 -070016
Carl Shapiro9b9ba282011-08-14 15:30:39 -070017#include "jni_internal.h"
Elliott Hughes0c9cd562011-08-12 10:59:29 -070018
Ian Rogers0cfe1fb2011-08-26 03:29:44 -070019#include <cmath>
20
Carl Shapiro9b9ba282011-08-14 15:30:39 -070021#include "common_test.h"
Elliott Hughes726079d2011-10-07 18:43:44 -070022#include "ScopedLocalRef.h"
Ian Rogers1f539342012-10-03 21:09:42 -070023#include "sirt_ref.h"
Elliott Hughes0c9cd562011-08-12 10:59:29 -070024
25namespace art {
26
Brian Carlstromf734cf52011-08-17 16:28:14 -070027class JniInternalTest : public CommonTest {
Elliott Hughesc7ac37f2011-08-12 12:21:58 -070028 protected:
29 virtual void SetUp() {
Brian Carlstromf734cf52011-08-17 16:28:14 -070030 CommonTest::SetUp();
Elliott Hughes5174fe62011-08-23 15:12:35 -070031
Elliott Hughesa2501992011-08-26 19:39:54 -070032 vm_ = Runtime::Current()->GetJavaVM();
33
Elliott Hughes5174fe62011-08-23 15:12:35 -070034 // Turn on -verbose:jni for the JNI tests.
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -080035 gLogVerbosity.jni = true;
Elliott Hughes5174fe62011-08-23 15:12:35 -070036
Brian Carlstrom4d571432012-05-16 00:21:41 -070037 vm_->AttachCurrentThread(&env_, NULL);
Elliott Hughesb465ab02011-08-24 11:21:21 -070038
Elliott Hughes726079d2011-10-07 18:43:44 -070039 ScopedLocalRef<jclass> aioobe(env_, env_->FindClass("java/lang/ArrayIndexOutOfBoundsException"));
40 CHECK(aioobe.get() != NULL);
41 aioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(aioobe.get()));
Elliott Hughesb465ab02011-08-24 11:21:21 -070042
Elliott Hughesb264f082012-04-06 17:10:10 -070043 ScopedLocalRef<jclass> ase(env_, env_->FindClass("java/lang/ArrayStoreException"));
44 CHECK(ase.get() != NULL);
45 ase_ = reinterpret_cast<jclass>(env_->NewGlobalRef(ase.get()));
46
Elliott Hughes726079d2011-10-07 18:43:44 -070047 ScopedLocalRef<jclass> sioobe(env_, env_->FindClass("java/lang/StringIndexOutOfBoundsException"));
48 CHECK(sioobe.get() != NULL);
49 sioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(sioobe.get()));
50 }
51
Brian Carlstrom4d571432012-05-16 00:21:41 -070052 void CleanUpJniEnv() {
53 if (aioobe_ != NULL) {
54 env_->DeleteGlobalRef(aioobe_);
55 aioobe_ = NULL;
56 }
57 if (ase_ != NULL) {
58 env_->DeleteGlobalRef(ase_);
59 ase_ = NULL;
60 }
61 if (sioobe_ != NULL) {
62 env_->DeleteGlobalRef(sioobe_);
63 sioobe_ = NULL;
64 }
65 }
66
Elliott Hughes726079d2011-10-07 18:43:44 -070067 virtual void TearDown() {
Brian Carlstrom4d571432012-05-16 00:21:41 -070068 CleanUpJniEnv();
Elliott Hughes726079d2011-10-07 18:43:44 -070069 CommonTest::TearDown();
Elliott Hughesc7ac37f2011-08-12 12:21:58 -070070 }
Elliott Hughesb465ab02011-08-24 11:21:21 -070071
Mathieu Chartier66f19252012-09-18 08:57:04 -070072 AbstractMethod::InvokeStub* DoCompile(AbstractMethod*& method, Object*& receiver, bool is_static,
Ian Rogers00f7d0e2012-07-19 15:28:27 -070073 const char* method_name, const char* method_signature)
Ian Rogersb726dcb2012-09-05 08:57:23 -070074 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Elliott Hughes77405792012-03-15 15:22:12 -070075 const char* class_name = is_static ? "StaticLeafMethods" : "NonStaticLeafMethods";
Ian Rogers00f7d0e2012-07-19 15:28:27 -070076 jobject jclass_loader(LoadDex(class_name));
Ian Rogers1f539342012-10-03 21:09:42 -070077 Thread* self = Thread::Current();
78 SirtRef<ClassLoader>
79 class_loader(self,
80 ScopedObjectAccessUnchecked(self).Decode<ClassLoader*>(jclass_loader));
Elliott Hughes77405792012-03-15 15:22:12 -070081 if (is_static) {
82 CompileDirectMethod(class_loader.get(), class_name, method_name, method_signature);
83 } else {
84 CompileVirtualMethod(NULL, "java.lang.Class", "isFinalizable", "()Z");
85 CompileDirectMethod(NULL, "java.lang.Object", "<init>", "()V");
86 CompileVirtualMethod(class_loader.get(), class_name, method_name, method_signature);
87 }
88
89 Class* c = class_linker_->FindClass(DotToDescriptor(class_name).c_str(), class_loader.get());
90 CHECK(c != NULL);
91
Ian Rogers00f7d0e2012-07-19 15:28:27 -070092 method = is_static ? c->FindDirectMethod(method_name, method_signature)
93 : c->FindVirtualMethod(method_name, method_signature);
Elliott Hughes77405792012-03-15 15:22:12 -070094 CHECK(method != NULL);
95
Ian Rogers50b35e22012-10-04 10:09:15 -070096 receiver = (is_static ? NULL : c->AllocObject(self));
Elliott Hughes77405792012-03-15 15:22:12 -070097
Mathieu Chartier66f19252012-09-18 08:57:04 -070098 AbstractMethod::InvokeStub* stub = method->GetInvokeStub();
Elliott Hughes77405792012-03-15 15:22:12 -070099 CHECK(stub != NULL);
100
101 return stub;
102 }
103
Ian Rogersb726dcb2012-09-05 08:57:23 -0700104 void InvokeNopMethod(bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700105 AbstractMethod* method;
Elliott Hughes77405792012-03-15 15:22:12 -0700106 Object* receiver;
Mathieu Chartier66f19252012-09-18 08:57:04 -0700107 AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "nop", "()V");
Elliott Hughes77405792012-03-15 15:22:12 -0700108 (*stub)(method, receiver, Thread::Current(), NULL, NULL);
109 }
110
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700111 void InvokeIdentityByteMethod(bool is_static)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700112 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700113 AbstractMethod* method;
Elliott Hughes77405792012-03-15 15:22:12 -0700114 Object* receiver;
Mathieu Chartier66f19252012-09-18 08:57:04 -0700115 AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "identity", "(B)B");
Elliott Hughes77405792012-03-15 15:22:12 -0700116
117 JValue args[1];
118 JValue result;
119
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700120 args[0].SetB(0);
121 result.SetB(-1);
Elliott Hughes77405792012-03-15 15:22:12 -0700122 (*stub)(method, receiver, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700123 EXPECT_EQ(0, result.GetB());
Elliott Hughes77405792012-03-15 15:22:12 -0700124
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700125 args[0].SetB(-1);
126 result.SetB(0);
Elliott Hughes77405792012-03-15 15:22:12 -0700127 (*stub)(method, receiver, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700128 EXPECT_EQ(-1, result.GetB());
Elliott Hughes77405792012-03-15 15:22:12 -0700129
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700130 args[0].SetB(SCHAR_MAX);
131 result.SetB(0);
Elliott Hughes77405792012-03-15 15:22:12 -0700132 (*stub)(method, receiver, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700133 EXPECT_EQ(SCHAR_MAX, result.GetB());
Elliott Hughes77405792012-03-15 15:22:12 -0700134
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700135 args[0].SetB(SCHAR_MIN);
136 result.SetB(0);
Elliott Hughes77405792012-03-15 15:22:12 -0700137 (*stub)(method, receiver, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700138 EXPECT_EQ(SCHAR_MIN, result.GetB());
Elliott Hughes77405792012-03-15 15:22:12 -0700139 }
140
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700141 void InvokeIdentityIntMethod(bool is_static)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700142 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700143 AbstractMethod* method;
Elliott Hughes77405792012-03-15 15:22:12 -0700144 Object* receiver;
Mathieu Chartier66f19252012-09-18 08:57:04 -0700145 AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "identity", "(I)I");
Elliott Hughes77405792012-03-15 15:22:12 -0700146
147 JValue args[1];
148 JValue result;
149
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700150 args[0].SetI(0);
151 result.SetI(-1);
Elliott Hughes77405792012-03-15 15:22:12 -0700152 (*stub)(method, receiver, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700153 EXPECT_EQ(0, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700154
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700155 args[0].SetI(-1);
156 result.SetI(0);
Elliott Hughes77405792012-03-15 15:22:12 -0700157 (*stub)(method, receiver, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700158 EXPECT_EQ(-1, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700159
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700160 args[0].SetI(INT_MAX);
161 result.SetI(0);
Elliott Hughes77405792012-03-15 15:22:12 -0700162 (*stub)(method, receiver, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700163 EXPECT_EQ(INT_MAX, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700164
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700165 args[0].SetI(INT_MIN);
166 result.SetI(0);
Elliott Hughes77405792012-03-15 15:22:12 -0700167 (*stub)(method, receiver, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700168 EXPECT_EQ(INT_MIN, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700169 }
170
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700171 void InvokeIdentityDoubleMethod(bool is_static)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700172 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700173 AbstractMethod* method;
Elliott Hughes77405792012-03-15 15:22:12 -0700174 Object* receiver;
Mathieu Chartier66f19252012-09-18 08:57:04 -0700175 AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "identity", "(D)D");
Elliott Hughes77405792012-03-15 15:22:12 -0700176
177 JValue args[1];
178 JValue result;
179
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700180 args[0].SetD(0.0);
181 result.SetD(-1.0);
Elliott Hughes77405792012-03-15 15:22:12 -0700182 (*stub)(method, receiver, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700183 EXPECT_EQ(0.0, result.GetD());
Elliott Hughes77405792012-03-15 15:22:12 -0700184
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700185 args[0].SetD(-1.0);
186 result.SetD(0.0);
Elliott Hughes77405792012-03-15 15:22:12 -0700187 (*stub)(method, receiver, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700188 EXPECT_EQ(-1.0, result.GetD());
Elliott Hughes77405792012-03-15 15:22:12 -0700189
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700190 args[0].SetD(DBL_MAX);
191 result.SetD(0.0);
Elliott Hughes77405792012-03-15 15:22:12 -0700192 (*stub)(method, receiver, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700193 EXPECT_EQ(DBL_MAX, result.GetD());
Elliott Hughes77405792012-03-15 15:22:12 -0700194
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700195 args[0].SetD(DBL_MIN);
196 result.SetD(0.0);
Elliott Hughes77405792012-03-15 15:22:12 -0700197 (*stub)(method, receiver, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700198 EXPECT_EQ(DBL_MIN, result.GetD());
Elliott Hughes77405792012-03-15 15:22:12 -0700199 }
200
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700201 void InvokeSumIntIntMethod(bool is_static)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700202 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700203 AbstractMethod* method;
Elliott Hughes77405792012-03-15 15:22:12 -0700204 Object* receiver;
Mathieu Chartier66f19252012-09-18 08:57:04 -0700205 AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(II)I");
Elliott Hughes77405792012-03-15 15:22:12 -0700206
207 JValue result;
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700208 result.SetI(-1);
Elliott Hughes77405792012-03-15 15:22:12 -0700209 JValue args[2];
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700210 args[0].SetI(0);
211 args[1].SetI(0);
Elliott Hughes77405792012-03-15 15:22:12 -0700212 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700213 EXPECT_EQ(0, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700214
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700215 result.SetI(0);
216 args[0].SetI(1);
217 args[1].SetI(2);
Elliott Hughes77405792012-03-15 15:22:12 -0700218 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700219 EXPECT_EQ(3, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700220
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700221 result.SetI(0);
222 args[0].SetI(-2);
223 args[1].SetI(5);
Elliott Hughes77405792012-03-15 15:22:12 -0700224 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700225 EXPECT_EQ(3, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700226
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700227 result.SetI(1234);
228 args[0].SetI(INT_MAX);
229 args[1].SetI(INT_MIN);
Elliott Hughes77405792012-03-15 15:22:12 -0700230 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700231 EXPECT_EQ(-1, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700232
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700233 result.SetI(INT_MIN);
234 args[0].SetI(INT_MAX);
235 args[1].SetI(INT_MAX);
Elliott Hughes77405792012-03-15 15:22:12 -0700236 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700237 EXPECT_EQ(-2, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700238 }
239
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700240 void InvokeSumIntIntIntMethod(bool is_static)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700241 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700242 AbstractMethod* method;
Elliott Hughes77405792012-03-15 15:22:12 -0700243 Object* receiver;
Mathieu Chartier66f19252012-09-18 08:57:04 -0700244 AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(III)I");
Elliott Hughes77405792012-03-15 15:22:12 -0700245
246 JValue result;
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700247 result.SetI(-1);
Elliott Hughes77405792012-03-15 15:22:12 -0700248 JValue args[3];
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700249 args[0].SetI(0);
250 args[1].SetI(0);
251 args[2].SetI(0);
Elliott Hughes77405792012-03-15 15:22:12 -0700252 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700253 EXPECT_EQ(0, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700254
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700255 result.SetI(0);
256 args[0].SetI(1);
257 args[1].SetI(2);
258 args[2].SetI(3);
Elliott Hughes77405792012-03-15 15:22:12 -0700259 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700260 EXPECT_EQ(6, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700261
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700262 result.SetI(0);
263 args[0].SetI(-1);
264 args[1].SetI(2);
265 args[2].SetI(-3);
Elliott Hughes77405792012-03-15 15:22:12 -0700266 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700267 EXPECT_EQ(-2, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700268
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700269 result.SetI(1234);
270 args[0].SetI(INT_MAX);
271 args[1].SetI(INT_MIN);
272 args[2].SetI(INT_MAX);
Elliott Hughes77405792012-03-15 15:22:12 -0700273 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700274 EXPECT_EQ(2147483646, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700275
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700276 result.SetI(INT_MIN);
277 args[0].SetI(INT_MAX);
278 args[1].SetI(INT_MAX);
279 args[2].SetI(INT_MAX);
Elliott Hughes77405792012-03-15 15:22:12 -0700280 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700281 EXPECT_EQ(2147483645, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700282 }
283
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700284 void InvokeSumIntIntIntIntMethod(bool is_static)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700285 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700286 AbstractMethod* method;
Elliott Hughes77405792012-03-15 15:22:12 -0700287 Object* receiver;
Mathieu Chartier66f19252012-09-18 08:57:04 -0700288 AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(IIII)I");
Elliott Hughes77405792012-03-15 15:22:12 -0700289
290 JValue result;
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700291 result.SetI(-1);
Elliott Hughes77405792012-03-15 15:22:12 -0700292 JValue args[4];
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700293 args[0].SetI(0);
294 args[1].SetI(0);
295 args[2].SetI(0);
296 args[3].SetI(0);
Elliott Hughes77405792012-03-15 15:22:12 -0700297 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700298 EXPECT_EQ(0, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700299
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700300 result.SetI(0);
301 args[0].SetI(1);
302 args[1].SetI(2);
303 args[2].SetI(3);
304 args[3].SetI(4);
Elliott Hughes77405792012-03-15 15:22:12 -0700305 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700306 EXPECT_EQ(10, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700307
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700308 result.SetI(0);
309 args[0].SetI(-1);
310 args[1].SetI(2);
311 args[2].SetI(-3);
312 args[3].SetI(4);
Elliott Hughes77405792012-03-15 15:22:12 -0700313 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700314 EXPECT_EQ(2, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700315
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700316 result.SetI(1234);
317 args[0].SetI(INT_MAX);
318 args[1].SetI(INT_MIN);
319 args[2].SetI(INT_MAX);
320 args[3].SetI(INT_MIN);
Elliott Hughes77405792012-03-15 15:22:12 -0700321 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700322 EXPECT_EQ(-2, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700323
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700324 result.SetI(INT_MIN);
325 args[0].SetI(INT_MAX);
326 args[1].SetI(INT_MAX);
327 args[2].SetI(INT_MAX);
328 args[3].SetI(INT_MAX);
Elliott Hughes77405792012-03-15 15:22:12 -0700329 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700330 EXPECT_EQ(-4, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700331 }
332
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700333 void InvokeSumIntIntIntIntIntMethod(bool is_static)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700334 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700335 AbstractMethod* method;
Elliott Hughes77405792012-03-15 15:22:12 -0700336 Object* receiver;
Mathieu Chartier66f19252012-09-18 08:57:04 -0700337 AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(IIIII)I");
Elliott Hughes77405792012-03-15 15:22:12 -0700338
339 JValue result;
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700340 result.SetI(-1.0);
Elliott Hughes77405792012-03-15 15:22:12 -0700341 JValue args[5];
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700342 args[0].SetI(0);
343 args[1].SetI(0);
344 args[2].SetI(0);
345 args[3].SetI(0);
346 args[4].SetI(0);
Elliott Hughes77405792012-03-15 15:22:12 -0700347 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700348 EXPECT_EQ(0, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700349
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700350 result.SetI(0);
351 args[0].SetI(1);
352 args[1].SetI(2);
353 args[2].SetI(3);
354 args[3].SetI(4);
355 args[4].SetI(5);
Elliott Hughes77405792012-03-15 15:22:12 -0700356 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700357 EXPECT_EQ(15, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700358
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700359 result.SetI(0);
360 args[0].SetI(-1);
361 args[1].SetI(2);
362 args[2].SetI(-3);
363 args[3].SetI(4);
364 args[4].SetI(-5);
Elliott Hughes77405792012-03-15 15:22:12 -0700365 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700366 EXPECT_EQ(-3, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700367
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700368 result.SetI(1234);
369 args[0].SetI(INT_MAX);
370 args[1].SetI(INT_MIN);
371 args[2].SetI(INT_MAX);
372 args[3].SetI(INT_MIN);
373 args[4].SetI(INT_MAX);
Elliott Hughes77405792012-03-15 15:22:12 -0700374 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700375 EXPECT_EQ(2147483645, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700376
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700377 result.SetI(INT_MIN);
378 args[0].SetI(INT_MAX);
379 args[1].SetI(INT_MAX);
380 args[2].SetI(INT_MAX);
381 args[3].SetI(INT_MAX);
382 args[4].SetI(INT_MAX);
Elliott Hughes77405792012-03-15 15:22:12 -0700383 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700384 EXPECT_EQ(2147483643, result.GetI());
Elliott Hughes77405792012-03-15 15:22:12 -0700385 }
386
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700387 void InvokeSumDoubleDoubleMethod(bool is_static)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700388 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700389 AbstractMethod* method;
Elliott Hughes77405792012-03-15 15:22:12 -0700390 Object* receiver;
Mathieu Chartier66f19252012-09-18 08:57:04 -0700391 AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(DD)D");
Elliott Hughes77405792012-03-15 15:22:12 -0700392
393 JValue args[2];
394 JValue result;
395
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700396 args[0].SetD(0.0);
397 args[1].SetD(0.0);
398 result.SetD(-1.0);
Elliott Hughes77405792012-03-15 15:22:12 -0700399 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700400 EXPECT_EQ(0.0, result.GetD());
Elliott Hughes77405792012-03-15 15:22:12 -0700401
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700402 args[0].SetD(1.0);
403 args[1].SetD(2.0);
404 result.SetD(0.0);
Elliott Hughes77405792012-03-15 15:22:12 -0700405 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700406 EXPECT_EQ(3.0, result.GetD());
Elliott Hughes77405792012-03-15 15:22:12 -0700407
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700408 args[0].SetD(1.0);
409 args[1].SetD(-2.0);
410 result.SetD(0.0);
Elliott Hughes77405792012-03-15 15:22:12 -0700411 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700412 EXPECT_EQ(-1.0, result.GetD());
Elliott Hughes77405792012-03-15 15:22:12 -0700413
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700414 args[0].SetD(DBL_MAX);
415 args[1].SetD(DBL_MIN);
416 result.SetD(0.0);
Elliott Hughes77405792012-03-15 15:22:12 -0700417 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700418 EXPECT_EQ(1.7976931348623157e308, result.GetD());
Elliott Hughes77405792012-03-15 15:22:12 -0700419
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700420 args[0].SetD(DBL_MAX);
421 args[1].SetD(DBL_MAX);
422 result.SetD(0.0);
Elliott Hughes77405792012-03-15 15:22:12 -0700423 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700424 EXPECT_EQ(INFINITY, result.GetD());
Elliott Hughes77405792012-03-15 15:22:12 -0700425 }
426
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700427 void InvokeSumDoubleDoubleDoubleMethod(bool is_static)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700428 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700429 AbstractMethod* method;
Elliott Hughes77405792012-03-15 15:22:12 -0700430 Object* receiver;
Mathieu Chartier66f19252012-09-18 08:57:04 -0700431 AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(DDD)D");
Elliott Hughes77405792012-03-15 15:22:12 -0700432
433 JValue args[3];
434 JValue result;
435
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700436 args[0].SetD(0.0);
437 args[1].SetD(0.0);
438 args[2].SetD(0.0);
439 result.SetD(-1.0);
Elliott Hughes77405792012-03-15 15:22:12 -0700440 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700441 EXPECT_EQ(0.0, result.GetD());
Elliott Hughes77405792012-03-15 15:22:12 -0700442
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700443 args[0].SetD(1.0);
444 args[1].SetD(2.0);
445 args[2].SetD(3.0);
446 result.SetD(0.0);
Elliott Hughes77405792012-03-15 15:22:12 -0700447 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700448 EXPECT_EQ(6.0, result.GetD());
Elliott Hughes77405792012-03-15 15:22:12 -0700449
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700450 args[0].SetD(1.0);
451 args[1].SetD(-2.0);
452 args[2].SetD(3.0);
453 result.SetD(0.0);
Elliott Hughes77405792012-03-15 15:22:12 -0700454 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700455 EXPECT_EQ(2.0, result.GetD());
Elliott Hughes77405792012-03-15 15:22:12 -0700456 }
457
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700458 void InvokeSumDoubleDoubleDoubleDoubleMethod(bool is_static)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700459 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700460 AbstractMethod* method;
Elliott Hughes77405792012-03-15 15:22:12 -0700461 Object* receiver;
Mathieu Chartier66f19252012-09-18 08:57:04 -0700462 AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(DDDD)D");
Elliott Hughes77405792012-03-15 15:22:12 -0700463
464 JValue args[4];
465 JValue result;
466
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700467 args[0].SetD(0.0);
468 args[1].SetD(0.0);
469 args[2].SetD(0.0);
470 args[3].SetD(0.0);
471 result.SetD(-1.0);
Elliott Hughes77405792012-03-15 15:22:12 -0700472 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700473 EXPECT_EQ(0.0, result.GetD());
Elliott Hughes77405792012-03-15 15:22:12 -0700474
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700475 args[0].SetD(1.0);
476 args[1].SetD(2.0);
477 args[2].SetD(3.0);
478 args[3].SetD(4.0);
479 result.SetD(0.0);
Elliott Hughes77405792012-03-15 15:22:12 -0700480 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700481 EXPECT_EQ(10.0, result.GetD());
Elliott Hughes77405792012-03-15 15:22:12 -0700482
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700483 args[0].SetD(1.0);
484 args[1].SetD(-2.0);
485 args[2].SetD(3.0);
486 args[3].SetD(-4.0);
487 result.SetD(0.0);
Elliott Hughes77405792012-03-15 15:22:12 -0700488 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700489 EXPECT_EQ(-2.0, result.GetD());
Elliott Hughes77405792012-03-15 15:22:12 -0700490 }
491
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700492 void InvokeSumDoubleDoubleDoubleDoubleDoubleMethod(bool is_static)
Ian Rogersb726dcb2012-09-05 08:57:23 -0700493 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Mathieu Chartier66f19252012-09-18 08:57:04 -0700494 AbstractMethod* method;
Elliott Hughes77405792012-03-15 15:22:12 -0700495 Object* receiver;
Mathieu Chartier66f19252012-09-18 08:57:04 -0700496 AbstractMethod::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(DDDDD)D");
Elliott Hughes77405792012-03-15 15:22:12 -0700497
498 JValue args[5];
499 JValue result;
500
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700501 args[0].SetD(0.0);
502 args[1].SetD(0.0);
503 args[2].SetD(0.0);
504 args[3].SetD(0.0);
505 args[4].SetD(0.0);
506 result.SetD(-1.0);
Elliott Hughes77405792012-03-15 15:22:12 -0700507 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700508 EXPECT_EQ(0.0, result.GetD());
Elliott Hughes77405792012-03-15 15:22:12 -0700509
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700510 args[0].SetD(1.0);
511 args[1].SetD(2.0);
512 args[2].SetD(3.0);
513 args[3].SetD(4.0);
514 args[4].SetD(5.0);
515 result.SetD(0.0);
Elliott Hughes77405792012-03-15 15:22:12 -0700516 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700517 EXPECT_EQ(15.0, result.GetD());
Elliott Hughes77405792012-03-15 15:22:12 -0700518
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700519 args[0].SetD(1.0);
520 args[1].SetD(-2.0);
521 args[2].SetD(3.0);
522 args[3].SetD(-4.0);
523 args[4].SetD(5.0);
524 result.SetD(0.0);
Elliott Hughes77405792012-03-15 15:22:12 -0700525 (*stub)(method, NULL, Thread::Current(), args, &result);
Elliott Hughesf24d3ce2012-04-11 17:43:37 -0700526 EXPECT_EQ(3.0, result.GetD());
Elliott Hughes77405792012-03-15 15:22:12 -0700527 }
528
Elliott Hughesa2501992011-08-26 19:39:54 -0700529 JavaVMExt* vm_;
Brian Carlstrom4d571432012-05-16 00:21:41 -0700530 JNIEnv* env_;
Elliott Hughes814e4032011-08-23 12:07:56 -0700531 jclass aioobe_;
Elliott Hughesb264f082012-04-06 17:10:10 -0700532 jclass ase_;
Elliott Hughesb465ab02011-08-24 11:21:21 -0700533 jclass sioobe_;
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700534};
535
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700536TEST_F(JniInternalTest, AllocObject) {
537 jclass c = env_->FindClass("java/lang/String");
538 ASSERT_TRUE(c != NULL);
539 jobject o = env_->AllocObject(c);
540 ASSERT_TRUE(o != NULL);
541
542 // We have an instance of the class we asked for...
543 ASSERT_TRUE(env_->IsInstanceOf(o, c));
544 // ...whose fields haven't been initialized because
545 // we didn't call a constructor.
546 ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "count", "I")));
547 ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "offset", "I")));
548 ASSERT_TRUE(env_->GetObjectField(o, env_->GetFieldID(c, "value", "[C")) == NULL);
549}
550
Elliott Hughesc7ac37f2011-08-12 12:21:58 -0700551TEST_F(JniInternalTest, GetVersion) {
552 ASSERT_EQ(JNI_VERSION_1_6, env_->GetVersion());
553}
554
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700555#define EXPECT_CLASS_FOUND(NAME) \
Elliott Hughesbd935992011-08-22 11:59:34 -0700556 EXPECT_TRUE(env_->FindClass(NAME) != NULL); \
557 EXPECT_FALSE(env_->ExceptionCheck())
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700558
559#define EXPECT_CLASS_NOT_FOUND(NAME) \
Elliott Hughesbd935992011-08-22 11:59:34 -0700560 EXPECT_TRUE(env_->FindClass(NAME) == NULL); \
561 EXPECT_TRUE(env_->ExceptionCheck()); \
562 env_->ExceptionClear()
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700563
564TEST_F(JniInternalTest, FindClass) {
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700565 // Reference types...
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700566 EXPECT_CLASS_FOUND("java/lang/String");
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700567 // ...for arrays too, where you must include "L;".
568 EXPECT_CLASS_FOUND("[Ljava/lang/String;");
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700569 // Primitive arrays are okay too, if the primitive type is valid.
570 EXPECT_CLASS_FOUND("[C");
Elliott Hughesa2501992011-08-26 19:39:54 -0700571
Elliott Hughesb264f082012-04-06 17:10:10 -0700572 {
Elliott Hughesb264f082012-04-06 17:10:10 -0700573 // We support . as well as / for compatibility, if -Xcheck:jni is off.
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700574 CheckJniAbortCatcher check_jni_abort_catcher;
Elliott Hughesb264f082012-04-06 17:10:10 -0700575 EXPECT_CLASS_FOUND("java.lang.String");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700576 check_jni_abort_catcher.Check("illegal class name 'java.lang.String'");
Elliott Hughesb264f082012-04-06 17:10:10 -0700577 EXPECT_CLASS_NOT_FOUND("Ljava.lang.String;");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700578 check_jni_abort_catcher.Check("illegal class name 'Ljava.lang.String;'");
Elliott Hughesb264f082012-04-06 17:10:10 -0700579 EXPECT_CLASS_FOUND("[Ljava.lang.String;");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700580 check_jni_abort_catcher.Check("illegal class name '[Ljava.lang.String;'");
Elliott Hughesb264f082012-04-06 17:10:10 -0700581 EXPECT_CLASS_NOT_FOUND("[java.lang.String");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700582 check_jni_abort_catcher.Check("illegal class name '[java.lang.String'");
Elliott Hughesb264f082012-04-06 17:10:10 -0700583
584 // You can't include the "L;" in a JNI class descriptor.
585 EXPECT_CLASS_NOT_FOUND("Ljava/lang/String;");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700586 check_jni_abort_catcher.Check("illegal class name 'Ljava/lang/String;'");
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700587
Elliott Hughesb264f082012-04-06 17:10:10 -0700588 // But you must include it for an array of any reference type.
589 EXPECT_CLASS_NOT_FOUND("[java/lang/String");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700590 check_jni_abort_catcher.Check("illegal class name '[java/lang/String'");
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700591
592 EXPECT_CLASS_NOT_FOUND("[K");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700593 check_jni_abort_catcher.Check("illegal class name '[K'");
Elliott Hughesb264f082012-04-06 17:10:10 -0700594 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700595
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700596 // But primitive types aren't allowed...
597 EXPECT_CLASS_NOT_FOUND("C");
598 EXPECT_CLASS_NOT_FOUND("K");
599}
600
Elliott Hughescdf53122011-08-19 15:46:09 -0700601#define EXPECT_EXCEPTION(exception_class) \
602 do { \
603 EXPECT_TRUE(env_->ExceptionCheck()); \
604 jthrowable exception = env_->ExceptionOccurred(); \
605 EXPECT_NE(static_cast<jthrowable>(NULL), exception); \
Elliott Hughescdf53122011-08-19 15:46:09 -0700606 env_->ExceptionClear(); \
Elliott Hughesa2501992011-08-26 19:39:54 -0700607 EXPECT_TRUE(env_->IsInstanceOf(exception, exception_class)); \
Elliott Hughescdf53122011-08-19 15:46:09 -0700608 } while (false)
609
610TEST_F(JniInternalTest, GetFieldID) {
611 jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError");
612 ASSERT_TRUE(jlnsfe != NULL);
613 jclass c = env_->FindClass("java/lang/String");
614 ASSERT_TRUE(c != NULL);
615
616 // Wrong type.
617 jfieldID fid = env_->GetFieldID(c, "count", "J");
618 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
619 EXPECT_EXCEPTION(jlnsfe);
620
Ian Rogersb17d08b2011-09-02 16:16:49 -0700621 // Wrong type where type doesn't exist.
622 fid = env_->GetFieldID(c, "count", "Lrod/jane/freddy;");
623 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
624 EXPECT_EXCEPTION(jlnsfe);
625
Elliott Hughescdf53122011-08-19 15:46:09 -0700626 // Wrong name.
627 fid = env_->GetFieldID(c, "Count", "I");
628 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
629 EXPECT_EXCEPTION(jlnsfe);
630
631 // Good declared field lookup.
632 fid = env_->GetFieldID(c, "count", "I");
633 EXPECT_NE(static_cast<jfieldID>(NULL), fid);
634 EXPECT_TRUE(fid != NULL);
635 EXPECT_FALSE(env_->ExceptionCheck());
636
637 // Good superclass field lookup.
638 c = env_->FindClass("java/lang/StringBuilder");
639 fid = env_->GetFieldID(c, "count", "I");
640 EXPECT_NE(static_cast<jfieldID>(NULL), fid);
641 EXPECT_TRUE(fid != NULL);
642 EXPECT_FALSE(env_->ExceptionCheck());
643
644 // Not instance.
645 fid = env_->GetFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
646 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
647 EXPECT_EXCEPTION(jlnsfe);
648}
649
650TEST_F(JniInternalTest, GetStaticFieldID) {
651 jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError");
652 ASSERT_TRUE(jlnsfe != NULL);
653 jclass c = env_->FindClass("java/lang/String");
654 ASSERT_TRUE(c != NULL);
655
656 // Wrong type.
657 jfieldID fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "J");
658 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
659 EXPECT_EXCEPTION(jlnsfe);
660
Ian Rogersb17d08b2011-09-02 16:16:49 -0700661 // Wrong type where type doesn't exist.
662 fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Lrod/jane/freddy;");
663 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
664 EXPECT_EXCEPTION(jlnsfe);
665
Elliott Hughescdf53122011-08-19 15:46:09 -0700666 // Wrong name.
667 fid = env_->GetStaticFieldID(c, "cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
668 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
669 EXPECT_EXCEPTION(jlnsfe);
670
671 // Good declared field lookup.
672 fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
673 EXPECT_NE(static_cast<jfieldID>(NULL), fid);
674 EXPECT_TRUE(fid != NULL);
675 EXPECT_FALSE(env_->ExceptionCheck());
676
677 // Not static.
678 fid = env_->GetStaticFieldID(c, "count", "I");
679 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
680 EXPECT_EXCEPTION(jlnsfe);
681}
682
Ian Rogers4dd71f12011-08-16 14:16:02 -0700683TEST_F(JniInternalTest, GetMethodID) {
684 jclass jlobject = env_->FindClass("java/lang/Object");
685 jclass jlstring = env_->FindClass("java/lang/String");
686 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
687
688 // Sanity check that no exceptions are pending
Elliott Hughescdf53122011-08-19 15:46:09 -0700689 ASSERT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700690
691 // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
692 // a pending exception
693 jmethodID method = env_->GetMethodID(jlobject, "foo", "()V");
694 EXPECT_EQ(static_cast<jmethodID>(NULL), method);
Elliott Hughescdf53122011-08-19 15:46:09 -0700695 EXPECT_EXCEPTION(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700696
697 // Check that java.lang.Object.equals() does exist
Ian Rogers4dd71f12011-08-16 14:16:02 -0700698 method = env_->GetMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
699 EXPECT_NE(static_cast<jmethodID>(NULL), method);
700 EXPECT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700701
702 // Check that GetMethodID for java.lang.String.valueOf(int) fails as the
703 // method is static
704 method = env_->GetMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;");
705 EXPECT_EQ(static_cast<jmethodID>(NULL), method);
Elliott Hughescdf53122011-08-19 15:46:09 -0700706 EXPECT_EXCEPTION(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700707}
708
709TEST_F(JniInternalTest, GetStaticMethodID) {
710 jclass jlobject = env_->FindClass("java/lang/Object");
711 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
712
713 // Sanity check that no exceptions are pending
Elliott Hughescdf53122011-08-19 15:46:09 -0700714 ASSERT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700715
716 // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
717 // a pending exception
718 jmethodID method = env_->GetStaticMethodID(jlobject, "foo", "()V");
719 EXPECT_EQ(static_cast<jmethodID>(NULL), method);
Elliott Hughescdf53122011-08-19 15:46:09 -0700720 EXPECT_EXCEPTION(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700721
722 // Check that GetStaticMethodID for java.lang.Object.equals(Object) fails as
723 // the method is not static
724 method = env_->GetStaticMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
725 EXPECT_EQ(static_cast<jmethodID>(NULL), method);
Elliott Hughescdf53122011-08-19 15:46:09 -0700726 EXPECT_EXCEPTION(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700727
728 // Check that java.lang.String.valueOf(int) does exist
Ian Rogers4dd71f12011-08-16 14:16:02 -0700729 jclass jlstring = env_->FindClass("java/lang/String");
730 method = env_->GetStaticMethodID(jlstring, "valueOf",
731 "(I)Ljava/lang/String;");
732 EXPECT_NE(static_cast<jmethodID>(NULL), method);
733 EXPECT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700734}
735
Elliott Hughescdf53122011-08-19 15:46:09 -0700736TEST_F(JniInternalTest, FromReflectedField_ToReflectedField) {
737 jclass jlrField = env_->FindClass("java/lang/reflect/Field");
738 jclass c = env_->FindClass("java/lang/String");
739 ASSERT_TRUE(c != NULL);
740 jfieldID fid = env_->GetFieldID(c, "count", "I");
741 ASSERT_TRUE(fid != NULL);
742 // Turn the fid into a java.lang.reflect.Field...
743 jobject field = env_->ToReflectedField(c, fid, JNI_FALSE);
744 ASSERT_TRUE(c != NULL);
745 ASSERT_TRUE(env_->IsInstanceOf(field, jlrField));
746 // ...and back again.
747 jfieldID fid2 = env_->FromReflectedField(field);
748 ASSERT_TRUE(fid2 != NULL);
749}
750
751TEST_F(JniInternalTest, FromReflectedMethod_ToReflectedMethod) {
752 jclass jlrMethod = env_->FindClass("java/lang/reflect/Method");
753 jclass c = env_->FindClass("java/lang/String");
754 ASSERT_TRUE(c != NULL);
755 jmethodID mid = env_->GetMethodID(c, "length", "()I");
756 ASSERT_TRUE(mid != NULL);
757 // Turn the mid into a java.lang.reflect.Method...
758 jobject method = env_->ToReflectedMethod(c, mid, JNI_FALSE);
759 ASSERT_TRUE(c != NULL);
760 ASSERT_TRUE(env_->IsInstanceOf(method, jlrMethod));
761 // ...and back again.
762 jmethodID mid2 = env_->FromReflectedMethod(method);
763 ASSERT_TRUE(mid2 != NULL);
764}
765
Elliott Hughes5174fe62011-08-23 15:12:35 -0700766void BogusMethod() {
767 // You can't pass NULL function pointers to RegisterNatives.
768}
769
Ian Rogers4dd71f12011-08-16 14:16:02 -0700770TEST_F(JniInternalTest, RegisterNatives) {
771 jclass jlobject = env_->FindClass("java/lang/Object");
772 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
773
774 // Sanity check that no exceptions are pending
Elliott Hughescdf53122011-08-19 15:46:09 -0700775 ASSERT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700776
777 // Check that registering to a non-existent java.lang.Object.foo() causes a
778 // NoSuchMethodError
779 {
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700780 JNINativeMethod methods[] = { { "foo", "()V", NULL } };
Ian Rogers4dd71f12011-08-16 14:16:02 -0700781 env_->RegisterNatives(jlobject, methods, 1);
782 }
Elliott Hughescdf53122011-08-19 15:46:09 -0700783 EXPECT_EXCEPTION(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700784
785 // Check that registering non-native methods causes a NoSuchMethodError
786 {
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700787 JNINativeMethod methods[] = { { "equals", "(Ljava/lang/Object;)Z", NULL } };
Ian Rogers4dd71f12011-08-16 14:16:02 -0700788 env_->RegisterNatives(jlobject, methods, 1);
789 }
Elliott Hughescdf53122011-08-19 15:46:09 -0700790 EXPECT_EXCEPTION(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700791
792 // Check that registering native methods is successful
793 {
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700794 JNINativeMethod methods[] = { { "notify", "()V", reinterpret_cast<void*>(BogusMethod) } };
Ian Rogers4dd71f12011-08-16 14:16:02 -0700795 env_->RegisterNatives(jlobject, methods, 1);
796 }
797 EXPECT_FALSE(env_->ExceptionCheck());
Elliott Hughes5174fe62011-08-23 15:12:35 -0700798
799 env_->UnregisterNatives(jlobject);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700800}
801
Elliott Hughes75770752011-08-24 17:52:38 -0700802#define EXPECT_PRIMITIVE_ARRAY(new_fn, get_region_fn, set_region_fn, get_elements_fn, release_elements_fn, scalar_type, expected_class_descriptor) \
Elliott Hughes814e4032011-08-23 12:07:56 -0700803 jsize size = 4; \
804 /* Allocate an array and check it has the right type and length. */ \
805 scalar_type ## Array a = env_->new_fn(size); \
806 EXPECT_TRUE(a != NULL); \
807 EXPECT_TRUE(env_->IsInstanceOf(a, env_->FindClass(expected_class_descriptor))); \
808 EXPECT_EQ(size, env_->GetArrayLength(a)); \
809 /* AIOOBE for negative start offset. */ \
810 env_->get_region_fn(a, -1, 1, NULL); \
811 EXPECT_EXCEPTION(aioobe_); \
812 env_->set_region_fn(a, -1, 1, NULL); \
813 EXPECT_EXCEPTION(aioobe_); \
814 /* AIOOBE for negative length. */ \
815 env_->get_region_fn(a, 0, -1, NULL); \
816 EXPECT_EXCEPTION(aioobe_); \
817 env_->set_region_fn(a, 0, -1, NULL); \
818 EXPECT_EXCEPTION(aioobe_); \
819 /* AIOOBE for buffer overrun. */ \
820 env_->get_region_fn(a, size - 1, size, NULL); \
821 EXPECT_EXCEPTION(aioobe_); \
822 env_->set_region_fn(a, size - 1, size, NULL); \
823 EXPECT_EXCEPTION(aioobe_); \
824 /* Prepare a couple of buffers. */ \
Elliott Hughesee0fa762012-03-26 17:12:41 -0700825 UniquePtr<scalar_type[]> src_buf(new scalar_type[size]); \
826 UniquePtr<scalar_type[]> dst_buf(new scalar_type[size]); \
Elliott Hughes814e4032011-08-23 12:07:56 -0700827 for (jsize i = 0; i < size; ++i) { src_buf[i] = scalar_type(i); } \
828 for (jsize i = 0; i < size; ++i) { dst_buf[i] = scalar_type(-1); } \
829 /* Copy all of src_buf onto the heap. */ \
Elliott Hughesee0fa762012-03-26 17:12:41 -0700830 env_->set_region_fn(a, 0, size, &src_buf[0]); \
Elliott Hughes814e4032011-08-23 12:07:56 -0700831 /* Copy back only part. */ \
832 env_->get_region_fn(a, 1, size - 2, &dst_buf[1]); \
Elliott Hughesee0fa762012-03-26 17:12:41 -0700833 EXPECT_NE(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) << "short copy equal"; \
Elliott Hughes814e4032011-08-23 12:07:56 -0700834 /* Copy the missing pieces. */ \
Elliott Hughesee0fa762012-03-26 17:12:41 -0700835 env_->get_region_fn(a, 0, 1, &dst_buf[0]); \
Elliott Hughes814e4032011-08-23 12:07:56 -0700836 env_->get_region_fn(a, size - 1, 1, &dst_buf[size - 1]); \
Elliott Hughesee0fa762012-03-26 17:12:41 -0700837 EXPECT_EQ(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) << "fixed copy not equal"; \
Elliott Hughes814e4032011-08-23 12:07:56 -0700838 /* Copy back the whole array. */ \
Elliott Hughesee0fa762012-03-26 17:12:41 -0700839 env_->get_region_fn(a, 0, size, &dst_buf[0]); \
840 EXPECT_EQ(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) << "full copy not equal"; \
Elliott Hughes75770752011-08-24 17:52:38 -0700841 /* GetPrimitiveArrayCritical */ \
842 void* v = env_->GetPrimitiveArrayCritical(a, NULL); \
Elliott Hughesee0fa762012-03-26 17:12:41 -0700843 EXPECT_EQ(memcmp(&src_buf[0], v, size * sizeof(scalar_type)), 0) << "GetPrimitiveArrayCritical not equal"; \
Elliott Hughes75770752011-08-24 17:52:38 -0700844 env_->ReleasePrimitiveArrayCritical(a, v, 0); \
845 /* GetXArrayElements */ \
846 scalar_type* xs = env_->get_elements_fn(a, NULL); \
Elliott Hughesee0fa762012-03-26 17:12:41 -0700847 EXPECT_EQ(memcmp(&src_buf[0], xs, size * sizeof(scalar_type)), 0) << # get_elements_fn " not equal"; \
Elliott Hughes75770752011-08-24 17:52:38 -0700848 env_->release_elements_fn(a, xs, 0); \
849 EXPECT_EQ(reinterpret_cast<uintptr_t>(v), reinterpret_cast<uintptr_t>(xs))
Elliott Hughesbd935992011-08-22 11:59:34 -0700850
Elliott Hughes814e4032011-08-23 12:07:56 -0700851TEST_F(JniInternalTest, BooleanArrays) {
Elliott Hughes75770752011-08-24 17:52:38 -0700852 EXPECT_PRIMITIVE_ARRAY(NewBooleanArray, GetBooleanArrayRegion, SetBooleanArrayRegion, GetBooleanArrayElements, ReleaseBooleanArrayElements, jboolean, "[Z");
Elliott Hughes814e4032011-08-23 12:07:56 -0700853}
854TEST_F(JniInternalTest, ByteArrays) {
Elliott Hughes75770752011-08-24 17:52:38 -0700855 EXPECT_PRIMITIVE_ARRAY(NewByteArray, GetByteArrayRegion, SetByteArrayRegion, GetByteArrayElements, ReleaseByteArrayElements, jbyte, "[B");
Elliott Hughes814e4032011-08-23 12:07:56 -0700856}
857TEST_F(JniInternalTest, CharArrays) {
Elliott Hughes75770752011-08-24 17:52:38 -0700858 EXPECT_PRIMITIVE_ARRAY(NewCharArray, GetCharArrayRegion, SetCharArrayRegion, GetCharArrayElements, ReleaseCharArrayElements, jchar, "[C");
Elliott Hughes814e4032011-08-23 12:07:56 -0700859}
860TEST_F(JniInternalTest, DoubleArrays) {
Elliott Hughes75770752011-08-24 17:52:38 -0700861 EXPECT_PRIMITIVE_ARRAY(NewDoubleArray, GetDoubleArrayRegion, SetDoubleArrayRegion, GetDoubleArrayElements, ReleaseDoubleArrayElements, jdouble, "[D");
Elliott Hughes814e4032011-08-23 12:07:56 -0700862}
863TEST_F(JniInternalTest, FloatArrays) {
Elliott Hughes75770752011-08-24 17:52:38 -0700864 EXPECT_PRIMITIVE_ARRAY(NewFloatArray, GetFloatArrayRegion, SetFloatArrayRegion, GetFloatArrayElements, ReleaseFloatArrayElements, jfloat, "[F");
Elliott Hughes814e4032011-08-23 12:07:56 -0700865}
866TEST_F(JniInternalTest, IntArrays) {
Elliott Hughes75770752011-08-24 17:52:38 -0700867 EXPECT_PRIMITIVE_ARRAY(NewIntArray, GetIntArrayRegion, SetIntArrayRegion, GetIntArrayElements, ReleaseIntArrayElements, jint, "[I");
Elliott Hughes814e4032011-08-23 12:07:56 -0700868}
869TEST_F(JniInternalTest, LongArrays) {
Elliott Hughes75770752011-08-24 17:52:38 -0700870 EXPECT_PRIMITIVE_ARRAY(NewLongArray, GetLongArrayRegion, SetLongArrayRegion, GetLongArrayElements, ReleaseLongArrayElements, jlong, "[J");
Elliott Hughes814e4032011-08-23 12:07:56 -0700871}
872TEST_F(JniInternalTest, ShortArrays) {
Elliott Hughes75770752011-08-24 17:52:38 -0700873 EXPECT_PRIMITIVE_ARRAY(NewShortArray, GetShortArrayRegion, SetShortArrayRegion, GetShortArrayElements, ReleaseShortArrayElements, jshort, "[S");
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700874}
875
Elliott Hughesf2682d52011-08-15 16:37:04 -0700876TEST_F(JniInternalTest, NewObjectArray) {
877 // TODO: death tests for negative array sizes.
878
Elliott Hughesf2682d52011-08-15 16:37:04 -0700879 // TODO: check non-NULL initial elements.
880
Elliott Hughesbd935992011-08-22 11:59:34 -0700881 jclass element_class = env_->FindClass("java/lang/String");
882 ASSERT_TRUE(element_class != NULL);
883 jclass array_class = env_->FindClass("[Ljava/lang/String;");
884 ASSERT_TRUE(array_class != NULL);
Elliott Hughesf2682d52011-08-15 16:37:04 -0700885
Elliott Hughesbd935992011-08-22 11:59:34 -0700886 jobjectArray a;
Elliott Hughesf2682d52011-08-15 16:37:04 -0700887
Elliott Hughesbd935992011-08-22 11:59:34 -0700888 a = env_->NewObjectArray(0, element_class, NULL);
889 EXPECT_TRUE(a != NULL);
890 EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
891 EXPECT_EQ(0, env_->GetArrayLength(a));
892
893 a = env_->NewObjectArray(1, element_class, NULL);
894 EXPECT_TRUE(a != NULL);
895 EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
896 EXPECT_EQ(1, env_->GetArrayLength(a));
Elliott Hughes75770752011-08-24 17:52:38 -0700897 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), NULL));
898
899 jstring s = env_->NewStringUTF("poop");
900 a = env_->NewObjectArray(2, element_class, s);
901 EXPECT_TRUE(a != NULL);
902 EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
903 EXPECT_EQ(2, env_->GetArrayLength(a));
904 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), s));
905 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 1), s));
Elliott Hughesbd935992011-08-22 11:59:34 -0700906}
907
908TEST_F(JniInternalTest, GetArrayLength) {
909 // Already tested in NewObjectArray/NewPrimitiveArray.
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700910}
911
Elliott Hughes37f7a402011-08-22 18:56:01 -0700912TEST_F(JniInternalTest, GetObjectClass) {
913 jclass string_class = env_->FindClass("java/lang/String");
914 ASSERT_TRUE(string_class != NULL);
915 jclass class_class = env_->FindClass("java/lang/Class");
916 ASSERT_TRUE(class_class != NULL);
917
918 jstring s = env_->NewStringUTF("poop");
919 jclass c = env_->GetObjectClass(s);
920 ASSERT_TRUE(env_->IsSameObject(string_class, c));
921
922 jclass c2 = env_->GetObjectClass(c);
923 ASSERT_TRUE(env_->IsSameObject(class_class, env_->GetObjectClass(c2)));
924}
925
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700926TEST_F(JniInternalTest, GetSuperclass) {
927 jclass object_class = env_->FindClass("java/lang/Object");
928 ASSERT_TRUE(object_class != NULL);
929 jclass string_class = env_->FindClass("java/lang/String");
930 ASSERT_TRUE(string_class != NULL);
Ian Rogersdc180202012-01-29 14:47:29 -0800931 jclass runnable_interface = env_->FindClass("java/lang/Runnable");
932 ASSERT_TRUE(runnable_interface != NULL);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700933 ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(string_class)));
934 ASSERT_TRUE(env_->GetSuperclass(object_class) == NULL);
Ian Rogersdc180202012-01-29 14:47:29 -0800935 ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(runnable_interface)));
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700936}
937
Elliott Hughes37f7a402011-08-22 18:56:01 -0700938TEST_F(JniInternalTest, IsAssignableFrom) {
939 jclass object_class = env_->FindClass("java/lang/Object");
940 ASSERT_TRUE(object_class != NULL);
941 jclass string_class = env_->FindClass("java/lang/String");
942 ASSERT_TRUE(string_class != NULL);
943
944 ASSERT_TRUE(env_->IsAssignableFrom(object_class, string_class));
945 ASSERT_FALSE(env_->IsAssignableFrom(string_class, object_class));
946}
947
Elliott Hughesb465ab02011-08-24 11:21:21 -0700948TEST_F(JniInternalTest, GetObjectRefType) {
949 jclass local = env_->FindClass("java/lang/Object");
950 ASSERT_TRUE(local != NULL);
951 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(local));
952
953 jobject global = env_->NewGlobalRef(local);
954 EXPECT_EQ(JNIGlobalRefType, env_->GetObjectRefType(global));
955
956 jweak weak_global = env_->NewWeakGlobalRef(local);
957 EXPECT_EQ(JNIWeakGlobalRefType, env_->GetObjectRefType(weak_global));
958
959 jobject invalid = reinterpret_cast<jobject>(this);
960 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(invalid));
961
962 // TODO: invoke a native method and test that its arguments are considered local references.
963}
964
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700965TEST_F(JniInternalTest, NewStringUTF) {
966 EXPECT_TRUE(env_->NewStringUTF(NULL) == NULL);
Elliott Hughes814e4032011-08-23 12:07:56 -0700967 jstring s;
968
969 s = env_->NewStringUTF("");
970 EXPECT_TRUE(s != NULL);
971 EXPECT_EQ(0, env_->GetStringLength(s));
972 EXPECT_EQ(0, env_->GetStringUTFLength(s));
973 s = env_->NewStringUTF("hello");
974 EXPECT_TRUE(s != NULL);
975 EXPECT_EQ(5, env_->GetStringLength(s));
976 EXPECT_EQ(5, env_->GetStringUTFLength(s));
977
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700978 // TODO: check some non-ASCII strings.
Elliott Hughesf2682d52011-08-15 16:37:04 -0700979}
980
Elliott Hughes814e4032011-08-23 12:07:56 -0700981TEST_F(JniInternalTest, NewString) {
Elliott Hughes814e4032011-08-23 12:07:56 -0700982 jchar chars[] = { 'h', 'i' };
983 jstring s;
984 s = env_->NewString(chars, 0);
985 EXPECT_TRUE(s != NULL);
986 EXPECT_EQ(0, env_->GetStringLength(s));
987 EXPECT_EQ(0, env_->GetStringUTFLength(s));
988 s = env_->NewString(chars, 2);
989 EXPECT_TRUE(s != NULL);
990 EXPECT_EQ(2, env_->GetStringLength(s));
991 EXPECT_EQ(2, env_->GetStringUTFLength(s));
992
993 // TODO: check some non-ASCII strings.
994}
995
Jesse Wilson25e79a52011-11-18 15:31:58 -0500996TEST_F(JniInternalTest, NewStringNullCharsZeroLength) {
997 jstring s = env_->NewString(NULL, 0);
998 EXPECT_TRUE(s != NULL);
999 EXPECT_EQ(0, env_->GetStringLength(s));
1000}
1001
Brian Carlstrom36258122011-12-09 12:55:51 -08001002// TODO: fix gtest death tests on host http://b/5690440 (and target)
1003TEST_F(JniInternalTest, DISABLED_NewStringNullCharsNonzeroLength) {
Jesse Wilson25e79a52011-11-18 15:31:58 -05001004 ASSERT_DEATH(env_->NewString(NULL, 1), "");
1005}
1006
Elliott Hughesb465ab02011-08-24 11:21:21 -07001007TEST_F(JniInternalTest, GetStringLength_GetStringUTFLength) {
1008 // Already tested in the NewString/NewStringUTF tests.
1009}
1010
1011TEST_F(JniInternalTest, GetStringRegion_GetStringUTFRegion) {
1012 jstring s = env_->NewStringUTF("hello");
1013 ASSERT_TRUE(s != NULL);
1014
1015 env_->GetStringRegion(s, -1, 0, NULL);
1016 EXPECT_EXCEPTION(sioobe_);
1017 env_->GetStringRegion(s, 0, -1, NULL);
1018 EXPECT_EXCEPTION(sioobe_);
1019 env_->GetStringRegion(s, 0, 10, NULL);
1020 EXPECT_EXCEPTION(sioobe_);
1021 env_->GetStringRegion(s, 10, 1, NULL);
1022 EXPECT_EXCEPTION(sioobe_);
1023
1024 jchar chars[4] = { 'x', 'x', 'x', 'x' };
1025 env_->GetStringRegion(s, 1, 2, &chars[1]);
1026 EXPECT_EQ('x', chars[0]);
1027 EXPECT_EQ('e', chars[1]);
1028 EXPECT_EQ('l', chars[2]);
1029 EXPECT_EQ('x', chars[3]);
1030
1031 env_->GetStringUTFRegion(s, -1, 0, NULL);
1032 EXPECT_EXCEPTION(sioobe_);
1033 env_->GetStringUTFRegion(s, 0, -1, NULL);
1034 EXPECT_EXCEPTION(sioobe_);
1035 env_->GetStringUTFRegion(s, 0, 10, NULL);
1036 EXPECT_EXCEPTION(sioobe_);
1037 env_->GetStringUTFRegion(s, 10, 1, NULL);
1038 EXPECT_EXCEPTION(sioobe_);
1039
1040 char bytes[4] = { 'x', 'x', 'x', 'x' };
1041 env_->GetStringUTFRegion(s, 1, 2, &bytes[1]);
1042 EXPECT_EQ('x', bytes[0]);
1043 EXPECT_EQ('e', bytes[1]);
1044 EXPECT_EQ('l', bytes[2]);
1045 EXPECT_EQ('x', bytes[3]);
1046}
1047
Elliott Hughes75770752011-08-24 17:52:38 -07001048TEST_F(JniInternalTest, GetStringUTFChars_ReleaseStringUTFChars) {
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001049 // Passing in a NULL jstring is ignored normally, but caught by -Xcheck:jni.
Elliott Hughesb264f082012-04-06 17:10:10 -07001050 {
Elliott Hughesb264f082012-04-06 17:10:10 -07001051 CheckJniAbortCatcher check_jni_abort_catcher;
1052 EXPECT_TRUE(env_->GetStringUTFChars(NULL, NULL) == NULL);
Elliott Hughes56ef0422012-06-19 14:35:04 -07001053 check_jni_abort_catcher.Check("GetStringUTFChars received null jstring");
Elliott Hughesb264f082012-04-06 17:10:10 -07001054 }
Elliott Hughes75770752011-08-24 17:52:38 -07001055
1056 jstring s = env_->NewStringUTF("hello");
1057 ASSERT_TRUE(s != NULL);
1058
1059 const char* utf = env_->GetStringUTFChars(s, NULL);
1060 EXPECT_STREQ("hello", utf);
1061 env_->ReleaseStringUTFChars(s, utf);
1062
1063 jboolean is_copy = JNI_FALSE;
1064 utf = env_->GetStringUTFChars(s, &is_copy);
1065 EXPECT_EQ(JNI_TRUE, is_copy);
1066 EXPECT_STREQ("hello", utf);
1067 env_->ReleaseStringUTFChars(s, utf);
1068}
1069
1070TEST_F(JniInternalTest, GetStringChars_ReleaseStringChars) {
1071 jstring s = env_->NewStringUTF("hello");
1072 ASSERT_TRUE(s != NULL);
1073
1074 jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
1075 const jchar* chars = env_->GetStringChars(s, NULL);
1076 EXPECT_EQ(expected[0], chars[0]);
1077 EXPECT_EQ(expected[1], chars[1]);
1078 EXPECT_EQ(expected[2], chars[2]);
1079 EXPECT_EQ(expected[3], chars[3]);
1080 EXPECT_EQ(expected[4], chars[4]);
1081 env_->ReleaseStringChars(s, chars);
1082
1083 jboolean is_copy = JNI_FALSE;
1084 chars = env_->GetStringChars(s, &is_copy);
1085 EXPECT_EQ(JNI_FALSE, is_copy);
1086 EXPECT_EQ(expected[0], chars[0]);
1087 EXPECT_EQ(expected[1], chars[1]);
1088 EXPECT_EQ(expected[2], chars[2]);
1089 EXPECT_EQ(expected[3], chars[3]);
1090 EXPECT_EQ(expected[4], chars[4]);
1091 env_->ReleaseStringChars(s, chars);
1092}
1093
1094TEST_F(JniInternalTest, GetStringCritical_ReleaseStringCritical) {
1095 jstring s = env_->NewStringUTF("hello");
1096 ASSERT_TRUE(s != NULL);
1097
1098 jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
1099 const jchar* chars = env_->GetStringCritical(s, NULL);
1100 EXPECT_EQ(expected[0], chars[0]);
1101 EXPECT_EQ(expected[1], chars[1]);
1102 EXPECT_EQ(expected[2], chars[2]);
1103 EXPECT_EQ(expected[3], chars[3]);
1104 EXPECT_EQ(expected[4], chars[4]);
1105 env_->ReleaseStringCritical(s, chars);
1106
1107 jboolean is_copy = JNI_FALSE;
1108 chars = env_->GetStringCritical(s, &is_copy);
1109 EXPECT_EQ(JNI_FALSE, is_copy);
1110 EXPECT_EQ(expected[0], chars[0]);
1111 EXPECT_EQ(expected[1], chars[1]);
1112 EXPECT_EQ(expected[2], chars[2]);
1113 EXPECT_EQ(expected[3], chars[3]);
1114 EXPECT_EQ(expected[4], chars[4]);
1115 env_->ReleaseStringCritical(s, chars);
1116}
1117
Elliott Hughes814e4032011-08-23 12:07:56 -07001118TEST_F(JniInternalTest, GetObjectArrayElement_SetObjectArrayElement) {
Elliott Hughesb264f082012-04-06 17:10:10 -07001119 jclass java_lang_Class = env_->FindClass("java/lang/Class");
1120 ASSERT_TRUE(java_lang_Class != NULL);
Elliott Hughes289da822011-08-16 10:11:20 -07001121
Elliott Hughesb264f082012-04-06 17:10:10 -07001122 jobjectArray array = env_->NewObjectArray(1, java_lang_Class, NULL);
Elliott Hughes289da822011-08-16 10:11:20 -07001123 EXPECT_TRUE(array != NULL);
Elliott Hughes814e4032011-08-23 12:07:56 -07001124 EXPECT_TRUE(env_->GetObjectArrayElement(array, 0) == NULL);
Elliott Hughesb264f082012-04-06 17:10:10 -07001125 env_->SetObjectArrayElement(array, 0, java_lang_Class);
1126 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(array, 0), java_lang_Class));
Elliott Hughesa5b897e2011-08-16 11:33:06 -07001127
1128 // ArrayIndexOutOfBounds for negative index.
Elliott Hughesb264f082012-04-06 17:10:10 -07001129 env_->SetObjectArrayElement(array, -1, java_lang_Class);
Elliott Hughes814e4032011-08-23 12:07:56 -07001130 EXPECT_EXCEPTION(aioobe_);
Elliott Hughesa5b897e2011-08-16 11:33:06 -07001131
1132 // ArrayIndexOutOfBounds for too-large index.
Elliott Hughesb264f082012-04-06 17:10:10 -07001133 env_->SetObjectArrayElement(array, 1, java_lang_Class);
Elliott Hughes814e4032011-08-23 12:07:56 -07001134 EXPECT_EXCEPTION(aioobe_);
Elliott Hughesa5b897e2011-08-16 11:33:06 -07001135
Elliott Hughesb264f082012-04-06 17:10:10 -07001136 // ArrayStoreException thrown for bad types.
1137 env_->SetObjectArrayElement(array, 0, env_->NewStringUTF("not a jclass!"));
1138 EXPECT_EXCEPTION(ase_);
Elliott Hughes289da822011-08-16 10:11:20 -07001139}
1140
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001141#define EXPECT_STATIC_PRIMITIVE_FIELD(type, field_name, sig, value1, value2) \
1142 do { \
1143 jfieldID fid = env_->GetStaticFieldID(c, field_name, sig); \
1144 EXPECT_TRUE(fid != NULL); \
1145 env_->SetStatic ## type ## Field(c, fid, value1); \
Brian Carlstrom2e3d1b22012-01-09 18:01:56 -08001146 EXPECT_TRUE(value1 == env_->GetStatic ## type ## Field(c, fid)); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001147 env_->SetStatic ## type ## Field(c, fid, value2); \
Brian Carlstrom2e3d1b22012-01-09 18:01:56 -08001148 EXPECT_TRUE(value2 == env_->GetStatic ## type ## Field(c, fid)); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001149 } while (false)
1150
1151#define EXPECT_PRIMITIVE_FIELD(instance, type, field_name, sig, value1, value2) \
1152 do { \
1153 jfieldID fid = env_->GetFieldID(c, field_name, sig); \
1154 EXPECT_TRUE(fid != NULL); \
1155 env_->Set ## type ## Field(instance, fid, value1); \
Brian Carlstrom2e3d1b22012-01-09 18:01:56 -08001156 EXPECT_TRUE(value1 == env_->Get ## type ## Field(instance, fid)); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001157 env_->Set ## type ## Field(instance, fid, value2); \
Brian Carlstrom2e3d1b22012-01-09 18:01:56 -08001158 EXPECT_TRUE(value2 == env_->Get ## type ## Field(instance, fid)); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001159 } while (false)
1160
1161
Shih-wei Liao5b8b1ed2012-02-23 23:48:21 -08001162#if !defined(ART_USE_LLVM_COMPILER)
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001163TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001164 Thread::Current()->TransitionFromSuspendedToRunnable();
1165 LoadDex("AllFields");
Brian Carlstrom25c33252011-09-18 15:58:35 -07001166 runtime_->Start();
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001167
1168 jclass c = env_->FindClass("AllFields");
1169 ASSERT_TRUE(c != NULL);
1170 jobject o = env_->AllocObject(c);
1171 ASSERT_TRUE(o != NULL);
1172
1173 EXPECT_STATIC_PRIMITIVE_FIELD(Boolean, "sZ", "Z", true, false);
1174 EXPECT_STATIC_PRIMITIVE_FIELD(Byte, "sB", "B", 1, 2);
1175 EXPECT_STATIC_PRIMITIVE_FIELD(Char, "sC", "C", 'a', 'b');
1176 EXPECT_STATIC_PRIMITIVE_FIELD(Double, "sD", "D", 1.0, 2.0);
1177 EXPECT_STATIC_PRIMITIVE_FIELD(Float, "sF", "F", 1.0, 2.0);
1178 EXPECT_STATIC_PRIMITIVE_FIELD(Int, "sI", "I", 1, 2);
1179 EXPECT_STATIC_PRIMITIVE_FIELD(Long, "sJ", "J", 1, 2);
1180 EXPECT_STATIC_PRIMITIVE_FIELD(Short, "sS", "S", 1, 2);
1181
1182 EXPECT_PRIMITIVE_FIELD(o, Boolean, "iZ", "Z", true, false);
1183 EXPECT_PRIMITIVE_FIELD(o, Byte, "iB", "B", 1, 2);
1184 EXPECT_PRIMITIVE_FIELD(o, Char, "iC", "C", 'a', 'b');
1185 EXPECT_PRIMITIVE_FIELD(o, Double, "iD", "D", 1.0, 2.0);
1186 EXPECT_PRIMITIVE_FIELD(o, Float, "iF", "F", 1.0, 2.0);
1187 EXPECT_PRIMITIVE_FIELD(o, Int, "iI", "I", 1, 2);
1188 EXPECT_PRIMITIVE_FIELD(o, Long, "iJ", "J", 1, 2);
1189 EXPECT_PRIMITIVE_FIELD(o, Short, "iS", "S", 1, 2);
1190}
1191
1192TEST_F(JniInternalTest, GetObjectField_SetObjectField) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001193 Thread::Current()->TransitionFromSuspendedToRunnable();
1194 LoadDex("AllFields");
Brian Carlstrom25c33252011-09-18 15:58:35 -07001195 runtime_->Start();
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001196
1197 jclass c = env_->FindClass("AllFields");
1198 ASSERT_TRUE(c != NULL);
1199 jobject o = env_->AllocObject(c);
1200 ASSERT_TRUE(o != NULL);
1201
1202 jstring s1 = env_->NewStringUTF("hello");
1203 ASSERT_TRUE(s1 != NULL);
1204 jstring s2 = env_->NewStringUTF("world");
1205 ASSERT_TRUE(s2 != NULL);
1206
1207 jfieldID s_fid = env_->GetStaticFieldID(c, "sObject", "Ljava/lang/Object;");
1208 ASSERT_TRUE(s_fid != NULL);
1209 jfieldID i_fid = env_->GetFieldID(c, "iObject", "Ljava/lang/Object;");
1210 ASSERT_TRUE(i_fid != NULL);
1211
1212 env_->SetStaticObjectField(c, s_fid, s1);
1213 ASSERT_TRUE(env_->IsSameObject(s1, env_->GetStaticObjectField(c, s_fid)));
1214 env_->SetStaticObjectField(c, s_fid, s2);
1215 ASSERT_TRUE(env_->IsSameObject(s2, env_->GetStaticObjectField(c, s_fid)));
1216
1217 env_->SetObjectField(o, i_fid, s1);
1218 ASSERT_TRUE(env_->IsSameObject(s1, env_->GetObjectField(o, i_fid)));
1219 env_->SetObjectField(o, i_fid, s2);
1220 ASSERT_TRUE(env_->IsSameObject(s2, env_->GetObjectField(o, i_fid)));
1221}
Shih-wei Liao5b8b1ed2012-02-23 23:48:21 -08001222#endif
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001223
Elliott Hughes18c07532011-08-18 15:50:51 -07001224TEST_F(JniInternalTest, NewLocalRef_NULL) {
1225 EXPECT_TRUE(env_->NewLocalRef(NULL) == NULL);
1226}
1227
1228TEST_F(JniInternalTest, NewLocalRef) {
1229 jstring s = env_->NewStringUTF("");
1230 ASSERT_TRUE(s != NULL);
1231 jobject o = env_->NewLocalRef(s);
1232 EXPECT_TRUE(o != NULL);
1233 EXPECT_TRUE(o != s);
1234
Elliott Hughes2ced6a52011-10-16 18:44:48 -07001235 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(o));
Elliott Hughes18c07532011-08-18 15:50:51 -07001236}
1237
1238TEST_F(JniInternalTest, DeleteLocalRef_NULL) {
1239 env_->DeleteLocalRef(NULL);
1240}
1241
1242TEST_F(JniInternalTest, DeleteLocalRef) {
1243 jstring s = env_->NewStringUTF("");
1244 ASSERT_TRUE(s != NULL);
1245 env_->DeleteLocalRef(s);
1246
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001247 // Currently, deleting an already-deleted reference is just a CheckJNI warning.
Elliott Hughesb264f082012-04-06 17:10:10 -07001248 {
Elliott Hughesb264f082012-04-06 17:10:10 -07001249 CheckJniAbortCatcher check_jni_abort_catcher;
1250 env_->DeleteLocalRef(s);
Ian Rogers120f1c72012-09-28 17:17:10 -07001251 check_jni_abort_catcher.Check("native code passing in reference to invalid local reference: 0x1500001");
Elliott Hughesb264f082012-04-06 17:10:10 -07001252 }
Elliott Hughes18c07532011-08-18 15:50:51 -07001253
1254 s = env_->NewStringUTF("");
1255 ASSERT_TRUE(s != NULL);
1256 jobject o = env_->NewLocalRef(s);
1257 ASSERT_TRUE(o != NULL);
1258
1259 env_->DeleteLocalRef(s);
1260 env_->DeleteLocalRef(o);
1261}
1262
Elliott Hughes2ced6a52011-10-16 18:44:48 -07001263TEST_F(JniInternalTest, PushLocalFrame_PopLocalFrame) {
1264 jobject original = env_->NewStringUTF("");
1265 ASSERT_TRUE(original != NULL);
1266
1267 jobject outer;
1268 jobject inner1, inner2;
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001269 ScopedObjectAccess soa(env_);
Elliott Hughes2ced6a52011-10-16 18:44:48 -07001270 Object* inner2_direct_pointer;
1271 {
1272 env_->PushLocalFrame(4);
1273 outer = env_->NewLocalRef(original);
1274
1275 {
1276 env_->PushLocalFrame(4);
1277 inner1 = env_->NewLocalRef(outer);
1278 inner2 = env_->NewStringUTF("survivor");
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001279 inner2_direct_pointer = soa.Decode<Object*>(inner2);
Elliott Hughes2ced6a52011-10-16 18:44:48 -07001280 env_->PopLocalFrame(inner2);
1281 }
1282
1283 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original));
1284 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(outer));
1285 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1));
1286
1287 // Our local reference for the survivor is invalid because the survivor
1288 // gets a new local reference...
1289 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
1290 // ...but the survivor should be in the local reference table.
Brian Carlstrom4d571432012-05-16 00:21:41 -07001291 JNIEnvExt* env = reinterpret_cast<JNIEnvExt*>(env_);
1292 EXPECT_TRUE(env->locals.ContainsDirectPointer(inner2_direct_pointer));
Elliott Hughes2ced6a52011-10-16 18:44:48 -07001293
1294 env_->PopLocalFrame(NULL);
1295 }
1296 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original));
1297 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(outer));
1298 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1));
1299 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
1300}
1301
Elliott Hughes18c07532011-08-18 15:50:51 -07001302TEST_F(JniInternalTest, NewGlobalRef_NULL) {
1303 EXPECT_TRUE(env_->NewGlobalRef(NULL) == NULL);
1304}
1305
1306TEST_F(JniInternalTest, NewGlobalRef) {
1307 jstring s = env_->NewStringUTF("");
1308 ASSERT_TRUE(s != NULL);
1309 jobject o = env_->NewGlobalRef(s);
1310 EXPECT_TRUE(o != NULL);
1311 EXPECT_TRUE(o != s);
1312
1313 // TODO: check that o is a global reference.
1314}
1315
1316TEST_F(JniInternalTest, DeleteGlobalRef_NULL) {
1317 env_->DeleteGlobalRef(NULL);
1318}
1319
1320TEST_F(JniInternalTest, DeleteGlobalRef) {
1321 jstring s = env_->NewStringUTF("");
1322 ASSERT_TRUE(s != NULL);
1323
1324 jobject o = env_->NewGlobalRef(s);
1325 ASSERT_TRUE(o != NULL);
1326 env_->DeleteGlobalRef(o);
1327
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001328 // Currently, deleting an already-deleted reference is just a CheckJNI warning.
Elliott Hughesb264f082012-04-06 17:10:10 -07001329 {
Elliott Hughesb264f082012-04-06 17:10:10 -07001330 CheckJniAbortCatcher check_jni_abort_catcher;
1331 env_->DeleteGlobalRef(o);
Ian Rogers120f1c72012-09-28 17:17:10 -07001332 check_jni_abort_catcher.Check("native code passing in reference to invalid global reference: 0x10005a");
Elliott Hughesb264f082012-04-06 17:10:10 -07001333 }
Elliott Hughes18c07532011-08-18 15:50:51 -07001334
1335 jobject o1 = env_->NewGlobalRef(s);
1336 ASSERT_TRUE(o1 != NULL);
1337 jobject o2 = env_->NewGlobalRef(s);
1338 ASSERT_TRUE(o2 != NULL);
1339
1340 env_->DeleteGlobalRef(o1);
1341 env_->DeleteGlobalRef(o2);
1342}
1343
1344TEST_F(JniInternalTest, NewWeakGlobalRef_NULL) {
1345 EXPECT_TRUE(env_->NewWeakGlobalRef(NULL) == NULL);
1346}
1347
1348TEST_F(JniInternalTest, NewWeakGlobalRef) {
1349 jstring s = env_->NewStringUTF("");
1350 ASSERT_TRUE(s != NULL);
1351 jobject o = env_->NewWeakGlobalRef(s);
1352 EXPECT_TRUE(o != NULL);
1353 EXPECT_TRUE(o != s);
1354
1355 // TODO: check that o is a weak global reference.
1356}
1357
1358TEST_F(JniInternalTest, DeleteWeakGlobalRef_NULL) {
1359 env_->DeleteWeakGlobalRef(NULL);
1360}
1361
1362TEST_F(JniInternalTest, DeleteWeakGlobalRef) {
1363 jstring s = env_->NewStringUTF("");
1364 ASSERT_TRUE(s != NULL);
1365
1366 jobject o = env_->NewWeakGlobalRef(s);
1367 ASSERT_TRUE(o != NULL);
1368 env_->DeleteWeakGlobalRef(o);
1369
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001370 // Currently, deleting an already-deleted reference is just a CheckJNI warning.
Elliott Hughesb264f082012-04-06 17:10:10 -07001371 {
Elliott Hughesb264f082012-04-06 17:10:10 -07001372 CheckJniAbortCatcher check_jni_abort_catcher;
1373 env_->DeleteWeakGlobalRef(o);
Elliott Hughes56ef0422012-06-19 14:35:04 -07001374 check_jni_abort_catcher.Check("native code passing in reference to invalid weak global reference: 0x100003");
Elliott Hughesb264f082012-04-06 17:10:10 -07001375 }
Elliott Hughes18c07532011-08-18 15:50:51 -07001376
1377 jobject o1 = env_->NewWeakGlobalRef(s);
1378 ASSERT_TRUE(o1 != NULL);
1379 jobject o2 = env_->NewWeakGlobalRef(s);
1380 ASSERT_TRUE(o2 != NULL);
1381
1382 env_->DeleteWeakGlobalRef(o1);
1383 env_->DeleteWeakGlobalRef(o2);
1384}
1385
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001386TEST_F(JniInternalTest, StaticMainMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001387 ScopedObjectAccess soa(Thread::Current());
1388 jobject jclass_loader = LoadDex("Main");
Ian Rogers1f539342012-10-03 21:09:42 -07001389 SirtRef<ClassLoader> class_loader(soa.Self(), soa.Decode<ClassLoader*>(jclass_loader));
Brian Carlstrom40381fb2011-10-19 14:13:40 -07001390 CompileDirectMethod(class_loader.get(), "Main", "main", "([Ljava/lang/String;)V");
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001391
Brian Carlstrom40381fb2011-10-19 14:13:40 -07001392 Class* klass = class_linker_->FindClass("LMain;", class_loader.get());
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001393 ASSERT_TRUE(klass != NULL);
1394
Mathieu Chartier66f19252012-09-18 08:57:04 -07001395 AbstractMethod* method = klass->FindDirectMethod("main", "([Ljava/lang/String;)V");
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001396 ASSERT_TRUE(method != NULL);
1397
Mathieu Chartier66f19252012-09-18 08:57:04 -07001398 AbstractMethod::InvokeStub* stub = method->GetInvokeStub();
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001399
Elliott Hughes77405792012-03-15 15:22:12 -07001400 JValue args[1];
Elliott Hughesf24d3ce2012-04-11 17:43:37 -07001401 args[0].SetL(NULL);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001402
Elliott Hughes77405792012-03-15 15:22:12 -07001403 (*stub)(method, NULL, Thread::Current(), args, NULL);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001404}
1405
1406TEST_F(JniInternalTest, StaticNopMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001407 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001408 InvokeNopMethod(true);
1409}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001410
Elliott Hughes77405792012-03-15 15:22:12 -07001411TEST_F(JniInternalTest, NonStaticNopMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001412 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001413 InvokeNopMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001414}
1415
1416TEST_F(JniInternalTest, StaticIdentityByteMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001417 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001418 InvokeIdentityByteMethod(true);
1419}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001420
Elliott Hughes77405792012-03-15 15:22:12 -07001421TEST_F(JniInternalTest, NonStaticIdentityByteMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001422 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001423 InvokeIdentityByteMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001424}
1425
1426TEST_F(JniInternalTest, StaticIdentityIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001427 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001428 InvokeIdentityIntMethod(true);
1429}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001430
Elliott Hughes77405792012-03-15 15:22:12 -07001431TEST_F(JniInternalTest, NonStaticIdentityIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001432 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001433 InvokeIdentityIntMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001434}
1435
1436TEST_F(JniInternalTest, StaticIdentityDoubleMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001437 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001438 InvokeIdentityDoubleMethod(true);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001439}
1440
Elliott Hughes77405792012-03-15 15:22:12 -07001441TEST_F(JniInternalTest, NonStaticIdentityDoubleMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001442 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001443 InvokeIdentityDoubleMethod(false);
Shih-wei Liao5b8b1ed2012-02-23 23:48:21 -08001444}
1445
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001446TEST_F(JniInternalTest, StaticSumIntIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001447 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001448 InvokeSumIntIntMethod(true);
1449}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001450
Elliott Hughes77405792012-03-15 15:22:12 -07001451TEST_F(JniInternalTest, NonStaticSumIntIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001452 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001453 InvokeSumIntIntMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001454}
1455
1456TEST_F(JniInternalTest, StaticSumIntIntIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001457 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001458 InvokeSumIntIntIntMethod(true);
1459}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001460
Elliott Hughes77405792012-03-15 15:22:12 -07001461TEST_F(JniInternalTest, NonStaticSumIntIntIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001462 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001463 InvokeSumIntIntIntMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001464}
1465
1466TEST_F(JniInternalTest, StaticSumIntIntIntIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001467 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001468 InvokeSumIntIntIntIntMethod(true);
1469}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001470
Elliott Hughes77405792012-03-15 15:22:12 -07001471TEST_F(JniInternalTest, NonStaticSumIntIntIntIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001472 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001473 InvokeSumIntIntIntIntMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001474}
1475
1476TEST_F(JniInternalTest, StaticSumIntIntIntIntIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001477 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001478 InvokeSumIntIntIntIntIntMethod(true);
1479}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001480
Elliott Hughes77405792012-03-15 15:22:12 -07001481TEST_F(JniInternalTest, NonStaticSumIntIntIntIntIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001482 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001483 InvokeSumIntIntIntIntIntMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001484}
1485
1486TEST_F(JniInternalTest, StaticSumDoubleDoubleMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001487 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001488 InvokeSumDoubleDoubleMethod(true);
1489}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001490
Elliott Hughes77405792012-03-15 15:22:12 -07001491TEST_F(JniInternalTest, NonStaticSumDoubleDoubleMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001492 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001493 InvokeSumDoubleDoubleMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001494}
1495
1496TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001497 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001498 InvokeSumDoubleDoubleDoubleMethod(true);
1499}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001500
Elliott Hughes77405792012-03-15 15:22:12 -07001501TEST_F(JniInternalTest, NonStaticSumDoubleDoubleDoubleMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001502 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001503 InvokeSumDoubleDoubleDoubleMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001504}
1505
1506TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001507 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001508 InvokeSumDoubleDoubleDoubleDoubleMethod(true);
1509}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001510
Elliott Hughes77405792012-03-15 15:22:12 -07001511TEST_F(JniInternalTest, NonStaticSumDoubleDoubleDoubleDoubleMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001512 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001513 InvokeSumDoubleDoubleDoubleDoubleMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001514}
1515
1516TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleDoubleMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001517 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001518 InvokeSumDoubleDoubleDoubleDoubleDoubleMethod(true);
1519}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001520
Elliott Hughes77405792012-03-15 15:22:12 -07001521TEST_F(JniInternalTest, NonStaticSumDoubleDoubleDoubleDoubleDoubleMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001522 ScopedObjectAccess soa(Thread::Current());
Elliott Hughes77405792012-03-15 15:22:12 -07001523 InvokeSumDoubleDoubleDoubleDoubleDoubleMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001524}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001525
Elliott Hughes37f7a402011-08-22 18:56:01 -07001526TEST_F(JniInternalTest, Throw) {
1527 EXPECT_EQ(JNI_ERR, env_->Throw(NULL));
1528
1529 jclass exception_class = env_->FindClass("java/lang/RuntimeException");
1530 ASSERT_TRUE(exception_class != NULL);
1531 jthrowable exception = reinterpret_cast<jthrowable>(env_->AllocObject(exception_class));
1532 ASSERT_TRUE(exception != NULL);
1533
1534 EXPECT_EQ(JNI_OK, env_->Throw(exception));
1535 EXPECT_TRUE(env_->ExceptionCheck());
Elliott Hughesa2501992011-08-26 19:39:54 -07001536 jthrowable thrown_exception = env_->ExceptionOccurred();
Elliott Hughes37f7a402011-08-22 18:56:01 -07001537 env_->ExceptionClear();
Elliott Hughesa2501992011-08-26 19:39:54 -07001538 EXPECT_TRUE(env_->IsSameObject(exception, thrown_exception));
Elliott Hughes37f7a402011-08-22 18:56:01 -07001539}
1540
1541TEST_F(JniInternalTest, ThrowNew) {
1542 EXPECT_EQ(JNI_ERR, env_->Throw(NULL));
1543
1544 jclass exception_class = env_->FindClass("java/lang/RuntimeException");
1545 ASSERT_TRUE(exception_class != NULL);
1546
Elliott Hughes5cb5ad22011-10-02 12:13:39 -07001547 jthrowable thrown_exception;
1548
Elliott Hughes37f7a402011-08-22 18:56:01 -07001549 EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, "hello world"));
1550 EXPECT_TRUE(env_->ExceptionCheck());
Elliott Hughes5cb5ad22011-10-02 12:13:39 -07001551 thrown_exception = env_->ExceptionOccurred();
1552 env_->ExceptionClear();
1553 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class));
1554
1555 EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, NULL));
1556 EXPECT_TRUE(env_->ExceptionCheck());
1557 thrown_exception = env_->ExceptionOccurred();
Elliott Hughes37f7a402011-08-22 18:56:01 -07001558 env_->ExceptionClear();
Elliott Hughesa2501992011-08-26 19:39:54 -07001559 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class));
Elliott Hughes37f7a402011-08-22 18:56:01 -07001560}
1561
Elliott Hughesb465ab02011-08-24 11:21:21 -07001562// TODO: this test is DISABLED until we can actually run java.nio.Buffer's <init>.
1563TEST_F(JniInternalTest, DISABLED_NewDirectBuffer_GetDirectBufferAddress_GetDirectBufferCapacity) {
1564 jclass buffer_class = env_->FindClass("java/nio/Buffer");
1565 ASSERT_TRUE(buffer_class != NULL);
1566
1567 char bytes[1024];
1568 jobject buffer = env_->NewDirectByteBuffer(bytes, sizeof(bytes));
1569 ASSERT_TRUE(buffer != NULL);
1570 ASSERT_TRUE(env_->IsInstanceOf(buffer, buffer_class));
1571 ASSERT_TRUE(env_->GetDirectBufferAddress(buffer) == bytes);
1572 ASSERT_TRUE(env_->GetDirectBufferCapacity(buffer) == sizeof(bytes));
1573}
1574
Ian Rogers6d0b13e2012-02-07 09:25:29 -08001575TEST_F(JniInternalTest, MonitorEnterExit) {
1576 // Create an object to torture
1577 jclass object_class = env_->FindClass("java/lang/Object");
1578 ASSERT_TRUE(object_class != NULL);
1579 jobject object = env_->AllocObject(object_class);
1580 ASSERT_TRUE(object != NULL);
1581
1582 // Expected class of exceptions
1583 jclass imse_class = env_->FindClass("java/lang/IllegalMonitorStateException");
1584 ASSERT_TRUE(imse_class != NULL);
1585
1586 jthrowable thrown_exception;
1587
1588 // Unlock of unowned monitor
1589 env_->MonitorExit(object);
1590 EXPECT_TRUE(env_->ExceptionCheck());
1591 thrown_exception = env_->ExceptionOccurred();
1592 env_->ExceptionClear();
1593 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class));
1594
1595 // Lock of unowned monitor
1596 env_->MonitorEnter(object);
1597 EXPECT_FALSE(env_->ExceptionCheck());
1598 // Regular unlock
1599 env_->MonitorExit(object);
1600 EXPECT_FALSE(env_->ExceptionCheck());
1601
1602 // Recursively lock a lot
1603 size_t max_recursive_lock = 1024;
1604 for (size_t i = 0; i < max_recursive_lock; i++) {
1605 env_->MonitorEnter(object);
1606 EXPECT_FALSE(env_->ExceptionCheck());
1607 }
1608 // Recursively unlock a lot
1609 for (size_t i = 0; i < max_recursive_lock; i++) {
1610 env_->MonitorExit(object);
1611 EXPECT_FALSE(env_->ExceptionCheck());
1612 }
1613
1614 // Unlock of unowned monitor
1615 env_->MonitorExit(object);
1616 EXPECT_TRUE(env_->ExceptionCheck());
1617 thrown_exception = env_->ExceptionOccurred();
1618 env_->ExceptionClear();
1619 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class));
Elliott Hughesa92853e2012-02-07 16:09:27 -08001620
1621 // It's an error to call MonitorEnter or MonitorExit on NULL.
Elliott Hughesb264f082012-04-06 17:10:10 -07001622 {
1623 CheckJniAbortCatcher check_jni_abort_catcher;
1624 env_->MonitorEnter(NULL);
1625 check_jni_abort_catcher.Check("in call to MonitorEnter");
Elliott Hughesb264f082012-04-06 17:10:10 -07001626
Elliott Hughesb264f082012-04-06 17:10:10 -07001627 env_->MonitorExit(NULL);
1628 check_jni_abort_catcher.Check("in call to MonitorExit");
1629 }
Ian Rogers6d0b13e2012-02-07 09:25:29 -08001630}
1631
Brian Carlstrom4d571432012-05-16 00:21:41 -07001632TEST_F(JniInternalTest, DetachCurrentThread) {
1633 CleanUpJniEnv(); // cleanup now so TearDown won't have junk from wrong JNIEnv
1634 jint ok = vm_->DetachCurrentThread();
1635 EXPECT_EQ(JNI_OK, ok);
1636
1637 jint err = vm_->DetachCurrentThread();
1638 EXPECT_EQ(JNI_ERR, err);
1639 vm_->AttachCurrentThread(&env_, NULL); // need attached thread for CommonTest::TearDown
1640}
1641
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001642} // namespace art