blob: e1332d3395b3cfe88ae915c9f92e8e3e0ff91950 [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 */
Ian Rogersb033c752011-07-20 12:22:35 -070016
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070017#include "class_linker.h"
18#include "common_test.h"
19#include "dex_file.h"
Elliott Hughes90a33692011-08-30 13:27:07 -070020#include "gtest/gtest.h"
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070021#include "indirect_reference_table.h"
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070022#include "jni_internal.h"
Brian Carlstromdb4d5402011-08-09 12:18:28 -070023#include "mem_map.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070024#include "runtime.h"
Ian Rogers00f7d0e2012-07-19 15:28:27 -070025#include "ScopedLocalRef.h"
26#include "scoped_thread_state_change.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070027#include "thread.h"
Elliott Hughesa168c832012-06-12 15:34:20 -070028#include "UniquePtr.h"
Ian Rogersb033c752011-07-20 12:22:35 -070029
Elliott Hughesb264f082012-04-06 17:10:10 -070030extern "C" JNIEXPORT jint JNICALL Java_MyClassNatives_bar(JNIEnv*, jobject, jint count) {
Brian Carlstromb9cc1ca2012-01-27 00:57:42 -080031 return count + 1;
32}
33
Elliott Hughesb264f082012-04-06 17:10:10 -070034extern "C" JNIEXPORT jint JNICALL Java_MyClassNatives_sbar(JNIEnv*, jclass, jint count) {
Ian Rogers1cefdbd2012-02-29 09:34:50 -080035 return count + 1;
36}
37
Ian Rogersb033c752011-07-20 12:22:35 -070038namespace art {
39
Brian Carlstromf734cf52011-08-17 16:28:14 -070040class JniCompilerTest : public CommonTest {
Ian Rogersb033c752011-07-20 12:22:35 -070041 protected:
Ian Rogers00f7d0e2012-07-19 15:28:27 -070042 void CompileForTest(jobject class_loader, bool direct,
Brian Carlstrom40381fb2011-10-19 14:13:40 -070043 const char* method_name, const char* method_sig) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070044 ScopedObjectAccess soa(Thread::Current());
Brian Carlstrom25c33252011-09-18 15:58:35 -070045 // Compile the native method before starting the runtime
Ian Rogers00f7d0e2012-07-19 15:28:27 -070046 Class* c = class_linker_->FindClass("LMyClassNatives;", soa.Decode<ClassLoader*>(class_loader));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070047 Method* method;
48 if (direct) {
buzbeec143c552011-08-20 17:38:58 -070049 method = c->FindDirectMethod(method_name, method_sig);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070050 } else {
buzbeec143c552011-08-20 17:38:58 -070051 method = c->FindVirtualMethod(method_name, method_sig);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070052 }
53 ASSERT_TRUE(method != NULL);
Brian Carlstrom25c33252011-09-18 15:58:35 -070054 if (method->GetCode() != NULL) {
55 return;
56 }
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070057 CompileMethod(method);
Elliott Hughes1240dad2011-09-09 16:24:50 -070058 ASSERT_TRUE(method->GetCode() != NULL);
Brian Carlstrom25c33252011-09-18 15:58:35 -070059 }
60
Ian Rogers00f7d0e2012-07-19 15:28:27 -070061 void SetUpForTest(bool direct, const char* method_name, const char* method_sig,
Brian Carlstrom25c33252011-09-18 15:58:35 -070062 void* native_fnptr) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070063 // Initialize class loader and compile method when runtime not started.
64 if (!runtime_->IsStarted()){
65 {
66 ScopedObjectAccess soa(Thread::Current());
67 class_loader_ = LoadDex("MyClassNatives");
68 }
69 CompileForTest(class_loader_, direct, method_name, method_sig);
70 // Start runtime.
71 Thread::Current()->TransitionFromSuspendedToRunnable();
Brian Carlstrom25c33252011-09-18 15:58:35 -070072 runtime_->Start();
73 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -070074 // JNI operations after runtime start.
Brian Carlstrom25c33252011-09-18 15:58:35 -070075 env_ = Thread::Current()->GetJniEnv();
Elliott Hughesb264f082012-04-06 17:10:10 -070076 jklass_ = env_->FindClass("MyClassNatives");
Brian Carlstrom25c33252011-09-18 15:58:35 -070077 ASSERT_TRUE(jklass_ != NULL);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070078
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070079 if (direct) {
80 jmethod_ = env_->GetStaticMethodID(jklass_, method_name, method_sig);
81 } else {
82 jmethod_ = env_->GetMethodID(jklass_, method_name, method_sig);
83 }
84 ASSERT_TRUE(jmethod_ != NULL);
85
Ian Rogersbdb03912011-09-14 00:55:44 -070086 if (native_fnptr != NULL) {
Elliott Hughesb25c3f62012-03-26 16:35:06 -070087 JNINativeMethod methods[] = { { method_name, method_sig, native_fnptr } };
Shih-wei Liao31384c52011-09-06 15:27:45 -070088 ASSERT_EQ(JNI_OK, env_->RegisterNatives(jklass_, methods, 1));
Ian Rogersbdb03912011-09-14 00:55:44 -070089 } else {
90 env_->UnregisterNatives(jklass_);
Shih-wei Liao31384c52011-09-06 15:27:45 -070091 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070092
93 jmethodID constructor = env_->GetMethodID(jklass_, "<init>", "()V");
94 jobj_ = env_->NewObject(jklass_, constructor);
95 ASSERT_TRUE(jobj_ != NULL);
Ian Rogersb033c752011-07-20 12:22:35 -070096 }
97
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070098 public:
99 static jclass jklass_;
100 static jobject jobj_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700101 static jobject class_loader_;
102
Elliott Hughesa21039c2012-06-21 12:09:25 -0700103
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700104 protected:
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700105 JNIEnv* env_;
106 jmethodID jmethod_;
Ian Rogersb033c752011-07-20 12:22:35 -0700107};
108
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700109jclass JniCompilerTest::jklass_;
110jobject JniCompilerTest::jobj_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700111jobject JniCompilerTest::class_loader_;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700112
Elliott Hughesb264f082012-04-06 17:10:10 -0700113int gJava_MyClassNatives_foo_calls = 0;
114void Java_MyClassNatives_foo(JNIEnv* env, jobject thisObj) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700115 // 1 = thisObj
116 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
117 {
118 MutexLock mu(*GlobalSynchronization::thread_suspend_count_lock_);
119 EXPECT_EQ(kNative, Thread::Current()->GetState());
120 GlobalSynchronization::mutator_lock_->AssertNotHeld();
121 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700122 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
123 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700124 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700125 gJava_MyClassNatives_foo_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700126}
127
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700128TEST_F(JniCompilerTest, CompileAndRunNoArgMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700129 SetUpForTest(false, "foo", "()V",
Elliott Hughesb264f082012-04-06 17:10:10 -0700130 reinterpret_cast<void*>(&Java_MyClassNatives_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700131
Elliott Hughesb264f082012-04-06 17:10:10 -0700132 EXPECT_EQ(0, gJava_MyClassNatives_foo_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700133 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700134 EXPECT_EQ(1, gJava_MyClassNatives_foo_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700135 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700136 EXPECT_EQ(2, gJava_MyClassNatives_foo_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700137}
138
Shih-wei Liao31384c52011-09-06 15:27:45 -0700139TEST_F(JniCompilerTest, CompileAndRunIntMethodThroughStub) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700140 SetUpForTest(false, "bar", "(I)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700141 NULL /* calling through stub will link with &Java_MyClassNatives_bar */);
Shih-wei Liao31384c52011-09-06 15:27:45 -0700142
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700143 ScopedObjectAccess soa(Thread::Current());
Shih-wei Liao31384c52011-09-06 15:27:45 -0700144 std::string reason;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700145 ASSERT_TRUE(
146 Runtime::Current()->GetJavaVM()->LoadNativeLibrary("", soa.Decode<ClassLoader*>(class_loader_),
147 reason)) << reason;
Shih-wei Liao31384c52011-09-06 15:27:45 -0700148
149 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 24);
150 EXPECT_EQ(25, result);
151}
152
Ian Rogers1cefdbd2012-02-29 09:34:50 -0800153TEST_F(JniCompilerTest, CompileAndRunStaticIntMethodThroughStub) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700154 SetUpForTest(true, "sbar", "(I)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700155 NULL /* calling through stub will link with &Java_MyClassNatives_sbar */);
Ian Rogers1cefdbd2012-02-29 09:34:50 -0800156
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700157 ScopedObjectAccess soa(Thread::Current());
Ian Rogers1cefdbd2012-02-29 09:34:50 -0800158 std::string reason;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700159 ASSERT_TRUE(
160 Runtime::Current()->GetJavaVM()->LoadNativeLibrary("", soa.Decode<ClassLoader*>(class_loader_),
161 reason)) << reason;
Ian Rogers1cefdbd2012-02-29 09:34:50 -0800162
163 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 42);
164 EXPECT_EQ(43, result);
165}
166
Elliott Hughesb264f082012-04-06 17:10:10 -0700167int gJava_MyClassNatives_fooI_calls = 0;
168jint Java_MyClassNatives_fooI(JNIEnv* env, jobject thisObj, jint x) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700169 // 1 = thisObj
170 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
171 {
172 MutexLock mu(*GlobalSynchronization::thread_suspend_count_lock_);
173 EXPECT_EQ(kNative, Thread::Current()->GetState());
174 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700175 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
176 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700177 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700178 gJava_MyClassNatives_fooI_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700179 return x;
180}
181
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700182TEST_F(JniCompilerTest, CompileAndRunIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700183 SetUpForTest(false, "fooI", "(I)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700184 reinterpret_cast<void*>(&Java_MyClassNatives_fooI));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700185
Elliott Hughesb264f082012-04-06 17:10:10 -0700186 EXPECT_EQ(0, gJava_MyClassNatives_fooI_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700187 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
188 EXPECT_EQ(42, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700189 EXPECT_EQ(1, gJava_MyClassNatives_fooI_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700190 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFED00D);
191 EXPECT_EQ(static_cast<jint>(0xCAFED00D), result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700192 EXPECT_EQ(2, gJava_MyClassNatives_fooI_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700193}
194
Elliott Hughesb264f082012-04-06 17:10:10 -0700195int gJava_MyClassNatives_fooII_calls = 0;
196jint Java_MyClassNatives_fooII(JNIEnv* env, jobject thisObj, jint x, jint y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700197 // 1 = thisObj
198 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
199 {
200 MutexLock mu(*GlobalSynchronization::thread_suspend_count_lock_);
201 EXPECT_EQ(kNative, Thread::Current()->GetState());
202 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700203 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
204 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700205 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700206 gJava_MyClassNatives_fooII_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700207 return x - y; // non-commutative operator
208}
209
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700210TEST_F(JniCompilerTest, CompileAndRunIntIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700211 SetUpForTest(false, "fooII", "(II)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700212 reinterpret_cast<void*>(&Java_MyClassNatives_fooII));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700213
Elliott Hughesb264f082012-04-06 17:10:10 -0700214 EXPECT_EQ(0, gJava_MyClassNatives_fooII_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700215 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 99, 10);
216 EXPECT_EQ(99 - 10, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700217 EXPECT_EQ(1, gJava_MyClassNatives_fooII_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700218 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFEBABE,
219 0xCAFED00D);
220 EXPECT_EQ(static_cast<jint>(0xCAFEBABE - 0xCAFED00D), result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700221 EXPECT_EQ(2, gJava_MyClassNatives_fooII_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700222}
223
Elliott Hughesb264f082012-04-06 17:10:10 -0700224int gJava_MyClassNatives_fooJJ_calls = 0;
225jlong Java_MyClassNatives_fooJJ(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700226 // 1 = thisObj
227 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
228 {
229 MutexLock mu(*GlobalSynchronization::thread_suspend_count_lock_);
230 EXPECT_EQ(kNative, Thread::Current()->GetState());
231 }
Ian Rogers9b269d22011-09-04 14:06:05 -0700232 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
233 EXPECT_TRUE(thisObj != NULL);
234 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700235 gJava_MyClassNatives_fooJJ_calls++;
Ian Rogers9b269d22011-09-04 14:06:05 -0700236 return x - y; // non-commutative operator
237}
238
239TEST_F(JniCompilerTest, CompileAndRunLongLongMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700240 SetUpForTest(false, "fooJJ", "(JJ)J",
Elliott Hughesb264f082012-04-06 17:10:10 -0700241 reinterpret_cast<void*>(&Java_MyClassNatives_fooJJ));
Ian Rogers9b269d22011-09-04 14:06:05 -0700242
Elliott Hughesb264f082012-04-06 17:10:10 -0700243 EXPECT_EQ(0, gJava_MyClassNatives_fooJJ_calls);
Ian Rogers9b269d22011-09-04 14:06:05 -0700244 jlong a = 0x1234567890ABCDEFll;
245 jlong b = 0xFEDCBA0987654321ll;
246 jlong result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, a, b);
247 EXPECT_EQ(a - b, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700248 EXPECT_EQ(1, gJava_MyClassNatives_fooJJ_calls);
Ian Rogers9b269d22011-09-04 14:06:05 -0700249 result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, b, a);
250 EXPECT_EQ(b - a, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700251 EXPECT_EQ(2, gJava_MyClassNatives_fooJJ_calls);
Ian Rogers9b269d22011-09-04 14:06:05 -0700252}
253
Elliott Hughesb264f082012-04-06 17:10:10 -0700254int gJava_MyClassNatives_fooDD_calls = 0;
255jdouble Java_MyClassNatives_fooDD(JNIEnv* env, jobject thisObj, jdouble x, jdouble y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700256 // 1 = thisObj
257 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
258 {
259 MutexLock mu(*GlobalSynchronization::thread_suspend_count_lock_);
260 EXPECT_EQ(kNative, Thread::Current()->GetState());
261 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700262 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
263 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700264 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700265 gJava_MyClassNatives_fooDD_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700266 return x - y; // non-commutative operator
267}
268
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700269TEST_F(JniCompilerTest, CompileAndRunDoubleDoubleMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700270 SetUpForTest(false, "fooDD", "(DD)D",
Elliott Hughesb264f082012-04-06 17:10:10 -0700271 reinterpret_cast<void*>(&Java_MyClassNatives_fooDD));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700272
Elliott Hughesb264f082012-04-06 17:10:10 -0700273 EXPECT_EQ(0, gJava_MyClassNatives_fooDD_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700274 jdouble result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_,
275 99.0, 10.0);
276 EXPECT_EQ(99.0 - 10.0, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700277 EXPECT_EQ(1, gJava_MyClassNatives_fooDD_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700278 jdouble a = 3.14159265358979323846;
279 jdouble b = 0.69314718055994530942;
280 result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_, a, b);
281 EXPECT_EQ(a - b, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700282 EXPECT_EQ(2, gJava_MyClassNatives_fooDD_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700283}
284
Elliott Hughes3e778f72012-05-21 15:29:52 -0700285int gJava_MyClassNatives_fooJJ_synchronized_calls = 0;
286jlong Java_MyClassNatives_fooJJ_synchronized(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700287 // 1 = thisObj
288 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
289 {
290 MutexLock mu(*GlobalSynchronization::thread_suspend_count_lock_);
291 EXPECT_EQ(kNative, Thread::Current()->GetState());
292 }
Elliott Hughes3e778f72012-05-21 15:29:52 -0700293 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
294 EXPECT_TRUE(thisObj != NULL);
295 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
296 gJava_MyClassNatives_fooJJ_synchronized_calls++;
297 return x | y;
298}
299
300TEST_F(JniCompilerTest, CompileAndRun_fooJJ_synchronized) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700301 SetUpForTest(false, "fooJJ_synchronized", "(JJ)J",
Elliott Hughes3e778f72012-05-21 15:29:52 -0700302 reinterpret_cast<void*>(&Java_MyClassNatives_fooJJ_synchronized));
303
304 EXPECT_EQ(0, gJava_MyClassNatives_fooJJ_synchronized_calls);
305 jlong a = 0x1000000020000000ULL;
306 jlong b = 0x00ff000000aa0000ULL;
307 jlong result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, a, b);
308 EXPECT_EQ(a | b, result);
309 EXPECT_EQ(1, gJava_MyClassNatives_fooJJ_synchronized_calls);
310}
311
Elliott Hughesb264f082012-04-06 17:10:10 -0700312int gJava_MyClassNatives_fooIOO_calls = 0;
313jobject Java_MyClassNatives_fooIOO(JNIEnv* env, jobject thisObj, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700314 jobject z) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700315 // 3 = this + y + z
316 EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
317 {
318 MutexLock mu(*GlobalSynchronization::thread_suspend_count_lock_);
319 EXPECT_EQ(kNative, Thread::Current()->GetState());
320 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700321 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
322 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700323 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700324 gJava_MyClassNatives_fooIOO_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700325 switch (x) {
326 case 1:
327 return y;
328 case 2:
329 return z;
330 default:
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700331 return thisObj;
Ian Rogersb033c752011-07-20 12:22:35 -0700332 }
333}
334
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700335TEST_F(JniCompilerTest, CompileAndRunIntObjectObjectMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700336 SetUpForTest(false, "fooIOO",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700337 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700338 reinterpret_cast<void*>(&Java_MyClassNatives_fooIOO));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700339
Elliott Hughesb264f082012-04-06 17:10:10 -0700340 EXPECT_EQ(0, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700341 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, NULL);
342 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700343 EXPECT_EQ(1, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700344
345 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, jklass_);
346 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700347 EXPECT_EQ(2, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700348 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, NULL, jklass_);
349 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700350 EXPECT_EQ(3, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700351 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, NULL, jklass_);
352 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700353 EXPECT_EQ(4, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700354
355 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, jklass_, NULL);
356 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700357 EXPECT_EQ(5, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700358 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, jklass_, NULL);
359 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700360 EXPECT_EQ(6, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700361 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, jklass_, NULL);
362 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700363 EXPECT_EQ(7, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700364}
365
Elliott Hughesb264f082012-04-06 17:10:10 -0700366int gJava_MyClassNatives_fooSII_calls = 0;
367jint Java_MyClassNatives_fooSII(JNIEnv* env, jclass klass, jint x, jint y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700368 // 1 = klass
369 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
370 {
371 MutexLock mu(*GlobalSynchronization::thread_suspend_count_lock_);
372 EXPECT_EQ(kNative, Thread::Current()->GetState());
373 }
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700374 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
375 EXPECT_TRUE(klass != NULL);
376 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Elliott Hughesb264f082012-04-06 17:10:10 -0700377 gJava_MyClassNatives_fooSII_calls++;
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700378 return x + y;
379}
380
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700381TEST_F(JniCompilerTest, CompileAndRunStaticIntIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700382 SetUpForTest(true, "fooSII", "(II)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700383 reinterpret_cast<void*>(&Java_MyClassNatives_fooSII));
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700384
Elliott Hughesb264f082012-04-06 17:10:10 -0700385 EXPECT_EQ(0, gJava_MyClassNatives_fooSII_calls);
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700386 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 20, 30);
387 EXPECT_EQ(50, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700388 EXPECT_EQ(1, gJava_MyClassNatives_fooSII_calls);
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700389}
390
Elliott Hughesb264f082012-04-06 17:10:10 -0700391int gJava_MyClassNatives_fooSDD_calls = 0;
392jdouble Java_MyClassNatives_fooSDD(JNIEnv* env, jclass klass, jdouble x, jdouble y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700393 // 1 = klass
394 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
395 {
396 MutexLock mu(*GlobalSynchronization::thread_suspend_count_lock_);
397 EXPECT_EQ(kNative, Thread::Current()->GetState());
398 }
Ian Rogers7a99c112011-09-07 12:48:27 -0700399 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
400 EXPECT_TRUE(klass != NULL);
401 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Elliott Hughesb264f082012-04-06 17:10:10 -0700402 gJava_MyClassNatives_fooSDD_calls++;
Ian Rogers7a99c112011-09-07 12:48:27 -0700403 return x - y; // non-commutative operator
404}
405
406TEST_F(JniCompilerTest, CompileAndRunStaticDoubleDoubleMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700407 SetUpForTest(true, "fooSDD", "(DD)D",
Elliott Hughesb264f082012-04-06 17:10:10 -0700408 reinterpret_cast<void*>(&Java_MyClassNatives_fooSDD));
Ian Rogers7a99c112011-09-07 12:48:27 -0700409
Elliott Hughesb264f082012-04-06 17:10:10 -0700410 EXPECT_EQ(0, gJava_MyClassNatives_fooSDD_calls);
Ian Rogers7a99c112011-09-07 12:48:27 -0700411 jdouble result = env_->CallStaticDoubleMethod(jklass_, jmethod_, 99.0, 10.0);
412 EXPECT_EQ(99.0 - 10.0, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700413 EXPECT_EQ(1, gJava_MyClassNatives_fooSDD_calls);
Ian Rogers7a99c112011-09-07 12:48:27 -0700414 jdouble a = 3.14159265358979323846;
415 jdouble b = 0.69314718055994530942;
416 result = env_->CallStaticDoubleMethod(jklass_, jmethod_, a, b);
417 EXPECT_EQ(a - b, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700418 EXPECT_EQ(2, gJava_MyClassNatives_fooSDD_calls);
Ian Rogers7a99c112011-09-07 12:48:27 -0700419}
420
Elliott Hughesb264f082012-04-06 17:10:10 -0700421int gJava_MyClassNatives_fooSIOO_calls = 0;
422jobject Java_MyClassNatives_fooSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700423 jobject z) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700424 // 3 = klass + y + z
425 EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
426 {
427 MutexLock mu(*GlobalSynchronization::thread_suspend_count_lock_);
428 EXPECT_EQ(kNative, Thread::Current()->GetState());
429 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700430 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
431 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700432 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Elliott Hughesb264f082012-04-06 17:10:10 -0700433 gJava_MyClassNatives_fooSIOO_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700434 switch (x) {
435 case 1:
436 return y;
437 case 2:
438 return z;
439 default:
440 return klass;
441 }
442}
443
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700444
445TEST_F(JniCompilerTest, CompileAndRunStaticIntObjectObjectMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700446 SetUpForTest(true, "fooSIOO",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700447 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700448 reinterpret_cast<void*>(&Java_MyClassNatives_fooSIOO));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700449
Elliott Hughesb264f082012-04-06 17:10:10 -0700450 EXPECT_EQ(0, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700451 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
452 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700453 EXPECT_EQ(1, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700454
455 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
456 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700457 EXPECT_EQ(2, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700458 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
459 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700460 EXPECT_EQ(3, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700461 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
462 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700463 EXPECT_EQ(4, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700464
465 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
466 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700467 EXPECT_EQ(5, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700468 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
469 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700470 EXPECT_EQ(6, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700471 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
472 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700473 EXPECT_EQ(7, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700474}
475
Elliott Hughesb264f082012-04-06 17:10:10 -0700476int gJava_MyClassNatives_fooSSIOO_calls = 0;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700477jobject Java_MyClassNatives_fooSSIOO(JNIEnv* env, jclass klass, jint x, jobject y, jobject z) {
478 // 3 = klass + y + z
479 EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
480 {
481 MutexLock mu(*GlobalSynchronization::thread_suspend_count_lock_);
482 EXPECT_EQ(kNative, Thread::Current()->GetState());
483 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700484 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
485 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700486 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Elliott Hughesb264f082012-04-06 17:10:10 -0700487 gJava_MyClassNatives_fooSSIOO_calls++;
Ian Rogersdf20fe02011-07-20 20:34:16 -0700488 switch (x) {
489 case 1:
490 return y;
491 case 2:
492 return z;
493 default:
494 return klass;
495 }
496}
497
Ian Rogersdf20fe02011-07-20 20:34:16 -0700498TEST_F(JniCompilerTest, CompileAndRunStaticSynchronizedIntObjectObjectMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700499 SetUpForTest(true, "fooSSIOO",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700500 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700501 reinterpret_cast<void*>(&Java_MyClassNatives_fooSSIOO));
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700502
Elliott Hughesb264f082012-04-06 17:10:10 -0700503 EXPECT_EQ(0, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700504 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
505 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700506 EXPECT_EQ(1, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700507
508 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
509 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700510 EXPECT_EQ(2, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700511 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
512 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700513 EXPECT_EQ(3, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700514 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
515 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700516 EXPECT_EQ(4, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700517
518 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
519 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700520 EXPECT_EQ(5, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700521 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
522 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700523 EXPECT_EQ(6, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700524 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
525 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700526 EXPECT_EQ(7, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogersdf20fe02011-07-20 20:34:16 -0700527}
528
Elliott Hughesb264f082012-04-06 17:10:10 -0700529void Java_MyClassNatives_throwException(JNIEnv* env, jobject) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700530 jclass c = env->FindClass("java/lang/RuntimeException");
531 env->ThrowNew(c, "hello");
532}
Ian Rogers45a76cb2011-07-21 22:00:15 -0700533
Elliott Hughesa2501992011-08-26 19:39:54 -0700534TEST_F(JniCompilerTest, ExceptionHandling) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700535 {
536 ASSERT_FALSE(runtime_->IsStarted());
537 ScopedObjectAccess soa(Thread::Current());
538 class_loader_ = LoadDex("MyClassNatives");
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700539
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700540 // all compilation needs to happen before Runtime::Start
541 CompileForTest(class_loader_, false, "foo", "()V");
542 CompileForTest(class_loader_, false, "throwException", "()V");
543 CompileForTest(class_loader_, false, "foo", "()V");
544 }
545 // Start runtime to avoid re-initialization in SetupForTest.
546 Thread::Current()->TransitionFromSuspendedToRunnable();
547 runtime_->Start();
Brian Carlstrom25c33252011-09-18 15:58:35 -0700548
Elliott Hughesb264f082012-04-06 17:10:10 -0700549 gJava_MyClassNatives_foo_calls = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700550
Ian Rogers67375ac2011-09-14 00:55:44 -0700551 // Check a single call of a JNI method is ok
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700552 SetUpForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClassNatives_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700553 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700554 EXPECT_EQ(1, gJava_MyClassNatives_foo_calls);
Ian Rogers67375ac2011-09-14 00:55:44 -0700555 EXPECT_FALSE(Thread::Current()->IsExceptionPending());
Elliott Hughesa2501992011-08-26 19:39:54 -0700556
Ian Rogers67375ac2011-09-14 00:55:44 -0700557 // Get class for exception we expect to be thrown
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700558 ScopedLocalRef<jclass> jlre(env_, env_->FindClass("java/lang/RuntimeException"));
559 SetUpForTest(false, "throwException", "()V",
Elliott Hughesb264f082012-04-06 17:10:10 -0700560 reinterpret_cast<void*>(&Java_MyClassNatives_throwException));
561 // Call Java_MyClassNatives_throwException (JNI method that throws exception)
Elliott Hughesa2501992011-08-26 19:39:54 -0700562 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700563 EXPECT_EQ(1, gJava_MyClassNatives_foo_calls);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700564 EXPECT_TRUE(env_->ExceptionCheck() == JNI_TRUE);
565 ScopedLocalRef<jthrowable> exception(env_, env_->ExceptionOccurred());
566 env_->ExceptionClear();
567 EXPECT_TRUE(env_->IsInstanceOf(exception.get(), jlre.get()));
Elliott Hughesa2501992011-08-26 19:39:54 -0700568
Ian Rogers67375ac2011-09-14 00:55:44 -0700569 // Check a single call of a JNI method is ok
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700570 SetUpForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClassNatives_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700571 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700572 EXPECT_EQ(2, gJava_MyClassNatives_foo_calls);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700573}
574
Elliott Hughesb264f082012-04-06 17:10:10 -0700575jint Java_MyClassNatives_nativeUpCall(JNIEnv* env, jobject thisObj, jint i) {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700576 if (i <= 0) {
Ian Rogersaaa20802011-09-11 21:47:37 -0700577 // We want to check raw Object*/Array* below
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700578 ScopedObjectAccess soa(env);
Ian Rogersaaa20802011-09-11 21:47:37 -0700579
580 // Build stack trace
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700581 jobject internal = Thread::Current()->CreateInternalStackTrace(soa);
Elliott Hughes01158d72011-09-19 19:47:10 -0700582 jobjectArray ste_array = Thread::InternalStackTraceToStackTraceElementArray(env, internal);
Ian Rogersaaa20802011-09-11 21:47:37 -0700583 ObjectArray<StackTraceElement>* trace_array =
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700584 soa.Decode<ObjectArray<StackTraceElement>*>(ste_array);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700585 EXPECT_TRUE(trace_array != NULL);
586 EXPECT_EQ(11, trace_array->GetLength());
587
Ian Rogersaaa20802011-09-11 21:47:37 -0700588 // Check stack trace entries have expected values
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700589 for (int32_t i = 0; i < trace_array->GetLength(); ++i) {
590 EXPECT_EQ(-2, trace_array->Get(i)->GetLineNumber());
Ian Rogersaaa20802011-09-11 21:47:37 -0700591 StackTraceElement* ste = trace_array->Get(i);
592 EXPECT_STREQ("MyClassNatives.java", ste->GetFileName()->ToModifiedUtf8().c_str());
Elliott Hughesb264f082012-04-06 17:10:10 -0700593 EXPECT_STREQ("MyClassNatives", ste->GetDeclaringClass()->ToModifiedUtf8().c_str());
Ian Rogersaaa20802011-09-11 21:47:37 -0700594 EXPECT_STREQ("fooI", ste->GetMethodName()->ToModifiedUtf8().c_str());
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700595 }
Ian Rogersaaa20802011-09-11 21:47:37 -0700596
597 // end recursion
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700598 return 0;
599 } else {
Elliott Hughesb264f082012-04-06 17:10:10 -0700600 jclass jklass = env->FindClass("MyClassNatives");
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700601 EXPECT_TRUE(jklass != NULL);
602 jmethodID jmethod = env->GetMethodID(jklass, "fooI", "(I)I");
603 EXPECT_TRUE(jmethod != NULL);
604
Ian Rogersaaa20802011-09-11 21:47:37 -0700605 // Recurse with i - 1
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700606 jint result = env->CallNonvirtualIntMethod(thisObj, jklass, jmethod, i - 1);
Ian Rogersaaa20802011-09-11 21:47:37 -0700607
608 // Return sum of all depths
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700609 return i + result;
610 }
611}
612
613TEST_F(JniCompilerTest, NativeStackTraceElement) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700614 SetUpForTest(false, "fooI", "(I)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700615 reinterpret_cast<void*>(&Java_MyClassNatives_nativeUpCall));
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700616 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 10);
Ian Rogersaaa20802011-09-11 21:47:37 -0700617 EXPECT_EQ(10+9+8+7+6+5+4+3+2+1, result);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700618}
619
Elliott Hughesb264f082012-04-06 17:10:10 -0700620jobject Java_MyClassNatives_fooO(JNIEnv* env, jobject, jobject x) {
Shih-wei Liao558788e2011-09-01 02:39:11 -0700621 return env->NewGlobalRef(x);
622}
623
Ian Rogersb9231c82011-09-05 22:13:19 -0700624TEST_F(JniCompilerTest, ReturnGlobalRef) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700625 SetUpForTest(false, "fooO", "(Ljava/lang/Object;)Ljava/lang/Object;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700626 reinterpret_cast<void*>(&Java_MyClassNatives_fooO));
Shih-wei Liao558788e2011-09-01 02:39:11 -0700627 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, jobj_);
628 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(result));
629 EXPECT_TRUE(env_->IsSameObject(result, jobj_));
630}
631
Ian Rogersdc51b792011-09-22 20:41:37 -0700632jint local_ref_test(JNIEnv* env, jobject thisObj, jint x) {
633 // Add 10 local references
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700634 ScopedObjectAccess soa(env);
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700635 for (int i = 0; i < 10; i++) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700636 soa.AddLocalReference<jobject>(soa.Decode<Object*>(thisObj));
Ian Rogersdc51b792011-09-22 20:41:37 -0700637 }
638 return x+1;
639}
640
641TEST_F(JniCompilerTest, LocalReferenceTableClearingTest) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700642 SetUpForTest(false, "fooI", "(I)I", reinterpret_cast<void*>(&local_ref_test));
Ian Rogersdc51b792011-09-22 20:41:37 -0700643 // 1000 invocations of a method that adds 10 local references
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700644 for (int i = 0; i < 1000; i++) {
Ian Rogersdc51b792011-09-22 20:41:37 -0700645 jint result = env_->CallIntMethod(jobj_, jmethod_, i);
646 EXPECT_TRUE(result == i + 1);
647 }
648}
649
Ian Rogersb9231c82011-09-05 22:13:19 -0700650void my_arraycopy(JNIEnv* env, jclass klass, jobject src, jint src_pos, jobject dst, jint dst_pos, jint length) {
651 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, klass));
652 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, dst));
Ian Rogers82f3e092011-09-05 22:54:45 -0700653 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, src));
Ian Rogersb9231c82011-09-05 22:13:19 -0700654 EXPECT_EQ(1234, src_pos);
655 EXPECT_EQ(5678, dst_pos);
656 EXPECT_EQ(9876, length);
657}
658
659TEST_F(JniCompilerTest, JavaLangSystemArrayCopy) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700660 SetUpForTest(true, "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V",
Ian Rogersb9231c82011-09-05 22:13:19 -0700661 reinterpret_cast<void*>(&my_arraycopy));
Ian Rogers82f3e092011-09-05 22:54:45 -0700662 env_->CallStaticVoidMethod(jklass_, jmethod_, jobj_, 1234, jklass_, 5678, 9876);
Ian Rogersb9231c82011-09-05 22:13:19 -0700663}
664
Ian Rogers67375ac2011-09-14 00:55:44 -0700665jboolean my_casi(JNIEnv* env, jobject unsafe, jobject obj, jlong offset, jint expected, jint newval) {
666 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, unsafe));
667 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, obj));
668 EXPECT_EQ(0x12345678ABCDEF88ll, offset);
669 EXPECT_EQ(static_cast<jint>(0xCAFEF00D), expected);
670 EXPECT_EQ(static_cast<jint>(0xEBADF00D), newval);
671 return JNI_TRUE;
672}
673
674TEST_F(JniCompilerTest, CompareAndSwapInt) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700675 SetUpForTest(false, "compareAndSwapInt", "(Ljava/lang/Object;JII)Z",
Ian Rogers67375ac2011-09-14 00:55:44 -0700676 reinterpret_cast<void*>(&my_casi));
677 jboolean result = env_->CallBooleanMethod(jobj_, jmethod_, jobj_, 0x12345678ABCDEF88ll, 0xCAFEF00D, 0xEBADF00D);
678 EXPECT_EQ(result, JNI_TRUE);
679}
680
Ian Rogersc7792842012-03-03 15:36:20 -0800681jint my_gettext(JNIEnv* env, jclass klass, jlong val1, jobject obj1, jlong val2, jobject obj2) {
682 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
683 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, obj1));
684 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, obj2));
685 EXPECT_EQ(0x12345678ABCDEF88ll, val1);
686 EXPECT_EQ(0x7FEDCBA987654321ll, val2);
687 return 42;
688}
689
690TEST_F(JniCompilerTest, GetText) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700691 SetUpForTest(true, "getText", "(JLjava/lang/Object;JLjava/lang/Object;)I",
Ian Rogersc7792842012-03-03 15:36:20 -0800692 reinterpret_cast<void*>(&my_gettext));
693 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 0x12345678ABCDEF88ll, jobj_,
694 0x7FEDCBA987654321ll, jobj_);
695 EXPECT_EQ(result, 42);
696}
697
Elliott Hughesb264f082012-04-06 17:10:10 -0700698// This should return jclass, but we're imitating a bug pattern.
699jobject Java_MyClassNatives_instanceMethodThatShouldReturnClass(JNIEnv* env, jobject) {
700 return env->NewStringUTF("not a class!");
701}
702
703// This should return jclass, but we're imitating a bug pattern.
704jobject Java_MyClassNatives_staticMethodThatShouldReturnClass(JNIEnv* env, jclass) {
705 return env->NewStringUTF("not a class!");
706}
707
708TEST_F(JniCompilerTest, UpcallReturnTypeChecking_Instance) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700709 SetUpForTest(false, "instanceMethodThatShouldReturnClass", "()Ljava/lang/Class;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700710 reinterpret_cast<void*>(&Java_MyClassNatives_instanceMethodThatShouldReturnClass));
711
712 CheckJniAbortCatcher check_jni_abort_catcher;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700713 // TODO: check type of returns with portable JNI compiler.
714 // This native method is bad, and tries to return a jstring as a jclass.
715 env_->CallObjectMethod(jobj_, jmethod_);
716 check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.instanceMethodThatShouldReturnClass()");
717
718 // Here, we just call the method incorrectly; we should catch that too.
Elliott Hughesb264f082012-04-06 17:10:10 -0700719 env_->CallVoidMethod(jobj_, jmethod_);
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700720 check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.instanceMethodThatShouldReturnClass()");
721 env_->CallStaticVoidMethod(jklass_, jmethod_);
722 check_jni_abort_catcher.Check("calling non-static method java.lang.Class MyClassNatives.instanceMethodThatShouldReturnClass() with CallStaticVoidMethodV");
Elliott Hughesb264f082012-04-06 17:10:10 -0700723}
724
725TEST_F(JniCompilerTest, UpcallReturnTypeChecking_Static) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700726 SetUpForTest(true, "staticMethodThatShouldReturnClass", "()Ljava/lang/Class;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700727 reinterpret_cast<void*>(&Java_MyClassNatives_staticMethodThatShouldReturnClass));
728
729 CheckJniAbortCatcher check_jni_abort_catcher;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700730 // TODO: check type of returns with portable JNI compiler.
731 // This native method is bad, and tries to return a jstring as a jclass.
732 env_->CallStaticObjectMethod(jklass_, jmethod_);
733 check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.staticMethodThatShouldReturnClass()");
734
735 // Here, we just call the method incorrectly; we should catch that too.
736 env_->CallStaticVoidMethod(jklass_, jmethod_);
737 check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.staticMethodThatShouldReturnClass()");
Elliott Hughesb264f082012-04-06 17:10:10 -0700738 env_->CallVoidMethod(jobj_, jmethod_);
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700739 check_jni_abort_catcher.Check("calling static method java.lang.Class MyClassNatives.staticMethodThatShouldReturnClass() with CallVoidMethodV");
Elliott Hughesb264f082012-04-06 17:10:10 -0700740}
741
742// This should take jclass, but we're imitating a bug pattern.
743void Java_MyClassNatives_instanceMethodThatShouldTakeClass(JNIEnv*, jobject, jclass) {
744}
745
746// This should take jclass, but we're imitating a bug pattern.
747void Java_MyClassNatives_staticMethodThatShouldTakeClass(JNIEnv*, jclass, jclass) {
748}
749
750TEST_F(JniCompilerTest, UpcallArgumentTypeChecking_Instance) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700751 SetUpForTest(false, "instanceMethodThatShouldTakeClass", "(ILjava/lang/Class;)V",
Elliott Hughesb264f082012-04-06 17:10:10 -0700752 reinterpret_cast<void*>(&Java_MyClassNatives_instanceMethodThatShouldTakeClass));
753
754 CheckJniAbortCatcher check_jni_abort_catcher;
755 // We deliberately pass a bad second argument here.
756 env_->CallVoidMethod(jobj_, jmethod_, 123, env_->NewStringUTF("not a class!"));
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700757 check_jni_abort_catcher.Check("bad arguments passed to void MyClassNatives.instanceMethodThatShouldTakeClass(int, java.lang.Class)");
Elliott Hughesb264f082012-04-06 17:10:10 -0700758}
759
760TEST_F(JniCompilerTest, UpcallArgumentTypeChecking_Static) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700761 SetUpForTest(true, "staticMethodThatShouldTakeClass", "(ILjava/lang/Class;)V",
Elliott Hughesb264f082012-04-06 17:10:10 -0700762 reinterpret_cast<void*>(&Java_MyClassNatives_staticMethodThatShouldTakeClass));
763
764 CheckJniAbortCatcher check_jni_abort_catcher;
765 // We deliberately pass a bad second argument here.
766 env_->CallStaticVoidMethod(jklass_, jmethod_, 123, env_->NewStringUTF("not a class!"));
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700767 check_jni_abort_catcher.Check("bad arguments passed to void MyClassNatives.staticMethodThatShouldTakeClass(int, java.lang.Class)");
Elliott Hughesb264f082012-04-06 17:10:10 -0700768}
769
Ian Rogersb033c752011-07-20 12:22:35 -0700770} // namespace art