blob: e1f62fc655bdd51e5c140937361933829b93eb67 [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 */
Elliott Hughes0c9cd562011-08-12 10:59:29 -070016
Carl Shapiro9b9ba282011-08-14 15:30:39 -070017#include "jni_internal.h"
Elliott Hughes0c9cd562011-08-12 10:59:29 -070018
Carl Shapiro9b9ba282011-08-14 15:30:39 -070019#include <sys/mman.h>
20
Ian Rogers0cfe1fb2011-08-26 03:29:44 -070021#include <cmath>
22
Carl Shapiro9b9ba282011-08-14 15:30:39 -070023#include "common_test.h"
Elliott Hughes726079d2011-10-07 18:43:44 -070024#include "ScopedLocalRef.h"
Elliott Hughes0c9cd562011-08-12 10:59:29 -070025
26namespace art {
27
Brian Carlstromf734cf52011-08-17 16:28:14 -070028class JniInternalTest : public CommonTest {
Elliott Hughesc7ac37f2011-08-12 12:21:58 -070029 protected:
30 virtual void SetUp() {
Brian Carlstromf734cf52011-08-17 16:28:14 -070031 CommonTest::SetUp();
Elliott Hughes5174fe62011-08-23 15:12:35 -070032
Elliott Hughesa2501992011-08-26 19:39:54 -070033 vm_ = Runtime::Current()->GetJavaVM();
34
Elliott Hughes5174fe62011-08-23 15:12:35 -070035 // Turn on -verbose:jni for the JNI tests.
Elliott Hughes4dd9b4d2011-12-12 18:29:24 -080036 gLogVerbosity.jni = true;
Elliott Hughes5174fe62011-08-23 15:12:35 -070037
Elliott Hughesc7ac37f2011-08-12 12:21:58 -070038 env_ = Thread::Current()->GetJniEnv();
Elliott Hughesb465ab02011-08-24 11:21:21 -070039
Elliott Hughes726079d2011-10-07 18:43:44 -070040 ScopedLocalRef<jclass> aioobe(env_, env_->FindClass("java/lang/ArrayIndexOutOfBoundsException"));
41 CHECK(aioobe.get() != NULL);
42 aioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(aioobe.get()));
Elliott Hughesb465ab02011-08-24 11:21:21 -070043
Elliott Hughes726079d2011-10-07 18:43:44 -070044 ScopedLocalRef<jclass> sioobe(env_, env_->FindClass("java/lang/StringIndexOutOfBoundsException"));
45 CHECK(sioobe.get() != NULL);
46 sioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(sioobe.get()));
47 }
48
49 virtual void TearDown() {
50 env_->DeleteGlobalRef(aioobe_);
51 env_->DeleteGlobalRef(sioobe_);
52 CommonTest::TearDown();
Elliott Hughesc7ac37f2011-08-12 12:21:58 -070053 }
Elliott Hughesb465ab02011-08-24 11:21:21 -070054
Elliott Hughes77405792012-03-15 15:22:12 -070055 Method::InvokeStub* DoCompile(Method*& method, Object*& receiver, bool is_static, const char* method_name, const char* method_signature) {
56 const char* class_name = is_static ? "StaticLeafMethods" : "NonStaticLeafMethods";
57 SirtRef<ClassLoader> class_loader(LoadDex(class_name));
58 if (is_static) {
59 CompileDirectMethod(class_loader.get(), class_name, method_name, method_signature);
60 } else {
61 CompileVirtualMethod(NULL, "java.lang.Class", "isFinalizable", "()Z");
62 CompileDirectMethod(NULL, "java.lang.Object", "<init>", "()V");
63 CompileVirtualMethod(class_loader.get(), class_name, method_name, method_signature);
64 }
65
66 Class* c = class_linker_->FindClass(DotToDescriptor(class_name).c_str(), class_loader.get());
67 CHECK(c != NULL);
68
69 method = is_static ? c->FindDirectMethod(method_name, method_signature) : c->FindVirtualMethod(method_name, method_signature);
70 CHECK(method != NULL);
71
72 receiver = (is_static ? NULL : c->AllocObject());
73
74 Method::InvokeStub* stub = method->GetInvokeStub();
75 CHECK(stub != NULL);
76
77 return stub;
78 }
79
80 void InvokeNopMethod(bool is_static) {
81 // TODO: remove this when we have a working x86 compiler.
82#if !defined(__arm__)
83 if (!is_static) {
84 return;
85 }
86#endif
87 Method* method;
88 Object* receiver;
89 Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "nop", "()V");
90 (*stub)(method, receiver, Thread::Current(), NULL, NULL);
91 }
92
93 void InvokeIdentityByteMethod(bool is_static) {
94 // TODO: remove this when we have a working x86 compiler.
95#if !defined(__arm__)
96 if (!is_static) {
97 return;
98 }
99#endif
100 Method* method;
101 Object* receiver;
102 Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "identity", "(B)B");
103
104 JValue args[1];
105 JValue result;
106
107 args[0].i = 0;
108 result.b = -1;
109 (*stub)(method, receiver, Thread::Current(), args, &result);
110 EXPECT_EQ(0, result.b);
111
112 args[0].i = -1;
113 result.b = 0;
114 (*stub)(method, receiver, Thread::Current(), args, &result);
115 EXPECT_EQ(-1, result.b);
116
117 args[0].i = SCHAR_MAX;
118 result.b = 0;
119 (*stub)(method, receiver, Thread::Current(), args, &result);
120 EXPECT_EQ(SCHAR_MAX, result.b);
121
122 args[0].i = SCHAR_MIN;
123 result.b = 0;
124 (*stub)(method, receiver, Thread::Current(), args, &result);
125 EXPECT_EQ(SCHAR_MIN, result.b);
126 }
127
128 void InvokeIdentityIntMethod(bool is_static) {
129 // TODO: remove this when we have a working x86 compiler.
130#if !defined(__arm__)
131 if (!is_static) {
132 return;
133 }
134#endif
135 Method* method;
136 Object* receiver;
137 Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "identity", "(I)I");
138
139 JValue args[1];
140 JValue result;
141
142 args[0].i = 0;
143 result.i = -1;
144 (*stub)(method, receiver, Thread::Current(), args, &result);
145 EXPECT_EQ(0, result.i);
146
147 args[0].i = -1;
148 result.i = 0;
149 (*stub)(method, receiver, Thread::Current(), args, &result);
150 EXPECT_EQ(-1, result.i);
151
152 args[0].i = INT_MAX;
153 result.i = 0;
154 (*stub)(method, receiver, Thread::Current(), args, &result);
155 EXPECT_EQ(INT_MAX, result.i);
156
157 args[0].i = INT_MIN;
158 result.i = 0;
159 (*stub)(method, receiver, Thread::Current(), args, &result);
160 EXPECT_EQ(INT_MIN, result.i);
161 }
162
163 void InvokeIdentityDoubleMethod(bool is_static) {
164 // TODO: remove this when we have a working x86 compiler.
165#if !defined(__arm__)
166 if (!is_static) {
167 return;
168 }
169#endif
170 Method* method;
171 Object* receiver;
172 Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "identity", "(D)D");
173
174 JValue args[1];
175 JValue result;
176
177 args[0].d = 0.0;
178 result.d = -1.0;
179 (*stub)(method, receiver, Thread::Current(), args, &result);
180 EXPECT_EQ(0.0, result.d);
181
182 args[0].d = -1.0;
183 result.d = 0.0;
184 (*stub)(method, receiver, Thread::Current(), args, &result);
185 EXPECT_EQ(-1.0, result.d);
186
187 args[0].d = DBL_MAX;
188 result.d = 0.0;
189 (*stub)(method, receiver, Thread::Current(), args, &result);
190 EXPECT_EQ(DBL_MAX, result.d);
191
192 args[0].d = DBL_MIN;
193 result.d = 0.0;
194 (*stub)(method, receiver, Thread::Current(), args, &result);
195 EXPECT_EQ(DBL_MIN, result.d);
196 }
197
198 void InvokeSumIntIntMethod(bool is_static) {
199 // TODO: remove this when we have a working x86 compiler.
200#if !defined(__arm__)
201 if (!is_static) {
202 return;
203 }
204#endif
205 Method* method;
206 Object* receiver;
207 Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(II)I");
208
209 JValue result;
210 result.i = -1;
211 JValue args[2];
212 args[0].i = 0;
213 args[1].i = 0;
214 (*stub)(method, NULL, Thread::Current(), args, &result);
215 EXPECT_EQ(0, result.i);
216
217 result.i = 0;
218 args[0].i = 1;
219 args[1].i = 2;
220 (*stub)(method, NULL, Thread::Current(), args, &result);
221 EXPECT_EQ(3, result.i);
222
223 result.i = 0;
224 args[0].i = -2;
225 args[1].i = 5;
226 (*stub)(method, NULL, Thread::Current(), args, &result);
227 EXPECT_EQ(3, result.i);
228
229 result.i = 1234;
230 args[0].i = INT_MAX;
231 args[1].i = INT_MIN;
232 (*stub)(method, NULL, Thread::Current(), args, &result);
233 EXPECT_EQ(-1, result.i);
234
235 result.i = INT_MIN;
236 args[0].i = INT_MAX;
237 args[1].i = INT_MAX;
238 (*stub)(method, NULL, Thread::Current(), args, &result);
239 EXPECT_EQ(-2, result.i);
240 }
241
242 void InvokeSumIntIntIntMethod(bool is_static) {
243 // TODO: remove this when we have a working x86 compiler.
244#if !defined(__arm__)
245 if (!is_static) {
246 return;
247 }
248#endif
249 Method* method;
250 Object* receiver;
251 Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(III)I");
252
253 JValue result;
254 result.i = -1;
255 JValue args[3];
256 args[0].i = 0;
257 args[1].i = 0;
258 args[2].i = 0;
259 (*stub)(method, NULL, Thread::Current(), args, &result);
260 EXPECT_EQ(0, result.i);
261
262 result.i = 0;
263 args[0].i = 1;
264 args[1].i = 2;
265 args[2].i = 3;
266 (*stub)(method, NULL, Thread::Current(), args, &result);
267 EXPECT_EQ(6, result.i);
268
269 result.i = 0;
270 args[0].i = -1;
271 args[1].i = 2;
272 args[2].i = -3;
273 (*stub)(method, NULL, Thread::Current(), args, &result);
274 EXPECT_EQ(-2, result.i);
275
276 result.i = 1234;
277 args[0].i = INT_MAX;
278 args[1].i = INT_MIN;
279 args[2].i = INT_MAX;
280 (*stub)(method, NULL, Thread::Current(), args, &result);
281 EXPECT_EQ(2147483646, result.i);
282
283 result.i = INT_MIN;
284 args[0].i = INT_MAX;
285 args[1].i = INT_MAX;
286 args[2].i = INT_MAX;
287 (*stub)(method, NULL, Thread::Current(), args, &result);
288 EXPECT_EQ(2147483645, result.i);
289 }
290
291 void InvokeSumIntIntIntIntMethod(bool is_static) {
292 // TODO: remove this when we have a working x86 compiler.
293#if !defined(__arm__)
294 if (!is_static) {
295 return;
296 }
297#endif
298 Method* method;
299 Object* receiver;
300 Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(IIII)I");
301
302 JValue result;
303 result.i = -1;
304 JValue args[4];
305 args[0].i = 0;
306 args[1].i = 0;
307 args[2].i = 0;
308 args[3].i = 0;
309 (*stub)(method, NULL, Thread::Current(), args, &result);
310 EXPECT_EQ(0, result.i);
311
312 result.i = 0;
313 args[0].i = 1;
314 args[1].i = 2;
315 args[2].i = 3;
316 args[3].i = 4;
317 (*stub)(method, NULL, Thread::Current(), args, &result);
318 EXPECT_EQ(10, result.i);
319
320 result.i = 0;
321 args[0].i = -1;
322 args[1].i = 2;
323 args[2].i = -3;
324 args[3].i = 4;
325 (*stub)(method, NULL, Thread::Current(), args, &result);
326 EXPECT_EQ(2, result.i);
327
328 result.i = 1234;
329 args[0].i = INT_MAX;
330 args[1].i = INT_MIN;
331 args[2].i = INT_MAX;
332 args[3].i = INT_MIN;
333 (*stub)(method, NULL, Thread::Current(), args, &result);
334 EXPECT_EQ(-2, result.i);
335
336 result.i = INT_MIN;
337 args[0].i = INT_MAX;
338 args[1].i = INT_MAX;
339 args[2].i = INT_MAX;
340 args[3].i = INT_MAX;
341 (*stub)(method, NULL, Thread::Current(), args, &result);
342 EXPECT_EQ(-4, result.i);
343 }
344
345 void InvokeSumIntIntIntIntIntMethod(bool is_static) {
346 // TODO: remove this when we have a working x86 compiler.
347#if !defined(__arm__)
348 if (!is_static) {
349 return;
350 }
351#endif
352 Method* method;
353 Object* receiver;
354 Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(IIIII)I");
355
356 JValue result;
357 result.i = -1.0;
358 JValue args[5];
359 args[0].i = 0;
360 args[1].i = 0;
361 args[2].i = 0;
362 args[3].i = 0;
363 args[4].i = 0;
364 (*stub)(method, NULL, Thread::Current(), args, &result);
365 EXPECT_EQ(0, result.i);
366
367 result.i = 0;
368 args[0].i = 1;
369 args[1].i = 2;
370 args[2].i = 3;
371 args[3].i = 4;
372 args[4].i = 5;
373 (*stub)(method, NULL, Thread::Current(), args, &result);
374 EXPECT_EQ(15, result.i);
375
376 result.i = 0;
377 args[0].i = -1;
378 args[1].i = 2;
379 args[2].i = -3;
380 args[3].i = 4;
381 args[4].i = -5;
382 (*stub)(method, NULL, Thread::Current(), args, &result);
383 EXPECT_EQ(-3, result.i);
384
385 result.i = 1234;
386 args[0].i = INT_MAX;
387 args[1].i = INT_MIN;
388 args[2].i = INT_MAX;
389 args[3].i = INT_MIN;
390 args[4].i = INT_MAX;
391 (*stub)(method, NULL, Thread::Current(), args, &result);
392 EXPECT_EQ(2147483645, result.i);
393
394 result.i = INT_MIN;
395 args[0].i = INT_MAX;
396 args[1].i = INT_MAX;
397 args[2].i = INT_MAX;
398 args[3].i = INT_MAX;
399 args[4].i = INT_MAX;
400 (*stub)(method, NULL, Thread::Current(), args, &result);
401 EXPECT_EQ(2147483643, result.i);
402 }
403
404 void InvokeSumDoubleDoubleMethod(bool is_static) {
405 // TODO: remove this when we have a working x86 compiler.
406#if !defined(__arm__)
407 if (!is_static) {
408 return;
409 }
410#endif
411 Method* method;
412 Object* receiver;
413 Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(DD)D");
414
415 JValue args[2];
416 JValue result;
417
418 args[0].d = 0.0;
419 args[1].d = 0.0;
420 result.d = -1.0;
421 (*stub)(method, NULL, Thread::Current(), args, &result);
422 EXPECT_EQ(0.0, result.d);
423
424 args[0].d = 1.0;
425 args[1].d = 2.0;
426 result.d = 0.0;
427 (*stub)(method, NULL, Thread::Current(), args, &result);
428 EXPECT_EQ(3.0, result.d);
429
430 args[0].d = 1.0;
431 args[1].d = -2.0;
432 result.d = 0.0;
433 (*stub)(method, NULL, Thread::Current(), args, &result);
434 EXPECT_EQ(-1.0, result.d);
435
436 args[0].d = DBL_MAX;
437 args[1].d = DBL_MIN;
438 result.d = 0.0;
439 (*stub)(method, NULL, Thread::Current(), args, &result);
440 EXPECT_EQ(1.7976931348623157e308, result.d);
441
442 args[0].d = DBL_MAX;
443 args[1].d = DBL_MAX;
444 result.d = 0.0;
445 (*stub)(method, NULL, Thread::Current(), args, &result);
446 EXPECT_EQ(INFINITY, result.d);
447 }
448
449 void InvokeSumDoubleDoubleDoubleMethod(bool is_static) {
450 // TODO: remove this when we have a working x86 compiler.
451#if !defined(__arm__)
452 if (!is_static) {
453 return;
454 }
455#endif
456 Method* method;
457 Object* receiver;
458 Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(DDD)D");
459
460 JValue args[3];
461 JValue result;
462
463 args[0].d = 0.0;
464 args[1].d = 0.0;
465 args[2].d = 0.0;
466 result.d = -1.0;
467 (*stub)(method, NULL, Thread::Current(), args, &result);
468 EXPECT_EQ(0.0, result.d);
469
470 args[0].d = 1.0;
471 args[1].d = 2.0;
472 args[2].d = 3.0;
473 result.d = 0.0;
474 (*stub)(method, NULL, Thread::Current(), args, &result);
475 EXPECT_EQ(6.0, result.d);
476
477 args[0].d = 1.0;
478 args[1].d = -2.0;
479 args[2].d = 3.0;
480 result.d = 0.0;
481 (*stub)(method, NULL, Thread::Current(), args, &result);
482 EXPECT_EQ(2.0, result.d);
483 }
484
485 void InvokeSumDoubleDoubleDoubleDoubleMethod(bool is_static) {
486 // TODO: remove this when we have a working x86 compiler.
487#if !defined(__arm__)
488 if (!is_static) {
489 return;
490 }
491#endif
492 Method* method;
493 Object* receiver;
494 Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(DDDD)D");
495
496 JValue args[4];
497 JValue result;
498
499 args[0].d = 0.0;
500 args[1].d = 0.0;
501 args[2].d = 0.0;
502 args[3].d = 0.0;
503 result.d = -1.0;
504 (*stub)(method, NULL, Thread::Current(), args, &result);
505 EXPECT_EQ(0.0, result.d);
506
507 args[0].d = 1.0;
508 args[1].d = 2.0;
509 args[2].d = 3.0;
510 args[3].d = 4.0;
511 result.d = 0.0;
512 (*stub)(method, NULL, Thread::Current(), args, &result);
513 EXPECT_EQ(10.0, result.d);
514
515 args[0].d = 1.0;
516 args[1].d = -2.0;
517 args[2].d = 3.0;
518 args[3].d = -4.0;
519 result.d = 0.0;
520 (*stub)(method, NULL, Thread::Current(), args, &result);
521 EXPECT_EQ(-2.0, result.d);
522 }
523
524 void InvokeSumDoubleDoubleDoubleDoubleDoubleMethod(bool is_static) {
525 // TODO: remove this when we have a working x86 compiler.
526#if !defined(__arm__)
527 if (!is_static) {
528 return;
529 }
530#endif
531 Method* method;
532 Object* receiver;
533 Method::InvokeStub* stub = DoCompile(method, receiver, is_static, "sum", "(DDDDD)D");
534
535 JValue args[5];
536 JValue result;
537
538 args[0].d = 0.0;
539 args[1].d = 0.0;
540 args[2].d = 0.0;
541 args[3].d = 0.0;
542 args[4].d = 0.0;
543 result.d = -1.0;
544 (*stub)(method, NULL, Thread::Current(), args, &result);
545 EXPECT_EQ(0.0, result.d);
546
547 args[0].d = 1.0;
548 args[1].d = 2.0;
549 args[2].d = 3.0;
550 args[3].d = 4.0;
551 args[4].d = 5.0;
552 result.d = 0.0;
553 (*stub)(method, NULL, Thread::Current(), args, &result);
554 EXPECT_EQ(15.0, result.d);
555
556 args[0].d = 1.0;
557 args[1].d = -2.0;
558 args[2].d = 3.0;
559 args[3].d = -4.0;
560 args[4].d = 5.0;
561 result.d = 0.0;
562 (*stub)(method, NULL, Thread::Current(), args, &result);
563 EXPECT_EQ(3.0, result.d);
564 }
565
Elliott Hughesa2501992011-08-26 19:39:54 -0700566 JavaVMExt* vm_;
567 JNIEnvExt* env_;
Elliott Hughes814e4032011-08-23 12:07:56 -0700568 jclass aioobe_;
Elliott Hughesb465ab02011-08-24 11:21:21 -0700569 jclass sioobe_;
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700570};
571
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700572TEST_F(JniInternalTest, AllocObject) {
573 jclass c = env_->FindClass("java/lang/String");
574 ASSERT_TRUE(c != NULL);
575 jobject o = env_->AllocObject(c);
576 ASSERT_TRUE(o != NULL);
577
578 // We have an instance of the class we asked for...
579 ASSERT_TRUE(env_->IsInstanceOf(o, c));
580 // ...whose fields haven't been initialized because
581 // we didn't call a constructor.
582 ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "count", "I")));
583 ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "offset", "I")));
584 ASSERT_TRUE(env_->GetObjectField(o, env_->GetFieldID(c, "value", "[C")) == NULL);
585}
586
Elliott Hughesc7ac37f2011-08-12 12:21:58 -0700587TEST_F(JniInternalTest, GetVersion) {
588 ASSERT_EQ(JNI_VERSION_1_6, env_->GetVersion());
589}
590
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700591#define EXPECT_CLASS_FOUND(NAME) \
Elliott Hughesbd935992011-08-22 11:59:34 -0700592 EXPECT_TRUE(env_->FindClass(NAME) != NULL); \
593 EXPECT_FALSE(env_->ExceptionCheck())
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700594
595#define EXPECT_CLASS_NOT_FOUND(NAME) \
Elliott Hughesbd935992011-08-22 11:59:34 -0700596 EXPECT_TRUE(env_->FindClass(NAME) == NULL); \
597 EXPECT_TRUE(env_->ExceptionCheck()); \
598 env_->ExceptionClear()
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700599
Elliott Hughesa2501992011-08-26 19:39:54 -0700600std::string gCheckJniAbortMessage;
601void TestCheckJniAbortHook(const std::string& reason) {
602 gCheckJniAbortMessage = reason;
603}
604
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700605TEST_F(JniInternalTest, FindClass) {
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700606 // Reference types...
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700607 EXPECT_CLASS_FOUND("java/lang/String");
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700608 // ...for arrays too, where you must include "L;".
609 EXPECT_CLASS_FOUND("[Ljava/lang/String;");
Elliott Hughesa2501992011-08-26 19:39:54 -0700610
611 vm_->check_jni_abort_hook = TestCheckJniAbortHook;
612 // We support . as well as / for compatibility, if -Xcheck:jni is off.
613 EXPECT_CLASS_FOUND("java.lang.String");
614 EXPECT_CLASS_NOT_FOUND("Ljava.lang.String;");
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700615 EXPECT_CLASS_FOUND("[Ljava.lang.String;");
616 EXPECT_CLASS_NOT_FOUND("[java.lang.String");
617
Elliott Hughesa2501992011-08-26 19:39:54 -0700618 // You can't include the "L;" in a JNI class descriptor.
619 EXPECT_CLASS_NOT_FOUND("Ljava/lang/String;");
620 // But you must include it for an array of any reference type.
621 EXPECT_CLASS_NOT_FOUND("[java/lang/String");
622 vm_->check_jni_abort_hook = NULL;
623
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700624 // Primitive arrays are okay (if the primitive type is valid)...
625 EXPECT_CLASS_FOUND("[C");
Elliott Hughesa2501992011-08-26 19:39:54 -0700626 vm_->check_jni_abort_hook = TestCheckJniAbortHook;
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700627 EXPECT_CLASS_NOT_FOUND("[K");
Elliott Hughesa2501992011-08-26 19:39:54 -0700628 vm_->check_jni_abort_hook = NULL;
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700629 // But primitive types aren't allowed...
630 EXPECT_CLASS_NOT_FOUND("C");
631 EXPECT_CLASS_NOT_FOUND("K");
632}
633
Elliott Hughescdf53122011-08-19 15:46:09 -0700634#define EXPECT_EXCEPTION(exception_class) \
635 do { \
636 EXPECT_TRUE(env_->ExceptionCheck()); \
637 jthrowable exception = env_->ExceptionOccurred(); \
638 EXPECT_NE(static_cast<jthrowable>(NULL), exception); \
Elliott Hughescdf53122011-08-19 15:46:09 -0700639 env_->ExceptionClear(); \
Elliott Hughesa2501992011-08-26 19:39:54 -0700640 EXPECT_TRUE(env_->IsInstanceOf(exception, exception_class)); \
Elliott Hughescdf53122011-08-19 15:46:09 -0700641 } while (false)
642
643TEST_F(JniInternalTest, GetFieldID) {
644 jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError");
645 ASSERT_TRUE(jlnsfe != NULL);
646 jclass c = env_->FindClass("java/lang/String");
647 ASSERT_TRUE(c != NULL);
648
649 // Wrong type.
650 jfieldID fid = env_->GetFieldID(c, "count", "J");
651 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
652 EXPECT_EXCEPTION(jlnsfe);
653
Ian Rogersb17d08b2011-09-02 16:16:49 -0700654 // Wrong type where type doesn't exist.
655 fid = env_->GetFieldID(c, "count", "Lrod/jane/freddy;");
656 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
657 EXPECT_EXCEPTION(jlnsfe);
658
Elliott Hughescdf53122011-08-19 15:46:09 -0700659 // Wrong name.
660 fid = env_->GetFieldID(c, "Count", "I");
661 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
662 EXPECT_EXCEPTION(jlnsfe);
663
664 // Good declared field lookup.
665 fid = env_->GetFieldID(c, "count", "I");
666 EXPECT_NE(static_cast<jfieldID>(NULL), fid);
667 EXPECT_TRUE(fid != NULL);
668 EXPECT_FALSE(env_->ExceptionCheck());
669
670 // Good superclass field lookup.
671 c = env_->FindClass("java/lang/StringBuilder");
672 fid = env_->GetFieldID(c, "count", "I");
673 EXPECT_NE(static_cast<jfieldID>(NULL), fid);
674 EXPECT_TRUE(fid != NULL);
675 EXPECT_FALSE(env_->ExceptionCheck());
676
677 // Not instance.
678 fid = env_->GetFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
679 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
680 EXPECT_EXCEPTION(jlnsfe);
681}
682
683TEST_F(JniInternalTest, GetStaticFieldID) {
684 jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError");
685 ASSERT_TRUE(jlnsfe != NULL);
686 jclass c = env_->FindClass("java/lang/String");
687 ASSERT_TRUE(c != NULL);
688
689 // Wrong type.
690 jfieldID fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "J");
691 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
692 EXPECT_EXCEPTION(jlnsfe);
693
Ian Rogersb17d08b2011-09-02 16:16:49 -0700694 // Wrong type where type doesn't exist.
695 fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Lrod/jane/freddy;");
696 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
697 EXPECT_EXCEPTION(jlnsfe);
698
Elliott Hughescdf53122011-08-19 15:46:09 -0700699 // Wrong name.
700 fid = env_->GetStaticFieldID(c, "cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
701 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
702 EXPECT_EXCEPTION(jlnsfe);
703
704 // Good declared field lookup.
705 fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
706 EXPECT_NE(static_cast<jfieldID>(NULL), fid);
707 EXPECT_TRUE(fid != NULL);
708 EXPECT_FALSE(env_->ExceptionCheck());
709
710 // Not static.
711 fid = env_->GetStaticFieldID(c, "count", "I");
712 EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
713 EXPECT_EXCEPTION(jlnsfe);
714}
715
Ian Rogers4dd71f12011-08-16 14:16:02 -0700716TEST_F(JniInternalTest, GetMethodID) {
717 jclass jlobject = env_->FindClass("java/lang/Object");
718 jclass jlstring = env_->FindClass("java/lang/String");
719 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
720
721 // Sanity check that no exceptions are pending
Elliott Hughescdf53122011-08-19 15:46:09 -0700722 ASSERT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700723
724 // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
725 // a pending exception
726 jmethodID method = env_->GetMethodID(jlobject, "foo", "()V");
727 EXPECT_EQ(static_cast<jmethodID>(NULL), method);
Elliott Hughescdf53122011-08-19 15:46:09 -0700728 EXPECT_EXCEPTION(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700729
730 // Check that java.lang.Object.equals() does exist
Ian Rogers4dd71f12011-08-16 14:16:02 -0700731 method = env_->GetMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
732 EXPECT_NE(static_cast<jmethodID>(NULL), method);
733 EXPECT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700734
735 // Check that GetMethodID for java.lang.String.valueOf(int) fails as the
736 // method is static
737 method = env_->GetMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;");
738 EXPECT_EQ(static_cast<jmethodID>(NULL), method);
Elliott Hughescdf53122011-08-19 15:46:09 -0700739 EXPECT_EXCEPTION(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700740}
741
742TEST_F(JniInternalTest, GetStaticMethodID) {
743 jclass jlobject = env_->FindClass("java/lang/Object");
744 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
745
746 // Sanity check that no exceptions are pending
Elliott Hughescdf53122011-08-19 15:46:09 -0700747 ASSERT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700748
749 // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
750 // a pending exception
751 jmethodID method = env_->GetStaticMethodID(jlobject, "foo", "()V");
752 EXPECT_EQ(static_cast<jmethodID>(NULL), method);
Elliott Hughescdf53122011-08-19 15:46:09 -0700753 EXPECT_EXCEPTION(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700754
755 // Check that GetStaticMethodID for java.lang.Object.equals(Object) fails as
756 // the method is not static
757 method = env_->GetStaticMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
758 EXPECT_EQ(static_cast<jmethodID>(NULL), method);
Elliott Hughescdf53122011-08-19 15:46:09 -0700759 EXPECT_EXCEPTION(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700760
761 // Check that java.lang.String.valueOf(int) does exist
Ian Rogers4dd71f12011-08-16 14:16:02 -0700762 jclass jlstring = env_->FindClass("java/lang/String");
763 method = env_->GetStaticMethodID(jlstring, "valueOf",
764 "(I)Ljava/lang/String;");
765 EXPECT_NE(static_cast<jmethodID>(NULL), method);
766 EXPECT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700767}
768
Elliott Hughescdf53122011-08-19 15:46:09 -0700769TEST_F(JniInternalTest, FromReflectedField_ToReflectedField) {
770 jclass jlrField = env_->FindClass("java/lang/reflect/Field");
771 jclass c = env_->FindClass("java/lang/String");
772 ASSERT_TRUE(c != NULL);
773 jfieldID fid = env_->GetFieldID(c, "count", "I");
774 ASSERT_TRUE(fid != NULL);
775 // Turn the fid into a java.lang.reflect.Field...
776 jobject field = env_->ToReflectedField(c, fid, JNI_FALSE);
777 ASSERT_TRUE(c != NULL);
778 ASSERT_TRUE(env_->IsInstanceOf(field, jlrField));
779 // ...and back again.
780 jfieldID fid2 = env_->FromReflectedField(field);
781 ASSERT_TRUE(fid2 != NULL);
782}
783
784TEST_F(JniInternalTest, FromReflectedMethod_ToReflectedMethod) {
785 jclass jlrMethod = env_->FindClass("java/lang/reflect/Method");
786 jclass c = env_->FindClass("java/lang/String");
787 ASSERT_TRUE(c != NULL);
788 jmethodID mid = env_->GetMethodID(c, "length", "()I");
789 ASSERT_TRUE(mid != NULL);
790 // Turn the mid into a java.lang.reflect.Method...
791 jobject method = env_->ToReflectedMethod(c, mid, JNI_FALSE);
792 ASSERT_TRUE(c != NULL);
793 ASSERT_TRUE(env_->IsInstanceOf(method, jlrMethod));
794 // ...and back again.
795 jmethodID mid2 = env_->FromReflectedMethod(method);
796 ASSERT_TRUE(mid2 != NULL);
797}
798
Elliott Hughes5174fe62011-08-23 15:12:35 -0700799void BogusMethod() {
800 // You can't pass NULL function pointers to RegisterNatives.
801}
802
Ian Rogers4dd71f12011-08-16 14:16:02 -0700803TEST_F(JniInternalTest, RegisterNatives) {
804 jclass jlobject = env_->FindClass("java/lang/Object");
805 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
806
807 // Sanity check that no exceptions are pending
Elliott Hughescdf53122011-08-19 15:46:09 -0700808 ASSERT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700809
810 // Check that registering to a non-existent java.lang.Object.foo() causes a
811 // NoSuchMethodError
812 {
813 JNINativeMethod methods[] = {{"foo", "()V", NULL}};
814 env_->RegisterNatives(jlobject, methods, 1);
815 }
Elliott Hughescdf53122011-08-19 15:46:09 -0700816 EXPECT_EXCEPTION(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700817
818 // Check that registering non-native methods causes a NoSuchMethodError
819 {
820 JNINativeMethod methods[] = {{"equals", "(Ljava/lang/Object;)Z", NULL}};
821 env_->RegisterNatives(jlobject, methods, 1);
822 }
Elliott Hughescdf53122011-08-19 15:46:09 -0700823 EXPECT_EXCEPTION(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700824
825 // Check that registering native methods is successful
826 {
Ian Rogersf3773f02012-02-13 16:45:29 -0800827 JNINativeMethod methods[] = {{"notify", "()V", reinterpret_cast<void*>(BogusMethod)}};
Ian Rogers4dd71f12011-08-16 14:16:02 -0700828 env_->RegisterNatives(jlobject, methods, 1);
829 }
830 EXPECT_FALSE(env_->ExceptionCheck());
Elliott Hughes5174fe62011-08-23 15:12:35 -0700831
832 env_->UnregisterNatives(jlobject);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700833}
834
Elliott Hughes75770752011-08-24 17:52:38 -0700835#define EXPECT_PRIMITIVE_ARRAY(new_fn, get_region_fn, set_region_fn, get_elements_fn, release_elements_fn, scalar_type, expected_class_descriptor) \
Elliott Hughes814e4032011-08-23 12:07:56 -0700836 jsize size = 4; \
837 /* Allocate an array and check it has the right type and length. */ \
838 scalar_type ## Array a = env_->new_fn(size); \
839 EXPECT_TRUE(a != NULL); \
840 EXPECT_TRUE(env_->IsInstanceOf(a, env_->FindClass(expected_class_descriptor))); \
841 EXPECT_EQ(size, env_->GetArrayLength(a)); \
842 /* AIOOBE for negative start offset. */ \
843 env_->get_region_fn(a, -1, 1, NULL); \
844 EXPECT_EXCEPTION(aioobe_); \
845 env_->set_region_fn(a, -1, 1, NULL); \
846 EXPECT_EXCEPTION(aioobe_); \
847 /* AIOOBE for negative length. */ \
848 env_->get_region_fn(a, 0, -1, NULL); \
849 EXPECT_EXCEPTION(aioobe_); \
850 env_->set_region_fn(a, 0, -1, NULL); \
851 EXPECT_EXCEPTION(aioobe_); \
852 /* AIOOBE for buffer overrun. */ \
853 env_->get_region_fn(a, size - 1, size, NULL); \
854 EXPECT_EXCEPTION(aioobe_); \
855 env_->set_region_fn(a, size - 1, size, NULL); \
856 EXPECT_EXCEPTION(aioobe_); \
857 /* Prepare a couple of buffers. */ \
858 scalar_type src_buf[size]; \
859 scalar_type dst_buf[size]; \
860 for (jsize i = 0; i < size; ++i) { src_buf[i] = scalar_type(i); } \
861 for (jsize i = 0; i < size; ++i) { dst_buf[i] = scalar_type(-1); } \
862 /* Copy all of src_buf onto the heap. */ \
863 env_->set_region_fn(a, 0, size, src_buf); \
864 /* Copy back only part. */ \
865 env_->get_region_fn(a, 1, size - 2, &dst_buf[1]); \
Elliott Hughescc607472011-10-17 15:34:11 -0700866 EXPECT_NE(memcmp(src_buf, dst_buf, sizeof(src_buf)), 0) << "short copy equal"; \
Elliott Hughes814e4032011-08-23 12:07:56 -0700867 /* Copy the missing pieces. */ \
868 env_->get_region_fn(a, 0, 1, dst_buf); \
869 env_->get_region_fn(a, size - 1, 1, &dst_buf[size - 1]); \
Elliott Hughescc607472011-10-17 15:34:11 -0700870 EXPECT_EQ(memcmp(src_buf, dst_buf, sizeof(src_buf)), 0) << "fixed copy not equal"; \
Elliott Hughes814e4032011-08-23 12:07:56 -0700871 /* Copy back the whole array. */ \
872 env_->get_region_fn(a, 0, size, dst_buf); \
Elliott Hughescc607472011-10-17 15:34:11 -0700873 EXPECT_EQ(memcmp(src_buf, dst_buf, sizeof(src_buf)), 0) << "full copy not equal"; \
Elliott Hughes75770752011-08-24 17:52:38 -0700874 /* GetPrimitiveArrayCritical */ \
875 void* v = env_->GetPrimitiveArrayCritical(a, NULL); \
Elliott Hughescc607472011-10-17 15:34:11 -0700876 EXPECT_EQ(memcmp(src_buf, v, sizeof(src_buf)), 0) << "GetPrimitiveArrayCritical not equal"; \
Elliott Hughes75770752011-08-24 17:52:38 -0700877 env_->ReleasePrimitiveArrayCritical(a, v, 0); \
878 /* GetXArrayElements */ \
879 scalar_type* xs = env_->get_elements_fn(a, NULL); \
Elliott Hughescc607472011-10-17 15:34:11 -0700880 EXPECT_EQ(memcmp(src_buf, xs, sizeof(src_buf)), 0) << # get_elements_fn " not equal"; \
Elliott Hughes75770752011-08-24 17:52:38 -0700881 env_->release_elements_fn(a, xs, 0); \
882 EXPECT_EQ(reinterpret_cast<uintptr_t>(v), reinterpret_cast<uintptr_t>(xs))
Elliott Hughesbd935992011-08-22 11:59:34 -0700883
Elliott Hughes814e4032011-08-23 12:07:56 -0700884TEST_F(JniInternalTest, BooleanArrays) {
Elliott Hughes75770752011-08-24 17:52:38 -0700885 EXPECT_PRIMITIVE_ARRAY(NewBooleanArray, GetBooleanArrayRegion, SetBooleanArrayRegion, GetBooleanArrayElements, ReleaseBooleanArrayElements, jboolean, "[Z");
Elliott Hughes814e4032011-08-23 12:07:56 -0700886}
887TEST_F(JniInternalTest, ByteArrays) {
Elliott Hughes75770752011-08-24 17:52:38 -0700888 EXPECT_PRIMITIVE_ARRAY(NewByteArray, GetByteArrayRegion, SetByteArrayRegion, GetByteArrayElements, ReleaseByteArrayElements, jbyte, "[B");
Elliott Hughes814e4032011-08-23 12:07:56 -0700889}
890TEST_F(JniInternalTest, CharArrays) {
Elliott Hughes75770752011-08-24 17:52:38 -0700891 EXPECT_PRIMITIVE_ARRAY(NewCharArray, GetCharArrayRegion, SetCharArrayRegion, GetCharArrayElements, ReleaseCharArrayElements, jchar, "[C");
Elliott Hughes814e4032011-08-23 12:07:56 -0700892}
893TEST_F(JniInternalTest, DoubleArrays) {
Elliott Hughes75770752011-08-24 17:52:38 -0700894 EXPECT_PRIMITIVE_ARRAY(NewDoubleArray, GetDoubleArrayRegion, SetDoubleArrayRegion, GetDoubleArrayElements, ReleaseDoubleArrayElements, jdouble, "[D");
Elliott Hughes814e4032011-08-23 12:07:56 -0700895}
896TEST_F(JniInternalTest, FloatArrays) {
Elliott Hughes75770752011-08-24 17:52:38 -0700897 EXPECT_PRIMITIVE_ARRAY(NewFloatArray, GetFloatArrayRegion, SetFloatArrayRegion, GetFloatArrayElements, ReleaseFloatArrayElements, jfloat, "[F");
Elliott Hughes814e4032011-08-23 12:07:56 -0700898}
899TEST_F(JniInternalTest, IntArrays) {
Elliott Hughes75770752011-08-24 17:52:38 -0700900 EXPECT_PRIMITIVE_ARRAY(NewIntArray, GetIntArrayRegion, SetIntArrayRegion, GetIntArrayElements, ReleaseIntArrayElements, jint, "[I");
Elliott Hughes814e4032011-08-23 12:07:56 -0700901}
902TEST_F(JniInternalTest, LongArrays) {
Elliott Hughes75770752011-08-24 17:52:38 -0700903 EXPECT_PRIMITIVE_ARRAY(NewLongArray, GetLongArrayRegion, SetLongArrayRegion, GetLongArrayElements, ReleaseLongArrayElements, jlong, "[J");
Elliott Hughes814e4032011-08-23 12:07:56 -0700904}
905TEST_F(JniInternalTest, ShortArrays) {
Elliott Hughes75770752011-08-24 17:52:38 -0700906 EXPECT_PRIMITIVE_ARRAY(NewShortArray, GetShortArrayRegion, SetShortArrayRegion, GetShortArrayElements, ReleaseShortArrayElements, jshort, "[S");
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700907}
908
Elliott Hughesf2682d52011-08-15 16:37:04 -0700909TEST_F(JniInternalTest, NewObjectArray) {
910 // TODO: death tests for negative array sizes.
911
Elliott Hughesf2682d52011-08-15 16:37:04 -0700912 // TODO: check non-NULL initial elements.
913
Elliott Hughesbd935992011-08-22 11:59:34 -0700914 jclass element_class = env_->FindClass("java/lang/String");
915 ASSERT_TRUE(element_class != NULL);
916 jclass array_class = env_->FindClass("[Ljava/lang/String;");
917 ASSERT_TRUE(array_class != NULL);
Elliott Hughesf2682d52011-08-15 16:37:04 -0700918
Elliott Hughesbd935992011-08-22 11:59:34 -0700919 jobjectArray a;
Elliott Hughesf2682d52011-08-15 16:37:04 -0700920
Elliott Hughesbd935992011-08-22 11:59:34 -0700921 a = env_->NewObjectArray(0, element_class, NULL);
922 EXPECT_TRUE(a != NULL);
923 EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
924 EXPECT_EQ(0, env_->GetArrayLength(a));
925
926 a = env_->NewObjectArray(1, element_class, NULL);
927 EXPECT_TRUE(a != NULL);
928 EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
929 EXPECT_EQ(1, env_->GetArrayLength(a));
Elliott Hughes75770752011-08-24 17:52:38 -0700930 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), NULL));
931
932 jstring s = env_->NewStringUTF("poop");
933 a = env_->NewObjectArray(2, element_class, s);
934 EXPECT_TRUE(a != NULL);
935 EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
936 EXPECT_EQ(2, env_->GetArrayLength(a));
937 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), s));
938 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 1), s));
Elliott Hughesbd935992011-08-22 11:59:34 -0700939}
940
941TEST_F(JniInternalTest, GetArrayLength) {
942 // Already tested in NewObjectArray/NewPrimitiveArray.
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700943}
944
Elliott Hughes37f7a402011-08-22 18:56:01 -0700945TEST_F(JniInternalTest, GetObjectClass) {
946 jclass string_class = env_->FindClass("java/lang/String");
947 ASSERT_TRUE(string_class != NULL);
948 jclass class_class = env_->FindClass("java/lang/Class");
949 ASSERT_TRUE(class_class != NULL);
950
951 jstring s = env_->NewStringUTF("poop");
952 jclass c = env_->GetObjectClass(s);
953 ASSERT_TRUE(env_->IsSameObject(string_class, c));
954
955 jclass c2 = env_->GetObjectClass(c);
956 ASSERT_TRUE(env_->IsSameObject(class_class, env_->GetObjectClass(c2)));
957}
958
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700959TEST_F(JniInternalTest, GetSuperclass) {
960 jclass object_class = env_->FindClass("java/lang/Object");
961 ASSERT_TRUE(object_class != NULL);
962 jclass string_class = env_->FindClass("java/lang/String");
963 ASSERT_TRUE(string_class != NULL);
Ian Rogersdc180202012-01-29 14:47:29 -0800964 jclass runnable_interface = env_->FindClass("java/lang/Runnable");
965 ASSERT_TRUE(runnable_interface != NULL);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700966 ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(string_class)));
967 ASSERT_TRUE(env_->GetSuperclass(object_class) == NULL);
Ian Rogersdc180202012-01-29 14:47:29 -0800968 ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(runnable_interface)));
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700969}
970
Elliott Hughes37f7a402011-08-22 18:56:01 -0700971TEST_F(JniInternalTest, IsAssignableFrom) {
972 jclass object_class = env_->FindClass("java/lang/Object");
973 ASSERT_TRUE(object_class != NULL);
974 jclass string_class = env_->FindClass("java/lang/String");
975 ASSERT_TRUE(string_class != NULL);
976
977 ASSERT_TRUE(env_->IsAssignableFrom(object_class, string_class));
978 ASSERT_FALSE(env_->IsAssignableFrom(string_class, object_class));
979}
980
Elliott Hughesb465ab02011-08-24 11:21:21 -0700981TEST_F(JniInternalTest, GetObjectRefType) {
982 jclass local = env_->FindClass("java/lang/Object");
983 ASSERT_TRUE(local != NULL);
984 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(local));
985
986 jobject global = env_->NewGlobalRef(local);
987 EXPECT_EQ(JNIGlobalRefType, env_->GetObjectRefType(global));
988
989 jweak weak_global = env_->NewWeakGlobalRef(local);
990 EXPECT_EQ(JNIWeakGlobalRefType, env_->GetObjectRefType(weak_global));
991
992 jobject invalid = reinterpret_cast<jobject>(this);
993 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(invalid));
994
995 // TODO: invoke a native method and test that its arguments are considered local references.
996}
997
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700998TEST_F(JniInternalTest, NewStringUTF) {
999 EXPECT_TRUE(env_->NewStringUTF(NULL) == NULL);
Elliott Hughes814e4032011-08-23 12:07:56 -07001000 jstring s;
1001
1002 s = env_->NewStringUTF("");
1003 EXPECT_TRUE(s != NULL);
1004 EXPECT_EQ(0, env_->GetStringLength(s));
1005 EXPECT_EQ(0, env_->GetStringUTFLength(s));
1006 s = env_->NewStringUTF("hello");
1007 EXPECT_TRUE(s != NULL);
1008 EXPECT_EQ(5, env_->GetStringLength(s));
1009 EXPECT_EQ(5, env_->GetStringUTFLength(s));
1010
Elliott Hughes8a26c5c2011-08-15 18:35:43 -07001011 // TODO: check some non-ASCII strings.
Elliott Hughesf2682d52011-08-15 16:37:04 -07001012}
1013
Elliott Hughes814e4032011-08-23 12:07:56 -07001014TEST_F(JniInternalTest, NewString) {
Elliott Hughes814e4032011-08-23 12:07:56 -07001015 jchar chars[] = { 'h', 'i' };
1016 jstring s;
1017 s = env_->NewString(chars, 0);
1018 EXPECT_TRUE(s != NULL);
1019 EXPECT_EQ(0, env_->GetStringLength(s));
1020 EXPECT_EQ(0, env_->GetStringUTFLength(s));
1021 s = env_->NewString(chars, 2);
1022 EXPECT_TRUE(s != NULL);
1023 EXPECT_EQ(2, env_->GetStringLength(s));
1024 EXPECT_EQ(2, env_->GetStringUTFLength(s));
1025
1026 // TODO: check some non-ASCII strings.
1027}
1028
Jesse Wilson25e79a52011-11-18 15:31:58 -05001029TEST_F(JniInternalTest, NewStringNullCharsZeroLength) {
1030 jstring s = env_->NewString(NULL, 0);
1031 EXPECT_TRUE(s != NULL);
1032 EXPECT_EQ(0, env_->GetStringLength(s));
1033}
1034
Brian Carlstrom36258122011-12-09 12:55:51 -08001035// TODO: fix gtest death tests on host http://b/5690440 (and target)
1036TEST_F(JniInternalTest, DISABLED_NewStringNullCharsNonzeroLength) {
Jesse Wilson25e79a52011-11-18 15:31:58 -05001037 ASSERT_DEATH(env_->NewString(NULL, 1), "");
1038}
1039
Elliott Hughesb465ab02011-08-24 11:21:21 -07001040TEST_F(JniInternalTest, GetStringLength_GetStringUTFLength) {
1041 // Already tested in the NewString/NewStringUTF tests.
1042}
1043
1044TEST_F(JniInternalTest, GetStringRegion_GetStringUTFRegion) {
1045 jstring s = env_->NewStringUTF("hello");
1046 ASSERT_TRUE(s != NULL);
1047
1048 env_->GetStringRegion(s, -1, 0, NULL);
1049 EXPECT_EXCEPTION(sioobe_);
1050 env_->GetStringRegion(s, 0, -1, NULL);
1051 EXPECT_EXCEPTION(sioobe_);
1052 env_->GetStringRegion(s, 0, 10, NULL);
1053 EXPECT_EXCEPTION(sioobe_);
1054 env_->GetStringRegion(s, 10, 1, NULL);
1055 EXPECT_EXCEPTION(sioobe_);
1056
1057 jchar chars[4] = { 'x', 'x', 'x', 'x' };
1058 env_->GetStringRegion(s, 1, 2, &chars[1]);
1059 EXPECT_EQ('x', chars[0]);
1060 EXPECT_EQ('e', chars[1]);
1061 EXPECT_EQ('l', chars[2]);
1062 EXPECT_EQ('x', chars[3]);
1063
1064 env_->GetStringUTFRegion(s, -1, 0, NULL);
1065 EXPECT_EXCEPTION(sioobe_);
1066 env_->GetStringUTFRegion(s, 0, -1, NULL);
1067 EXPECT_EXCEPTION(sioobe_);
1068 env_->GetStringUTFRegion(s, 0, 10, NULL);
1069 EXPECT_EXCEPTION(sioobe_);
1070 env_->GetStringUTFRegion(s, 10, 1, NULL);
1071 EXPECT_EXCEPTION(sioobe_);
1072
1073 char bytes[4] = { 'x', 'x', 'x', 'x' };
1074 env_->GetStringUTFRegion(s, 1, 2, &bytes[1]);
1075 EXPECT_EQ('x', bytes[0]);
1076 EXPECT_EQ('e', bytes[1]);
1077 EXPECT_EQ('l', bytes[2]);
1078 EXPECT_EQ('x', bytes[3]);
1079}
1080
Elliott Hughes75770752011-08-24 17:52:38 -07001081TEST_F(JniInternalTest, GetStringUTFChars_ReleaseStringUTFChars) {
Elliott Hughesa2501992011-08-26 19:39:54 -07001082 vm_->check_jni_abort_hook = TestCheckJniAbortHook;
1083 // Passing in a NULL jstring is ignored normally, but caught by -Xcheck:jni.
Elliott Hughes75770752011-08-24 17:52:38 -07001084 EXPECT_TRUE(env_->GetStringUTFChars(NULL, NULL) == NULL);
Elliott Hughesa2501992011-08-26 19:39:54 -07001085 vm_->check_jni_abort_hook = NULL;
Elliott Hughes75770752011-08-24 17:52:38 -07001086
1087 jstring s = env_->NewStringUTF("hello");
1088 ASSERT_TRUE(s != NULL);
1089
1090 const char* utf = env_->GetStringUTFChars(s, NULL);
1091 EXPECT_STREQ("hello", utf);
1092 env_->ReleaseStringUTFChars(s, utf);
1093
1094 jboolean is_copy = JNI_FALSE;
1095 utf = env_->GetStringUTFChars(s, &is_copy);
1096 EXPECT_EQ(JNI_TRUE, is_copy);
1097 EXPECT_STREQ("hello", utf);
1098 env_->ReleaseStringUTFChars(s, utf);
1099}
1100
1101TEST_F(JniInternalTest, GetStringChars_ReleaseStringChars) {
1102 jstring s = env_->NewStringUTF("hello");
1103 ASSERT_TRUE(s != NULL);
1104
1105 jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
1106 const jchar* chars = env_->GetStringChars(s, NULL);
1107 EXPECT_EQ(expected[0], chars[0]);
1108 EXPECT_EQ(expected[1], chars[1]);
1109 EXPECT_EQ(expected[2], chars[2]);
1110 EXPECT_EQ(expected[3], chars[3]);
1111 EXPECT_EQ(expected[4], chars[4]);
1112 env_->ReleaseStringChars(s, chars);
1113
1114 jboolean is_copy = JNI_FALSE;
1115 chars = env_->GetStringChars(s, &is_copy);
1116 EXPECT_EQ(JNI_FALSE, is_copy);
1117 EXPECT_EQ(expected[0], chars[0]);
1118 EXPECT_EQ(expected[1], chars[1]);
1119 EXPECT_EQ(expected[2], chars[2]);
1120 EXPECT_EQ(expected[3], chars[3]);
1121 EXPECT_EQ(expected[4], chars[4]);
1122 env_->ReleaseStringChars(s, chars);
1123}
1124
1125TEST_F(JniInternalTest, GetStringCritical_ReleaseStringCritical) {
1126 jstring s = env_->NewStringUTF("hello");
1127 ASSERT_TRUE(s != NULL);
1128
1129 jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
1130 const jchar* chars = env_->GetStringCritical(s, NULL);
1131 EXPECT_EQ(expected[0], chars[0]);
1132 EXPECT_EQ(expected[1], chars[1]);
1133 EXPECT_EQ(expected[2], chars[2]);
1134 EXPECT_EQ(expected[3], chars[3]);
1135 EXPECT_EQ(expected[4], chars[4]);
1136 env_->ReleaseStringCritical(s, chars);
1137
1138 jboolean is_copy = JNI_FALSE;
1139 chars = env_->GetStringCritical(s, &is_copy);
1140 EXPECT_EQ(JNI_FALSE, is_copy);
1141 EXPECT_EQ(expected[0], chars[0]);
1142 EXPECT_EQ(expected[1], chars[1]);
1143 EXPECT_EQ(expected[2], chars[2]);
1144 EXPECT_EQ(expected[3], chars[3]);
1145 EXPECT_EQ(expected[4], chars[4]);
1146 env_->ReleaseStringCritical(s, chars);
1147}
1148
Elliott Hughes814e4032011-08-23 12:07:56 -07001149TEST_F(JniInternalTest, GetObjectArrayElement_SetObjectArrayElement) {
Brian Carlstrom5b8e4c82011-09-18 01:38:59 -07001150 jclass c = env_->FindClass("java/lang/Object");
Elliott Hughes289da822011-08-16 10:11:20 -07001151 ASSERT_TRUE(c != NULL);
1152
1153 jobjectArray array = env_->NewObjectArray(1, c, NULL);
1154 EXPECT_TRUE(array != NULL);
Elliott Hughes814e4032011-08-23 12:07:56 -07001155 EXPECT_TRUE(env_->GetObjectArrayElement(array, 0) == NULL);
Elliott Hughes289da822011-08-16 10:11:20 -07001156 env_->SetObjectArrayElement(array, 0, c);
Elliott Hughes814e4032011-08-23 12:07:56 -07001157 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(array, 0), c));
Elliott Hughesa5b897e2011-08-16 11:33:06 -07001158
1159 // ArrayIndexOutOfBounds for negative index.
Elliott Hughesa5b897e2011-08-16 11:33:06 -07001160 env_->SetObjectArrayElement(array, -1, c);
Elliott Hughes814e4032011-08-23 12:07:56 -07001161 EXPECT_EXCEPTION(aioobe_);
Elliott Hughesa5b897e2011-08-16 11:33:06 -07001162
1163 // ArrayIndexOutOfBounds for too-large index.
Elliott Hughesa5b897e2011-08-16 11:33:06 -07001164 env_->SetObjectArrayElement(array, 1, c);
Elliott Hughes814e4032011-08-23 12:07:56 -07001165 EXPECT_EXCEPTION(aioobe_);
Elliott Hughesa5b897e2011-08-16 11:33:06 -07001166
Elliott Hughes289da822011-08-16 10:11:20 -07001167 // TODO: check ArrayStoreException thrown for bad types.
1168}
1169
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001170#define EXPECT_STATIC_PRIMITIVE_FIELD(type, field_name, sig, value1, value2) \
1171 do { \
1172 jfieldID fid = env_->GetStaticFieldID(c, field_name, sig); \
1173 EXPECT_TRUE(fid != NULL); \
1174 env_->SetStatic ## type ## Field(c, fid, value1); \
Brian Carlstrom2e3d1b22012-01-09 18:01:56 -08001175 EXPECT_TRUE(value1 == env_->GetStatic ## type ## Field(c, fid)); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001176 env_->SetStatic ## type ## Field(c, fid, value2); \
Brian Carlstrom2e3d1b22012-01-09 18:01:56 -08001177 EXPECT_TRUE(value2 == env_->GetStatic ## type ## Field(c, fid)); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001178 } while (false)
1179
1180#define EXPECT_PRIMITIVE_FIELD(instance, type, field_name, sig, value1, value2) \
1181 do { \
1182 jfieldID fid = env_->GetFieldID(c, field_name, sig); \
1183 EXPECT_TRUE(fid != NULL); \
1184 env_->Set ## type ## Field(instance, fid, value1); \
Brian Carlstrom2e3d1b22012-01-09 18:01:56 -08001185 EXPECT_TRUE(value1 == env_->Get ## type ## Field(instance, fid)); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001186 env_->Set ## type ## Field(instance, fid, value2); \
Brian Carlstrom2e3d1b22012-01-09 18:01:56 -08001187 EXPECT_TRUE(value2 == env_->Get ## type ## Field(instance, fid)); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001188 } while (false)
1189
1190
Shih-wei Liao5b8b1ed2012-02-23 23:48:21 -08001191#if !defined(ART_USE_LLVM_COMPILER)
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001192TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -07001193 SirtRef<ClassLoader> class_loader(LoadDex("AllFields"));
Brian Carlstrom25c33252011-09-18 15:58:35 -07001194 runtime_->Start();
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001195
1196 jclass c = env_->FindClass("AllFields");
1197 ASSERT_TRUE(c != NULL);
1198 jobject o = env_->AllocObject(c);
1199 ASSERT_TRUE(o != NULL);
1200
1201 EXPECT_STATIC_PRIMITIVE_FIELD(Boolean, "sZ", "Z", true, false);
1202 EXPECT_STATIC_PRIMITIVE_FIELD(Byte, "sB", "B", 1, 2);
1203 EXPECT_STATIC_PRIMITIVE_FIELD(Char, "sC", "C", 'a', 'b');
1204 EXPECT_STATIC_PRIMITIVE_FIELD(Double, "sD", "D", 1.0, 2.0);
1205 EXPECT_STATIC_PRIMITIVE_FIELD(Float, "sF", "F", 1.0, 2.0);
1206 EXPECT_STATIC_PRIMITIVE_FIELD(Int, "sI", "I", 1, 2);
1207 EXPECT_STATIC_PRIMITIVE_FIELD(Long, "sJ", "J", 1, 2);
1208 EXPECT_STATIC_PRIMITIVE_FIELD(Short, "sS", "S", 1, 2);
1209
1210 EXPECT_PRIMITIVE_FIELD(o, Boolean, "iZ", "Z", true, false);
1211 EXPECT_PRIMITIVE_FIELD(o, Byte, "iB", "B", 1, 2);
1212 EXPECT_PRIMITIVE_FIELD(o, Char, "iC", "C", 'a', 'b');
1213 EXPECT_PRIMITIVE_FIELD(o, Double, "iD", "D", 1.0, 2.0);
1214 EXPECT_PRIMITIVE_FIELD(o, Float, "iF", "F", 1.0, 2.0);
1215 EXPECT_PRIMITIVE_FIELD(o, Int, "iI", "I", 1, 2);
1216 EXPECT_PRIMITIVE_FIELD(o, Long, "iJ", "J", 1, 2);
1217 EXPECT_PRIMITIVE_FIELD(o, Short, "iS", "S", 1, 2);
1218}
1219
1220TEST_F(JniInternalTest, GetObjectField_SetObjectField) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -07001221 SirtRef<ClassLoader> class_loader(LoadDex("AllFields"));
Brian Carlstrom25c33252011-09-18 15:58:35 -07001222 runtime_->Start();
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001223
1224 jclass c = env_->FindClass("AllFields");
1225 ASSERT_TRUE(c != NULL);
1226 jobject o = env_->AllocObject(c);
1227 ASSERT_TRUE(o != NULL);
1228
1229 jstring s1 = env_->NewStringUTF("hello");
1230 ASSERT_TRUE(s1 != NULL);
1231 jstring s2 = env_->NewStringUTF("world");
1232 ASSERT_TRUE(s2 != NULL);
1233
1234 jfieldID s_fid = env_->GetStaticFieldID(c, "sObject", "Ljava/lang/Object;");
1235 ASSERT_TRUE(s_fid != NULL);
1236 jfieldID i_fid = env_->GetFieldID(c, "iObject", "Ljava/lang/Object;");
1237 ASSERT_TRUE(i_fid != NULL);
1238
1239 env_->SetStaticObjectField(c, s_fid, s1);
1240 ASSERT_TRUE(env_->IsSameObject(s1, env_->GetStaticObjectField(c, s_fid)));
1241 env_->SetStaticObjectField(c, s_fid, s2);
1242 ASSERT_TRUE(env_->IsSameObject(s2, env_->GetStaticObjectField(c, s_fid)));
1243
1244 env_->SetObjectField(o, i_fid, s1);
1245 ASSERT_TRUE(env_->IsSameObject(s1, env_->GetObjectField(o, i_fid)));
1246 env_->SetObjectField(o, i_fid, s2);
1247 ASSERT_TRUE(env_->IsSameObject(s2, env_->GetObjectField(o, i_fid)));
1248}
Shih-wei Liao5b8b1ed2012-02-23 23:48:21 -08001249#endif
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001250
Elliott Hughes18c07532011-08-18 15:50:51 -07001251TEST_F(JniInternalTest, NewLocalRef_NULL) {
1252 EXPECT_TRUE(env_->NewLocalRef(NULL) == NULL);
1253}
1254
1255TEST_F(JniInternalTest, NewLocalRef) {
1256 jstring s = env_->NewStringUTF("");
1257 ASSERT_TRUE(s != NULL);
1258 jobject o = env_->NewLocalRef(s);
1259 EXPECT_TRUE(o != NULL);
1260 EXPECT_TRUE(o != s);
1261
Elliott Hughes2ced6a52011-10-16 18:44:48 -07001262 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(o));
Elliott Hughes18c07532011-08-18 15:50:51 -07001263}
1264
1265TEST_F(JniInternalTest, DeleteLocalRef_NULL) {
1266 env_->DeleteLocalRef(NULL);
1267}
1268
1269TEST_F(JniInternalTest, DeleteLocalRef) {
1270 jstring s = env_->NewStringUTF("");
1271 ASSERT_TRUE(s != NULL);
1272 env_->DeleteLocalRef(s);
1273
1274 // Currently, deleting an already-deleted reference is just a warning.
Elliott Hughesa2501992011-08-26 19:39:54 -07001275 vm_->check_jni_abort_hook = TestCheckJniAbortHook;
Elliott Hughes18c07532011-08-18 15:50:51 -07001276 env_->DeleteLocalRef(s);
Elliott Hughesa2501992011-08-26 19:39:54 -07001277 vm_->check_jni_abort_hook = NULL;
Elliott Hughes18c07532011-08-18 15:50:51 -07001278
1279 s = env_->NewStringUTF("");
1280 ASSERT_TRUE(s != NULL);
1281 jobject o = env_->NewLocalRef(s);
1282 ASSERT_TRUE(o != NULL);
1283
1284 env_->DeleteLocalRef(s);
1285 env_->DeleteLocalRef(o);
1286}
1287
Elliott Hughes2ced6a52011-10-16 18:44:48 -07001288TEST_F(JniInternalTest, PushLocalFrame_PopLocalFrame) {
1289 jobject original = env_->NewStringUTF("");
1290 ASSERT_TRUE(original != NULL);
1291
1292 jobject outer;
1293 jobject inner1, inner2;
1294 Object* inner2_direct_pointer;
1295 {
1296 env_->PushLocalFrame(4);
1297 outer = env_->NewLocalRef(original);
1298
1299 {
1300 env_->PushLocalFrame(4);
1301 inner1 = env_->NewLocalRef(outer);
1302 inner2 = env_->NewStringUTF("survivor");
1303 inner2_direct_pointer = Decode<Object*>(env_, inner2);
1304 env_->PopLocalFrame(inner2);
1305 }
1306
1307 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original));
1308 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(outer));
1309 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1));
1310
1311 // Our local reference for the survivor is invalid because the survivor
1312 // gets a new local reference...
1313 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
1314 // ...but the survivor should be in the local reference table.
1315 EXPECT_TRUE(env_->locals.ContainsDirectPointer(inner2_direct_pointer));
1316
1317 env_->PopLocalFrame(NULL);
1318 }
1319 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original));
1320 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(outer));
1321 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1));
1322 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
1323}
1324
Elliott Hughes18c07532011-08-18 15:50:51 -07001325TEST_F(JniInternalTest, NewGlobalRef_NULL) {
1326 EXPECT_TRUE(env_->NewGlobalRef(NULL) == NULL);
1327}
1328
1329TEST_F(JniInternalTest, NewGlobalRef) {
1330 jstring s = env_->NewStringUTF("");
1331 ASSERT_TRUE(s != NULL);
1332 jobject o = env_->NewGlobalRef(s);
1333 EXPECT_TRUE(o != NULL);
1334 EXPECT_TRUE(o != s);
1335
1336 // TODO: check that o is a global reference.
1337}
1338
1339TEST_F(JniInternalTest, DeleteGlobalRef_NULL) {
1340 env_->DeleteGlobalRef(NULL);
1341}
1342
1343TEST_F(JniInternalTest, DeleteGlobalRef) {
1344 jstring s = env_->NewStringUTF("");
1345 ASSERT_TRUE(s != NULL);
1346
1347 jobject o = env_->NewGlobalRef(s);
1348 ASSERT_TRUE(o != NULL);
1349 env_->DeleteGlobalRef(o);
1350
Elliott Hughesa2501992011-08-26 19:39:54 -07001351 vm_->check_jni_abort_hook = TestCheckJniAbortHook;
Elliott Hughes18c07532011-08-18 15:50:51 -07001352 // Currently, deleting an already-deleted reference is just a warning.
1353 env_->DeleteGlobalRef(o);
Elliott Hughesa2501992011-08-26 19:39:54 -07001354 vm_->check_jni_abort_hook = NULL;
Elliott Hughes18c07532011-08-18 15:50:51 -07001355
1356 jobject o1 = env_->NewGlobalRef(s);
1357 ASSERT_TRUE(o1 != NULL);
1358 jobject o2 = env_->NewGlobalRef(s);
1359 ASSERT_TRUE(o2 != NULL);
1360
1361 env_->DeleteGlobalRef(o1);
1362 env_->DeleteGlobalRef(o2);
1363}
1364
1365TEST_F(JniInternalTest, NewWeakGlobalRef_NULL) {
1366 EXPECT_TRUE(env_->NewWeakGlobalRef(NULL) == NULL);
1367}
1368
1369TEST_F(JniInternalTest, NewWeakGlobalRef) {
1370 jstring s = env_->NewStringUTF("");
1371 ASSERT_TRUE(s != NULL);
1372 jobject o = env_->NewWeakGlobalRef(s);
1373 EXPECT_TRUE(o != NULL);
1374 EXPECT_TRUE(o != s);
1375
1376 // TODO: check that o is a weak global reference.
1377}
1378
1379TEST_F(JniInternalTest, DeleteWeakGlobalRef_NULL) {
1380 env_->DeleteWeakGlobalRef(NULL);
1381}
1382
1383TEST_F(JniInternalTest, DeleteWeakGlobalRef) {
1384 jstring s = env_->NewStringUTF("");
1385 ASSERT_TRUE(s != NULL);
1386
1387 jobject o = env_->NewWeakGlobalRef(s);
1388 ASSERT_TRUE(o != NULL);
1389 env_->DeleteWeakGlobalRef(o);
1390
Elliott Hughesa2501992011-08-26 19:39:54 -07001391 vm_->check_jni_abort_hook = TestCheckJniAbortHook;
Elliott Hughes18c07532011-08-18 15:50:51 -07001392 // Currently, deleting an already-deleted reference is just a warning.
1393 env_->DeleteWeakGlobalRef(o);
Elliott Hughesa2501992011-08-26 19:39:54 -07001394 vm_->check_jni_abort_hook = NULL;
Elliott Hughes18c07532011-08-18 15:50:51 -07001395
1396 jobject o1 = env_->NewWeakGlobalRef(s);
1397 ASSERT_TRUE(o1 != NULL);
1398 jobject o2 = env_->NewWeakGlobalRef(s);
1399 ASSERT_TRUE(o2 != NULL);
1400
1401 env_->DeleteWeakGlobalRef(o1);
1402 env_->DeleteWeakGlobalRef(o2);
1403}
1404
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001405TEST_F(JniInternalTest, StaticMainMethod) {
Brian Carlstrom40381fb2011-10-19 14:13:40 -07001406 SirtRef<ClassLoader> class_loader(LoadDex("Main"));
1407 CompileDirectMethod(class_loader.get(), "Main", "main", "([Ljava/lang/String;)V");
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001408
Brian Carlstrom40381fb2011-10-19 14:13:40 -07001409 Class* klass = class_linker_->FindClass("LMain;", class_loader.get());
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001410 ASSERT_TRUE(klass != NULL);
1411
1412 Method* method = klass->FindDirectMethod("main", "([Ljava/lang/String;)V");
1413 ASSERT_TRUE(method != NULL);
1414
Brian Carlstrom9baa4ae2011-09-01 21:14:14 -07001415 Method::InvokeStub* stub = method->GetInvokeStub();
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001416
Elliott Hughes77405792012-03-15 15:22:12 -07001417 JValue args[1];
1418 args[0].l = NULL;
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001419
Elliott Hughes77405792012-03-15 15:22:12 -07001420 (*stub)(method, NULL, Thread::Current(), args, NULL);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001421}
1422
1423TEST_F(JniInternalTest, StaticNopMethod) {
Elliott Hughes77405792012-03-15 15:22:12 -07001424 InvokeNopMethod(true);
1425}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001426
Elliott Hughes77405792012-03-15 15:22:12 -07001427TEST_F(JniInternalTest, NonStaticNopMethod) {
1428 InvokeNopMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001429}
1430
1431TEST_F(JniInternalTest, StaticIdentityByteMethod) {
Elliott Hughes77405792012-03-15 15:22:12 -07001432 InvokeIdentityByteMethod(true);
1433}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001434
Elliott Hughes77405792012-03-15 15:22:12 -07001435TEST_F(JniInternalTest, NonStaticIdentityByteMethod) {
1436 InvokeIdentityByteMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001437}
1438
1439TEST_F(JniInternalTest, StaticIdentityIntMethod) {
Elliott Hughes77405792012-03-15 15:22:12 -07001440 InvokeIdentityIntMethod(true);
1441}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001442
Elliott Hughes77405792012-03-15 15:22:12 -07001443TEST_F(JniInternalTest, NonStaticIdentityIntMethod) {
1444 InvokeIdentityIntMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001445}
1446
1447TEST_F(JniInternalTest, StaticIdentityDoubleMethod) {
Elliott Hughes77405792012-03-15 15:22:12 -07001448 InvokeIdentityDoubleMethod(true);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001449}
1450
Elliott Hughes77405792012-03-15 15:22:12 -07001451TEST_F(JniInternalTest, NonStaticIdentityDoubleMethod) {
1452 InvokeIdentityDoubleMethod(false);
Shih-wei Liao5b8b1ed2012-02-23 23:48:21 -08001453}
1454
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001455TEST_F(JniInternalTest, StaticSumIntIntMethod) {
Elliott Hughes77405792012-03-15 15:22:12 -07001456 InvokeSumIntIntMethod(true);
1457}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001458
Elliott Hughes77405792012-03-15 15:22:12 -07001459TEST_F(JniInternalTest, NonStaticSumIntIntMethod) {
1460 InvokeSumIntIntMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001461}
1462
1463TEST_F(JniInternalTest, StaticSumIntIntIntMethod) {
Elliott Hughes77405792012-03-15 15:22:12 -07001464 InvokeSumIntIntIntMethod(true);
1465}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001466
Elliott Hughes77405792012-03-15 15:22:12 -07001467TEST_F(JniInternalTest, NonStaticSumIntIntIntMethod) {
1468 InvokeSumIntIntIntMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001469}
1470
1471TEST_F(JniInternalTest, StaticSumIntIntIntIntMethod) {
Elliott Hughes77405792012-03-15 15:22:12 -07001472 InvokeSumIntIntIntIntMethod(true);
1473}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001474
Elliott Hughes77405792012-03-15 15:22:12 -07001475TEST_F(JniInternalTest, NonStaticSumIntIntIntIntMethod) {
1476 InvokeSumIntIntIntIntMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001477}
1478
1479TEST_F(JniInternalTest, StaticSumIntIntIntIntIntMethod) {
Elliott Hughes77405792012-03-15 15:22:12 -07001480 InvokeSumIntIntIntIntIntMethod(true);
1481}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001482
Elliott Hughes77405792012-03-15 15:22:12 -07001483TEST_F(JniInternalTest, NonStaticSumIntIntIntIntIntMethod) {
1484 InvokeSumIntIntIntIntIntMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001485}
1486
1487TEST_F(JniInternalTest, StaticSumDoubleDoubleMethod) {
Elliott Hughes77405792012-03-15 15:22:12 -07001488 InvokeSumDoubleDoubleMethod(true);
1489}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001490
Elliott Hughes77405792012-03-15 15:22:12 -07001491TEST_F(JniInternalTest, NonStaticSumDoubleDoubleMethod) {
1492 InvokeSumDoubleDoubleMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001493}
1494
1495TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleMethod) {
Elliott Hughes77405792012-03-15 15:22:12 -07001496 InvokeSumDoubleDoubleDoubleMethod(true);
1497}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001498
Elliott Hughes77405792012-03-15 15:22:12 -07001499TEST_F(JniInternalTest, NonStaticSumDoubleDoubleDoubleMethod) {
1500 InvokeSumDoubleDoubleDoubleMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001501}
1502
1503TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleMethod) {
Elliott Hughes77405792012-03-15 15:22:12 -07001504 InvokeSumDoubleDoubleDoubleDoubleMethod(true);
1505}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001506
Elliott Hughes77405792012-03-15 15:22:12 -07001507TEST_F(JniInternalTest, NonStaticSumDoubleDoubleDoubleDoubleMethod) {
1508 InvokeSumDoubleDoubleDoubleDoubleMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001509}
1510
1511TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleDoubleMethod) {
Elliott Hughes77405792012-03-15 15:22:12 -07001512 InvokeSumDoubleDoubleDoubleDoubleDoubleMethod(true);
1513}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001514
Elliott Hughes77405792012-03-15 15:22:12 -07001515TEST_F(JniInternalTest, NonStaticSumDoubleDoubleDoubleDoubleDoubleMethod) {
1516 InvokeSumDoubleDoubleDoubleDoubleDoubleMethod(false);
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001517}
Carl Shapiro9b9ba282011-08-14 15:30:39 -07001518
Elliott Hughes37f7a402011-08-22 18:56:01 -07001519TEST_F(JniInternalTest, Throw) {
1520 EXPECT_EQ(JNI_ERR, env_->Throw(NULL));
1521
1522 jclass exception_class = env_->FindClass("java/lang/RuntimeException");
1523 ASSERT_TRUE(exception_class != NULL);
1524 jthrowable exception = reinterpret_cast<jthrowable>(env_->AllocObject(exception_class));
1525 ASSERT_TRUE(exception != NULL);
1526
1527 EXPECT_EQ(JNI_OK, env_->Throw(exception));
1528 EXPECT_TRUE(env_->ExceptionCheck());
Elliott Hughesa2501992011-08-26 19:39:54 -07001529 jthrowable thrown_exception = env_->ExceptionOccurred();
Elliott Hughes37f7a402011-08-22 18:56:01 -07001530 env_->ExceptionClear();
Elliott Hughesa2501992011-08-26 19:39:54 -07001531 EXPECT_TRUE(env_->IsSameObject(exception, thrown_exception));
Elliott Hughes37f7a402011-08-22 18:56:01 -07001532}
1533
1534TEST_F(JniInternalTest, ThrowNew) {
1535 EXPECT_EQ(JNI_ERR, env_->Throw(NULL));
1536
1537 jclass exception_class = env_->FindClass("java/lang/RuntimeException");
1538 ASSERT_TRUE(exception_class != NULL);
1539
Elliott Hughes5cb5ad22011-10-02 12:13:39 -07001540 jthrowable thrown_exception;
1541
Elliott Hughes37f7a402011-08-22 18:56:01 -07001542 EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, "hello world"));
1543 EXPECT_TRUE(env_->ExceptionCheck());
Elliott Hughes5cb5ad22011-10-02 12:13:39 -07001544 thrown_exception = env_->ExceptionOccurred();
1545 env_->ExceptionClear();
1546 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class));
1547
1548 EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, NULL));
1549 EXPECT_TRUE(env_->ExceptionCheck());
1550 thrown_exception = env_->ExceptionOccurred();
Elliott Hughes37f7a402011-08-22 18:56:01 -07001551 env_->ExceptionClear();
Elliott Hughesa2501992011-08-26 19:39:54 -07001552 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class));
Elliott Hughes37f7a402011-08-22 18:56:01 -07001553}
1554
Elliott Hughesb465ab02011-08-24 11:21:21 -07001555// TODO: this test is DISABLED until we can actually run java.nio.Buffer's <init>.
1556TEST_F(JniInternalTest, DISABLED_NewDirectBuffer_GetDirectBufferAddress_GetDirectBufferCapacity) {
1557 jclass buffer_class = env_->FindClass("java/nio/Buffer");
1558 ASSERT_TRUE(buffer_class != NULL);
1559
1560 char bytes[1024];
1561 jobject buffer = env_->NewDirectByteBuffer(bytes, sizeof(bytes));
1562 ASSERT_TRUE(buffer != NULL);
1563 ASSERT_TRUE(env_->IsInstanceOf(buffer, buffer_class));
1564 ASSERT_TRUE(env_->GetDirectBufferAddress(buffer) == bytes);
1565 ASSERT_TRUE(env_->GetDirectBufferCapacity(buffer) == sizeof(bytes));
1566}
1567
Ian Rogers6d0b13e2012-02-07 09:25:29 -08001568TEST_F(JniInternalTest, MonitorEnterExit) {
1569 // Create an object to torture
1570 jclass object_class = env_->FindClass("java/lang/Object");
1571 ASSERT_TRUE(object_class != NULL);
1572 jobject object = env_->AllocObject(object_class);
1573 ASSERT_TRUE(object != NULL);
1574
1575 // Expected class of exceptions
1576 jclass imse_class = env_->FindClass("java/lang/IllegalMonitorStateException");
1577 ASSERT_TRUE(imse_class != NULL);
1578
1579 jthrowable thrown_exception;
1580
1581 // Unlock of unowned monitor
1582 env_->MonitorExit(object);
1583 EXPECT_TRUE(env_->ExceptionCheck());
1584 thrown_exception = env_->ExceptionOccurred();
1585 env_->ExceptionClear();
1586 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class));
1587
1588 // Lock of unowned monitor
1589 env_->MonitorEnter(object);
1590 EXPECT_FALSE(env_->ExceptionCheck());
1591 // Regular unlock
1592 env_->MonitorExit(object);
1593 EXPECT_FALSE(env_->ExceptionCheck());
1594
1595 // Recursively lock a lot
1596 size_t max_recursive_lock = 1024;
1597 for (size_t i = 0; i < max_recursive_lock; i++) {
1598 env_->MonitorEnter(object);
1599 EXPECT_FALSE(env_->ExceptionCheck());
1600 }
1601 // Recursively unlock a lot
1602 for (size_t i = 0; i < max_recursive_lock; i++) {
1603 env_->MonitorExit(object);
1604 EXPECT_FALSE(env_->ExceptionCheck());
1605 }
1606
1607 // Unlock of unowned monitor
1608 env_->MonitorExit(object);
1609 EXPECT_TRUE(env_->ExceptionCheck());
1610 thrown_exception = env_->ExceptionOccurred();
1611 env_->ExceptionClear();
1612 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class));
Elliott Hughesa92853e2012-02-07 16:09:27 -08001613
1614 // It's an error to call MonitorEnter or MonitorExit on NULL.
1615 vm_->check_jni_abort_hook = TestCheckJniAbortHook;
1616 env_->MonitorEnter(NULL);
1617 EXPECT_TRUE(gCheckJniAbortMessage.find("in call to MonitorEnter") != std::string::npos);
1618 env_->MonitorExit(NULL);
1619 EXPECT_TRUE(gCheckJniAbortMessage.find("in call to MonitorExit") != std::string::npos);
1620 vm_->check_jni_abort_hook = NULL;
Ian Rogers6d0b13e2012-02-07 09:25:29 -08001621}
1622
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001623} // namespace art