blob: f51b6c97eb79f357c4153e484035df5a8d5884f4 [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
Brian Carlstromf734cf52011-08-17 16:28:14 -070013class JniInternalTest : public CommonTest {
Elliott Hughesc7ac37f2011-08-12 12:21:58 -070014 protected:
15 virtual void SetUp() {
Brian Carlstromf734cf52011-08-17 16:28:14 -070016 CommonTest::SetUp();
Elliott Hughesc7ac37f2011-08-12 12:21:58 -070017 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
Ian Rogers4dd71f12011-08-16 14:16:02 -070079 method = env_->GetMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
80 EXPECT_NE(static_cast<jmethodID>(NULL), method);
81 EXPECT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -070082
83 // Check that GetMethodID for java.lang.String.valueOf(int) fails as the
84 // method is static
85 method = env_->GetMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;");
86 EXPECT_EQ(static_cast<jmethodID>(NULL), method);
87 EXPECT_TRUE(env_->ExceptionCheck());
88 exception = env_->ExceptionOccurred();
89 EXPECT_NE(static_cast<jthrowable>(NULL), exception);
90 EXPECT_TRUE(env_->IsInstanceOf(exception, jlnsme));
91 env_->ExceptionClear();
92}
93
94TEST_F(JniInternalTest, GetStaticMethodID) {
95 jclass jlobject = env_->FindClass("java/lang/Object");
96 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
97
98 // Sanity check that no exceptions are pending
99 EXPECT_FALSE(env_->ExceptionCheck());
100
101 // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
102 // a pending exception
103 jmethodID method = env_->GetStaticMethodID(jlobject, "foo", "()V");
104 EXPECT_EQ(static_cast<jmethodID>(NULL), method);
105 EXPECT_TRUE(env_->ExceptionCheck());
106 jthrowable exception = env_->ExceptionOccurred();
107 EXPECT_NE(static_cast<jthrowable>(NULL), exception);
108 EXPECT_TRUE(env_->IsInstanceOf(exception, jlnsme));
109 env_->ExceptionClear();
110
111 // Check that GetStaticMethodID for java.lang.Object.equals(Object) fails as
112 // the method is not static
113 method = env_->GetStaticMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
114 EXPECT_EQ(static_cast<jmethodID>(NULL), method);
115 EXPECT_TRUE(env_->ExceptionCheck());
116 exception = env_->ExceptionOccurred();
117 EXPECT_NE(static_cast<jthrowable>(NULL), exception);
118 EXPECT_TRUE(env_->IsInstanceOf(exception, jlnsme));
119 env_->ExceptionClear();
120
121 // Check that java.lang.String.valueOf(int) does exist
Ian Rogers4dd71f12011-08-16 14:16:02 -0700122 jclass jlstring = env_->FindClass("java/lang/String");
123 method = env_->GetStaticMethodID(jlstring, "valueOf",
124 "(I)Ljava/lang/String;");
125 EXPECT_NE(static_cast<jmethodID>(NULL), method);
126 EXPECT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700127}
128
129TEST_F(JniInternalTest, RegisterNatives) {
130 jclass jlobject = env_->FindClass("java/lang/Object");
131 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
132
133 // Sanity check that no exceptions are pending
134 EXPECT_FALSE(env_->ExceptionCheck());
135
136 // Check that registering to a non-existent java.lang.Object.foo() causes a
137 // NoSuchMethodError
138 {
139 JNINativeMethod methods[] = {{"foo", "()V", NULL}};
140 env_->RegisterNatives(jlobject, methods, 1);
141 }
142 EXPECT_TRUE(env_->ExceptionCheck());
143 jthrowable exception = env_->ExceptionOccurred();
144 EXPECT_NE(static_cast<jthrowable>(NULL), exception);
145 EXPECT_TRUE(env_->IsInstanceOf(exception, jlnsme));
146 env_->ExceptionClear();
147
148 // Check that registering non-native methods causes a NoSuchMethodError
149 {
150 JNINativeMethod methods[] = {{"equals", "(Ljava/lang/Object;)Z", NULL}};
151 env_->RegisterNatives(jlobject, methods, 1);
152 }
153 EXPECT_TRUE(env_->ExceptionCheck());
154 exception = env_->ExceptionOccurred();
155 EXPECT_NE(static_cast<jthrowable>(NULL), exception);
156 EXPECT_TRUE(env_->IsInstanceOf(exception, jlnsme));
157 env_->ExceptionClear();
158
159 // Check that registering native methods is successful
160 {
161 JNINativeMethod methods[] = {{"hashCode", "()I", NULL}};
162 env_->RegisterNatives(jlobject, methods, 1);
163 }
164 EXPECT_FALSE(env_->ExceptionCheck());
165}
166
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700167TEST_F(JniInternalTest, NewPrimitiveArray) {
168 // TODO: death tests for negative array sizes.
169
Elliott Hughesf2682d52011-08-15 16:37:04 -0700170 // TODO: check returned array size.
171
172 // TODO: check returned array class.
173
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700174 EXPECT_TRUE(env_->NewBooleanArray(0) != NULL);
175 EXPECT_TRUE(env_->NewByteArray(0) != NULL);
176 EXPECT_TRUE(env_->NewCharArray(0) != NULL);
177 EXPECT_TRUE(env_->NewDoubleArray(0) != NULL);
178 EXPECT_TRUE(env_->NewFloatArray(0) != NULL);
179 EXPECT_TRUE(env_->NewIntArray(0) != NULL);
180 EXPECT_TRUE(env_->NewLongArray(0) != NULL);
181 EXPECT_TRUE(env_->NewShortArray(0) != NULL);
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700182
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700183 EXPECT_TRUE(env_->NewBooleanArray(1) != NULL);
184 EXPECT_TRUE(env_->NewByteArray(1) != NULL);
185 EXPECT_TRUE(env_->NewCharArray(1) != NULL);
186 EXPECT_TRUE(env_->NewDoubleArray(1) != NULL);
187 EXPECT_TRUE(env_->NewFloatArray(1) != NULL);
188 EXPECT_TRUE(env_->NewIntArray(1) != NULL);
189 EXPECT_TRUE(env_->NewLongArray(1) != NULL);
190 EXPECT_TRUE(env_->NewShortArray(1) != NULL);
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700191}
192
Elliott Hughesf2682d52011-08-15 16:37:04 -0700193TEST_F(JniInternalTest, NewObjectArray) {
194 // TODO: death tests for negative array sizes.
195
196 // TODO: check returned array size.
197
198 // TODO: check returned array class.
199
200 // TODO: check non-NULL initial elements.
201
Elliott Hughes289da822011-08-16 10:11:20 -0700202 jclass c = env_->FindClass("[Ljava/lang/String;");
203 ASSERT_TRUE(c != NULL);
Elliott Hughesf2682d52011-08-15 16:37:04 -0700204
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700205 EXPECT_TRUE(env_->NewObjectArray(0, c, NULL) != NULL);
Elliott Hughesf2682d52011-08-15 16:37:04 -0700206
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700207 EXPECT_TRUE(env_->NewObjectArray(1, c, NULL) != NULL);
208}
209
210TEST_F(JniInternalTest, NewStringUTF) {
211 EXPECT_TRUE(env_->NewStringUTF(NULL) == NULL);
212 EXPECT_TRUE(env_->NewStringUTF("") != NULL);
213 EXPECT_TRUE(env_->NewStringUTF("hello") != NULL);
214 // TODO: check some non-ASCII strings.
Elliott Hughesf2682d52011-08-15 16:37:04 -0700215}
216
Elliott Hughes289da822011-08-16 10:11:20 -0700217TEST_F(JniInternalTest, SetObjectArrayElement) {
218 jclass c = env_->FindClass("[Ljava/lang/Object;");
219 ASSERT_TRUE(c != NULL);
220
221 jobjectArray array = env_->NewObjectArray(1, c, NULL);
222 EXPECT_TRUE(array != NULL);
223 env_->SetObjectArrayElement(array, 0, c);
224 // TODO: check reading value back
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700225
226 // ArrayIndexOutOfBounds for negative index.
227 // TODO: check exception type
228 env_->SetObjectArrayElement(array, -1, c);
229 EXPECT_TRUE(env_->ExceptionCheck());
230 env_->ExceptionClear();
231
232 // ArrayIndexOutOfBounds for too-large index.
233 // TODO: check exception type
234 env_->SetObjectArrayElement(array, 1, c);
235 EXPECT_TRUE(env_->ExceptionCheck());
236 env_->ExceptionClear();
237
Elliott Hughes289da822011-08-16 10:11:20 -0700238 // TODO: check ArrayStoreException thrown for bad types.
239}
240
Elliott Hughes18c07532011-08-18 15:50:51 -0700241TEST_F(JniInternalTest, NewLocalRef_NULL) {
242 EXPECT_TRUE(env_->NewLocalRef(NULL) == NULL);
243}
244
245TEST_F(JniInternalTest, NewLocalRef) {
246 jstring s = env_->NewStringUTF("");
247 ASSERT_TRUE(s != NULL);
248 jobject o = env_->NewLocalRef(s);
249 EXPECT_TRUE(o != NULL);
250 EXPECT_TRUE(o != s);
251
252 // TODO: check that o is a local reference.
253}
254
255TEST_F(JniInternalTest, DeleteLocalRef_NULL) {
256 env_->DeleteLocalRef(NULL);
257}
258
259TEST_F(JniInternalTest, DeleteLocalRef) {
260 jstring s = env_->NewStringUTF("");
261 ASSERT_TRUE(s != NULL);
262 env_->DeleteLocalRef(s);
263
264 // Currently, deleting an already-deleted reference is just a warning.
265 env_->DeleteLocalRef(s);
266
267 s = env_->NewStringUTF("");
268 ASSERT_TRUE(s != NULL);
269 jobject o = env_->NewLocalRef(s);
270 ASSERT_TRUE(o != NULL);
271
272 env_->DeleteLocalRef(s);
273 env_->DeleteLocalRef(o);
274}
275
276TEST_F(JniInternalTest, NewGlobalRef_NULL) {
277 EXPECT_TRUE(env_->NewGlobalRef(NULL) == NULL);
278}
279
280TEST_F(JniInternalTest, NewGlobalRef) {
281 jstring s = env_->NewStringUTF("");
282 ASSERT_TRUE(s != NULL);
283 jobject o = env_->NewGlobalRef(s);
284 EXPECT_TRUE(o != NULL);
285 EXPECT_TRUE(o != s);
286
287 // TODO: check that o is a global reference.
288}
289
290TEST_F(JniInternalTest, DeleteGlobalRef_NULL) {
291 env_->DeleteGlobalRef(NULL);
292}
293
294TEST_F(JniInternalTest, DeleteGlobalRef) {
295 jstring s = env_->NewStringUTF("");
296 ASSERT_TRUE(s != NULL);
297
298 jobject o = env_->NewGlobalRef(s);
299 ASSERT_TRUE(o != NULL);
300 env_->DeleteGlobalRef(o);
301
302 // Currently, deleting an already-deleted reference is just a warning.
303 env_->DeleteGlobalRef(o);
304
305 jobject o1 = env_->NewGlobalRef(s);
306 ASSERT_TRUE(o1 != NULL);
307 jobject o2 = env_->NewGlobalRef(s);
308 ASSERT_TRUE(o2 != NULL);
309
310 env_->DeleteGlobalRef(o1);
311 env_->DeleteGlobalRef(o2);
312}
313
314TEST_F(JniInternalTest, NewWeakGlobalRef_NULL) {
315 EXPECT_TRUE(env_->NewWeakGlobalRef(NULL) == NULL);
316}
317
318TEST_F(JniInternalTest, NewWeakGlobalRef) {
319 jstring s = env_->NewStringUTF("");
320 ASSERT_TRUE(s != NULL);
321 jobject o = env_->NewWeakGlobalRef(s);
322 EXPECT_TRUE(o != NULL);
323 EXPECT_TRUE(o != s);
324
325 // TODO: check that o is a weak global reference.
326}
327
328TEST_F(JniInternalTest, DeleteWeakGlobalRef_NULL) {
329 env_->DeleteWeakGlobalRef(NULL);
330}
331
332TEST_F(JniInternalTest, DeleteWeakGlobalRef) {
333 jstring s = env_->NewStringUTF("");
334 ASSERT_TRUE(s != NULL);
335
336 jobject o = env_->NewWeakGlobalRef(s);
337 ASSERT_TRUE(o != NULL);
338 env_->DeleteWeakGlobalRef(o);
339
340 // Currently, deleting an already-deleted reference is just a warning.
341 env_->DeleteWeakGlobalRef(o);
342
343 jobject o1 = env_->NewWeakGlobalRef(s);
344 ASSERT_TRUE(o1 != NULL);
345 jobject o2 = env_->NewWeakGlobalRef(s);
346 ASSERT_TRUE(o2 != NULL);
347
348 env_->DeleteWeakGlobalRef(o1);
349 env_->DeleteWeakGlobalRef(o2);
350}
351
Carl Shapiro9b9ba282011-08-14 15:30:39 -0700352bool EnsureInvokeStub(Method* method);
353
354byte* AllocateCode(void* code, size_t length) {
355 int prot = PROT_READ | PROT_WRITE | PROT_EXEC;
356 void* addr = mmap(NULL, length, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
357 CHECK(addr != MAP_FAILED);
358 memcpy(addr, code, length);
359 __builtin___clear_cache(addr, (byte*)addr + length);
360 // Set the low-order bit so a BLX will switch to Thumb mode.
361 return reinterpret_cast<byte*>(reinterpret_cast<uintptr_t>(addr) | 1);
362}
363
364Method::InvokeStub* AllocateStub(Method* method,
365 byte* code,
366 size_t length) {
367 CHECK(method->GetInvokeStub() == NULL);
368 EnsureInvokeStub(method);
369 Method::InvokeStub* stub = method->GetInvokeStub();
370 CHECK(stub != NULL);
371 method->SetCode(AllocateCode(code, length));
372 CHECK(method->GetCode() != NULL);
373 return stub;
374}
375
376void FreeStub(Method* method, size_t length) {
377 void* addr = const_cast<void*>(method->GetCode());
378 munmap(addr, length);
379 method->SetCode(NULL);
380}
381
382#if defined(__arm__)
383TEST_F(JniInternalTest, StaticMainMethod) {
384 scoped_ptr<DexFile> dex(OpenDexFileBase64(kMainDex));
385
386 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
387 ASSERT_TRUE(class_loader != NULL);
388
389 Class* klass = class_linker_->FindClass("LMain;", class_loader);
390 ASSERT_TRUE(klass != NULL);
391
392 Method* method = klass->FindDirectMethod("main", "([Ljava/lang/String;)V");
393 ASSERT_TRUE(method != NULL);
394
395 byte main_LV_code[] = {
396 0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8, 0x00, 0x00,
397 0xcd, 0xf8, 0x14, 0x10, 0x03, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
398 };
399
400 Method::InvokeStub* stub = AllocateStub(method,
401 main_LV_code,
402 sizeof(main_LV_code));
403
404 Object* arg = NULL;
405
406 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), NULL);
407
408 FreeStub(method, sizeof(main_LV_code));
409}
410
411TEST_F(JniInternalTest, StaticNopMethod) {
412 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
413
414 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
415 ASSERT_TRUE(class_loader != NULL);
416
417 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
418 ASSERT_TRUE(klass != NULL);
419
420 Method* method = klass->FindDirectMethod("nop", "()V");
421 ASSERT_TRUE(method != NULL);
422
423 byte nop_V_code[] = {
424 0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
425 0x00, 0x00, 0x03, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
426 };
427
428 Method::InvokeStub* stub = AllocateStub(method,
429 nop_V_code,
430 sizeof(nop_V_code));
431 ASSERT_TRUE(stub);
432
433 (*stub)(method, NULL, NULL, NULL, NULL);
434
435 FreeStub(method, sizeof(nop_V_code));
436}
437
438TEST_F(JniInternalTest, StaticIdentityByteMethod) {
439 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
440
441 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
442 ASSERT_TRUE(class_loader != NULL);
443
444 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
445 ASSERT_TRUE(klass != NULL);
446
447 Method* method = klass->FindDirectMethod("identity", "(B)B");
448 ASSERT_TRUE(method != NULL);
449
450 byte identity_BB_code[] = {
451 0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
452 0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0x05, 0x98,
453 0x03, 0xb0, 0xbd, 0xe8, 0x00, 0x80, 0x00, 0x00,
454 };
455
456 Method::InvokeStub* stub = AllocateStub(method,
457 identity_BB_code,
458 sizeof(identity_BB_code));
459
460 int arg;
461 JValue result;
462
463 arg = 0;
464 result.b = -1;
465 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
466 EXPECT_EQ(0, result.b);
467
468 arg = -1;
469 result.b = 0;
470 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
471 EXPECT_EQ(-1, result.b);
472
473 arg = SCHAR_MAX;
474 result.b = 0;
475 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
476 EXPECT_EQ(SCHAR_MAX, result.b);
477
478 arg = SCHAR_MIN;
479 result.b = 0;
480 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
481 EXPECT_EQ(SCHAR_MIN, result.b);
482
483 FreeStub(method, sizeof(identity_BB_code));
484}
485
486TEST_F(JniInternalTest, StaticIdentityIntMethod) {
487 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
488
489 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
490 ASSERT_TRUE(class_loader != NULL);
491
492 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
493 ASSERT_TRUE(klass != NULL);
494
495 Method* method = klass->FindDirectMethod("identity", "(I)I");
496 ASSERT_TRUE(method != NULL);
497
498 byte identity_II_code[] = {
499 0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
500 0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0x05, 0x98,
501 0x03, 0xb0, 0xbd, 0xe8, 0x00, 0x80, 0x00, 0x00,
502 };
503
504 Method::InvokeStub* stub = AllocateStub(method,
505 identity_II_code,
506 sizeof(identity_II_code));
507
508 int arg;
509 JValue result;
510
511 arg = 0;
512 result.i = -1;
513 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
514 EXPECT_EQ(0, result.i);
515
516 arg = -1;
517 result.i = 0;
518 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
519 EXPECT_EQ(-1, result.i);
520
521 arg = INT_MAX;
522 result.i = 0;
523 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
524 EXPECT_EQ(INT_MAX, result.i);
525
526 arg = INT_MIN;
527 result.i = 0;
528 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
529 EXPECT_EQ(INT_MIN, result.i);
530
531 FreeStub(method, sizeof(identity_II_code));
532}
533
534TEST_F(JniInternalTest, StaticIdentityDoubleMethod) {
535 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
536
537 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
538 ASSERT_TRUE(class_loader != NULL);
539
540 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
541 ASSERT_TRUE(klass != NULL);
542
543 Method* method = klass->FindDirectMethod("identity", "(D)D");
544 ASSERT_TRUE(method != NULL);
545
546 byte identity_DD_code[] = {
547 0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
548 0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0xcd, 0xf8,
549 0x18, 0x20, 0x05, 0x98, 0x06, 0x99, 0x03, 0xb0,
550 0xbd, 0xe8, 0x00, 0x80,
551 };
552
553 Method::InvokeStub* stub = AllocateStub(method,
554 identity_DD_code,
555 sizeof(identity_DD_code));
556
557 double arg;
558 JValue result;
559
560 arg = 0.0;
561 result.d = -1.0;
562 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
563 EXPECT_EQ(0.0, result.d);
564
565 arg = -1.0;
566 result.d = 0.0;
567 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
568 EXPECT_EQ(-1.0, result.d);
569
570 arg = DBL_MAX;
571 result.d = 0.0;
572 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
573 EXPECT_EQ(DBL_MAX, result.d);
574
575 arg = DBL_MIN;
576 result.d = 0.0;
577 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(&arg), &result);
578 EXPECT_EQ(DBL_MIN, result.d);
579
580 FreeStub(method, sizeof(identity_DD_code));
581}
582
583TEST_F(JniInternalTest, StaticSumIntIntMethod) {
584 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
585
586 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
587 ASSERT_TRUE(class_loader != NULL);
588
589 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
590 ASSERT_TRUE(klass != NULL);
591
592 Method* method = klass->FindDirectMethod("sum", "(II)I");
593 ASSERT_TRUE(method != NULL);
594
595 byte sum_III_code[] = {
596 0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
597 0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0xcd, 0xf8,
598 0x18, 0x20, 0x05, 0x98, 0x06, 0x99, 0x42, 0x18,
599 0xcd, 0xf8, 0x04, 0x20, 0x01, 0x98, 0x03, 0xb0,
600 0xbd, 0xe8, 0x00, 0x80,
601 };
602
603 Method::InvokeStub* stub = AllocateStub(method,
604 sum_III_code,
605 sizeof(sum_III_code));
606
607 int args[2];
608 JValue result;
609
610 args[0] = 0;
611 args[1] = 0;
612 result.i = -1;
613 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
614 EXPECT_EQ(0, result.i);
615
616 args[0] = 1;
617 args[1] = 2;
618 result.i = 0;
619 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
620 EXPECT_EQ(3, result.i);
621
622 args[0] = -2;
623 args[1] = 5;
624 result.i = 0;
625 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
626 EXPECT_EQ(3, result.i);
627
628 args[0] = INT_MAX;
629 args[1] = INT_MIN;
630 result.i = 1234;
631 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
632 EXPECT_EQ(-1, result.i);
633
634 args[0] = INT_MAX;
635 args[1] = INT_MAX;
636 result.i = INT_MIN;
637 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
638 EXPECT_EQ(-2, result.i);
639
640 FreeStub(method, sizeof(sum_III_code));
641}
642
643TEST_F(JniInternalTest, StaticSumIntIntIntMethod) {
644 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
645
646 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
647 ASSERT_TRUE(class_loader != NULL);
648
649 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
650 ASSERT_TRUE(klass != NULL);
651
652 Method* method = klass->FindDirectMethod("sum", "(III)I");
653 ASSERT_TRUE(method != NULL);
654
655 byte sum_IIII_code[] = {
656 0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
657 0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0xcd, 0xf8,
658 0x18, 0x20, 0xcd, 0xf8, 0x1c, 0x30, 0x05, 0x98,
659 0x06, 0x99, 0x42, 0x18, 0xcd, 0xf8, 0x04, 0x20,
660 0x01, 0x9b, 0xdd, 0xf8, 0x1c, 0xc0, 0x13, 0xeb,
661 0x0c, 0x03, 0xcd, 0xf8, 0x04, 0x30, 0x01, 0x98,
662 0x03, 0xb0, 0xbd, 0xe8, 0x00, 0x80, 0x00, 0x00,
663 };
664
665 Method::InvokeStub* stub = AllocateStub(method,
666 sum_IIII_code,
667 sizeof(sum_IIII_code));
668
669 int args[3];
670 JValue result;
671
672 args[0] = 0;
673 args[1] = 0;
674 args[2] = 0;
675 result.i = -1;
676 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
677 EXPECT_EQ(0, result.i);
678
679 args[0] = 1;
680 args[1] = 2;
681 args[2] = 3;
682 result.i = 0;
683 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
684 EXPECT_EQ(6, result.i);
685
686 args[0] = -1;
687 args[1] = 2;
688 args[2] = -3;
689 result.i = 0;
690 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
691 EXPECT_EQ(-2, result.i);
692
693 args[0] = INT_MAX;
694 args[1] = INT_MIN;
695 args[2] = INT_MAX;
696 result.i = 1234;
697 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
698 EXPECT_EQ(2147483646, result.i);
699
700 args[0] = INT_MAX;
701 args[1] = INT_MAX;
702 args[2] = INT_MAX;
703 result.i = INT_MIN;
704 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
705 EXPECT_EQ(2147483645, result.i);
706
707 FreeStub(method, sizeof(sum_IIII_code));
708}
709
710TEST_F(JniInternalTest, StaticSumIntIntIntIntMethod) {
711 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
712
713 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
714 ASSERT_TRUE(class_loader != NULL);
715
716 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
717 ASSERT_TRUE(klass != NULL);
718
719 Method* method = klass->FindDirectMethod("sum", "(IIII)I");
720 ASSERT_TRUE(method != NULL);
721
722 byte sum_IIIII_code[] = {
723 0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
724 0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0xcd, 0xf8,
725 0x18, 0x20, 0xcd, 0xf8, 0x1c, 0x30, 0x05, 0x98,
726 0x06, 0x99, 0x42, 0x18, 0xcd, 0xf8, 0x04, 0x20,
727 0x01, 0x9b, 0xdd, 0xf8, 0x1c, 0xc0, 0x13, 0xeb,
728 0x0c, 0x03, 0xcd, 0xf8, 0x04, 0x30, 0x01, 0x98,
729 0x08, 0x99, 0x40, 0x18, 0xcd, 0xf8, 0x04, 0x00,
730 0x01, 0x98, 0x03, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
731 };
732
733 Method::InvokeStub* stub = AllocateStub(method,
734 sum_IIIII_code,
735 sizeof(sum_IIIII_code));
736
737 int args[4];
738 JValue result;
739
740 args[0] = 0;
741 args[1] = 0;
742 args[2] = 0;
743 args[3] = 0;
744 result.i = -1;
745 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
746 EXPECT_EQ(0, result.i);
747
748 args[0] = 1;
749 args[1] = 2;
750 args[2] = 3;
751 args[3] = 4;
752 result.i = 0;
753 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
754 EXPECT_EQ(10, result.i);
755
756 args[0] = -1;
757 args[1] = 2;
758 args[2] = -3;
759 args[3] = 4;
760 result.i = 0;
761 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
762 EXPECT_EQ(2, result.i);
763
764 args[0] = INT_MAX;
765 args[1] = INT_MIN;
766 args[2] = INT_MAX;
767 args[3] = INT_MIN;
768 result.i = 1234;
769 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
770 EXPECT_EQ(-2, result.i);
771
772 args[0] = INT_MAX;
773 args[1] = INT_MAX;
774 args[2] = INT_MAX;
775 args[3] = INT_MAX;
776 result.i = INT_MIN;
777 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
778 EXPECT_EQ(-4, result.i);
779
780 FreeStub(method, sizeof(sum_IIIII_code));
781}
782
783TEST_F(JniInternalTest, StaticSumIntIntIntIntIntMethod) {
784 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
785
786 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
787 ASSERT_TRUE(class_loader != NULL);
788
789 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
790 ASSERT_TRUE(klass != NULL);
791
792 Method* method = klass->FindDirectMethod("sum", "(IIIII)I");
793 ASSERT_TRUE(method != NULL);
794
795 byte sum_IIIIII_code[] = {
796 0x2d, 0xe9, 0x00, 0x40, 0x83, 0xb0, 0xcd, 0xf8,
797 0x00, 0x00, 0xcd, 0xf8, 0x14, 0x10, 0xcd, 0xf8,
798 0x18, 0x20, 0xcd, 0xf8, 0x1c, 0x30, 0x05, 0x98,
799 0x06, 0x99, 0x42, 0x18, 0xcd, 0xf8, 0x04, 0x20,
800 0x01, 0x9b, 0xdd, 0xf8, 0x1c, 0xc0, 0x13, 0xeb,
801 0x0c, 0x03, 0xcd, 0xf8, 0x04, 0x30, 0x01, 0x98,
802 0x08, 0x99, 0x40, 0x18, 0xcd, 0xf8, 0x04, 0x00,
803 0x01, 0x9a, 0x09, 0x9b, 0xd2, 0x18, 0xcd, 0xf8,
804 0x04, 0x20, 0x01, 0x98, 0x03, 0xb0, 0xbd, 0xe8,
805 0x00, 0x80, 0x00, 0x00,
806 };
807
808 Method::InvokeStub* stub = AllocateStub(method,
809 sum_IIIIII_code,
810 sizeof(sum_IIIIII_code));
811
812 int args[5];
813 JValue result;
814
815 args[0] = 0;
816 args[1] = 0;
817 args[2] = 0;
818 args[3] = 0;
819 args[4] = 0;
820 result.i = -1.0;
821 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
822 EXPECT_EQ(0, result.i);
823
824 args[0] = 1;
825 args[1] = 2;
826 args[2] = 3;
827 args[3] = 4;
828 args[4] = 5;
829 result.i = 0;
830 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
831 EXPECT_EQ(15, result.i);
832
833 args[0] = -1;
834 args[1] = 2;
835 args[2] = -3;
836 args[3] = 4;
837 args[4] = -5;
838 result.i = 0;
839 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
840 EXPECT_EQ(-3, result.i);
841
842 args[0] = INT_MAX;
843 args[1] = INT_MIN;
844 args[2] = INT_MAX;
845 args[3] = INT_MIN;
846 args[4] = INT_MAX;
847 result.i = 1234;
848 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
849 EXPECT_EQ(2147483645, result.i);
850
851 args[0] = INT_MAX;
852 args[1] = INT_MAX;
853 args[2] = INT_MAX;
854 args[3] = INT_MAX;
855 args[4] = INT_MAX;
856 result.i = INT_MIN;
857 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
858 EXPECT_EQ(2147483643, result.i);
859
860 FreeStub(method, sizeof(sum_IIIIII_code));
861}
862
863TEST_F(JniInternalTest, StaticSumDoubleDoubleMethod) {
864 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
865
866 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
867 ASSERT_TRUE(class_loader != NULL);
868
869 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
870 ASSERT_TRUE(klass != NULL);
871
872 Method* method = klass->FindDirectMethod("sum", "(DD)D");
873 ASSERT_TRUE(method != NULL);
874
875 byte sum_DDD_code[] = {
876 0x2d, 0xe9, 0x00, 0x40, 0x87, 0xb0, 0xcd, 0xf8,
877 0x00, 0x00, 0xcd, 0xf8, 0x24, 0x10, 0xcd, 0xf8,
878 0x28, 0x20, 0xcd, 0xf8, 0x2c, 0x30, 0x9d, 0xed,
879 0x09, 0x0b, 0x9d, 0xed, 0x0b, 0x1b, 0x30, 0xee,
880 0x01, 0x2b, 0x8d, 0xed, 0x04, 0x2b, 0x04, 0x98,
881 0x05, 0x99, 0x07, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
882 };
883
884 Method::InvokeStub* stub = AllocateStub(method,
885 sum_DDD_code,
886 sizeof(sum_DDD_code));
887
888 double args[2];
889 JValue result;
890
891 args[0] = 0.0;
892 args[1] = 0.0;
893 result.d = -1.0;
894 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
895 EXPECT_EQ(0.0, result.d);
896
897 args[0] = 1.0;
898 args[1] = 2.0;
899 result.d = 0.0;
900 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
901 EXPECT_EQ(3.0, result.d);
902
903 args[0] = 1.0;
904 args[1] = -2.0;
905 result.d = 0.0;
906 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
907 EXPECT_EQ(-1.0, result.d);
908
909 args[0] = DBL_MAX;
910 args[1] = DBL_MIN;
911 result.d = 0.0;
912 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
913 EXPECT_EQ(1.7976931348623157e308, result.d);
914
915 args[0] = DBL_MAX;
916 args[1] = DBL_MAX;
917 result.d = 0.0;
918 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
919 EXPECT_EQ(INFINITY, result.d);
920
921 FreeStub(method, sizeof(sum_DDD_code));
922}
923
924TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleMethod) {
925 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
926
927 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
928 ASSERT_TRUE(class_loader != NULL);
929
930 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
931 ASSERT_TRUE(klass != NULL);
932
933 Method* method = klass->FindDirectMethod("sum", "(DDD)D");
934 ASSERT_TRUE(method != NULL);
935
936 byte sum_DDDD_code[] = {
937 0x2d, 0xe9, 0x00, 0x40, 0x87, 0xb0, 0xcd, 0xf8,
938 0x00, 0x00, 0xcd, 0xf8, 0x24, 0x10, 0xcd, 0xf8,
939 0x28, 0x20, 0xcd, 0xf8, 0x2c, 0x30, 0x9d, 0xed,
940 0x09, 0x0b, 0x9d, 0xed, 0x0b, 0x1b, 0x30, 0xee,
941 0x01, 0x2b, 0x8d, 0xed, 0x04, 0x2b, 0x9d, 0xed,
942 0x04, 0x3b, 0x9d, 0xed, 0x0d, 0x4b, 0x33, 0xee,
943 0x04, 0x3b, 0x8d, 0xed, 0x04, 0x3b, 0x04, 0x98,
944 0x05, 0x99, 0x07, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
945 };
946
947 Method::InvokeStub* stub = AllocateStub(method,
948 sum_DDDD_code,
949 sizeof(sum_DDDD_code));
950
951 double args[3];
952 JValue result;
953
954 args[0] = 0.0;
955 args[1] = 0.0;
956 args[2] = 0.0;
957 result.d = -1.0;
958 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
959 EXPECT_EQ(0.0, result.d);
960
961 args[0] = 1.0;
962 args[1] = 2.0;
963 args[2] = 3.0;
964 result.d = 0.0;
965 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
966 EXPECT_EQ(6.0, result.d);
967
968 args[0] = 1.0;
969 args[1] = -2.0;
970 args[2] = 3.0;
971 result.d = 0.0;
972 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
973 EXPECT_EQ(2.0, result.d);
974
975 FreeStub(method, sizeof(sum_DDDD_code));
976}
977
978TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleMethod) {
979 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
980
981 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
982 ASSERT_TRUE(class_loader != NULL);
983
984 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
985 ASSERT_TRUE(klass != NULL);
986
987 Method* method = klass->FindDirectMethod("sum", "(DDDD)D");
988 ASSERT_TRUE(method != NULL);
989
990 byte sum_DDDDD_code[] = {
991 0x2d, 0xe9, 0x00, 0x40, 0x87, 0xb0, 0xcd, 0xf8,
992 0x00, 0x00, 0xcd, 0xf8, 0x24, 0x10, 0xcd, 0xf8,
993 0x28, 0x20, 0xcd, 0xf8, 0x2c, 0x30, 0x9d, 0xed,
994 0x09, 0x0b, 0x9d, 0xed, 0x0b, 0x1b, 0x30, 0xee,
995 0x01, 0x2b, 0x8d, 0xed, 0x04, 0x2b, 0x9d, 0xed,
996 0x04, 0x3b, 0x9d, 0xed, 0x0d, 0x4b, 0x33, 0xee,
997 0x04, 0x3b, 0x8d, 0xed, 0x04, 0x3b, 0x9d, 0xed,
998 0x04, 0x5b, 0x9d, 0xed, 0x0f, 0x6b, 0x35, 0xee,
999 0x06, 0x5b, 0x8d, 0xed, 0x04, 0x5b, 0x04, 0x98,
1000 0x05, 0x99, 0x07, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
1001 };
1002
1003 Method::InvokeStub* stub = AllocateStub(method,
1004 sum_DDDDD_code,
1005 sizeof(sum_DDDDD_code));
1006
1007 double args[4];
1008 JValue result;
1009
1010 args[0] = 0.0;
1011 args[1] = 0.0;
1012 args[2] = 0.0;
1013 args[3] = 0.0;
1014 result.d = -1.0;
1015 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
1016 EXPECT_EQ(0.0, result.d);
1017
1018 args[0] = 1.0;
1019 args[1] = 2.0;
1020 args[2] = 3.0;
1021 args[3] = 4.0;
1022 result.d = 0.0;
1023 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
1024 EXPECT_EQ(10.0, result.d);
1025
1026 args[0] = 1.0;
1027 args[1] = -2.0;
1028 args[2] = 3.0;
1029 args[3] = -4.0;
1030 result.d = 0.0;
1031 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
1032 EXPECT_EQ(-2.0, result.d);
1033
1034 FreeStub(method, sizeof(sum_DDDDD_code));
1035}
1036
1037TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleDoubleMethod) {
1038 scoped_ptr<DexFile> dex(OpenDexFileBase64(kStaticLeafMethodsDex));
1039
1040 PathClassLoader* class_loader = AllocPathClassLoader(dex.get());
1041 ASSERT_TRUE(class_loader != NULL);
1042
1043 Class* klass = class_linker_->FindClass("LStaticLeafMethods;", class_loader);
1044 ASSERT_TRUE(klass != NULL);
1045
1046 Method* method = klass->FindDirectMethod("sum", "(DDDDD)D");
1047 ASSERT_TRUE(method != NULL);
1048
1049 byte sum_DDDDDD_code[] = {
1050 0x2d, 0xe9, 0x00, 0x40, 0x87, 0xb0, 0xcd, 0xf8,
1051 0x00, 0x00, 0xcd, 0xf8, 0x24, 0x10, 0xcd, 0xf8,
1052 0x28, 0x20, 0xcd, 0xf8, 0x2c, 0x30, 0x9d, 0xed,
1053 0x09, 0x0b, 0x9d, 0xed, 0x0b, 0x1b, 0x30, 0xee,
1054 0x01, 0x2b, 0x8d, 0xed, 0x04, 0x2b, 0x9d, 0xed,
1055 0x04, 0x3b, 0x9d, 0xed, 0x0d, 0x4b, 0x33, 0xee,
1056 0x04, 0x3b, 0x8d, 0xed, 0x04, 0x3b, 0x9d, 0xed,
1057 0x04, 0x5b, 0x9d, 0xed, 0x0f, 0x6b, 0x35, 0xee,
1058 0x06, 0x5b, 0x8d, 0xed, 0x04, 0x5b, 0x9d, 0xed,
1059 0x04, 0x7b, 0x9d, 0xed, 0x11, 0x0b, 0x37, 0xee,
1060 0x00, 0x7b, 0x8d, 0xed, 0x04, 0x7b, 0x04, 0x98,
1061 0x05, 0x99, 0x07, 0xb0, 0xbd, 0xe8, 0x00, 0x80,
1062 };
1063
1064 Method::InvokeStub* stub = AllocateStub(method,
1065 sum_DDDDDD_code,
1066 sizeof(sum_DDDDDD_code));
1067
1068 double args[5];
1069 JValue result;
1070
1071 args[0] = 0.0;
1072 args[1] = 0.0;
1073 args[2] = 0.0;
1074 args[3] = 0.0;
1075 args[4] = 0.0;
1076 result.d = -1.0;
1077 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
1078 EXPECT_EQ(0.0, result.d);
1079
1080 args[0] = 1.0;
1081 args[1] = 2.0;
1082 args[2] = 3.0;
1083 args[3] = 4.0;
1084 args[4] = 5.0;
1085 result.d = 0.0;
1086 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
1087 EXPECT_EQ(15.0, result.d);
1088
1089 args[0] = 1.0;
1090 args[1] = -2.0;
1091 args[2] = 3.0;
1092 args[3] = -4.0;
1093 args[4] = 5.0;
1094 result.d = 0.0;
1095 (*stub)(method, NULL, NULL, reinterpret_cast<byte*>(args), &result);
1096 EXPECT_EQ(3.0, result.d);
1097
1098 FreeStub(method, sizeof(sum_DDDDDD_code));
1099}
1100#endif // __arm__
1101
1102}