blob: 16976d499419e9db10b0d18ccf9f1604c68aab8c [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));
Mathieu Chartier66f19252012-09-18 08:57:04 -070047 AbstractMethod* method;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070048 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 }
Brian Carlstromfc7120c2012-08-27 13:43:25 -070053 ASSERT_TRUE(method != NULL) << method_name << " " << method_sig;
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);
Brian Carlstromfc7120c2012-08-27 13:43:25 -070058 ASSERT_TRUE(method->GetCode() != NULL) << method_name << " " << method_sig;
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 Carlstromfc7120c2012-08-27 13:43:25 -070077 ASSERT_TRUE(jklass_ != NULL) << method_name << " " << method_sig;
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 }
Brian Carlstromfc7120c2012-08-27 13:43:25 -070084 ASSERT_TRUE(jmethod_ != NULL) << method_name << " " << method_sig;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070085
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 } };
Brian Carlstromfc7120c2012-08-27 13:43:25 -070088 ASSERT_EQ(JNI_OK, env_->RegisterNatives(jklass_, methods, 1))
89 << method_name << " " << method_sig;
Ian Rogersbdb03912011-09-14 00:55:44 -070090 } else {
91 env_->UnregisterNatives(jklass_);
Shih-wei Liao31384c52011-09-06 15:27:45 -070092 }
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070093
94 jmethodID constructor = env_->GetMethodID(jklass_, "<init>", "()V");
95 jobj_ = env_->NewObject(jklass_, constructor);
Brian Carlstromfc7120c2012-08-27 13:43:25 -070096 ASSERT_TRUE(jobj_ != NULL) << method_name << " " << method_sig;
Ian Rogersb033c752011-07-20 12:22:35 -070097 }
98
Ian Rogerscdd1d2d2011-08-18 09:58:17 -070099 public:
100 static jclass jklass_;
101 static jobject jobj_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700102 static jobject class_loader_;
103
Elliott Hughesa21039c2012-06-21 12:09:25 -0700104
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700105 protected:
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700106 JNIEnv* env_;
107 jmethodID jmethod_;
Ian Rogersb033c752011-07-20 12:22:35 -0700108};
109
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700110jclass JniCompilerTest::jklass_;
111jobject JniCompilerTest::jobj_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700112jobject JniCompilerTest::class_loader_;
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700113
Elliott Hughesb264f082012-04-06 17:10:10 -0700114int gJava_MyClassNatives_foo_calls = 0;
115void Java_MyClassNatives_foo(JNIEnv* env, jobject thisObj) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700116 // 1 = thisObj
117 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700118 EXPECT_EQ(kNative, Thread::Current()->GetState());
119 Locks::mutator_lock_->AssertNotHeld(Thread::Current());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700120 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
121 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700122 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700123 gJava_MyClassNatives_foo_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700124}
125
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700126TEST_F(JniCompilerTest, CompileAndRunNoArgMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700127 SetUpForTest(false, "foo", "()V",
Elliott Hughesb264f082012-04-06 17:10:10 -0700128 reinterpret_cast<void*>(&Java_MyClassNatives_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700129
Elliott Hughesb264f082012-04-06 17:10:10 -0700130 EXPECT_EQ(0, gJava_MyClassNatives_foo_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700131 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700132 EXPECT_EQ(1, 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(2, gJava_MyClassNatives_foo_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700135}
136
Shih-wei Liao31384c52011-09-06 15:27:45 -0700137TEST_F(JniCompilerTest, CompileAndRunIntMethodThroughStub) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700138 SetUpForTest(false, "bar", "(I)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700139 NULL /* calling through stub will link with &Java_MyClassNatives_bar */);
Shih-wei Liao31384c52011-09-06 15:27:45 -0700140
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700141 ScopedObjectAccess soa(Thread::Current());
Shih-wei Liao31384c52011-09-06 15:27:45 -0700142 std::string reason;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700143 ASSERT_TRUE(
144 Runtime::Current()->GetJavaVM()->LoadNativeLibrary("", soa.Decode<ClassLoader*>(class_loader_),
145 reason)) << reason;
Shih-wei Liao31384c52011-09-06 15:27:45 -0700146
147 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 24);
148 EXPECT_EQ(25, result);
149}
150
Ian Rogers1cefdbd2012-02-29 09:34:50 -0800151TEST_F(JniCompilerTest, CompileAndRunStaticIntMethodThroughStub) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700152 SetUpForTest(true, "sbar", "(I)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700153 NULL /* calling through stub will link with &Java_MyClassNatives_sbar */);
Ian Rogers1cefdbd2012-02-29 09:34:50 -0800154
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700155 ScopedObjectAccess soa(Thread::Current());
Ian Rogers1cefdbd2012-02-29 09:34:50 -0800156 std::string reason;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700157 ASSERT_TRUE(
158 Runtime::Current()->GetJavaVM()->LoadNativeLibrary("", soa.Decode<ClassLoader*>(class_loader_),
159 reason)) << reason;
Ian Rogers1cefdbd2012-02-29 09:34:50 -0800160
161 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 42);
162 EXPECT_EQ(43, result);
163}
164
Elliott Hughesb264f082012-04-06 17:10:10 -0700165int gJava_MyClassNatives_fooI_calls = 0;
166jint Java_MyClassNatives_fooI(JNIEnv* env, jobject thisObj, jint x) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700167 // 1 = thisObj
168 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700169 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700170 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
171 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700172 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700173 gJava_MyClassNatives_fooI_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700174 return x;
175}
176
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700177TEST_F(JniCompilerTest, CompileAndRunIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700178 SetUpForTest(false, "fooI", "(I)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700179 reinterpret_cast<void*>(&Java_MyClassNatives_fooI));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700180
Elliott Hughesb264f082012-04-06 17:10:10 -0700181 EXPECT_EQ(0, gJava_MyClassNatives_fooI_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700182 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
183 EXPECT_EQ(42, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700184 EXPECT_EQ(1, gJava_MyClassNatives_fooI_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700185 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFED00D);
186 EXPECT_EQ(static_cast<jint>(0xCAFED00D), result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700187 EXPECT_EQ(2, gJava_MyClassNatives_fooI_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700188}
189
Elliott Hughesb264f082012-04-06 17:10:10 -0700190int gJava_MyClassNatives_fooII_calls = 0;
191jint Java_MyClassNatives_fooII(JNIEnv* env, jobject thisObj, jint x, jint y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700192 // 1 = thisObj
193 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700194 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700195 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
196 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700197 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700198 gJava_MyClassNatives_fooII_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700199 return x - y; // non-commutative operator
200}
201
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700202TEST_F(JniCompilerTest, CompileAndRunIntIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700203 SetUpForTest(false, "fooII", "(II)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700204 reinterpret_cast<void*>(&Java_MyClassNatives_fooII));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700205
Elliott Hughesb264f082012-04-06 17:10:10 -0700206 EXPECT_EQ(0, gJava_MyClassNatives_fooII_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700207 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 99, 10);
208 EXPECT_EQ(99 - 10, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700209 EXPECT_EQ(1, gJava_MyClassNatives_fooII_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700210 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFEBABE,
211 0xCAFED00D);
212 EXPECT_EQ(static_cast<jint>(0xCAFEBABE - 0xCAFED00D), result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700213 EXPECT_EQ(2, gJava_MyClassNatives_fooII_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700214}
215
Elliott Hughesb264f082012-04-06 17:10:10 -0700216int gJava_MyClassNatives_fooJJ_calls = 0;
217jlong Java_MyClassNatives_fooJJ(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700218 // 1 = thisObj
219 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700220 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogers9b269d22011-09-04 14:06:05 -0700221 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
222 EXPECT_TRUE(thisObj != NULL);
223 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700224 gJava_MyClassNatives_fooJJ_calls++;
Ian Rogers9b269d22011-09-04 14:06:05 -0700225 return x - y; // non-commutative operator
226}
227
228TEST_F(JniCompilerTest, CompileAndRunLongLongMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700229 SetUpForTest(false, "fooJJ", "(JJ)J",
Elliott Hughesb264f082012-04-06 17:10:10 -0700230 reinterpret_cast<void*>(&Java_MyClassNatives_fooJJ));
Ian Rogers9b269d22011-09-04 14:06:05 -0700231
Elliott Hughesb264f082012-04-06 17:10:10 -0700232 EXPECT_EQ(0, gJava_MyClassNatives_fooJJ_calls);
Ian Rogers9b269d22011-09-04 14:06:05 -0700233 jlong a = 0x1234567890ABCDEFll;
234 jlong b = 0xFEDCBA0987654321ll;
235 jlong result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, a, b);
236 EXPECT_EQ(a - b, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700237 EXPECT_EQ(1, gJava_MyClassNatives_fooJJ_calls);
Ian Rogers9b269d22011-09-04 14:06:05 -0700238 result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, b, a);
239 EXPECT_EQ(b - a, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700240 EXPECT_EQ(2, gJava_MyClassNatives_fooJJ_calls);
Ian Rogers9b269d22011-09-04 14:06:05 -0700241}
242
Elliott Hughesb264f082012-04-06 17:10:10 -0700243int gJava_MyClassNatives_fooDD_calls = 0;
244jdouble Java_MyClassNatives_fooDD(JNIEnv* env, jobject thisObj, jdouble x, jdouble y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700245 // 1 = thisObj
246 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700247 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700248 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
249 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700250 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700251 gJava_MyClassNatives_fooDD_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700252 return x - y; // non-commutative operator
253}
254
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700255TEST_F(JniCompilerTest, CompileAndRunDoubleDoubleMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700256 SetUpForTest(false, "fooDD", "(DD)D",
Elliott Hughesb264f082012-04-06 17:10:10 -0700257 reinterpret_cast<void*>(&Java_MyClassNatives_fooDD));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700258
Elliott Hughesb264f082012-04-06 17:10:10 -0700259 EXPECT_EQ(0, gJava_MyClassNatives_fooDD_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700260 jdouble result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_,
261 99.0, 10.0);
262 EXPECT_EQ(99.0 - 10.0, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700263 EXPECT_EQ(1, gJava_MyClassNatives_fooDD_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700264 jdouble a = 3.14159265358979323846;
265 jdouble b = 0.69314718055994530942;
266 result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_, a, b);
267 EXPECT_EQ(a - b, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700268 EXPECT_EQ(2, gJava_MyClassNatives_fooDD_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700269}
270
Elliott Hughes3e778f72012-05-21 15:29:52 -0700271int gJava_MyClassNatives_fooJJ_synchronized_calls = 0;
272jlong Java_MyClassNatives_fooJJ_synchronized(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700273 // 1 = thisObj
274 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700275 EXPECT_EQ(kNative, Thread::Current()->GetState());
Elliott Hughes3e778f72012-05-21 15:29:52 -0700276 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
277 EXPECT_TRUE(thisObj != NULL);
278 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
279 gJava_MyClassNatives_fooJJ_synchronized_calls++;
280 return x | y;
281}
282
283TEST_F(JniCompilerTest, CompileAndRun_fooJJ_synchronized) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700284 SetUpForTest(false, "fooJJ_synchronized", "(JJ)J",
Elliott Hughes3e778f72012-05-21 15:29:52 -0700285 reinterpret_cast<void*>(&Java_MyClassNatives_fooJJ_synchronized));
286
287 EXPECT_EQ(0, gJava_MyClassNatives_fooJJ_synchronized_calls);
288 jlong a = 0x1000000020000000ULL;
289 jlong b = 0x00ff000000aa0000ULL;
290 jlong result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, a, b);
291 EXPECT_EQ(a | b, result);
292 EXPECT_EQ(1, gJava_MyClassNatives_fooJJ_synchronized_calls);
293}
294
Elliott Hughesb264f082012-04-06 17:10:10 -0700295int gJava_MyClassNatives_fooIOO_calls = 0;
296jobject Java_MyClassNatives_fooIOO(JNIEnv* env, jobject thisObj, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700297 jobject z) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700298 // 3 = this + y + z
299 EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700300 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700301 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
302 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700303 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700304 gJava_MyClassNatives_fooIOO_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700305 switch (x) {
306 case 1:
307 return y;
308 case 2:
309 return z;
310 default:
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700311 return thisObj;
Ian Rogersb033c752011-07-20 12:22:35 -0700312 }
313}
314
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700315TEST_F(JniCompilerTest, CompileAndRunIntObjectObjectMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700316 SetUpForTest(false, "fooIOO",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700317 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700318 reinterpret_cast<void*>(&Java_MyClassNatives_fooIOO));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700319
Elliott Hughesb264f082012-04-06 17:10:10 -0700320 EXPECT_EQ(0, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700321 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, NULL);
322 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700323 EXPECT_EQ(1, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700324
325 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, jklass_);
326 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700327 EXPECT_EQ(2, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700328 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, NULL, jklass_);
329 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700330 EXPECT_EQ(3, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700331 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, NULL, jklass_);
332 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700333 EXPECT_EQ(4, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700334
335 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, jklass_, NULL);
336 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700337 EXPECT_EQ(5, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700338 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, jklass_, NULL);
339 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700340 EXPECT_EQ(6, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700341 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, jklass_, NULL);
342 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700343 EXPECT_EQ(7, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700344}
345
Elliott Hughesb264f082012-04-06 17:10:10 -0700346int gJava_MyClassNatives_fooSII_calls = 0;
347jint Java_MyClassNatives_fooSII(JNIEnv* env, jclass klass, jint x, jint y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700348 // 1 = klass
349 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700350 EXPECT_EQ(kNative, Thread::Current()->GetState());
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700351 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
352 EXPECT_TRUE(klass != NULL);
353 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Elliott Hughesb264f082012-04-06 17:10:10 -0700354 gJava_MyClassNatives_fooSII_calls++;
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700355 return x + y;
356}
357
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700358TEST_F(JniCompilerTest, CompileAndRunStaticIntIntMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700359 SetUpForTest(true, "fooSII", "(II)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700360 reinterpret_cast<void*>(&Java_MyClassNatives_fooSII));
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700361
Elliott Hughesb264f082012-04-06 17:10:10 -0700362 EXPECT_EQ(0, gJava_MyClassNatives_fooSII_calls);
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700363 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 20, 30);
364 EXPECT_EQ(50, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700365 EXPECT_EQ(1, gJava_MyClassNatives_fooSII_calls);
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700366}
367
Elliott Hughesb264f082012-04-06 17:10:10 -0700368int gJava_MyClassNatives_fooSDD_calls = 0;
369jdouble Java_MyClassNatives_fooSDD(JNIEnv* env, jclass klass, jdouble x, jdouble y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700370 // 1 = klass
371 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700372 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogers7a99c112011-09-07 12:48:27 -0700373 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
374 EXPECT_TRUE(klass != NULL);
375 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Elliott Hughesb264f082012-04-06 17:10:10 -0700376 gJava_MyClassNatives_fooSDD_calls++;
Ian Rogers7a99c112011-09-07 12:48:27 -0700377 return x - y; // non-commutative operator
378}
379
380TEST_F(JniCompilerTest, CompileAndRunStaticDoubleDoubleMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700381 SetUpForTest(true, "fooSDD", "(DD)D",
Elliott Hughesb264f082012-04-06 17:10:10 -0700382 reinterpret_cast<void*>(&Java_MyClassNatives_fooSDD));
Ian Rogers7a99c112011-09-07 12:48:27 -0700383
Elliott Hughesb264f082012-04-06 17:10:10 -0700384 EXPECT_EQ(0, gJava_MyClassNatives_fooSDD_calls);
Ian Rogers7a99c112011-09-07 12:48:27 -0700385 jdouble result = env_->CallStaticDoubleMethod(jklass_, jmethod_, 99.0, 10.0);
386 EXPECT_EQ(99.0 - 10.0, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700387 EXPECT_EQ(1, gJava_MyClassNatives_fooSDD_calls);
Ian Rogers7a99c112011-09-07 12:48:27 -0700388 jdouble a = 3.14159265358979323846;
389 jdouble b = 0.69314718055994530942;
390 result = env_->CallStaticDoubleMethod(jklass_, jmethod_, a, b);
391 EXPECT_EQ(a - b, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700392 EXPECT_EQ(2, gJava_MyClassNatives_fooSDD_calls);
Ian Rogers7a99c112011-09-07 12:48:27 -0700393}
394
Elliott Hughesb264f082012-04-06 17:10:10 -0700395int gJava_MyClassNatives_fooSIOO_calls = 0;
396jobject Java_MyClassNatives_fooSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700397 jobject z) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700398 // 3 = klass + y + z
399 EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700400 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700401 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
402 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700403 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Elliott Hughesb264f082012-04-06 17:10:10 -0700404 gJava_MyClassNatives_fooSIOO_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700405 switch (x) {
406 case 1:
407 return y;
408 case 2:
409 return z;
410 default:
411 return klass;
412 }
413}
414
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700415
416TEST_F(JniCompilerTest, CompileAndRunStaticIntObjectObjectMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700417 SetUpForTest(true, "fooSIOO",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700418 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700419 reinterpret_cast<void*>(&Java_MyClassNatives_fooSIOO));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700420
Elliott Hughesb264f082012-04-06 17:10:10 -0700421 EXPECT_EQ(0, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700422 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
423 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700424 EXPECT_EQ(1, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700425
426 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
427 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700428 EXPECT_EQ(2, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700429 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
430 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700431 EXPECT_EQ(3, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700432 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
433 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700434 EXPECT_EQ(4, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700435
436 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
437 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700438 EXPECT_EQ(5, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700439 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
440 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700441 EXPECT_EQ(6, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700442 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
443 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700444 EXPECT_EQ(7, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700445}
446
Elliott Hughesb264f082012-04-06 17:10:10 -0700447int gJava_MyClassNatives_fooSSIOO_calls = 0;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700448jobject Java_MyClassNatives_fooSSIOO(JNIEnv* env, jclass klass, jint x, jobject y, jobject z) {
449 // 3 = klass + y + z
450 EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700451 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700452 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
453 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700454 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Elliott Hughesb264f082012-04-06 17:10:10 -0700455 gJava_MyClassNatives_fooSSIOO_calls++;
Ian Rogersdf20fe02011-07-20 20:34:16 -0700456 switch (x) {
457 case 1:
458 return y;
459 case 2:
460 return z;
461 default:
462 return klass;
463 }
464}
465
Ian Rogersdf20fe02011-07-20 20:34:16 -0700466TEST_F(JniCompilerTest, CompileAndRunStaticSynchronizedIntObjectObjectMethod) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700467 SetUpForTest(true, "fooSSIOO",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700468 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700469 reinterpret_cast<void*>(&Java_MyClassNatives_fooSSIOO));
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700470
Elliott Hughesb264f082012-04-06 17:10:10 -0700471 EXPECT_EQ(0, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700472 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
473 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700474 EXPECT_EQ(1, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700475
476 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
477 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700478 EXPECT_EQ(2, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700479 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
480 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700481 EXPECT_EQ(3, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700482 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
483 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700484 EXPECT_EQ(4, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700485
486 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
487 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700488 EXPECT_EQ(5, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700489 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
490 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700491 EXPECT_EQ(6, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700492 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
493 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700494 EXPECT_EQ(7, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogersdf20fe02011-07-20 20:34:16 -0700495}
496
Elliott Hughesb264f082012-04-06 17:10:10 -0700497void Java_MyClassNatives_throwException(JNIEnv* env, jobject) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700498 jclass c = env->FindClass("java/lang/RuntimeException");
499 env->ThrowNew(c, "hello");
500}
Ian Rogers45a76cb2011-07-21 22:00:15 -0700501
Elliott Hughesa2501992011-08-26 19:39:54 -0700502TEST_F(JniCompilerTest, ExceptionHandling) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700503 {
504 ASSERT_FALSE(runtime_->IsStarted());
505 ScopedObjectAccess soa(Thread::Current());
506 class_loader_ = LoadDex("MyClassNatives");
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700507
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700508 // all compilation needs to happen before Runtime::Start
509 CompileForTest(class_loader_, false, "foo", "()V");
510 CompileForTest(class_loader_, false, "throwException", "()V");
511 CompileForTest(class_loader_, false, "foo", "()V");
512 }
513 // Start runtime to avoid re-initialization in SetupForTest.
514 Thread::Current()->TransitionFromSuspendedToRunnable();
515 runtime_->Start();
Brian Carlstrom25c33252011-09-18 15:58:35 -0700516
Elliott Hughesb264f082012-04-06 17:10:10 -0700517 gJava_MyClassNatives_foo_calls = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700518
Ian Rogers67375ac2011-09-14 00:55:44 -0700519 // Check a single call of a JNI method is ok
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700520 SetUpForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClassNatives_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700521 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700522 EXPECT_EQ(1, gJava_MyClassNatives_foo_calls);
Ian Rogers67375ac2011-09-14 00:55:44 -0700523 EXPECT_FALSE(Thread::Current()->IsExceptionPending());
Elliott Hughesa2501992011-08-26 19:39:54 -0700524
Ian Rogers67375ac2011-09-14 00:55:44 -0700525 // Get class for exception we expect to be thrown
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700526 ScopedLocalRef<jclass> jlre(env_, env_->FindClass("java/lang/RuntimeException"));
527 SetUpForTest(false, "throwException", "()V",
Elliott Hughesb264f082012-04-06 17:10:10 -0700528 reinterpret_cast<void*>(&Java_MyClassNatives_throwException));
529 // Call Java_MyClassNatives_throwException (JNI method that throws exception)
Elliott Hughesa2501992011-08-26 19:39:54 -0700530 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700531 EXPECT_EQ(1, gJava_MyClassNatives_foo_calls);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700532 EXPECT_TRUE(env_->ExceptionCheck() == JNI_TRUE);
533 ScopedLocalRef<jthrowable> exception(env_, env_->ExceptionOccurred());
534 env_->ExceptionClear();
535 EXPECT_TRUE(env_->IsInstanceOf(exception.get(), jlre.get()));
Elliott Hughesa2501992011-08-26 19:39:54 -0700536
Ian Rogers67375ac2011-09-14 00:55:44 -0700537 // Check a single call of a JNI method is ok
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700538 SetUpForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClassNatives_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700539 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700540 EXPECT_EQ(2, gJava_MyClassNatives_foo_calls);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700541}
542
Elliott Hughesb264f082012-04-06 17:10:10 -0700543jint Java_MyClassNatives_nativeUpCall(JNIEnv* env, jobject thisObj, jint i) {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700544 if (i <= 0) {
Ian Rogersaaa20802011-09-11 21:47:37 -0700545 // We want to check raw Object*/Array* below
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700546 ScopedObjectAccess soa(env);
Ian Rogersaaa20802011-09-11 21:47:37 -0700547
548 // Build stack trace
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700549 jobject internal = Thread::Current()->CreateInternalStackTrace(soa);
Elliott Hughes01158d72011-09-19 19:47:10 -0700550 jobjectArray ste_array = Thread::InternalStackTraceToStackTraceElementArray(env, internal);
Ian Rogersaaa20802011-09-11 21:47:37 -0700551 ObjectArray<StackTraceElement>* trace_array =
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700552 soa.Decode<ObjectArray<StackTraceElement>*>(ste_array);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700553 EXPECT_TRUE(trace_array != NULL);
554 EXPECT_EQ(11, trace_array->GetLength());
555
Ian Rogersaaa20802011-09-11 21:47:37 -0700556 // Check stack trace entries have expected values
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700557 for (int32_t i = 0; i < trace_array->GetLength(); ++i) {
558 EXPECT_EQ(-2, trace_array->Get(i)->GetLineNumber());
Ian Rogersaaa20802011-09-11 21:47:37 -0700559 StackTraceElement* ste = trace_array->Get(i);
560 EXPECT_STREQ("MyClassNatives.java", ste->GetFileName()->ToModifiedUtf8().c_str());
Elliott Hughesb264f082012-04-06 17:10:10 -0700561 EXPECT_STREQ("MyClassNatives", ste->GetDeclaringClass()->ToModifiedUtf8().c_str());
Ian Rogersaaa20802011-09-11 21:47:37 -0700562 EXPECT_STREQ("fooI", ste->GetMethodName()->ToModifiedUtf8().c_str());
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700563 }
Ian Rogersaaa20802011-09-11 21:47:37 -0700564
565 // end recursion
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700566 return 0;
567 } else {
Elliott Hughesb264f082012-04-06 17:10:10 -0700568 jclass jklass = env->FindClass("MyClassNatives");
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700569 EXPECT_TRUE(jklass != NULL);
570 jmethodID jmethod = env->GetMethodID(jklass, "fooI", "(I)I");
571 EXPECT_TRUE(jmethod != NULL);
572
Ian Rogersaaa20802011-09-11 21:47:37 -0700573 // Recurse with i - 1
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700574 jint result = env->CallNonvirtualIntMethod(thisObj, jklass, jmethod, i - 1);
Ian Rogersaaa20802011-09-11 21:47:37 -0700575
576 // Return sum of all depths
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700577 return i + result;
578 }
579}
580
581TEST_F(JniCompilerTest, NativeStackTraceElement) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700582 SetUpForTest(false, "fooI", "(I)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700583 reinterpret_cast<void*>(&Java_MyClassNatives_nativeUpCall));
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700584 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 10);
Ian Rogersaaa20802011-09-11 21:47:37 -0700585 EXPECT_EQ(10+9+8+7+6+5+4+3+2+1, result);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700586}
587
Elliott Hughesb264f082012-04-06 17:10:10 -0700588jobject Java_MyClassNatives_fooO(JNIEnv* env, jobject, jobject x) {
Shih-wei Liao558788e2011-09-01 02:39:11 -0700589 return env->NewGlobalRef(x);
590}
591
Ian Rogersb9231c82011-09-05 22:13:19 -0700592TEST_F(JniCompilerTest, ReturnGlobalRef) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700593 SetUpForTest(false, "fooO", "(Ljava/lang/Object;)Ljava/lang/Object;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700594 reinterpret_cast<void*>(&Java_MyClassNatives_fooO));
Shih-wei Liao558788e2011-09-01 02:39:11 -0700595 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, jobj_);
596 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(result));
597 EXPECT_TRUE(env_->IsSameObject(result, jobj_));
598}
599
Ian Rogersdc51b792011-09-22 20:41:37 -0700600jint local_ref_test(JNIEnv* env, jobject thisObj, jint x) {
601 // Add 10 local references
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700602 ScopedObjectAccess soa(env);
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700603 for (int i = 0; i < 10; i++) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700604 soa.AddLocalReference<jobject>(soa.Decode<Object*>(thisObj));
Ian Rogersdc51b792011-09-22 20:41:37 -0700605 }
606 return x+1;
607}
608
609TEST_F(JniCompilerTest, LocalReferenceTableClearingTest) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700610 SetUpForTest(false, "fooI", "(I)I", reinterpret_cast<void*>(&local_ref_test));
Ian Rogersdc51b792011-09-22 20:41:37 -0700611 // 1000 invocations of a method that adds 10 local references
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700612 for (int i = 0; i < 1000; i++) {
Ian Rogersdc51b792011-09-22 20:41:37 -0700613 jint result = env_->CallIntMethod(jobj_, jmethod_, i);
614 EXPECT_TRUE(result == i + 1);
615 }
616}
617
Ian Rogersb9231c82011-09-05 22:13:19 -0700618void my_arraycopy(JNIEnv* env, jclass klass, jobject src, jint src_pos, jobject dst, jint dst_pos, jint length) {
619 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, klass));
620 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, dst));
Ian Rogers82f3e092011-09-05 22:54:45 -0700621 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, src));
Ian Rogersb9231c82011-09-05 22:13:19 -0700622 EXPECT_EQ(1234, src_pos);
623 EXPECT_EQ(5678, dst_pos);
624 EXPECT_EQ(9876, length);
625}
626
627TEST_F(JniCompilerTest, JavaLangSystemArrayCopy) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700628 SetUpForTest(true, "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V",
Ian Rogersb9231c82011-09-05 22:13:19 -0700629 reinterpret_cast<void*>(&my_arraycopy));
Ian Rogers82f3e092011-09-05 22:54:45 -0700630 env_->CallStaticVoidMethod(jklass_, jmethod_, jobj_, 1234, jklass_, 5678, 9876);
Ian Rogersb9231c82011-09-05 22:13:19 -0700631}
632
Ian Rogers67375ac2011-09-14 00:55:44 -0700633jboolean my_casi(JNIEnv* env, jobject unsafe, jobject obj, jlong offset, jint expected, jint newval) {
634 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, unsafe));
635 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, obj));
636 EXPECT_EQ(0x12345678ABCDEF88ll, offset);
637 EXPECT_EQ(static_cast<jint>(0xCAFEF00D), expected);
638 EXPECT_EQ(static_cast<jint>(0xEBADF00D), newval);
639 return JNI_TRUE;
640}
641
642TEST_F(JniCompilerTest, CompareAndSwapInt) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700643 SetUpForTest(false, "compareAndSwapInt", "(Ljava/lang/Object;JII)Z",
Ian Rogers67375ac2011-09-14 00:55:44 -0700644 reinterpret_cast<void*>(&my_casi));
645 jboolean result = env_->CallBooleanMethod(jobj_, jmethod_, jobj_, 0x12345678ABCDEF88ll, 0xCAFEF00D, 0xEBADF00D);
646 EXPECT_EQ(result, JNI_TRUE);
647}
648
Ian Rogersc7792842012-03-03 15:36:20 -0800649jint my_gettext(JNIEnv* env, jclass klass, jlong val1, jobject obj1, jlong val2, jobject obj2) {
650 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
651 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, obj1));
652 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, obj2));
653 EXPECT_EQ(0x12345678ABCDEF88ll, val1);
654 EXPECT_EQ(0x7FEDCBA987654321ll, val2);
655 return 42;
656}
657
658TEST_F(JniCompilerTest, GetText) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700659 SetUpForTest(true, "getText", "(JLjava/lang/Object;JLjava/lang/Object;)I",
Ian Rogersc7792842012-03-03 15:36:20 -0800660 reinterpret_cast<void*>(&my_gettext));
661 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 0x12345678ABCDEF88ll, jobj_,
662 0x7FEDCBA987654321ll, jobj_);
663 EXPECT_EQ(result, 42);
664}
665
Brian Carlstromfc7120c2012-08-27 13:43:25 -0700666TEST_F(JniCompilerTest, GetSinkPropertiesNative) {
667 SetUpForTest(false, "getSinkPropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;", NULL);
668 // This space intentionally left blank. Just testing compilation succeeds.
669}
670
Elliott Hughesb264f082012-04-06 17:10:10 -0700671// This should return jclass, but we're imitating a bug pattern.
672jobject Java_MyClassNatives_instanceMethodThatShouldReturnClass(JNIEnv* env, jobject) {
673 return env->NewStringUTF("not a class!");
674}
675
676// This should return jclass, but we're imitating a bug pattern.
677jobject Java_MyClassNatives_staticMethodThatShouldReturnClass(JNIEnv* env, jclass) {
678 return env->NewStringUTF("not a class!");
679}
680
681TEST_F(JniCompilerTest, UpcallReturnTypeChecking_Instance) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700682 SetUpForTest(false, "instanceMethodThatShouldReturnClass", "()Ljava/lang/Class;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700683 reinterpret_cast<void*>(&Java_MyClassNatives_instanceMethodThatShouldReturnClass));
684
685 CheckJniAbortCatcher check_jni_abort_catcher;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700686 // TODO: check type of returns with portable JNI compiler.
687 // This native method is bad, and tries to return a jstring as a jclass.
688 env_->CallObjectMethod(jobj_, jmethod_);
689 check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.instanceMethodThatShouldReturnClass()");
690
691 // Here, we just call the method incorrectly; we should catch that too.
Elliott Hughesb264f082012-04-06 17:10:10 -0700692 env_->CallVoidMethod(jobj_, jmethod_);
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700693 check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.instanceMethodThatShouldReturnClass()");
694 env_->CallStaticVoidMethod(jklass_, jmethod_);
695 check_jni_abort_catcher.Check("calling non-static method java.lang.Class MyClassNatives.instanceMethodThatShouldReturnClass() with CallStaticVoidMethodV");
Elliott Hughesb264f082012-04-06 17:10:10 -0700696}
697
698TEST_F(JniCompilerTest, UpcallReturnTypeChecking_Static) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700699 SetUpForTest(true, "staticMethodThatShouldReturnClass", "()Ljava/lang/Class;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700700 reinterpret_cast<void*>(&Java_MyClassNatives_staticMethodThatShouldReturnClass));
701
702 CheckJniAbortCatcher check_jni_abort_catcher;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700703 // TODO: check type of returns with portable JNI compiler.
704 // This native method is bad, and tries to return a jstring as a jclass.
705 env_->CallStaticObjectMethod(jklass_, jmethod_);
706 check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.staticMethodThatShouldReturnClass()");
707
708 // Here, we just call the method incorrectly; we should catch that too.
709 env_->CallStaticVoidMethod(jklass_, jmethod_);
710 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 -0700711 env_->CallVoidMethod(jobj_, jmethod_);
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700712 check_jni_abort_catcher.Check("calling static method java.lang.Class MyClassNatives.staticMethodThatShouldReturnClass() with CallVoidMethodV");
Elliott Hughesb264f082012-04-06 17:10:10 -0700713}
714
715// This should take jclass, but we're imitating a bug pattern.
716void Java_MyClassNatives_instanceMethodThatShouldTakeClass(JNIEnv*, jobject, jclass) {
717}
718
719// This should take jclass, but we're imitating a bug pattern.
720void Java_MyClassNatives_staticMethodThatShouldTakeClass(JNIEnv*, jclass, jclass) {
721}
722
723TEST_F(JniCompilerTest, UpcallArgumentTypeChecking_Instance) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700724 SetUpForTest(false, "instanceMethodThatShouldTakeClass", "(ILjava/lang/Class;)V",
Elliott Hughesb264f082012-04-06 17:10:10 -0700725 reinterpret_cast<void*>(&Java_MyClassNatives_instanceMethodThatShouldTakeClass));
726
727 CheckJniAbortCatcher check_jni_abort_catcher;
728 // We deliberately pass a bad second argument here.
729 env_->CallVoidMethod(jobj_, jmethod_, 123, env_->NewStringUTF("not a class!"));
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700730 check_jni_abort_catcher.Check("bad arguments passed to void MyClassNatives.instanceMethodThatShouldTakeClass(int, java.lang.Class)");
Elliott Hughesb264f082012-04-06 17:10:10 -0700731}
732
733TEST_F(JniCompilerTest, UpcallArgumentTypeChecking_Static) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700734 SetUpForTest(true, "staticMethodThatShouldTakeClass", "(ILjava/lang/Class;)V",
Elliott Hughesb264f082012-04-06 17:10:10 -0700735 reinterpret_cast<void*>(&Java_MyClassNatives_staticMethodThatShouldTakeClass));
736
737 CheckJniAbortCatcher check_jni_abort_catcher;
738 // We deliberately pass a bad second argument here.
739 env_->CallStaticVoidMethod(jklass_, jmethod_, 123, env_->NewStringUTF("not a class!"));
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700740 check_jni_abort_catcher.Check("bad arguments passed to void MyClassNatives.staticMethodThatShouldTakeClass(int, java.lang.Class)");
Elliott Hughesb264f082012-04-06 17:10:10 -0700741}
742
Ian Rogersb033c752011-07-20 12:22:35 -0700743} // namespace art