blob: 4ed789817f3a3f146de250a5447c5f86c853584c [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"
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080024#include "mirror/class.h"
25#include "mirror/class_loader.h"
26#include "mirror/abstract_method-inl.h"
27#include "mirror/object_array-inl.h"
28#include "mirror/stack_trace_element.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070029#include "runtime.h"
Ian Rogers00f7d0e2012-07-19 15:28:27 -070030#include "ScopedLocalRef.h"
31#include "scoped_thread_state_change.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070032#include "thread.h"
Elliott Hughesa168c832012-06-12 15:34:20 -070033#include "UniquePtr.h"
Ian Rogersb033c752011-07-20 12:22:35 -070034
Elliott Hughesb264f082012-04-06 17:10:10 -070035extern "C" JNIEXPORT jint JNICALL Java_MyClassNatives_bar(JNIEnv*, jobject, jint count) {
Brian Carlstromb9cc1ca2012-01-27 00:57:42 -080036 return count + 1;
37}
38
Elliott Hughesb264f082012-04-06 17:10:10 -070039extern "C" JNIEXPORT jint JNICALL Java_MyClassNatives_sbar(JNIEnv*, jclass, jint count) {
Ian Rogers1cefdbd2012-02-29 09:34:50 -080040 return count + 1;
41}
42
Ian Rogersb033c752011-07-20 12:22:35 -070043namespace art {
44
Brian Carlstromf734cf52011-08-17 16:28:14 -070045class JniCompilerTest : public CommonTest {
Ian Rogersb033c752011-07-20 12:22:35 -070046 protected:
Ian Rogers00f7d0e2012-07-19 15:28:27 -070047 void CompileForTest(jobject class_loader, bool direct,
Brian Carlstrom40381fb2011-10-19 14:13:40 -070048 const char* method_name, const char* method_sig) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070049 ScopedObjectAccess soa(Thread::Current());
Brian Carlstrom25c33252011-09-18 15:58:35 -070050 // Compile the native method before starting the runtime
Ian Rogers2dd0e2c2013-01-24 12:42:14 -080051 mirror::Class* c = class_linker_->FindClass("LMyClassNatives;",
52 soa.Decode<mirror::ClassLoader*>(class_loader));
53 mirror::AbstractMethod* method;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070054 if (direct) {
buzbeec143c552011-08-20 17:38:58 -070055 method = c->FindDirectMethod(method_name, method_sig);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070056 } else {
buzbeec143c552011-08-20 17:38:58 -070057 method = c->FindVirtualMethod(method_name, method_sig);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070058 }
Brian Carlstromfc7120c2012-08-27 13:43:25 -070059 ASSERT_TRUE(method != NULL) << method_name << " " << method_sig;
Brian Carlstrom25c33252011-09-18 15:58:35 -070060 if (method->GetCode() != NULL) {
61 return;
62 }
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -070063 CompileMethod(method);
Brian Carlstromfc7120c2012-08-27 13:43:25 -070064 ASSERT_TRUE(method->GetCode() != NULL) << method_name << " " << method_sig;
Brian Carlstrom25c33252011-09-18 15:58:35 -070065 }
66
Ian Rogers00f7d0e2012-07-19 15:28:27 -070067 void SetUpForTest(bool direct, const char* method_name, const char* method_sig,
Brian Carlstrom25c33252011-09-18 15:58:35 -070068 void* native_fnptr) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070069 // Initialize class loader and compile method when runtime not started.
70 if (!runtime_->IsStarted()){
71 {
72 ScopedObjectAccess soa(Thread::Current());
73 class_loader_ = LoadDex("MyClassNatives");
74 }
75 CompileForTest(class_loader_, direct, method_name, method_sig);
76 // Start runtime.
77 Thread::Current()->TransitionFromSuspendedToRunnable();
Brian Carlstrom25c33252011-09-18 15:58:35 -070078 runtime_->Start();
79 }
Ian Rogers00f7d0e2012-07-19 15:28:27 -070080 // JNI operations after runtime start.
Brian Carlstrom25c33252011-09-18 15:58:35 -070081 env_ = Thread::Current()->GetJniEnv();
Elliott Hughesb264f082012-04-06 17:10:10 -070082 jklass_ = env_->FindClass("MyClassNatives");
Brian Carlstromfc7120c2012-08-27 13:43:25 -070083 ASSERT_TRUE(jklass_ != NULL) << method_name << " " << method_sig;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070084
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070085 if (direct) {
86 jmethod_ = env_->GetStaticMethodID(jklass_, method_name, method_sig);
87 } else {
88 jmethod_ = env_->GetMethodID(jklass_, method_name, method_sig);
89 }
Brian Carlstromfc7120c2012-08-27 13:43:25 -070090 ASSERT_TRUE(jmethod_ != NULL) << method_name << " " << method_sig;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070091
Ian Rogersbdb03912011-09-14 00:55:44 -070092 if (native_fnptr != NULL) {
Elliott Hughesb25c3f62012-03-26 16:35:06 -070093 JNINativeMethod methods[] = { { method_name, method_sig, native_fnptr } };
Brian Carlstromfc7120c2012-08-27 13:43:25 -070094 ASSERT_EQ(JNI_OK, env_->RegisterNatives(jklass_, methods, 1))
95 << method_name << " " << method_sig;
Ian Rogersbdb03912011-09-14 00:55:44 -070096 } else {
97 env_->UnregisterNatives(jklass_);
Shih-wei Liao31384c52011-09-06 15:27:45 -070098 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070099
100 jmethodID constructor = env_->GetMethodID(jklass_, "<init>", "()V");
101 jobj_ = env_->NewObject(jklass_, constructor);
Brian Carlstromfc7120c2012-08-27 13:43:25 -0700102 ASSERT_TRUE(jobj_ != NULL) << method_name << " " << method_sig;
Ian Rogersb033c752011-07-20 12:22:35 -0700103 }
104
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700105 public:
106 static jclass jklass_;
107 static jobject jobj_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700108 static jobject class_loader_;
109
Elliott Hughesa21039c2012-06-21 12:09:25 -0700110
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700111 protected:
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700112 JNIEnv* env_;
113 jmethodID jmethod_;
Ian Rogersb033c752011-07-20 12:22:35 -0700114};
115
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700116jclass JniCompilerTest::jklass_;
117jobject JniCompilerTest::jobj_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700118jobject JniCompilerTest::class_loader_;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700119
Elliott Hughesb264f082012-04-06 17:10:10 -0700120int gJava_MyClassNatives_foo_calls = 0;
121void Java_MyClassNatives_foo(JNIEnv* env, jobject thisObj) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700122 // 1 = thisObj
123 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700124 EXPECT_EQ(kNative, Thread::Current()->GetState());
125 Locks::mutator_lock_->AssertNotHeld(Thread::Current());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700126 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
127 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700128 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700129 gJava_MyClassNatives_foo_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700130}
131
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700132TEST_F(JniCompilerTest, CompileAndRunNoArgMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700133 SetUpForTest(false, "foo", "()V",
Elliott Hughesb264f082012-04-06 17:10:10 -0700134 reinterpret_cast<void*>(&Java_MyClassNatives_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700135
Elliott Hughesb264f082012-04-06 17:10:10 -0700136 EXPECT_EQ(0, gJava_MyClassNatives_foo_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700137 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700138 EXPECT_EQ(1, gJava_MyClassNatives_foo_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700139 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700140 EXPECT_EQ(2, gJava_MyClassNatives_foo_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700141}
142
Shih-wei Liao31384c52011-09-06 15:27:45 -0700143TEST_F(JniCompilerTest, CompileAndRunIntMethodThroughStub) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700144 SetUpForTest(false, "bar", "(I)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700145 NULL /* calling through stub will link with &Java_MyClassNatives_bar */);
Shih-wei Liao31384c52011-09-06 15:27:45 -0700146
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700147 ScopedObjectAccess soa(Thread::Current());
Shih-wei Liao31384c52011-09-06 15:27:45 -0700148 std::string reason;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700149 ASSERT_TRUE(
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800150 Runtime::Current()->GetJavaVM()->LoadNativeLibrary("", soa.Decode<mirror::ClassLoader*>(class_loader_),
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700151 reason)) << reason;
Shih-wei Liao31384c52011-09-06 15:27:45 -0700152
153 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 24);
154 EXPECT_EQ(25, result);
155}
156
Ian Rogers1cefdbd2012-02-29 09:34:50 -0800157TEST_F(JniCompilerTest, CompileAndRunStaticIntMethodThroughStub) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700158 SetUpForTest(true, "sbar", "(I)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700159 NULL /* calling through stub will link with &Java_MyClassNatives_sbar */);
Ian Rogers1cefdbd2012-02-29 09:34:50 -0800160
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700161 ScopedObjectAccess soa(Thread::Current());
Ian Rogers1cefdbd2012-02-29 09:34:50 -0800162 std::string reason;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700163 ASSERT_TRUE(
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800164 Runtime::Current()->GetJavaVM()->LoadNativeLibrary("", soa.Decode<mirror::ClassLoader*>(class_loader_),
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700165 reason)) << reason;
Ian Rogers1cefdbd2012-02-29 09:34:50 -0800166
167 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 42);
168 EXPECT_EQ(43, result);
169}
170
Elliott Hughesb264f082012-04-06 17:10:10 -0700171int gJava_MyClassNatives_fooI_calls = 0;
172jint Java_MyClassNatives_fooI(JNIEnv* env, jobject thisObj, jint x) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700173 // 1 = thisObj
174 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700175 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700176 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
177 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700178 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700179 gJava_MyClassNatives_fooI_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700180 return x;
181}
182
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700183TEST_F(JniCompilerTest, CompileAndRunIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700184 SetUpForTest(false, "fooI", "(I)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700185 reinterpret_cast<void*>(&Java_MyClassNatives_fooI));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700186
Elliott Hughesb264f082012-04-06 17:10:10 -0700187 EXPECT_EQ(0, gJava_MyClassNatives_fooI_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700188 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
189 EXPECT_EQ(42, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700190 EXPECT_EQ(1, gJava_MyClassNatives_fooI_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700191 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFED00D);
192 EXPECT_EQ(static_cast<jint>(0xCAFED00D), result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700193 EXPECT_EQ(2, gJava_MyClassNatives_fooI_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700194}
195
Elliott Hughesb264f082012-04-06 17:10:10 -0700196int gJava_MyClassNatives_fooII_calls = 0;
197jint Java_MyClassNatives_fooII(JNIEnv* env, jobject thisObj, jint x, jint y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700198 // 1 = thisObj
199 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700200 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700201 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
202 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700203 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700204 gJava_MyClassNatives_fooII_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700205 return x - y; // non-commutative operator
206}
207
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700208TEST_F(JniCompilerTest, CompileAndRunIntIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700209 SetUpForTest(false, "fooII", "(II)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700210 reinterpret_cast<void*>(&Java_MyClassNatives_fooII));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700211
Elliott Hughesb264f082012-04-06 17:10:10 -0700212 EXPECT_EQ(0, gJava_MyClassNatives_fooII_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700213 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 99, 10);
214 EXPECT_EQ(99 - 10, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700215 EXPECT_EQ(1, gJava_MyClassNatives_fooII_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700216 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFEBABE,
217 0xCAFED00D);
218 EXPECT_EQ(static_cast<jint>(0xCAFEBABE - 0xCAFED00D), result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700219 EXPECT_EQ(2, gJava_MyClassNatives_fooII_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700220}
221
Elliott Hughesb264f082012-04-06 17:10:10 -0700222int gJava_MyClassNatives_fooJJ_calls = 0;
223jlong Java_MyClassNatives_fooJJ(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700224 // 1 = thisObj
225 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700226 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogers9b269d22011-09-04 14:06:05 -0700227 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
228 EXPECT_TRUE(thisObj != NULL);
229 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700230 gJava_MyClassNatives_fooJJ_calls++;
Ian Rogers9b269d22011-09-04 14:06:05 -0700231 return x - y; // non-commutative operator
232}
233
234TEST_F(JniCompilerTest, CompileAndRunLongLongMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700235 SetUpForTest(false, "fooJJ", "(JJ)J",
Elliott Hughesb264f082012-04-06 17:10:10 -0700236 reinterpret_cast<void*>(&Java_MyClassNatives_fooJJ));
Ian Rogers9b269d22011-09-04 14:06:05 -0700237
Elliott Hughesb264f082012-04-06 17:10:10 -0700238 EXPECT_EQ(0, gJava_MyClassNatives_fooJJ_calls);
Ian Rogers9b269d22011-09-04 14:06:05 -0700239 jlong a = 0x1234567890ABCDEFll;
240 jlong b = 0xFEDCBA0987654321ll;
241 jlong result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, a, b);
242 EXPECT_EQ(a - b, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700243 EXPECT_EQ(1, gJava_MyClassNatives_fooJJ_calls);
Ian Rogers9b269d22011-09-04 14:06:05 -0700244 result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, b, a);
245 EXPECT_EQ(b - a, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700246 EXPECT_EQ(2, gJava_MyClassNatives_fooJJ_calls);
Ian Rogers9b269d22011-09-04 14:06:05 -0700247}
248
Elliott Hughesb264f082012-04-06 17:10:10 -0700249int gJava_MyClassNatives_fooDD_calls = 0;
250jdouble Java_MyClassNatives_fooDD(JNIEnv* env, jobject thisObj, jdouble x, jdouble y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700251 // 1 = thisObj
252 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700253 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700254 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
255 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700256 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700257 gJava_MyClassNatives_fooDD_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700258 return x - y; // non-commutative operator
259}
260
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700261TEST_F(JniCompilerTest, CompileAndRunDoubleDoubleMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700262 SetUpForTest(false, "fooDD", "(DD)D",
Elliott Hughesb264f082012-04-06 17:10:10 -0700263 reinterpret_cast<void*>(&Java_MyClassNatives_fooDD));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700264
Elliott Hughesb264f082012-04-06 17:10:10 -0700265 EXPECT_EQ(0, gJava_MyClassNatives_fooDD_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700266 jdouble result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_,
267 99.0, 10.0);
268 EXPECT_EQ(99.0 - 10.0, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700269 EXPECT_EQ(1, gJava_MyClassNatives_fooDD_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700270 jdouble a = 3.14159265358979323846;
271 jdouble b = 0.69314718055994530942;
272 result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_, a, b);
273 EXPECT_EQ(a - b, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700274 EXPECT_EQ(2, gJava_MyClassNatives_fooDD_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700275}
276
Elliott Hughes3e778f72012-05-21 15:29:52 -0700277int gJava_MyClassNatives_fooJJ_synchronized_calls = 0;
278jlong Java_MyClassNatives_fooJJ_synchronized(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700279 // 1 = thisObj
280 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700281 EXPECT_EQ(kNative, Thread::Current()->GetState());
Elliott Hughes3e778f72012-05-21 15:29:52 -0700282 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
283 EXPECT_TRUE(thisObj != NULL);
284 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
285 gJava_MyClassNatives_fooJJ_synchronized_calls++;
286 return x | y;
287}
288
289TEST_F(JniCompilerTest, CompileAndRun_fooJJ_synchronized) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700290 SetUpForTest(false, "fooJJ_synchronized", "(JJ)J",
Elliott Hughes3e778f72012-05-21 15:29:52 -0700291 reinterpret_cast<void*>(&Java_MyClassNatives_fooJJ_synchronized));
292
293 EXPECT_EQ(0, gJava_MyClassNatives_fooJJ_synchronized_calls);
294 jlong a = 0x1000000020000000ULL;
295 jlong b = 0x00ff000000aa0000ULL;
296 jlong result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, a, b);
297 EXPECT_EQ(a | b, result);
298 EXPECT_EQ(1, gJava_MyClassNatives_fooJJ_synchronized_calls);
299}
300
Elliott Hughesb264f082012-04-06 17:10:10 -0700301int gJava_MyClassNatives_fooIOO_calls = 0;
302jobject Java_MyClassNatives_fooIOO(JNIEnv* env, jobject thisObj, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700303 jobject z) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700304 // 3 = this + y + z
305 EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700306 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700307 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
308 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700309 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700310 gJava_MyClassNatives_fooIOO_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700311 switch (x) {
312 case 1:
313 return y;
314 case 2:
315 return z;
316 default:
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700317 return thisObj;
Ian Rogersb033c752011-07-20 12:22:35 -0700318 }
319}
320
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700321TEST_F(JniCompilerTest, CompileAndRunIntObjectObjectMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700322 SetUpForTest(false, "fooIOO",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700323 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700324 reinterpret_cast<void*>(&Java_MyClassNatives_fooIOO));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700325
Elliott Hughesb264f082012-04-06 17:10:10 -0700326 EXPECT_EQ(0, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700327 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, NULL);
328 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700329 EXPECT_EQ(1, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700330
331 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, jklass_);
332 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700333 EXPECT_EQ(2, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700334 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, NULL, jklass_);
335 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700336 EXPECT_EQ(3, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700337 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, NULL, jklass_);
338 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700339 EXPECT_EQ(4, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700340
341 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, jklass_, NULL);
342 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700343 EXPECT_EQ(5, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700344 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, jklass_, NULL);
345 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700346 EXPECT_EQ(6, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700347 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, jklass_, NULL);
348 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700349 EXPECT_EQ(7, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700350}
351
Elliott Hughesb264f082012-04-06 17:10:10 -0700352int gJava_MyClassNatives_fooSII_calls = 0;
353jint Java_MyClassNatives_fooSII(JNIEnv* env, jclass klass, jint x, jint y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700354 // 1 = klass
355 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700356 EXPECT_EQ(kNative, Thread::Current()->GetState());
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700357 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
358 EXPECT_TRUE(klass != NULL);
359 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Elliott Hughesb264f082012-04-06 17:10:10 -0700360 gJava_MyClassNatives_fooSII_calls++;
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700361 return x + y;
362}
363
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700364TEST_F(JniCompilerTest, CompileAndRunStaticIntIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700365 SetUpForTest(true, "fooSII", "(II)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700366 reinterpret_cast<void*>(&Java_MyClassNatives_fooSII));
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700367
Elliott Hughesb264f082012-04-06 17:10:10 -0700368 EXPECT_EQ(0, gJava_MyClassNatives_fooSII_calls);
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700369 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 20, 30);
370 EXPECT_EQ(50, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700371 EXPECT_EQ(1, gJava_MyClassNatives_fooSII_calls);
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700372}
373
Elliott Hughesb264f082012-04-06 17:10:10 -0700374int gJava_MyClassNatives_fooSDD_calls = 0;
375jdouble Java_MyClassNatives_fooSDD(JNIEnv* env, jclass klass, jdouble x, jdouble y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700376 // 1 = klass
377 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700378 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogers7a99c112011-09-07 12:48:27 -0700379 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
380 EXPECT_TRUE(klass != NULL);
381 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Elliott Hughesb264f082012-04-06 17:10:10 -0700382 gJava_MyClassNatives_fooSDD_calls++;
Ian Rogers7a99c112011-09-07 12:48:27 -0700383 return x - y; // non-commutative operator
384}
385
386TEST_F(JniCompilerTest, CompileAndRunStaticDoubleDoubleMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700387 SetUpForTest(true, "fooSDD", "(DD)D",
Elliott Hughesb264f082012-04-06 17:10:10 -0700388 reinterpret_cast<void*>(&Java_MyClassNatives_fooSDD));
Ian Rogers7a99c112011-09-07 12:48:27 -0700389
Elliott Hughesb264f082012-04-06 17:10:10 -0700390 EXPECT_EQ(0, gJava_MyClassNatives_fooSDD_calls);
Ian Rogers7a99c112011-09-07 12:48:27 -0700391 jdouble result = env_->CallStaticDoubleMethod(jklass_, jmethod_, 99.0, 10.0);
392 EXPECT_EQ(99.0 - 10.0, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700393 EXPECT_EQ(1, gJava_MyClassNatives_fooSDD_calls);
Ian Rogers7a99c112011-09-07 12:48:27 -0700394 jdouble a = 3.14159265358979323846;
395 jdouble b = 0.69314718055994530942;
396 result = env_->CallStaticDoubleMethod(jklass_, jmethod_, a, b);
397 EXPECT_EQ(a - b, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700398 EXPECT_EQ(2, gJava_MyClassNatives_fooSDD_calls);
Ian Rogers7a99c112011-09-07 12:48:27 -0700399}
400
Elliott Hughesb264f082012-04-06 17:10:10 -0700401int gJava_MyClassNatives_fooSIOO_calls = 0;
402jobject Java_MyClassNatives_fooSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700403 jobject z) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700404 // 3 = klass + y + z
405 EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700406 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700407 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
408 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700409 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Elliott Hughesb264f082012-04-06 17:10:10 -0700410 gJava_MyClassNatives_fooSIOO_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700411 switch (x) {
412 case 1:
413 return y;
414 case 2:
415 return z;
416 default:
417 return klass;
418 }
419}
420
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700421
422TEST_F(JniCompilerTest, CompileAndRunStaticIntObjectObjectMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700423 SetUpForTest(true, "fooSIOO",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700424 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700425 reinterpret_cast<void*>(&Java_MyClassNatives_fooSIOO));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700426
Elliott Hughesb264f082012-04-06 17:10:10 -0700427 EXPECT_EQ(0, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700428 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
429 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700430 EXPECT_EQ(1, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700431
432 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
433 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700434 EXPECT_EQ(2, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700435 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
436 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700437 EXPECT_EQ(3, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700438 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
439 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700440 EXPECT_EQ(4, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700441
442 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
443 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700444 EXPECT_EQ(5, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700445 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
446 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700447 EXPECT_EQ(6, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700448 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
449 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700450 EXPECT_EQ(7, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700451}
452
Elliott Hughesb264f082012-04-06 17:10:10 -0700453int gJava_MyClassNatives_fooSSIOO_calls = 0;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700454jobject Java_MyClassNatives_fooSSIOO(JNIEnv* env, jclass klass, jint x, jobject y, jobject z) {
455 // 3 = klass + y + z
456 EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700457 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700458 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
459 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700460 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Elliott Hughesb264f082012-04-06 17:10:10 -0700461 gJava_MyClassNatives_fooSSIOO_calls++;
Ian Rogersdf20fe02011-07-20 20:34:16 -0700462 switch (x) {
463 case 1:
464 return y;
465 case 2:
466 return z;
467 default:
468 return klass;
469 }
470}
471
Ian Rogersdf20fe02011-07-20 20:34:16 -0700472TEST_F(JniCompilerTest, CompileAndRunStaticSynchronizedIntObjectObjectMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700473 SetUpForTest(true, "fooSSIOO",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700474 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700475 reinterpret_cast<void*>(&Java_MyClassNatives_fooSSIOO));
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700476
Elliott Hughesb264f082012-04-06 17:10:10 -0700477 EXPECT_EQ(0, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700478 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
479 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700480 EXPECT_EQ(1, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700481
482 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
483 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700484 EXPECT_EQ(2, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700485 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
486 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700487 EXPECT_EQ(3, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700488 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
489 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700490 EXPECT_EQ(4, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700491
492 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
493 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700494 EXPECT_EQ(5, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700495 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
496 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700497 EXPECT_EQ(6, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700498 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
499 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700500 EXPECT_EQ(7, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogersdf20fe02011-07-20 20:34:16 -0700501}
502
Elliott Hughesb264f082012-04-06 17:10:10 -0700503void Java_MyClassNatives_throwException(JNIEnv* env, jobject) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700504 jclass c = env->FindClass("java/lang/RuntimeException");
505 env->ThrowNew(c, "hello");
506}
Ian Rogers45a76cb2011-07-21 22:00:15 -0700507
Elliott Hughesa2501992011-08-26 19:39:54 -0700508TEST_F(JniCompilerTest, ExceptionHandling) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700509 {
510 ASSERT_FALSE(runtime_->IsStarted());
511 ScopedObjectAccess soa(Thread::Current());
512 class_loader_ = LoadDex("MyClassNatives");
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700513
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700514 // all compilation needs to happen before Runtime::Start
515 CompileForTest(class_loader_, false, "foo", "()V");
516 CompileForTest(class_loader_, false, "throwException", "()V");
517 CompileForTest(class_loader_, false, "foo", "()V");
518 }
519 // Start runtime to avoid re-initialization in SetupForTest.
520 Thread::Current()->TransitionFromSuspendedToRunnable();
521 runtime_->Start();
Brian Carlstrom25c33252011-09-18 15:58:35 -0700522
Elliott Hughesb264f082012-04-06 17:10:10 -0700523 gJava_MyClassNatives_foo_calls = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700524
Ian Rogers67375ac2011-09-14 00:55:44 -0700525 // Check a single call of a JNI method is ok
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700526 SetUpForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClassNatives_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700527 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700528 EXPECT_EQ(1, gJava_MyClassNatives_foo_calls);
Ian Rogers67375ac2011-09-14 00:55:44 -0700529 EXPECT_FALSE(Thread::Current()->IsExceptionPending());
Elliott Hughesa2501992011-08-26 19:39:54 -0700530
Ian Rogers67375ac2011-09-14 00:55:44 -0700531 // Get class for exception we expect to be thrown
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700532 ScopedLocalRef<jclass> jlre(env_, env_->FindClass("java/lang/RuntimeException"));
533 SetUpForTest(false, "throwException", "()V",
Elliott Hughesb264f082012-04-06 17:10:10 -0700534 reinterpret_cast<void*>(&Java_MyClassNatives_throwException));
535 // Call Java_MyClassNatives_throwException (JNI method that throws exception)
Elliott Hughesa2501992011-08-26 19:39:54 -0700536 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700537 EXPECT_EQ(1, gJava_MyClassNatives_foo_calls);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700538 EXPECT_TRUE(env_->ExceptionCheck() == JNI_TRUE);
539 ScopedLocalRef<jthrowable> exception(env_, env_->ExceptionOccurred());
540 env_->ExceptionClear();
541 EXPECT_TRUE(env_->IsInstanceOf(exception.get(), jlre.get()));
Elliott Hughesa2501992011-08-26 19:39:54 -0700542
Ian Rogers67375ac2011-09-14 00:55:44 -0700543 // Check a single call of a JNI method is ok
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700544 SetUpForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClassNatives_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700545 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700546 EXPECT_EQ(2, gJava_MyClassNatives_foo_calls);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700547}
548
Elliott Hughesb264f082012-04-06 17:10:10 -0700549jint Java_MyClassNatives_nativeUpCall(JNIEnv* env, jobject thisObj, jint i) {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700550 if (i <= 0) {
Ian Rogersaaa20802011-09-11 21:47:37 -0700551 // We want to check raw Object*/Array* below
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700552 ScopedObjectAccess soa(env);
Ian Rogersaaa20802011-09-11 21:47:37 -0700553
554 // Build stack trace
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700555 jobject internal = Thread::Current()->CreateInternalStackTrace(soa);
Elliott Hughes01158d72011-09-19 19:47:10 -0700556 jobjectArray ste_array = Thread::InternalStackTraceToStackTraceElementArray(env, internal);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800557 mirror::ObjectArray<mirror::StackTraceElement>* trace_array =
558 soa.Decode<mirror::ObjectArray<mirror::StackTraceElement>*>(ste_array);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700559 EXPECT_TRUE(trace_array != NULL);
560 EXPECT_EQ(11, trace_array->GetLength());
561
Ian Rogersaaa20802011-09-11 21:47:37 -0700562 // Check stack trace entries have expected values
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700563 for (int32_t i = 0; i < trace_array->GetLength(); ++i) {
564 EXPECT_EQ(-2, trace_array->Get(i)->GetLineNumber());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800565 mirror::StackTraceElement* ste = trace_array->Get(i);
Ian Rogersaaa20802011-09-11 21:47:37 -0700566 EXPECT_STREQ("MyClassNatives.java", ste->GetFileName()->ToModifiedUtf8().c_str());
Elliott Hughesb264f082012-04-06 17:10:10 -0700567 EXPECT_STREQ("MyClassNatives", ste->GetDeclaringClass()->ToModifiedUtf8().c_str());
Ian Rogersaaa20802011-09-11 21:47:37 -0700568 EXPECT_STREQ("fooI", ste->GetMethodName()->ToModifiedUtf8().c_str());
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700569 }
Ian Rogersaaa20802011-09-11 21:47:37 -0700570
571 // end recursion
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700572 return 0;
573 } else {
Elliott Hughesb264f082012-04-06 17:10:10 -0700574 jclass jklass = env->FindClass("MyClassNatives");
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700575 EXPECT_TRUE(jklass != NULL);
576 jmethodID jmethod = env->GetMethodID(jklass, "fooI", "(I)I");
577 EXPECT_TRUE(jmethod != NULL);
578
Ian Rogersaaa20802011-09-11 21:47:37 -0700579 // Recurse with i - 1
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700580 jint result = env->CallNonvirtualIntMethod(thisObj, jklass, jmethod, i - 1);
Ian Rogersaaa20802011-09-11 21:47:37 -0700581
582 // Return sum of all depths
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700583 return i + result;
584 }
585}
586
587TEST_F(JniCompilerTest, NativeStackTraceElement) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700588 SetUpForTest(false, "fooI", "(I)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700589 reinterpret_cast<void*>(&Java_MyClassNatives_nativeUpCall));
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700590 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 10);
Ian Rogersaaa20802011-09-11 21:47:37 -0700591 EXPECT_EQ(10+9+8+7+6+5+4+3+2+1, result);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700592}
593
Elliott Hughesb264f082012-04-06 17:10:10 -0700594jobject Java_MyClassNatives_fooO(JNIEnv* env, jobject, jobject x) {
Shih-wei Liao558788e2011-09-01 02:39:11 -0700595 return env->NewGlobalRef(x);
596}
597
Ian Rogersb9231c82011-09-05 22:13:19 -0700598TEST_F(JniCompilerTest, ReturnGlobalRef) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700599 SetUpForTest(false, "fooO", "(Ljava/lang/Object;)Ljava/lang/Object;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700600 reinterpret_cast<void*>(&Java_MyClassNatives_fooO));
Shih-wei Liao558788e2011-09-01 02:39:11 -0700601 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, jobj_);
602 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(result));
603 EXPECT_TRUE(env_->IsSameObject(result, jobj_));
604}
605
Ian Rogersdc51b792011-09-22 20:41:37 -0700606jint local_ref_test(JNIEnv* env, jobject thisObj, jint x) {
607 // Add 10 local references
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700608 ScopedObjectAccess soa(env);
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700609 for (int i = 0; i < 10; i++) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800610 soa.AddLocalReference<jobject>(soa.Decode<mirror::Object*>(thisObj));
Ian Rogersdc51b792011-09-22 20:41:37 -0700611 }
612 return x+1;
613}
614
615TEST_F(JniCompilerTest, LocalReferenceTableClearingTest) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700616 SetUpForTest(false, "fooI", "(I)I", reinterpret_cast<void*>(&local_ref_test));
Ian Rogersdc51b792011-09-22 20:41:37 -0700617 // 1000 invocations of a method that adds 10 local references
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700618 for (int i = 0; i < 1000; i++) {
Ian Rogersdc51b792011-09-22 20:41:37 -0700619 jint result = env_->CallIntMethod(jobj_, jmethod_, i);
620 EXPECT_TRUE(result == i + 1);
621 }
622}
623
Ian Rogersb9231c82011-09-05 22:13:19 -0700624void my_arraycopy(JNIEnv* env, jclass klass, jobject src, jint src_pos, jobject dst, jint dst_pos, jint length) {
625 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, klass));
626 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, dst));
Ian Rogers82f3e092011-09-05 22:54:45 -0700627 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, src));
Ian Rogersb9231c82011-09-05 22:13:19 -0700628 EXPECT_EQ(1234, src_pos);
629 EXPECT_EQ(5678, dst_pos);
630 EXPECT_EQ(9876, length);
631}
632
633TEST_F(JniCompilerTest, JavaLangSystemArrayCopy) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700634 SetUpForTest(true, "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V",
Ian Rogersb9231c82011-09-05 22:13:19 -0700635 reinterpret_cast<void*>(&my_arraycopy));
Ian Rogers82f3e092011-09-05 22:54:45 -0700636 env_->CallStaticVoidMethod(jklass_, jmethod_, jobj_, 1234, jklass_, 5678, 9876);
Ian Rogersb9231c82011-09-05 22:13:19 -0700637}
638
Ian Rogers67375ac2011-09-14 00:55:44 -0700639jboolean my_casi(JNIEnv* env, jobject unsafe, jobject obj, jlong offset, jint expected, jint newval) {
640 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, unsafe));
641 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, obj));
642 EXPECT_EQ(0x12345678ABCDEF88ll, offset);
643 EXPECT_EQ(static_cast<jint>(0xCAFEF00D), expected);
644 EXPECT_EQ(static_cast<jint>(0xEBADF00D), newval);
645 return JNI_TRUE;
646}
647
648TEST_F(JniCompilerTest, CompareAndSwapInt) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700649 SetUpForTest(false, "compareAndSwapInt", "(Ljava/lang/Object;JII)Z",
Ian Rogers67375ac2011-09-14 00:55:44 -0700650 reinterpret_cast<void*>(&my_casi));
651 jboolean result = env_->CallBooleanMethod(jobj_, jmethod_, jobj_, 0x12345678ABCDEF88ll, 0xCAFEF00D, 0xEBADF00D);
652 EXPECT_EQ(result, JNI_TRUE);
653}
654
Ian Rogersc7792842012-03-03 15:36:20 -0800655jint my_gettext(JNIEnv* env, jclass klass, jlong val1, jobject obj1, jlong val2, jobject obj2) {
656 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
657 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, obj1));
658 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, obj2));
659 EXPECT_EQ(0x12345678ABCDEF88ll, val1);
660 EXPECT_EQ(0x7FEDCBA987654321ll, val2);
661 return 42;
662}
663
664TEST_F(JniCompilerTest, GetText) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700665 SetUpForTest(true, "getText", "(JLjava/lang/Object;JLjava/lang/Object;)I",
Ian Rogersc7792842012-03-03 15:36:20 -0800666 reinterpret_cast<void*>(&my_gettext));
667 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 0x12345678ABCDEF88ll, jobj_,
668 0x7FEDCBA987654321ll, jobj_);
669 EXPECT_EQ(result, 42);
670}
671
Brian Carlstromfc7120c2012-08-27 13:43:25 -0700672TEST_F(JniCompilerTest, GetSinkPropertiesNative) {
673 SetUpForTest(false, "getSinkPropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;", NULL);
674 // This space intentionally left blank. Just testing compilation succeeds.
675}
676
Elliott Hughesb264f082012-04-06 17:10:10 -0700677// This should return jclass, but we're imitating a bug pattern.
678jobject Java_MyClassNatives_instanceMethodThatShouldReturnClass(JNIEnv* env, jobject) {
679 return env->NewStringUTF("not a class!");
680}
681
682// This should return jclass, but we're imitating a bug pattern.
683jobject Java_MyClassNatives_staticMethodThatShouldReturnClass(JNIEnv* env, jclass) {
684 return env->NewStringUTF("not a class!");
685}
686
687TEST_F(JniCompilerTest, UpcallReturnTypeChecking_Instance) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700688 SetUpForTest(false, "instanceMethodThatShouldReturnClass", "()Ljava/lang/Class;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700689 reinterpret_cast<void*>(&Java_MyClassNatives_instanceMethodThatShouldReturnClass));
690
691 CheckJniAbortCatcher check_jni_abort_catcher;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700692 // TODO: check type of returns with portable JNI compiler.
693 // This native method is bad, and tries to return a jstring as a jclass.
694 env_->CallObjectMethod(jobj_, jmethod_);
695 check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.instanceMethodThatShouldReturnClass()");
696
697 // Here, we just call the method incorrectly; we should catch that too.
Elliott Hughesb264f082012-04-06 17:10:10 -0700698 env_->CallVoidMethod(jobj_, jmethod_);
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700699 check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.instanceMethodThatShouldReturnClass()");
700 env_->CallStaticVoidMethod(jklass_, jmethod_);
701 check_jni_abort_catcher.Check("calling non-static method java.lang.Class MyClassNatives.instanceMethodThatShouldReturnClass() with CallStaticVoidMethodV");
Elliott Hughesb264f082012-04-06 17:10:10 -0700702}
703
704TEST_F(JniCompilerTest, UpcallReturnTypeChecking_Static) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700705 SetUpForTest(true, "staticMethodThatShouldReturnClass", "()Ljava/lang/Class;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700706 reinterpret_cast<void*>(&Java_MyClassNatives_staticMethodThatShouldReturnClass));
707
708 CheckJniAbortCatcher check_jni_abort_catcher;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700709 // TODO: check type of returns with portable JNI compiler.
710 // This native method is bad, and tries to return a jstring as a jclass.
711 env_->CallStaticObjectMethod(jklass_, jmethod_);
712 check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.staticMethodThatShouldReturnClass()");
713
714 // Here, we just call the method incorrectly; we should catch that too.
715 env_->CallStaticVoidMethod(jklass_, jmethod_);
716 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 -0700717 env_->CallVoidMethod(jobj_, jmethod_);
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700718 check_jni_abort_catcher.Check("calling static method java.lang.Class MyClassNatives.staticMethodThatShouldReturnClass() with CallVoidMethodV");
Elliott Hughesb264f082012-04-06 17:10:10 -0700719}
720
721// This should take jclass, but we're imitating a bug pattern.
722void Java_MyClassNatives_instanceMethodThatShouldTakeClass(JNIEnv*, jobject, jclass) {
723}
724
725// This should take jclass, but we're imitating a bug pattern.
726void Java_MyClassNatives_staticMethodThatShouldTakeClass(JNIEnv*, jclass, jclass) {
727}
728
729TEST_F(JniCompilerTest, UpcallArgumentTypeChecking_Instance) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700730 SetUpForTest(false, "instanceMethodThatShouldTakeClass", "(ILjava/lang/Class;)V",
Elliott Hughesb264f082012-04-06 17:10:10 -0700731 reinterpret_cast<void*>(&Java_MyClassNatives_instanceMethodThatShouldTakeClass));
732
733 CheckJniAbortCatcher check_jni_abort_catcher;
734 // We deliberately pass a bad second argument here.
735 env_->CallVoidMethod(jobj_, jmethod_, 123, env_->NewStringUTF("not a class!"));
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700736 check_jni_abort_catcher.Check("bad arguments passed to void MyClassNatives.instanceMethodThatShouldTakeClass(int, java.lang.Class)");
Elliott Hughesb264f082012-04-06 17:10:10 -0700737}
738
739TEST_F(JniCompilerTest, UpcallArgumentTypeChecking_Static) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700740 SetUpForTest(true, "staticMethodThatShouldTakeClass", "(ILjava/lang/Class;)V",
Elliott Hughesb264f082012-04-06 17:10:10 -0700741 reinterpret_cast<void*>(&Java_MyClassNatives_staticMethodThatShouldTakeClass));
742
743 CheckJniAbortCatcher check_jni_abort_catcher;
744 // We deliberately pass a bad second argument here.
745 env_->CallStaticVoidMethod(jklass_, jmethod_, 123, env_->NewStringUTF("not a class!"));
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700746 check_jni_abort_catcher.Check("bad arguments passed to void MyClassNatives.staticMethodThatShouldTakeClass(int, java.lang.Class)");
Elliott Hughesb264f082012-04-06 17:10:10 -0700747}
748
Ian Rogersb033c752011-07-20 12:22:35 -0700749} // namespace art