blob: 04b3225f4d6023cc44cb39e308c39fe70e4584b7 [file] [log] [blame]
Elliott Hughes0c9cd562011-08-12 10:59:29 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
Carl Shapiro9b9ba282011-08-14 15:30:39 -07003#include "jni_internal.h"
Elliott Hughes0c9cd562011-08-12 10:59:29 -07004
Carl Shapiro9b9ba282011-08-14 15:30:39 -07005#include <cmath>
6#include <sys/mman.h>
7
8#include "common_test.h"
Elliott Hughes0c9cd562011-08-12 10:59:29 -07009#include "gtest/gtest.h"
10
11namespace art {
12
13class JniInternalTest : public RuntimeTest {
Elliott Hughesc7ac37f2011-08-12 12:21:58 -070014 protected:
15 virtual void SetUp() {
16 RuntimeTest::SetUp();
17 env_ = Thread::Current()->GetJniEnv();
18 }
19 JNIEnv* env_;
Elliott Hughes0c9cd562011-08-12 10:59:29 -070020};
21
Elliott Hughesc7ac37f2011-08-12 12:21:58 -070022TEST_F(JniInternalTest, GetVersion) {
23 ASSERT_EQ(JNI_VERSION_1_6, env_->GetVersion());
24}
25
Elliott Hughes0c9cd562011-08-12 10:59:29 -070026#define EXPECT_CLASS_FOUND(NAME) \
Elliott Hughesc7ac37f2011-08-12 12:21:58 -070027 EXPECT_TRUE(env_->FindClass(NAME) != NULL)
Elliott Hughes0c9cd562011-08-12 10:59:29 -070028
29#define EXPECT_CLASS_NOT_FOUND(NAME) \
Elliott Hughesc7ac37f2011-08-12 12:21:58 -070030 EXPECT_TRUE(env_->FindClass(NAME) == NULL)
Elliott Hughes0c9cd562011-08-12 10:59:29 -070031
32TEST_F(JniInternalTest, FindClass) {
Elliott Hughes0c9cd562011-08-12 10:59:29 -070033 // TODO: when these tests start failing because you're calling FindClass
34 // with a pending exception, fix EXPECT_CLASS_NOT_FOUND to assert that an
35 // exception was thrown and clear the exception.
36
37 // TODO: . is only allowed as an alternative to / if CheckJNI is off.
38
39 // Reference types...
40 // You can't include the "L;" in a JNI class descriptor.
41 EXPECT_CLASS_FOUND("java/lang/String");
42 EXPECT_CLASS_NOT_FOUND("Ljava/lang/String;");
43 // We support . as well as / for compatibility.
44 EXPECT_CLASS_FOUND("java.lang.String");
45 EXPECT_CLASS_NOT_FOUND("Ljava.lang.String;");
46 // ...for arrays too, where you must include "L;".
47 EXPECT_CLASS_FOUND("[Ljava/lang/String;");
48 EXPECT_CLASS_NOT_FOUND("[java/lang/String");
49 EXPECT_CLASS_FOUND("[Ljava.lang.String;");
50 EXPECT_CLASS_NOT_FOUND("[java.lang.String");
51
52 // Primitive arrays are okay (if the primitive type is valid)...
53 EXPECT_CLASS_FOUND("[C");
54 EXPECT_CLASS_NOT_FOUND("[K");
55 // But primitive types aren't allowed...
56 EXPECT_CLASS_NOT_FOUND("C");
57 EXPECT_CLASS_NOT_FOUND("K");
58}
59
Ian Rogers4dd71f12011-08-16 14:16:02 -070060TEST_F(JniInternalTest, GetMethodID) {
61 jclass jlobject = env_->FindClass("java/lang/Object");
62 jclass jlstring = env_->FindClass("java/lang/String");
63 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
64
65 // Sanity check that no exceptions are pending
66 EXPECT_FALSE(env_->ExceptionCheck());
67
68 // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
69 // a pending exception
70 jmethodID method = env_->GetMethodID(jlobject, "foo", "()V");
71 EXPECT_EQ(static_cast<jmethodID>(NULL), method);
72 EXPECT_TRUE(env_->ExceptionCheck());
73 jthrowable exception = env_->ExceptionOccurred();
74 EXPECT_NE(static_cast<jthrowable>(NULL), exception);
75 EXPECT_TRUE(env_->IsInstanceOf(exception, jlnsme));
76 env_->ExceptionClear();
77
78 // Check that java.lang.Object.equals() does exist
79#if defined(__arm__)
80 method = env_->GetMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
81 EXPECT_NE(static_cast<jmethodID>(NULL), method);
82 EXPECT_FALSE(env_->ExceptionCheck());
83#endif
84
85 // Check that GetMethodID for java.lang.String.valueOf(int) fails as the
86 // method is static
87 method = env_->GetMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;");
88 EXPECT_EQ(static_cast<jmethodID>(NULL), method);
89 EXPECT_TRUE(env_->ExceptionCheck());
90 exception = env_->ExceptionOccurred();
91 EXPECT_NE(static_cast<jthrowable>(NULL), exception);
92 EXPECT_TRUE(env_->IsInstanceOf(exception, jlnsme));
93 env_->ExceptionClear();
94}
95
96TEST_F(JniInternalTest, GetStaticMethodID) {
97 jclass jlobject = env_->FindClass("java/lang/Object");
98 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
99
100 // Sanity check that no exceptions are pending
101 EXPECT_FALSE(env_->ExceptionCheck());
102
103 // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
104 // a pending exception
105 jmethodID method = env_->GetStaticMethodID(jlobject, "foo", "()V");
106 EXPECT_EQ(static_cast<jmethodID>(NULL), method);
107 EXPECT_TRUE(env_->ExceptionCheck());
108 jthrowable exception = env_->ExceptionOccurred();
109 EXPECT_NE(static_cast<jthrowable>(NULL), exception);
110 EXPECT_TRUE(env_->IsInstanceOf(exception, jlnsme));
111 env_->ExceptionClear();
112
113 // Check that GetStaticMethodID for java.lang.Object.equals(Object) fails as
114 // the method is not static
115 method = env_->GetStaticMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
116 EXPECT_EQ(static_cast<jmethodID>(NULL), method);
117 EXPECT_TRUE(env_->ExceptionCheck());
118 exception = env_->ExceptionOccurred();
119 EXPECT_NE(static_cast<jthrowable>(NULL), exception);
120 EXPECT_TRUE(env_->IsInstanceOf(exception, jlnsme));
121 env_->ExceptionClear();
122
123 // Check that java.lang.String.valueOf(int) does exist
124#if defined(__arm__)
125 jclass jlstring = env_->FindClass("java/lang/String");
126 method = env_->GetStaticMethodID(jlstring, "valueOf",
127 "(I)Ljava/lang/String;");
128 EXPECT_NE(static_cast<jmethodID>(NULL), method);
129 EXPECT_FALSE(env_->ExceptionCheck());
130#endif
131}
132
133TEST_F(JniInternalTest, RegisterNatives) {
134 jclass jlobject = env_->FindClass("java/lang/Object");
135 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
136
137 // Sanity check that no exceptions are pending
138 EXPECT_FALSE(env_->ExceptionCheck());
139
140 // Check that registering to a non-existent java.lang.Object.foo() causes a
141 // NoSuchMethodError
142 {
143 JNINativeMethod methods[] = {{"foo", "()V", NULL}};
144 env_->RegisterNatives(jlobject, methods, 1);
145 }
146 EXPECT_TRUE(env_->ExceptionCheck());
147 jthrowable exception = env_->ExceptionOccurred();
148 EXPECT_NE(static_cast<jthrowable>(NULL), exception);
149 EXPECT_TRUE(env_->IsInstanceOf(exception, jlnsme));
150 env_->ExceptionClear();
151
152 // Check that registering non-native methods causes a NoSuchMethodError
153 {
154 JNINativeMethod methods[] = {{"equals", "(Ljava/lang/Object;)Z", NULL}};
155 env_->RegisterNatives(jlobject, methods, 1);
156 }
157 EXPECT_TRUE(env_->ExceptionCheck());
158 exception = env_->ExceptionOccurred();
159 EXPECT_NE(static_cast<jthrowable>(NULL), exception);
160 EXPECT_TRUE(env_->IsInstanceOf(exception, jlnsme));
161 env_->ExceptionClear();
162
163 // Check that registering native methods is successful
164 {
165 JNINativeMethod methods[] = {{"hashCode", "()I", NULL}};
166 env_->RegisterNatives(jlobject, methods, 1);
167 }
168 EXPECT_FALSE(env_->ExceptionCheck());
169}
170
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700171TEST_F(JniInternalTest, NewPrimitiveArray) {
172 // TODO: death tests for negative array sizes.
173
Elliott Hughesf2682d52011-08-15 16:37:04 -0700174 // TODO: check returned array size.
175
176 // TODO: check returned array class.
177
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700178 EXPECT_TRUE(env_->NewBooleanArray(0) != NULL);
179 EXPECT_TRUE(env_->NewByteArray(0) != NULL);
180 EXPECT_TRUE(env_->NewCharArray(0) != NULL);
181 EXPECT_TRUE(env_->NewDoubleArray(0) != NULL);
182 EXPECT_TRUE(env_->NewFloatArray(0) != NULL);
183 EXPECT_TRUE(env_->NewIntArray(0) != NULL);
184 EXPECT_TRUE(env_->NewLongArray(0) != NULL);
185 EXPECT_TRUE(env_->NewShortArray(0) != NULL);
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700186
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700187 EXPECT_TRUE(env_->NewBooleanArray(1) != NULL);
188 EXPECT_TRUE(env_->NewByteArray(1) != NULL);
189 EXPECT_TRUE(env_->NewCharArray(1) != NULL);
190 EXPECT_TRUE(env_->NewDoubleArray(1) != NULL);
191 EXPECT_TRUE(env_->NewFloatArray(1) != NULL);
192 EXPECT_TRUE(env_->NewIntArray(1) != NULL);
193 EXPECT_TRUE(env_->NewLongArray(1) != NULL);
194 EXPECT_TRUE(env_->NewShortArray(1) != NULL);
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700195}
196
Elliott Hughesf2682d52011-08-15 16:37:04 -0700197TEST_F(JniInternalTest, NewObjectArray) {
198 // TODO: death tests for negative array sizes.
199
200 // TODO: check returned array size.
201
202 // TODO: check returned array class.
203
204 // TODO: check non-NULL initial elements.
205
Elliott Hughes289da822011-08-16 10:11:20 -0700206 jclass c = env_->FindClass("[Ljava/lang/String;");
207 ASSERT_TRUE(c != NULL);
Elliott Hughesf2682d52011-08-15 16:37:04 -0700208
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700209 EXPECT_TRUE(env_->NewObjectArray(0, c, NULL) != NULL);
Elliott Hughesf2682d52011-08-15 16:37:04 -0700210
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700211 EXPECT_TRUE(env_->NewObjectArray(1, c, NULL) != NULL);
212}
213
214TEST_F(JniInternalTest, NewStringUTF) {
215 EXPECT_TRUE(env_->NewStringUTF(NULL) == NULL);
216 EXPECT_TRUE(env_->NewStringUTF("") != NULL);
217 EXPECT_TRUE(env_->NewStringUTF("hello") != NULL);
218 // TODO: check some non-ASCII strings.
Elliott Hughesf2682d52011-08-15 16:37:04 -0700219}
220
Elliott Hughes289da822011-08-16 10:11:20 -0700221TEST_F(JniInternalTest, SetObjectArrayElement) {
222 jclass c = env_->FindClass("[Ljava/lang/Object;");
223 ASSERT_TRUE(c != NULL);
224
225 jobjectArray array = env_->NewObjectArray(1, c, NULL);
226 EXPECT_TRUE(array != NULL);
227 env_->SetObjectArrayElement(array, 0, c);
228 // TODO: check reading value back
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700229
230 // ArrayIndexOutOfBounds for negative index.
231 // TODO: check exception type
232 env_->SetObjectArrayElement(array, -1, c);
233 EXPECT_TRUE(env_->ExceptionCheck());
234 env_->ExceptionClear();
235
236 // ArrayIndexOutOfBounds for too-large index.
237 // TODO: check exception type
238 env_->SetObjectArrayElement(array, 1, c);
239 EXPECT_TRUE(env_->ExceptionCheck());
240 env_->ExceptionClear();
241
Elliott Hughes289da822011-08-16 10:11:20 -0700242 // TODO: check ArrayStoreException thrown for bad types.
243}
244
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700245bool EnsureInvokeStub(Method* method);
246
247byte* AllocateCode(void* code, size_t length) {
248 int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
249 void* addr = mmap(NULL, length, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
250 CHECK(addr != MAP_FAILED);
251 memcpy(addr, code, length);
252 __builtin___clear_cache(addr, (byte*)addr + length);
253 // Set the low-order bit so a BLX will switch to Thumb mode.
254 return reinterpret_cast<byte*>(reinterpret_cast<uintptr_t>(addr) | 1);
255}
256
257Method::InvokeStub* AllocateStub(Method* method,
258 byte* code,
259 size_t length) {
260 CHECK(method->GetInvokeStub() == NULL);
261 EnsureInvokeStub(method);
262 Method::InvokeStub* stub = method->GetInvokeStub();
263 CHECK(stub != NULL);
264 method->SetCode(AllocateCode(code, length));
265 CHECK(method->GetCode() != NULL);
266 return stub;
267}
268
269void FreeStub(Method* method, size_t length) {
270 void* addr = const_cast<void*>(method->GetCode());
271 munmap(addr, length);
272 method->SetCode(NULL);
273}
274
275#if defined(__arm__)
276TEST_F(JniInternalTest, StaticMainMethod) {
277 scoped_ptr<DexFile> dex(OpenDexFileBase64(kMainDex));
278
279 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
280 ASSERT_TRUE(class_loader != NULL);
281
282 Class* klass = class_linker_->FindClass("LMain;", class_loader);
283 ASSERT_TRUE(klass != NULL);
284
285 Method* method = klass->FindDirectMethod("main", "([Ljava/lang/String;)V");
286 ASSERT_TRUE(method != NULL);
287
288 byte main_LV_code[] = {
289 0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8, 0x00, 0x00,
290 0xcd, 0xf8, 0x14, 0x10, 0x03, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
291 };
292
293 Method::InvokeStub* stub = AllocateStub(method,
294 main_LV_code,
295 sizeof(main_LV_code));
296
297 Object* arg = NULL;
298
299 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), NULL);
300
301 FreeStub(method, sizeof(main_LV_code));
302}
303
304TEST_F(JniInternalTest, StaticNopMethod) {
305 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
306
307 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
308 ASSERT_TRUE(class_loader != NULL);
309
310 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
311 ASSERT_TRUE(klass != NULL);
312
313 Method* method = klass->FindDirectMethod("nop", "()V");
314 ASSERT_TRUE(method != NULL);
315
316 byte nop_V_code[] = {
317 0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
318 0x00, 0x00, 0x03, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
319 };
320
321 Method::InvokeStub* stub = AllocateStub(method,
322 nop_V_code,
323 sizeof(nop_V_code));
324 ASSERT_TRUE(stub);
325
326 (*stub)(method, NULL, NULL, NULL, NULL);
327
328 FreeStub(method, sizeof(nop_V_code));
329}
330
331TEST_F(JniInternalTest, StaticIdentityByteMethod) {
332 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
333
334 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
335 ASSERT_TRUE(class_loader != NULL);
336
337 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
338 ASSERT_TRUE(klass != NULL);
339
340 Method* method = klass->FindDirectMethod("identity", "(B)B");
341 ASSERT_TRUE(method != NULL);
342
343 byte identity_BB_code[] = {
344 0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
345 0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0x05, 0x98,
346 0x03, 0xb0, 0xbd, 0xe8, 0x00, 0x80, 0x00, 0x00,
347 };
348
349 Method::InvokeStub* stub = AllocateStub(method,
350 identity_BB_code,
351 sizeof(identity_BB_code));
352
353 int arg;
354 JValue result;
355
356 arg = 0;
357 result.b = -1;
358 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
359 EXPECT_EQ(0, result.b);
360
361 arg = -1;
362 result.b = 0;
363 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
364 EXPECT_EQ(-1, result.b);
365
366 arg = SCHAR_MAX;
367 result.b = 0;
368 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
369 EXPECT_EQ(SCHAR_MAX, result.b);
370
371 arg = SCHAR_MIN;
372 result.b = 0;
373 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
374 EXPECT_EQ(SCHAR_MIN, result.b);
375
376 FreeStub(method, sizeof(identity_BB_code));
377}
378
379TEST_F(JniInternalTest, StaticIdentityIntMethod) {
380 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
381
382 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
383 ASSERT_TRUE(class_loader != NULL);
384
385 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
386 ASSERT_TRUE(klass != NULL);
387
388 Method* method = klass->FindDirectMethod("identity", "(I)I");
389 ASSERT_TRUE(method != NULL);
390
391 byte identity_II_code[] = {
392 0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
393 0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0x05, 0x98,
394 0x03, 0xb0, 0xbd, 0xe8, 0x00, 0x80, 0x00, 0x00,
395 };
396
397 Method::InvokeStub* stub = AllocateStub(method,
398 identity_II_code,
399 sizeof(identity_II_code));
400
401 int arg;
402 JValue result;
403
404 arg = 0;
405 result.i = -1;
406 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
407 EXPECT_EQ(0, result.i);
408
409 arg = -1;
410 result.i = 0;
411 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
412 EXPECT_EQ(-1, result.i);
413
414 arg = INT_MAX;
415 result.i = 0;
416 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
417 EXPECT_EQ(INT_MAX, result.i);
418
419 arg = INT_MIN;
420 result.i = 0;
421 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
422 EXPECT_EQ(INT_MIN, result.i);
423
424 FreeStub(method, sizeof(identity_II_code));
425}
426
427TEST_F(JniInternalTest, StaticIdentityDoubleMethod) {
428 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
429
430 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
431 ASSERT_TRUE(class_loader != NULL);
432
433 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
434 ASSERT_TRUE(klass != NULL);
435
436 Method* method = klass->FindDirectMethod("identity", "(D)D");
437 ASSERT_TRUE(method != NULL);
438
439 byte identity_DD_code[] = {
440 0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
441 0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0xcd, 0xf8,
442 0x18, 0x20, 0x05, 0x98, 0x06, 0x99, 0x03, 0xb0,
443 0xbd, 0xe8, 0x00, 0x80,
444 };
445
446 Method::InvokeStub* stub = AllocateStub(method,
447 identity_DD_code,
448 sizeof(identity_DD_code));
449
450 double arg;
451 JValue result;
452
453 arg = 0.0;
454 result.d = -1.0;
455 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
456 EXPECT_EQ(0.0, result.d);
457
458 arg = -1.0;
459 result.d = 0.0;
460 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
461 EXPECT_EQ(-1.0, result.d);
462
463 arg = DBL_MAX;
464 result.d = 0.0;
465 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
466 EXPECT_EQ(DBL_MAX, result.d);
467
468 arg = DBL_MIN;
469 result.d = 0.0;
470 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
471 EXPECT_EQ(DBL_MIN, result.d);
472
473 FreeStub(method, sizeof(identity_DD_code));
474}
475
476TEST_F(JniInternalTest, StaticSumIntIntMethod) {
477 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
478
479 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
480 ASSERT_TRUE(class_loader != NULL);
481
482 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
483 ASSERT_TRUE(klass != NULL);
484
485 Method* method = klass->FindDirectMethod("sum", "(II)I");
486 ASSERT_TRUE(method != NULL);
487
488 byte sum_III_code[] = {
489 0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
490 0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0xcd, 0xf8,
491 0x18, 0x20, 0x05, 0x98, 0x06, 0x99, 0x42, 0x18,
492 0xcd, 0xf8, 0x04, 0x20, 0x01, 0x98, 0x03, 0xb0,
493 0xbd, 0xe8, 0x00, 0x80,
494 };
495
496 Method::InvokeStub* stub = AllocateStub(method,
497 sum_III_code,
498 sizeof(sum_III_code));
499
500 int args[2];
501 JValue result;
502
503 args[0] = 0;
504 args[1] = 0;
505 result.i = -1;
506 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
507 EXPECT_EQ(0, result.i);
508
509 args[0] = 1;
510 args[1] = 2;
511 result.i = 0;
512 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
513 EXPECT_EQ(3, result.i);
514
515 args[0] = -2;
516 args[1] = 5;
517 result.i = 0;
518 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
519 EXPECT_EQ(3, result.i);
520
521 args[0] = INT_MAX;
522 args[1] = INT_MIN;
523 result.i = 1234;
524 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
525 EXPECT_EQ(-1, result.i);
526
527 args[0] = INT_MAX;
528 args[1] = INT_MAX;
529 result.i = INT_MIN;
530 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
531 EXPECT_EQ(-2, result.i);
532
533 FreeStub(method, sizeof(sum_III_code));
534}
535
536TEST_F(JniInternalTest, StaticSumIntIntIntMethod) {
537 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
538
539 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
540 ASSERT_TRUE(class_loader != NULL);
541
542 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
543 ASSERT_TRUE(klass != NULL);
544
545 Method* method = klass->FindDirectMethod("sum", "(III)I");
546 ASSERT_TRUE(method != NULL);
547
548 byte sum_IIII_code[] = {
549 0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
550 0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0xcd, 0xf8,
551 0x18, 0x20, 0xcd, 0xf8, 0x1c, 0x30, 0x05, 0x98,
552 0x06, 0x99, 0x42, 0x18, 0xcd, 0xf8, 0x04, 0x20,
553 0x01, 0x9b, 0xdd, 0xf8, 0x1c, 0xc0, 0x13, 0xeb,
554 0x0c, 0x03, 0xcd, 0xf8, 0x04, 0x30, 0x01, 0x98,
555 0x03, 0xb0, 0xbd, 0xe8, 0x00, 0x80, 0x00, 0x00,
556 };
557
558 Method::InvokeStub* stub = AllocateStub(method,
559 sum_IIII_code,
560 sizeof(sum_IIII_code));
561
562 int args[3];
563 JValue result;
564
565 args[0] = 0;
566 args[1] = 0;
567 args[2] = 0;
568 result.i = -1;
569 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
570 EXPECT_EQ(0, result.i);
571
572 args[0] = 1;
573 args[1] = 2;
574 args[2] = 3;
575 result.i = 0;
576 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
577 EXPECT_EQ(6, result.i);
578
579 args[0] = -1;
580 args[1] = 2;
581 args[2] = -3;
582 result.i = 0;
583 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
584 EXPECT_EQ(-2, result.i);
585
586 args[0] = INT_MAX;
587 args[1] = INT_MIN;
588 args[2] = INT_MAX;
589 result.i = 1234;
590 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
591 EXPECT_EQ(2147483646, result.i);
592
593 args[0] = INT_MAX;
594 args[1] = INT_MAX;
595 args[2] = INT_MAX;
596 result.i = INT_MIN;
597 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
598 EXPECT_EQ(2147483645, result.i);
599
600 FreeStub(method, sizeof(sum_IIII_code));
601}
602
603TEST_F(JniInternalTest, StaticSumIntIntIntIntMethod) {
604 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
605
606 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
607 ASSERT_TRUE(class_loader != NULL);
608
609 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
610 ASSERT_TRUE(klass != NULL);
611
612 Method* method = klass->FindDirectMethod("sum", "(IIII)I");
613 ASSERT_TRUE(method != NULL);
614
615 byte sum_IIIII_code[] = {
616 0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
617 0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0xcd, 0xf8,
618 0x18, 0x20, 0xcd, 0xf8, 0x1c, 0x30, 0x05, 0x98,
619 0x06, 0x99, 0x42, 0x18, 0xcd, 0xf8, 0x04, 0x20,
620 0x01, 0x9b, 0xdd, 0xf8, 0x1c, 0xc0, 0x13, 0xeb,
621 0x0c, 0x03, 0xcd, 0xf8, 0x04, 0x30, 0x01, 0x98,
622 0x08, 0x99, 0x40, 0x18, 0xcd, 0xf8, 0x04, 0x00,
623 0x01, 0x98, 0x03, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
624 };
625
626 Method::InvokeStub* stub = AllocateStub(method,
627 sum_IIIII_code,
628 sizeof(sum_IIIII_code));
629
630 int args[4];
631 JValue result;
632
633 args[0] = 0;
634 args[1] = 0;
635 args[2] = 0;
636 args[3] = 0;
637 result.i = -1;
638 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
639 EXPECT_EQ(0, result.i);
640
641 args[0] = 1;
642 args[1] = 2;
643 args[2] = 3;
644 args[3] = 4;
645 result.i = 0;
646 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
647 EXPECT_EQ(10, result.i);
648
649 args[0] = -1;
650 args[1] = 2;
651 args[2] = -3;
652 args[3] = 4;
653 result.i = 0;
654 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
655 EXPECT_EQ(2, result.i);
656
657 args[0] = INT_MAX;
658 args[1] = INT_MIN;
659 args[2] = INT_MAX;
660 args[3] = INT_MIN;
661 result.i = 1234;
662 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
663 EXPECT_EQ(-2, result.i);
664
665 args[0] = INT_MAX;
666 args[1] = INT_MAX;
667 args[2] = INT_MAX;
668 args[3] = INT_MAX;
669 result.i = INT_MIN;
670 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
671 EXPECT_EQ(-4, result.i);
672
673 FreeStub(method, sizeof(sum_IIIII_code));
674}
675
676TEST_F(JniInternalTest, StaticSumIntIntIntIntIntMethod) {
677 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
678
679 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
680 ASSERT_TRUE(class_loader != NULL);
681
682 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
683 ASSERT_TRUE(klass != NULL);
684
685 Method* method = klass->FindDirectMethod("sum", "(IIIII)I");
686 ASSERT_TRUE(method != NULL);
687
688 byte sum_IIIIII_code[] = {
689 0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
690 0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0xcd, 0xf8,
691 0x18, 0x20, 0xcd, 0xf8, 0x1c, 0x30, 0x05, 0x98,
692 0x06, 0x99, 0x42, 0x18, 0xcd, 0xf8, 0x04, 0x20,
693 0x01, 0x9b, 0xdd, 0xf8, 0x1c, 0xc0, 0x13, 0xeb,
694 0x0c, 0x03, 0xcd, 0xf8, 0x04, 0x30, 0x01, 0x98,
695 0x08, 0x99, 0x40, 0x18, 0xcd, 0xf8, 0x04, 0x00,
696 0x01, 0x9a, 0x09, 0x9b, 0xd2, 0x18, 0xcd, 0xf8,
697 0x04, 0x20, 0x01, 0x98, 0x03, 0xb0, 0xbd, 0xe8,
698 0x00, 0x80, 0x00, 0x00,
699 };
700
701 Method::InvokeStub* stub = AllocateStub(method,
702 sum_IIIIII_code,
703 sizeof(sum_IIIIII_code));
704
705 int args[5];
706 JValue result;
707
708 args[0] = 0;
709 args[1] = 0;
710 args[2] = 0;
711 args[3] = 0;
712 args[4] = 0;
713 result.i = -1.0;
714 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
715 EXPECT_EQ(0, result.i);
716
717 args[0] = 1;
718 args[1] = 2;
719 args[2] = 3;
720 args[3] = 4;
721 args[4] = 5;
722 result.i = 0;
723 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
724 EXPECT_EQ(15, result.i);
725
726 args[0] = -1;
727 args[1] = 2;
728 args[2] = -3;
729 args[3] = 4;
730 args[4] = -5;
731 result.i = 0;
732 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
733 EXPECT_EQ(-3, result.i);
734
735 args[0] = INT_MAX;
736 args[1] = INT_MIN;
737 args[2] = INT_MAX;
738 args[3] = INT_MIN;
739 args[4] = INT_MAX;
740 result.i = 1234;
741 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
742 EXPECT_EQ(2147483645, result.i);
743
744 args[0] = INT_MAX;
745 args[1] = INT_MAX;
746 args[2] = INT_MAX;
747 args[3] = INT_MAX;
748 args[4] = INT_MAX;
749 result.i = INT_MIN;
750 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
751 EXPECT_EQ(2147483643, result.i);
752
753 FreeStub(method, sizeof(sum_IIIIII_code));
754}
755
756TEST_F(JniInternalTest, StaticSumDoubleDoubleMethod) {
757 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
758
759 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
760 ASSERT_TRUE(class_loader != NULL);
761
762 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
763 ASSERT_TRUE(klass != NULL);
764
765 Method* method = klass->FindDirectMethod("sum", "(DD)D");
766 ASSERT_TRUE(method != NULL);
767
768 byte sum_DDD_code[] = {
769 0x2d, 0xe9, 0x00, 0x40, 0x87, 0xb0, 0xcd, 0xf8,
770 0x00, 0x00, 0xcd, 0xf8, 0x24, 0x10, 0xcd, 0xf8,
771 0x28, 0x20, 0xcd, 0xf8, 0x2c, 0x30, 0x9d, 0xed,
772 0x09, 0x0b, 0x9d, 0xed, 0x0b, 0x1b, 0x30, 0xee,
773 0x01, 0x2b, 0x8d, 0xed, 0x04, 0x2b, 0x04, 0x98,
774 0x05, 0x99, 0x07, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
775 };
776
777 Method::InvokeStub* stub = AllocateStub(method,
778 sum_DDD_code,
779 sizeof(sum_DDD_code));
780
781 double args[2];
782 JValue result;
783
784 args[0] = 0.0;
785 args[1] = 0.0;
786 result.d = -1.0;
787 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
788 EXPECT_EQ(0.0, result.d);
789
790 args[0] = 1.0;
791 args[1] = 2.0;
792 result.d = 0.0;
793 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
794 EXPECT_EQ(3.0, result.d);
795
796 args[0] = 1.0;
797 args[1] = -2.0;
798 result.d = 0.0;
799 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
800 EXPECT_EQ(-1.0, result.d);
801
802 args[0] = DBL_MAX;
803 args[1] = DBL_MIN;
804 result.d = 0.0;
805 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
806 EXPECT_EQ(1.7976931348623157e308, result.d);
807
808 args[0] = DBL_MAX;
809 args[1] = DBL_MAX;
810 result.d = 0.0;
811 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
812 EXPECT_EQ(INFINITY, result.d);
813
814 FreeStub(method, sizeof(sum_DDD_code));
815}
816
817TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleMethod) {
818 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
819
820 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
821 ASSERT_TRUE(class_loader != NULL);
822
823 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
824 ASSERT_TRUE(klass != NULL);
825
826 Method* method = klass->FindDirectMethod("sum", "(DDD)D");
827 ASSERT_TRUE(method != NULL);
828
829 byte sum_DDDD_code[] = {
830 0x2d, 0xe9, 0x00, 0x40, 0x87, 0xb0, 0xcd, 0xf8,
831 0x00, 0x00, 0xcd, 0xf8, 0x24, 0x10, 0xcd, 0xf8,
832 0x28, 0x20, 0xcd, 0xf8, 0x2c, 0x30, 0x9d, 0xed,
833 0x09, 0x0b, 0x9d, 0xed, 0x0b, 0x1b, 0x30, 0xee,
834 0x01, 0x2b, 0x8d, 0xed, 0x04, 0x2b, 0x9d, 0xed,
835 0x04, 0x3b, 0x9d, 0xed, 0x0d, 0x4b, 0x33, 0xee,
836 0x04, 0x3b, 0x8d, 0xed, 0x04, 0x3b, 0x04, 0x98,
837 0x05, 0x99, 0x07, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
838 };
839
840 Method::InvokeStub* stub = AllocateStub(method,
841 sum_DDDD_code,
842 sizeof(sum_DDDD_code));
843
844 double args[3];
845 JValue result;
846
847 args[0] = 0.0;
848 args[1] = 0.0;
849 args[2] = 0.0;
850 result.d = -1.0;
851 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
852 EXPECT_EQ(0.0, result.d);
853
854 args[0] = 1.0;
855 args[1] = 2.0;
856 args[2] = 3.0;
857 result.d = 0.0;
858 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
859 EXPECT_EQ(6.0, result.d);
860
861 args[0] = 1.0;
862 args[1] = -2.0;
863 args[2] = 3.0;
864 result.d = 0.0;
865 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
866 EXPECT_EQ(2.0, result.d);
867
868 FreeStub(method, sizeof(sum_DDDD_code));
869}
870
871TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleMethod) {
872 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
873
874 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
875 ASSERT_TRUE(class_loader != NULL);
876
877 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
878 ASSERT_TRUE(klass != NULL);
879
880 Method* method = klass->FindDirectMethod("sum", "(DDDD)D");
881 ASSERT_TRUE(method != NULL);
882
883 byte sum_DDDDD_code[] = {
884 0x2d, 0xe9, 0x00, 0x40, 0x87, 0xb0, 0xcd, 0xf8,
885 0x00, 0x00, 0xcd, 0xf8, 0x24, 0x10, 0xcd, 0xf8,
886 0x28, 0x20, 0xcd, 0xf8, 0x2c, 0x30, 0x9d, 0xed,
887 0x09, 0x0b, 0x9d, 0xed, 0x0b, 0x1b, 0x30, 0xee,
888 0x01, 0x2b, 0x8d, 0xed, 0x04, 0x2b, 0x9d, 0xed,
889 0x04, 0x3b, 0x9d, 0xed, 0x0d, 0x4b, 0x33, 0xee,
890 0x04, 0x3b, 0x8d, 0xed, 0x04, 0x3b, 0x9d, 0xed,
891 0x04, 0x5b, 0x9d, 0xed, 0x0f, 0x6b, 0x35, 0xee,
892 0x06, 0x5b, 0x8d, 0xed, 0x04, 0x5b, 0x04, 0x98,
893 0x05, 0x99, 0x07, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
894 };
895
896 Method::InvokeStub* stub = AllocateStub(method,
897 sum_DDDDD_code,
898 sizeof(sum_DDDDD_code));
899
900 double args[4];
901 JValue result;
902
903 args[0] = 0.0;
904 args[1] = 0.0;
905 args[2] = 0.0;
906 args[3] = 0.0;
907 result.d = -1.0;
908 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
909 EXPECT_EQ(0.0, result.d);
910
911 args[0] = 1.0;
912 args[1] = 2.0;
913 args[2] = 3.0;
914 args[3] = 4.0;
915 result.d = 0.0;
916 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
917 EXPECT_EQ(10.0, result.d);
918
919 args[0] = 1.0;
920 args[1] = -2.0;
921 args[2] = 3.0;
922 args[3] = -4.0;
923 result.d = 0.0;
924 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
925 EXPECT_EQ(-2.0, result.d);
926
927 FreeStub(method, sizeof(sum_DDDDD_code));
928}
929
930TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleDoubleMethod) {
931 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
932
933 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
934 ASSERT_TRUE(class_loader != NULL);
935
936 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
937 ASSERT_TRUE(klass != NULL);
938
939 Method* method = klass->FindDirectMethod("sum", "(DDDDD)D");
940 ASSERT_TRUE(method != NULL);
941
942 byte sum_DDDDDD_code[] = {
943 0x2d, 0xe9, 0x00, 0x40, 0x87, 0xb0, 0xcd, 0xf8,
944 0x00, 0x00, 0xcd, 0xf8, 0x24, 0x10, 0xcd, 0xf8,
945 0x28, 0x20, 0xcd, 0xf8, 0x2c, 0x30, 0x9d, 0xed,
946 0x09, 0x0b, 0x9d, 0xed, 0x0b, 0x1b, 0x30, 0xee,
947 0x01, 0x2b, 0x8d, 0xed, 0x04, 0x2b, 0x9d, 0xed,
948 0x04, 0x3b, 0x9d, 0xed, 0x0d, 0x4b, 0x33, 0xee,
949 0x04, 0x3b, 0x8d, 0xed, 0x04, 0x3b, 0x9d, 0xed,
950 0x04, 0x5b, 0x9d, 0xed, 0x0f, 0x6b, 0x35, 0xee,
951 0x06, 0x5b, 0x8d, 0xed, 0x04, 0x5b, 0x9d, 0xed,
952 0x04, 0x7b, 0x9d, 0xed, 0x11, 0x0b, 0x37, 0xee,
953 0x00, 0x7b, 0x8d, 0xed, 0x04, 0x7b, 0x04, 0x98,
954 0x05, 0x99, 0x07, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
955 };
956
957 Method::InvokeStub* stub = AllocateStub(method,
958 sum_DDDDDD_code,
959 sizeof(sum_DDDDDD_code));
960
961 double args[5];
962 JValue result;
963
964 args[0] = 0.0;
965 args[1] = 0.0;
966 args[2] = 0.0;
967 args[3] = 0.0;
968 args[4] = 0.0;
969 result.d = -1.0;
970 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
971 EXPECT_EQ(0.0, result.d);
972
973 args[0] = 1.0;
974 args[1] = 2.0;
975 args[2] = 3.0;
976 args[3] = 4.0;
977 args[4] = 5.0;
978 result.d = 0.0;
979 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
980 EXPECT_EQ(15.0, result.d);
981
982 args[0] = 1.0;
983 args[1] = -2.0;
984 args[2] = 3.0;
985 args[3] = -4.0;
986 args[4] = 5.0;
987 result.d = 0.0;
988 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
989 EXPECT_EQ(3.0, result.d);
990
991 FreeStub(method, sizeof(sum_DDDDDD_code));
992}
993#endif // __arm__
994
995}