blob: 5176752a9d57db3331388c0ab7362ce88dd0eb24 [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) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800133 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700134 SetUpForTest(false, "foo", "()V",
Elliott Hughesb264f082012-04-06 17:10:10 -0700135 reinterpret_cast<void*>(&Java_MyClassNatives_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700136
Elliott Hughesb264f082012-04-06 17:10:10 -0700137 EXPECT_EQ(0, gJava_MyClassNatives_foo_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700138 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700139 EXPECT_EQ(1, gJava_MyClassNatives_foo_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700140 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700141 EXPECT_EQ(2, gJava_MyClassNatives_foo_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700142}
143
Shih-wei Liao31384c52011-09-06 15:27:45 -0700144TEST_F(JniCompilerTest, CompileAndRunIntMethodThroughStub) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800145 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700146 SetUpForTest(false, "bar", "(I)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700147 NULL /* calling through stub will link with &Java_MyClassNatives_bar */);
Shih-wei Liao31384c52011-09-06 15:27:45 -0700148
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700149 ScopedObjectAccess soa(Thread::Current());
Shih-wei Liao31384c52011-09-06 15:27:45 -0700150 std::string reason;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700151 ASSERT_TRUE(
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800152 Runtime::Current()->GetJavaVM()->LoadNativeLibrary("", soa.Decode<mirror::ClassLoader*>(class_loader_),
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700153 reason)) << reason;
Shih-wei Liao31384c52011-09-06 15:27:45 -0700154
155 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 24);
156 EXPECT_EQ(25, result);
157}
158
Ian Rogers1cefdbd2012-02-29 09:34:50 -0800159TEST_F(JniCompilerTest, CompileAndRunStaticIntMethodThroughStub) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800160 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700161 SetUpForTest(true, "sbar", "(I)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700162 NULL /* calling through stub will link with &Java_MyClassNatives_sbar */);
Ian Rogers1cefdbd2012-02-29 09:34:50 -0800163
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700164 ScopedObjectAccess soa(Thread::Current());
Ian Rogers1cefdbd2012-02-29 09:34:50 -0800165 std::string reason;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700166 ASSERT_TRUE(
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800167 Runtime::Current()->GetJavaVM()->LoadNativeLibrary("", soa.Decode<mirror::ClassLoader*>(class_loader_),
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700168 reason)) << reason;
Ian Rogers1cefdbd2012-02-29 09:34:50 -0800169
170 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 42);
171 EXPECT_EQ(43, result);
172}
173
Elliott Hughesb264f082012-04-06 17:10:10 -0700174int gJava_MyClassNatives_fooI_calls = 0;
175jint Java_MyClassNatives_fooI(JNIEnv* env, jobject thisObj, jint x) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700176 // 1 = thisObj
177 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700178 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700179 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
180 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700181 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700182 gJava_MyClassNatives_fooI_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700183 return x;
184}
185
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700186TEST_F(JniCompilerTest, CompileAndRunIntMethod) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800187 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700188 SetUpForTest(false, "fooI", "(I)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700189 reinterpret_cast<void*>(&Java_MyClassNatives_fooI));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700190
Elliott Hughesb264f082012-04-06 17:10:10 -0700191 EXPECT_EQ(0, gJava_MyClassNatives_fooI_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700192 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 42);
193 EXPECT_EQ(42, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700194 EXPECT_EQ(1, gJava_MyClassNatives_fooI_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700195 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFED00D);
196 EXPECT_EQ(static_cast<jint>(0xCAFED00D), result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700197 EXPECT_EQ(2, gJava_MyClassNatives_fooI_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700198}
199
Elliott Hughesb264f082012-04-06 17:10:10 -0700200int gJava_MyClassNatives_fooII_calls = 0;
201jint Java_MyClassNatives_fooII(JNIEnv* env, jobject thisObj, jint x, jint y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700202 // 1 = thisObj
203 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700204 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700205 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
206 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700207 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700208 gJava_MyClassNatives_fooII_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700209 return x - y; // non-commutative operator
210}
211
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700212TEST_F(JniCompilerTest, CompileAndRunIntIntMethod) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800213 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700214 SetUpForTest(false, "fooII", "(II)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700215 reinterpret_cast<void*>(&Java_MyClassNatives_fooII));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700216
Elliott Hughesb264f082012-04-06 17:10:10 -0700217 EXPECT_EQ(0, gJava_MyClassNatives_fooII_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700218 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 99, 10);
219 EXPECT_EQ(99 - 10, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700220 EXPECT_EQ(1, gJava_MyClassNatives_fooII_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700221 result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 0xCAFEBABE,
222 0xCAFED00D);
223 EXPECT_EQ(static_cast<jint>(0xCAFEBABE - 0xCAFED00D), result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700224 EXPECT_EQ(2, gJava_MyClassNatives_fooII_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700225}
226
Elliott Hughesb264f082012-04-06 17:10:10 -0700227int gJava_MyClassNatives_fooJJ_calls = 0;
228jlong Java_MyClassNatives_fooJJ(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700229 // 1 = thisObj
230 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700231 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogers9b269d22011-09-04 14:06:05 -0700232 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
233 EXPECT_TRUE(thisObj != NULL);
234 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700235 gJava_MyClassNatives_fooJJ_calls++;
Ian Rogers9b269d22011-09-04 14:06:05 -0700236 return x - y; // non-commutative operator
237}
238
239TEST_F(JniCompilerTest, CompileAndRunLongLongMethod) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800240 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700241 SetUpForTest(false, "fooJJ", "(JJ)J",
Elliott Hughesb264f082012-04-06 17:10:10 -0700242 reinterpret_cast<void*>(&Java_MyClassNatives_fooJJ));
Ian Rogers9b269d22011-09-04 14:06:05 -0700243
Elliott Hughesb264f082012-04-06 17:10:10 -0700244 EXPECT_EQ(0, gJava_MyClassNatives_fooJJ_calls);
Ian Rogers9b269d22011-09-04 14:06:05 -0700245 jlong a = 0x1234567890ABCDEFll;
246 jlong b = 0xFEDCBA0987654321ll;
247 jlong result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, a, b);
248 EXPECT_EQ(a - b, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700249 EXPECT_EQ(1, gJava_MyClassNatives_fooJJ_calls);
Ian Rogers9b269d22011-09-04 14:06:05 -0700250 result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, b, a);
251 EXPECT_EQ(b - a, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700252 EXPECT_EQ(2, gJava_MyClassNatives_fooJJ_calls);
Ian Rogers9b269d22011-09-04 14:06:05 -0700253}
254
Elliott Hughesb264f082012-04-06 17:10:10 -0700255int gJava_MyClassNatives_fooDD_calls = 0;
256jdouble Java_MyClassNatives_fooDD(JNIEnv* env, jobject thisObj, jdouble x, jdouble y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700257 // 1 = thisObj
258 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700259 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700260 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
261 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700262 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700263 gJava_MyClassNatives_fooDD_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700264 return x - y; // non-commutative operator
265}
266
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700267TEST_F(JniCompilerTest, CompileAndRunDoubleDoubleMethod) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800268 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700269 SetUpForTest(false, "fooDD", "(DD)D",
Elliott Hughesb264f082012-04-06 17:10:10 -0700270 reinterpret_cast<void*>(&Java_MyClassNatives_fooDD));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700271
Elliott Hughesb264f082012-04-06 17:10:10 -0700272 EXPECT_EQ(0, gJava_MyClassNatives_fooDD_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700273 jdouble result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_,
274 99.0, 10.0);
275 EXPECT_EQ(99.0 - 10.0, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700276 EXPECT_EQ(1, gJava_MyClassNatives_fooDD_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700277 jdouble a = 3.14159265358979323846;
278 jdouble b = 0.69314718055994530942;
279 result = env_->CallNonvirtualDoubleMethod(jobj_, jklass_, jmethod_, a, b);
280 EXPECT_EQ(a - b, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700281 EXPECT_EQ(2, gJava_MyClassNatives_fooDD_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700282}
283
Elliott Hughes3e778f72012-05-21 15:29:52 -0700284int gJava_MyClassNatives_fooJJ_synchronized_calls = 0;
285jlong Java_MyClassNatives_fooJJ_synchronized(JNIEnv* env, jobject thisObj, jlong x, jlong y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700286 // 1 = thisObj
287 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700288 EXPECT_EQ(kNative, Thread::Current()->GetState());
Elliott Hughes3e778f72012-05-21 15:29:52 -0700289 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
290 EXPECT_TRUE(thisObj != NULL);
291 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
292 gJava_MyClassNatives_fooJJ_synchronized_calls++;
293 return x | y;
294}
295
296TEST_F(JniCompilerTest, CompileAndRun_fooJJ_synchronized) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800297 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700298 SetUpForTest(false, "fooJJ_synchronized", "(JJ)J",
Elliott Hughes3e778f72012-05-21 15:29:52 -0700299 reinterpret_cast<void*>(&Java_MyClassNatives_fooJJ_synchronized));
300
301 EXPECT_EQ(0, gJava_MyClassNatives_fooJJ_synchronized_calls);
302 jlong a = 0x1000000020000000ULL;
303 jlong b = 0x00ff000000aa0000ULL;
304 jlong result = env_->CallNonvirtualLongMethod(jobj_, jklass_, jmethod_, a, b);
305 EXPECT_EQ(a | b, result);
306 EXPECT_EQ(1, gJava_MyClassNatives_fooJJ_synchronized_calls);
307}
308
Elliott Hughesb264f082012-04-06 17:10:10 -0700309int gJava_MyClassNatives_fooIOO_calls = 0;
310jobject Java_MyClassNatives_fooIOO(JNIEnv* env, jobject thisObj, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700311 jobject z) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700312 // 3 = this + y + z
313 EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700314 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700315 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
316 EXPECT_TRUE(thisObj != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700317 EXPECT_TRUE(env->IsInstanceOf(thisObj, JniCompilerTest::jklass_));
Elliott Hughesb264f082012-04-06 17:10:10 -0700318 gJava_MyClassNatives_fooIOO_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700319 switch (x) {
320 case 1:
321 return y;
322 case 2:
323 return z;
324 default:
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700325 return thisObj;
Ian Rogersb033c752011-07-20 12:22:35 -0700326 }
327}
328
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700329TEST_F(JniCompilerTest, CompileAndRunIntObjectObjectMethod) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800330 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700331 SetUpForTest(false, "fooIOO",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700332 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700333 reinterpret_cast<void*>(&Java_MyClassNatives_fooIOO));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700334
Elliott Hughesb264f082012-04-06 17:10:10 -0700335 EXPECT_EQ(0, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700336 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, NULL);
337 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700338 EXPECT_EQ(1, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700339
340 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, NULL, jklass_);
341 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700342 EXPECT_EQ(2, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700343 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, NULL, jklass_);
344 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700345 EXPECT_EQ(3, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700346 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, NULL, jklass_);
347 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700348 EXPECT_EQ(4, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700349
350 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 0, jklass_, NULL);
351 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700352 EXPECT_EQ(5, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700353 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 1, jklass_, NULL);
354 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700355 EXPECT_EQ(6, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700356 result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, 2, jklass_, NULL);
357 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700358 EXPECT_EQ(7, gJava_MyClassNatives_fooIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700359}
360
Elliott Hughesb264f082012-04-06 17:10:10 -0700361int gJava_MyClassNatives_fooSII_calls = 0;
362jint Java_MyClassNatives_fooSII(JNIEnv* env, jclass klass, jint x, jint y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700363 // 1 = klass
364 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700365 EXPECT_EQ(kNative, Thread::Current()->GetState());
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700366 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
367 EXPECT_TRUE(klass != NULL);
368 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Elliott Hughesb264f082012-04-06 17:10:10 -0700369 gJava_MyClassNatives_fooSII_calls++;
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700370 return x + y;
371}
372
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700373TEST_F(JniCompilerTest, CompileAndRunStaticIntIntMethod) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800374 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700375 SetUpForTest(true, "fooSII", "(II)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700376 reinterpret_cast<void*>(&Java_MyClassNatives_fooSII));
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700377
Elliott Hughesb264f082012-04-06 17:10:10 -0700378 EXPECT_EQ(0, gJava_MyClassNatives_fooSII_calls);
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700379 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 20, 30);
380 EXPECT_EQ(50, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700381 EXPECT_EQ(1, gJava_MyClassNatives_fooSII_calls);
Shih-wei Liao82da44b2011-09-01 00:38:04 -0700382}
383
Elliott Hughesb264f082012-04-06 17:10:10 -0700384int gJava_MyClassNatives_fooSDD_calls = 0;
385jdouble Java_MyClassNatives_fooSDD(JNIEnv* env, jclass klass, jdouble x, jdouble y) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700386 // 1 = klass
387 EXPECT_EQ(1U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700388 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogers7a99c112011-09-07 12:48:27 -0700389 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
390 EXPECT_TRUE(klass != NULL);
391 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Elliott Hughesb264f082012-04-06 17:10:10 -0700392 gJava_MyClassNatives_fooSDD_calls++;
Ian Rogers7a99c112011-09-07 12:48:27 -0700393 return x - y; // non-commutative operator
394}
395
396TEST_F(JniCompilerTest, CompileAndRunStaticDoubleDoubleMethod) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800397 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700398 SetUpForTest(true, "fooSDD", "(DD)D",
Elliott Hughesb264f082012-04-06 17:10:10 -0700399 reinterpret_cast<void*>(&Java_MyClassNatives_fooSDD));
Ian Rogers7a99c112011-09-07 12:48:27 -0700400
Elliott Hughesb264f082012-04-06 17:10:10 -0700401 EXPECT_EQ(0, gJava_MyClassNatives_fooSDD_calls);
Ian Rogers7a99c112011-09-07 12:48:27 -0700402 jdouble result = env_->CallStaticDoubleMethod(jklass_, jmethod_, 99.0, 10.0);
403 EXPECT_EQ(99.0 - 10.0, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700404 EXPECT_EQ(1, gJava_MyClassNatives_fooSDD_calls);
Ian Rogers7a99c112011-09-07 12:48:27 -0700405 jdouble a = 3.14159265358979323846;
406 jdouble b = 0.69314718055994530942;
407 result = env_->CallStaticDoubleMethod(jklass_, jmethod_, a, b);
408 EXPECT_EQ(a - b, result);
Elliott Hughesb264f082012-04-06 17:10:10 -0700409 EXPECT_EQ(2, gJava_MyClassNatives_fooSDD_calls);
Ian Rogers7a99c112011-09-07 12:48:27 -0700410}
411
Elliott Hughesb264f082012-04-06 17:10:10 -0700412int gJava_MyClassNatives_fooSIOO_calls = 0;
413jobject Java_MyClassNatives_fooSIOO(JNIEnv* env, jclass klass, jint x, jobject y,
Ian Rogersb033c752011-07-20 12:22:35 -0700414 jobject z) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700415 // 3 = klass + y + z
416 EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700417 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700418 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
419 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700420 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Elliott Hughesb264f082012-04-06 17:10:10 -0700421 gJava_MyClassNatives_fooSIOO_calls++;
Ian Rogersb033c752011-07-20 12:22:35 -0700422 switch (x) {
423 case 1:
424 return y;
425 case 2:
426 return z;
427 default:
428 return klass;
429 }
430}
431
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700432
433TEST_F(JniCompilerTest, CompileAndRunStaticIntObjectObjectMethod) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800434 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700435 SetUpForTest(true, "fooSIOO",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700436 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700437 reinterpret_cast<void*>(&Java_MyClassNatives_fooSIOO));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700438
Elliott Hughesb264f082012-04-06 17:10:10 -0700439 EXPECT_EQ(0, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700440 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
441 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700442 EXPECT_EQ(1, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700443
444 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
445 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700446 EXPECT_EQ(2, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700447 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
448 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700449 EXPECT_EQ(3, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700450 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
451 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700452 EXPECT_EQ(4, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700453
454 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
455 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700456 EXPECT_EQ(5, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700457 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
458 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700459 EXPECT_EQ(6, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700460 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
461 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700462 EXPECT_EQ(7, gJava_MyClassNatives_fooSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700463}
464
Elliott Hughesb264f082012-04-06 17:10:10 -0700465int gJava_MyClassNatives_fooSSIOO_calls = 0;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700466jobject Java_MyClassNatives_fooSSIOO(JNIEnv* env, jclass klass, jint x, jobject y, jobject z) {
467 // 3 = klass + y + z
468 EXPECT_EQ(3U, Thread::Current()->NumStackReferences());
Ian Rogers50b35e22012-10-04 10:09:15 -0700469 EXPECT_EQ(kNative, Thread::Current()->GetState());
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700470 EXPECT_EQ(Thread::Current()->GetJniEnv(), env);
471 EXPECT_TRUE(klass != NULL);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700472 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
Elliott Hughesb264f082012-04-06 17:10:10 -0700473 gJava_MyClassNatives_fooSSIOO_calls++;
Ian Rogersdf20fe02011-07-20 20:34:16 -0700474 switch (x) {
475 case 1:
476 return y;
477 case 2:
478 return z;
479 default:
480 return klass;
481 }
482}
483
Ian Rogersdf20fe02011-07-20 20:34:16 -0700484TEST_F(JniCompilerTest, CompileAndRunStaticSynchronizedIntObjectObjectMethod) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800485 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700486 SetUpForTest(true, "fooSSIOO",
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700487 "(ILjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700488 reinterpret_cast<void*>(&Java_MyClassNatives_fooSSIOO));
Carl Shapiro419ec7b2011-08-03 14:48:33 -0700489
Elliott Hughesb264f082012-04-06 17:10:10 -0700490 EXPECT_EQ(0, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700491 jobject result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, NULL);
492 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700493 EXPECT_EQ(1, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700494
495 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, NULL, jobj_);
496 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700497 EXPECT_EQ(2, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700498 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, NULL, jobj_);
499 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700500 EXPECT_EQ(3, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700501 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, NULL, jobj_);
502 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700503 EXPECT_EQ(4, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700504
505 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 0, jobj_, NULL);
506 EXPECT_TRUE(env_->IsSameObject(jklass_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700507 EXPECT_EQ(5, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700508 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 1, jobj_, NULL);
509 EXPECT_TRUE(env_->IsSameObject(jobj_, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700510 EXPECT_EQ(6, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700511 result = env_->CallStaticObjectMethod(jklass_, jmethod_, 2, jobj_, NULL);
512 EXPECT_TRUE(env_->IsSameObject(NULL, result));
Elliott Hughesb264f082012-04-06 17:10:10 -0700513 EXPECT_EQ(7, gJava_MyClassNatives_fooSSIOO_calls);
Ian Rogersdf20fe02011-07-20 20:34:16 -0700514}
515
Elliott Hughesb264f082012-04-06 17:10:10 -0700516void Java_MyClassNatives_throwException(JNIEnv* env, jobject) {
Elliott Hughesa2501992011-08-26 19:39:54 -0700517 jclass c = env->FindClass("java/lang/RuntimeException");
518 env->ThrowNew(c, "hello");
519}
Ian Rogers45a76cb2011-07-21 22:00:15 -0700520
Elliott Hughesa2501992011-08-26 19:39:54 -0700521TEST_F(JniCompilerTest, ExceptionHandling) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800522 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700523 {
524 ASSERT_FALSE(runtime_->IsStarted());
525 ScopedObjectAccess soa(Thread::Current());
526 class_loader_ = LoadDex("MyClassNatives");
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700527
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700528 // all compilation needs to happen before Runtime::Start
529 CompileForTest(class_loader_, false, "foo", "()V");
530 CompileForTest(class_loader_, false, "throwException", "()V");
531 CompileForTest(class_loader_, false, "foo", "()V");
532 }
533 // Start runtime to avoid re-initialization in SetupForTest.
534 Thread::Current()->TransitionFromSuspendedToRunnable();
535 runtime_->Start();
Brian Carlstrom25c33252011-09-18 15:58:35 -0700536
Elliott Hughesb264f082012-04-06 17:10:10 -0700537 gJava_MyClassNatives_foo_calls = 0;
Elliott Hughesa2501992011-08-26 19:39:54 -0700538
Ian Rogers67375ac2011-09-14 00:55:44 -0700539 // Check a single call of a JNI method is ok
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700540 SetUpForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClassNatives_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700541 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700542 EXPECT_EQ(1, gJava_MyClassNatives_foo_calls);
Ian Rogers67375ac2011-09-14 00:55:44 -0700543 EXPECT_FALSE(Thread::Current()->IsExceptionPending());
Elliott Hughesa2501992011-08-26 19:39:54 -0700544
Ian Rogers67375ac2011-09-14 00:55:44 -0700545 // Get class for exception we expect to be thrown
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700546 ScopedLocalRef<jclass> jlre(env_, env_->FindClass("java/lang/RuntimeException"));
547 SetUpForTest(false, "throwException", "()V",
Elliott Hughesb264f082012-04-06 17:10:10 -0700548 reinterpret_cast<void*>(&Java_MyClassNatives_throwException));
549 // Call Java_MyClassNatives_throwException (JNI method that throws exception)
Elliott Hughesa2501992011-08-26 19:39:54 -0700550 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700551 EXPECT_EQ(1, gJava_MyClassNatives_foo_calls);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700552 EXPECT_TRUE(env_->ExceptionCheck() == JNI_TRUE);
553 ScopedLocalRef<jthrowable> exception(env_, env_->ExceptionOccurred());
554 env_->ExceptionClear();
555 EXPECT_TRUE(env_->IsInstanceOf(exception.get(), jlre.get()));
Elliott Hughesa2501992011-08-26 19:39:54 -0700556
Ian Rogers67375ac2011-09-14 00:55:44 -0700557 // Check a single call of a JNI method is ok
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700558 SetUpForTest(false, "foo", "()V", reinterpret_cast<void*>(&Java_MyClassNatives_foo));
Ian Rogerscdd1d2d2011-08-18 09:58:17 -0700559 env_->CallNonvirtualVoidMethod(jobj_, jklass_, jmethod_);
Elliott Hughesb264f082012-04-06 17:10:10 -0700560 EXPECT_EQ(2, gJava_MyClassNatives_foo_calls);
Ian Rogers45a76cb2011-07-21 22:00:15 -0700561}
562
Elliott Hughesb264f082012-04-06 17:10:10 -0700563jint Java_MyClassNatives_nativeUpCall(JNIEnv* env, jobject thisObj, jint i) {
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700564 if (i <= 0) {
Ian Rogersaaa20802011-09-11 21:47:37 -0700565 // We want to check raw Object*/Array* below
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700566 ScopedObjectAccess soa(env);
Ian Rogersaaa20802011-09-11 21:47:37 -0700567
568 // Build stack trace
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700569 jobject internal = Thread::Current()->CreateInternalStackTrace(soa);
Elliott Hughes01158d72011-09-19 19:47:10 -0700570 jobjectArray ste_array = Thread::InternalStackTraceToStackTraceElementArray(env, internal);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800571 mirror::ObjectArray<mirror::StackTraceElement>* trace_array =
572 soa.Decode<mirror::ObjectArray<mirror::StackTraceElement>*>(ste_array);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700573 EXPECT_TRUE(trace_array != NULL);
574 EXPECT_EQ(11, trace_array->GetLength());
575
Ian Rogersaaa20802011-09-11 21:47:37 -0700576 // Check stack trace entries have expected values
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700577 for (int32_t i = 0; i < trace_array->GetLength(); ++i) {
578 EXPECT_EQ(-2, trace_array->Get(i)->GetLineNumber());
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800579 mirror::StackTraceElement* ste = trace_array->Get(i);
Ian Rogersaaa20802011-09-11 21:47:37 -0700580 EXPECT_STREQ("MyClassNatives.java", ste->GetFileName()->ToModifiedUtf8().c_str());
Elliott Hughesb264f082012-04-06 17:10:10 -0700581 EXPECT_STREQ("MyClassNatives", ste->GetDeclaringClass()->ToModifiedUtf8().c_str());
Ian Rogersaaa20802011-09-11 21:47:37 -0700582 EXPECT_STREQ("fooI", ste->GetMethodName()->ToModifiedUtf8().c_str());
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700583 }
Ian Rogersaaa20802011-09-11 21:47:37 -0700584
585 // end recursion
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700586 return 0;
587 } else {
Elliott Hughesb264f082012-04-06 17:10:10 -0700588 jclass jklass = env->FindClass("MyClassNatives");
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700589 EXPECT_TRUE(jklass != NULL);
590 jmethodID jmethod = env->GetMethodID(jklass, "fooI", "(I)I");
591 EXPECT_TRUE(jmethod != NULL);
592
Ian Rogersaaa20802011-09-11 21:47:37 -0700593 // Recurse with i - 1
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700594 jint result = env->CallNonvirtualIntMethod(thisObj, jklass, jmethod, i - 1);
Ian Rogersaaa20802011-09-11 21:47:37 -0700595
596 // Return sum of all depths
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700597 return i + result;
598 }
599}
600
601TEST_F(JniCompilerTest, NativeStackTraceElement) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800602 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700603 SetUpForTest(false, "fooI", "(I)I",
Elliott Hughesb264f082012-04-06 17:10:10 -0700604 reinterpret_cast<void*>(&Java_MyClassNatives_nativeUpCall));
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700605 jint result = env_->CallNonvirtualIntMethod(jobj_, jklass_, jmethod_, 10);
Ian Rogersaaa20802011-09-11 21:47:37 -0700606 EXPECT_EQ(10+9+8+7+6+5+4+3+2+1, result);
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700607}
608
Elliott Hughesb264f082012-04-06 17:10:10 -0700609jobject Java_MyClassNatives_fooO(JNIEnv* env, jobject, jobject x) {
Shih-wei Liao558788e2011-09-01 02:39:11 -0700610 return env->NewGlobalRef(x);
611}
612
Ian Rogersb9231c82011-09-05 22:13:19 -0700613TEST_F(JniCompilerTest, ReturnGlobalRef) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800614 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700615 SetUpForTest(false, "fooO", "(Ljava/lang/Object;)Ljava/lang/Object;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700616 reinterpret_cast<void*>(&Java_MyClassNatives_fooO));
Shih-wei Liao558788e2011-09-01 02:39:11 -0700617 jobject result = env_->CallNonvirtualObjectMethod(jobj_, jklass_, jmethod_, jobj_);
618 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(result));
619 EXPECT_TRUE(env_->IsSameObject(result, jobj_));
620}
621
Ian Rogersdc51b792011-09-22 20:41:37 -0700622jint local_ref_test(JNIEnv* env, jobject thisObj, jint x) {
623 // Add 10 local references
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700624 ScopedObjectAccess soa(env);
Ian Rogers5a7a74a2011-09-26 16:32:29 -0700625 for (int i = 0; i < 10; i++) {
Ian Rogers2dd0e2c2013-01-24 12:42:14 -0800626 soa.AddLocalReference<jobject>(soa.Decode<mirror::Object*>(thisObj));
Ian Rogersdc51b792011-09-22 20:41:37 -0700627 }
628 return x+1;
629}
630
631TEST_F(JniCompilerTest, LocalReferenceTableClearingTest) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800632 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700633 SetUpForTest(false, "fooI", "(I)I", reinterpret_cast<void*>(&local_ref_test));
Ian Rogersdc51b792011-09-22 20:41:37 -0700634 // 1000 invocations of a method that adds 10 local references
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700635 for (int i = 0; i < 1000; i++) {
Ian Rogersdc51b792011-09-22 20:41:37 -0700636 jint result = env_->CallIntMethod(jobj_, jmethod_, i);
637 EXPECT_TRUE(result == i + 1);
638 }
639}
640
Ian Rogersb9231c82011-09-05 22:13:19 -0700641void my_arraycopy(JNIEnv* env, jclass klass, jobject src, jint src_pos, jobject dst, jint dst_pos, jint length) {
642 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, klass));
643 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jklass_, dst));
Ian Rogers82f3e092011-09-05 22:54:45 -0700644 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, src));
Ian Rogersb9231c82011-09-05 22:13:19 -0700645 EXPECT_EQ(1234, src_pos);
646 EXPECT_EQ(5678, dst_pos);
647 EXPECT_EQ(9876, length);
648}
649
650TEST_F(JniCompilerTest, JavaLangSystemArrayCopy) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800651 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700652 SetUpForTest(true, "arraycopy", "(Ljava/lang/Object;ILjava/lang/Object;II)V",
Ian Rogersb9231c82011-09-05 22:13:19 -0700653 reinterpret_cast<void*>(&my_arraycopy));
Ian Rogers82f3e092011-09-05 22:54:45 -0700654 env_->CallStaticVoidMethod(jklass_, jmethod_, jobj_, 1234, jklass_, 5678, 9876);
Ian Rogersb9231c82011-09-05 22:13:19 -0700655}
656
Ian Rogers67375ac2011-09-14 00:55:44 -0700657jboolean my_casi(JNIEnv* env, jobject unsafe, jobject obj, jlong offset, jint expected, jint newval) {
658 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, unsafe));
659 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, obj));
660 EXPECT_EQ(0x12345678ABCDEF88ll, offset);
661 EXPECT_EQ(static_cast<jint>(0xCAFEF00D), expected);
662 EXPECT_EQ(static_cast<jint>(0xEBADF00D), newval);
663 return JNI_TRUE;
664}
665
666TEST_F(JniCompilerTest, CompareAndSwapInt) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800667 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700668 SetUpForTest(false, "compareAndSwapInt", "(Ljava/lang/Object;JII)Z",
Ian Rogers67375ac2011-09-14 00:55:44 -0700669 reinterpret_cast<void*>(&my_casi));
670 jboolean result = env_->CallBooleanMethod(jobj_, jmethod_, jobj_, 0x12345678ABCDEF88ll, 0xCAFEF00D, 0xEBADF00D);
671 EXPECT_EQ(result, JNI_TRUE);
672}
673
Ian Rogersc7792842012-03-03 15:36:20 -0800674jint my_gettext(JNIEnv* env, jclass klass, jlong val1, jobject obj1, jlong val2, jobject obj2) {
675 EXPECT_TRUE(env->IsInstanceOf(JniCompilerTest::jobj_, klass));
676 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, obj1));
677 EXPECT_TRUE(env->IsSameObject(JniCompilerTest::jobj_, obj2));
678 EXPECT_EQ(0x12345678ABCDEF88ll, val1);
679 EXPECT_EQ(0x7FEDCBA987654321ll, val2);
680 return 42;
681}
682
683TEST_F(JniCompilerTest, GetText) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800684 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700685 SetUpForTest(true, "getText", "(JLjava/lang/Object;JLjava/lang/Object;)I",
Ian Rogersc7792842012-03-03 15:36:20 -0800686 reinterpret_cast<void*>(&my_gettext));
687 jint result = env_->CallStaticIntMethod(jklass_, jmethod_, 0x12345678ABCDEF88ll, jobj_,
688 0x7FEDCBA987654321ll, jobj_);
689 EXPECT_EQ(result, 42);
690}
691
Brian Carlstromfc7120c2012-08-27 13:43:25 -0700692TEST_F(JniCompilerTest, GetSinkPropertiesNative) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800693 TEST_DISABLED_FOR_PORTABLE();
Brian Carlstromfc7120c2012-08-27 13:43:25 -0700694 SetUpForTest(false, "getSinkPropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;", NULL);
695 // This space intentionally left blank. Just testing compilation succeeds.
696}
697
Elliott Hughesb264f082012-04-06 17:10:10 -0700698// This should return jclass, but we're imitating a bug pattern.
699jobject Java_MyClassNatives_instanceMethodThatShouldReturnClass(JNIEnv* env, jobject) {
700 return env->NewStringUTF("not a class!");
701}
702
703// This should return jclass, but we're imitating a bug pattern.
704jobject Java_MyClassNatives_staticMethodThatShouldReturnClass(JNIEnv* env, jclass) {
705 return env->NewStringUTF("not a class!");
706}
707
708TEST_F(JniCompilerTest, UpcallReturnTypeChecking_Instance) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800709 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700710 SetUpForTest(false, "instanceMethodThatShouldReturnClass", "()Ljava/lang/Class;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700711 reinterpret_cast<void*>(&Java_MyClassNatives_instanceMethodThatShouldReturnClass));
712
713 CheckJniAbortCatcher check_jni_abort_catcher;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700714 // TODO: check type of returns with portable JNI compiler.
715 // This native method is bad, and tries to return a jstring as a jclass.
716 env_->CallObjectMethod(jobj_, jmethod_);
717 check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.instanceMethodThatShouldReturnClass()");
718
719 // Here, we just call the method incorrectly; we should catch that too.
Elliott Hughesb264f082012-04-06 17:10:10 -0700720 env_->CallVoidMethod(jobj_, jmethod_);
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700721 check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.instanceMethodThatShouldReturnClass()");
722 env_->CallStaticVoidMethod(jklass_, jmethod_);
723 check_jni_abort_catcher.Check("calling non-static method java.lang.Class MyClassNatives.instanceMethodThatShouldReturnClass() with CallStaticVoidMethodV");
Elliott Hughesb264f082012-04-06 17:10:10 -0700724}
725
726TEST_F(JniCompilerTest, UpcallReturnTypeChecking_Static) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800727 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700728 SetUpForTest(true, "staticMethodThatShouldReturnClass", "()Ljava/lang/Class;",
Elliott Hughesb264f082012-04-06 17:10:10 -0700729 reinterpret_cast<void*>(&Java_MyClassNatives_staticMethodThatShouldReturnClass));
730
731 CheckJniAbortCatcher check_jni_abort_catcher;
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700732 // TODO: check type of returns with portable JNI compiler.
733 // This native method is bad, and tries to return a jstring as a jclass.
734 env_->CallStaticObjectMethod(jklass_, jmethod_);
735 check_jni_abort_catcher.Check("attempt to return an instance of java.lang.String from java.lang.Class MyClassNatives.staticMethodThatShouldReturnClass()");
736
737 // Here, we just call the method incorrectly; we should catch that too.
738 env_->CallStaticVoidMethod(jklass_, jmethod_);
739 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 -0700740 env_->CallVoidMethod(jobj_, jmethod_);
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700741 check_jni_abort_catcher.Check("calling static method java.lang.Class MyClassNatives.staticMethodThatShouldReturnClass() with CallVoidMethodV");
Elliott Hughesb264f082012-04-06 17:10:10 -0700742}
743
744// This should take jclass, but we're imitating a bug pattern.
745void Java_MyClassNatives_instanceMethodThatShouldTakeClass(JNIEnv*, jobject, jclass) {
746}
747
748// This should take jclass, but we're imitating a bug pattern.
749void Java_MyClassNatives_staticMethodThatShouldTakeClass(JNIEnv*, jclass, jclass) {
750}
751
752TEST_F(JniCompilerTest, UpcallArgumentTypeChecking_Instance) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800753 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700754 SetUpForTest(false, "instanceMethodThatShouldTakeClass", "(ILjava/lang/Class;)V",
Elliott Hughesb264f082012-04-06 17:10:10 -0700755 reinterpret_cast<void*>(&Java_MyClassNatives_instanceMethodThatShouldTakeClass));
756
757 CheckJniAbortCatcher check_jni_abort_catcher;
758 // We deliberately pass a bad second argument here.
759 env_->CallVoidMethod(jobj_, jmethod_, 123, env_->NewStringUTF("not a class!"));
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700760 check_jni_abort_catcher.Check("bad arguments passed to void MyClassNatives.instanceMethodThatShouldTakeClass(int, java.lang.Class)");
Elliott Hughesb264f082012-04-06 17:10:10 -0700761}
762
763TEST_F(JniCompilerTest, UpcallArgumentTypeChecking_Static) {
Brian Carlstrom265091e2013-01-30 14:08:26 -0800764 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700765 SetUpForTest(true, "staticMethodThatShouldTakeClass", "(ILjava/lang/Class;)V",
Elliott Hughesb264f082012-04-06 17:10:10 -0700766 reinterpret_cast<void*>(&Java_MyClassNatives_staticMethodThatShouldTakeClass));
767
768 CheckJniAbortCatcher check_jni_abort_catcher;
769 // We deliberately pass a bad second argument here.
770 env_->CallStaticVoidMethod(jklass_, jmethod_, 123, env_->NewStringUTF("not a class!"));
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700771 check_jni_abort_catcher.Check("bad arguments passed to void MyClassNatives.staticMethodThatShouldTakeClass(int, java.lang.Class)");
Elliott Hughesb264f082012-04-06 17:10:10 -0700772}
773
Ian Rogersb033c752011-07-20 12:22:35 -0700774} // namespace art