1/*
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 */
16
17#include "jni_internal.h"
18
19#include <limits.h>
20#include <cfloat>
21#include <cmath>
22
23#include "common_test.h"
24#include "invoke_arg_array_builder.h"
25#include "mirror/art_method-inl.h"
26#include "mirror/class-inl.h"
27#include "mirror/object_array-inl.h"
28#include "mirror/object-inl.h"
29#include "ScopedLocalRef.h"
30#include "sirt_ref.h"
31
32namespace art {
33
34class JniInternalTest : public CommonTest {
35 protected:
36  virtual void SetUp() {
37    CommonTest::SetUp();
38
39    vm_ = Runtime::Current()->GetJavaVM();
40
41    // Turn on -verbose:jni for the JNI tests.
42    // gLogVerbosity.jni = true;
43
44    vm_->AttachCurrentThread(&env_, NULL);
45
46    ScopedLocalRef<jclass> aioobe(env_,
47                                  env_->FindClass("java/lang/ArrayIndexOutOfBoundsException"));
48    CHECK(aioobe.get() != NULL);
49    aioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(aioobe.get()));
50
51    ScopedLocalRef<jclass> ase(env_, env_->FindClass("java/lang/ArrayStoreException"));
52    CHECK(ase.get() != NULL);
53    ase_ = reinterpret_cast<jclass>(env_->NewGlobalRef(ase.get()));
54
55    ScopedLocalRef<jclass> sioobe(env_,
56                                  env_->FindClass("java/lang/StringIndexOutOfBoundsException"));
57    CHECK(sioobe.get() != NULL);
58    sioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(sioobe.get()));
59  }
60
61  void CleanUpJniEnv() {
62    if (aioobe_ != NULL) {
63      env_->DeleteGlobalRef(aioobe_);
64      aioobe_ = NULL;
65    }
66    if (ase_ != NULL) {
67      env_->DeleteGlobalRef(ase_);
68      ase_ = NULL;
69    }
70    if (sioobe_ != NULL) {
71      env_->DeleteGlobalRef(sioobe_);
72      sioobe_ = NULL;
73    }
74  }
75
76  virtual void TearDown() {
77    CleanUpJniEnv();
78    CommonTest::TearDown();
79  }
80
81  void DoCompile(mirror::ArtMethod*& method,
82                 mirror::Object*& receiver,
83                 bool is_static, const char* method_name,
84                 const char* method_signature)
85      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
86    const char* class_name = is_static ? "StaticLeafMethods" : "NonStaticLeafMethods";
87    jobject jclass_loader(LoadDex(class_name));
88    Thread* self = Thread::Current();
89    SirtRef<mirror::ClassLoader>
90        class_loader(self,
91                     ScopedObjectAccessUnchecked(self).Decode<mirror::ClassLoader*>(jclass_loader));
92    if (is_static) {
93      CompileDirectMethod(class_loader.get(), class_name, method_name, method_signature);
94    } else {
95      CompileVirtualMethod(NULL, "java.lang.Class", "isFinalizable", "()Z");
96      CompileDirectMethod(NULL, "java.lang.Object", "<init>", "()V");
97      CompileVirtualMethod(class_loader.get(), class_name, method_name, method_signature);
98    }
99
100    mirror::Class* c = class_linker_->FindClass(DotToDescriptor(class_name).c_str(),
101                                                class_loader.get());
102    CHECK(c != NULL);
103
104    method = is_static ? c->FindDirectMethod(method_name, method_signature)
105                       : c->FindVirtualMethod(method_name, method_signature);
106    CHECK(method != NULL);
107
108    receiver = (is_static ? NULL : c->AllocObject(self));
109
110    // Start runtime.
111    bool started = runtime_->Start();
112    CHECK(started);
113    self->TransitionFromSuspendedToRunnable();
114  }
115
116  void InvokeNopMethod(bool is_static) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
117    mirror::ArtMethod* method;
118    mirror::Object* receiver;
119    DoCompile(method, receiver, is_static, "nop", "()V");
120
121    ArgArray arg_array(NULL, 0);
122    JValue result;
123
124    if (!is_static) {
125      arg_array.Append(reinterpret_cast<uint32_t>(receiver));
126    }
127
128    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'V');
129  }
130
131  void InvokeIdentityByteMethod(bool is_static)
132      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
133    mirror::ArtMethod* method;
134    mirror::Object* receiver;
135    DoCompile(method, receiver, is_static, "identity", "(I)I");
136
137    ArgArray arg_array(NULL, 0);
138    uint32_t* args = arg_array.GetArray();
139    JValue result;
140
141    if (!is_static) {
142      arg_array.Append(reinterpret_cast<uint32_t>(receiver));
143      args++;
144    }
145
146    arg_array.Append(0);
147    result.SetB(-1);
148    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'B');
149    EXPECT_EQ(0, result.GetB());
150
151    args[0] = -1;
152    result.SetB(0);
153    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'B');
154    EXPECT_EQ(-1, result.GetB());
155
156    args[0] = SCHAR_MAX;
157    result.SetB(0);
158    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'B');
159    EXPECT_EQ(SCHAR_MAX, result.GetB());
160
161    args[0] = (SCHAR_MIN << 24) >> 24;
162    result.SetB(0);
163    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'B');
164    EXPECT_EQ(SCHAR_MIN, result.GetB());
165  }
166
167  void InvokeIdentityIntMethod(bool is_static)
168      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
169    mirror::ArtMethod* method;
170    mirror::Object* receiver;
171    DoCompile(method, receiver, is_static, "identity", "(I)I");
172
173    ArgArray arg_array(NULL, 0);
174    uint32_t* args = arg_array.GetArray();
175    JValue result;
176
177    if (!is_static) {
178      arg_array.Append(reinterpret_cast<uint32_t>(receiver));
179      args++;
180    }
181
182    arg_array.Append(0);
183    result.SetI(-1);
184    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
185    EXPECT_EQ(0, result.GetI());
186
187    args[0] = -1;
188    result.SetI(0);
189    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
190    EXPECT_EQ(-1, result.GetI());
191
192    args[0] = INT_MAX;
193    result.SetI(0);
194    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
195    EXPECT_EQ(INT_MAX, result.GetI());
196
197    args[0] = INT_MIN;
198    result.SetI(0);
199    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
200    EXPECT_EQ(INT_MIN, result.GetI());
201  }
202
203  void InvokeIdentityDoubleMethod(bool is_static)
204      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
205    mirror::ArtMethod* method;
206    mirror::Object* receiver;
207    DoCompile(method, receiver, is_static, "identity", "(D)D");
208
209    ArgArray arg_array(NULL, 0);
210    uint32_t* args = arg_array.GetArray();
211    JValue value;
212    JValue result;
213
214    if (!is_static) {
215      arg_array.Append(reinterpret_cast<uint32_t>(receiver));
216      args++;
217    }
218
219    value.SetD(0.0);
220    arg_array.AppendWide(value.GetJ());
221    result.SetD(-1.0);
222    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
223    EXPECT_EQ(0.0, result.GetD());
224
225    value.SetD(-1.0);
226    args[0] = value.GetJ();
227    args[1] = value.GetJ() >> 32;
228    result.SetD(0.0);
229    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
230    EXPECT_EQ(-1.0, result.GetD());
231
232    value.SetD(DBL_MAX);
233    args[0] = value.GetJ();
234    args[1] = value.GetJ() >> 32;
235    result.SetD(0.0);
236    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
237    EXPECT_EQ(DBL_MAX, result.GetD());
238
239    value.SetD(DBL_MIN);
240    args[0] = value.GetJ();
241    args[1] = value.GetJ() >> 32;
242    result.SetD(0.0);
243    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
244    EXPECT_EQ(DBL_MIN, result.GetD());
245  }
246
247  void InvokeSumIntIntMethod(bool is_static)
248      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
249    mirror::ArtMethod* method;
250    mirror::Object* receiver;
251    DoCompile(method, receiver, is_static, "sum", "(II)I");
252
253    ArgArray arg_array(NULL, 0);
254    uint32_t* args = arg_array.GetArray();
255    JValue result;
256
257    if (!is_static) {
258      arg_array.Append(reinterpret_cast<uint32_t>(receiver));
259      args++;
260    }
261
262    arg_array.Append(0);
263    arg_array.Append(0);
264    result.SetI(-1);
265    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
266    EXPECT_EQ(0, result.GetI());
267
268    args[0] = 1;
269    args[1] = 2;
270    result.SetI(0);
271    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
272    EXPECT_EQ(3, result.GetI());
273
274    args[0] = -2;
275    args[1] = 5;
276    result.SetI(0);
277    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
278    EXPECT_EQ(3, result.GetI());
279
280    args[0] = INT_MAX;
281    args[1] = INT_MIN;
282    result.SetI(1234);
283    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
284    EXPECT_EQ(-1, result.GetI());
285
286    args[0] = INT_MAX;
287    args[1] = INT_MAX;
288    result.SetI(INT_MIN);
289    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
290    EXPECT_EQ(-2, result.GetI());
291  }
292
293  void InvokeSumIntIntIntMethod(bool is_static)
294      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
295    mirror::ArtMethod* method;
296    mirror::Object* receiver;
297    DoCompile(method, receiver, is_static, "sum", "(III)I");
298
299    ArgArray arg_array(NULL, 0);
300    uint32_t* args = arg_array.GetArray();
301    JValue result;
302
303    if (!is_static) {
304      arg_array.Append(reinterpret_cast<uint32_t>(receiver));
305      args++;
306    }
307
308    arg_array.Append(0);
309    arg_array.Append(0);
310    arg_array.Append(0);
311    result.SetI(-1);
312    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
313    EXPECT_EQ(0, result.GetI());
314
315    args[0] = 1;
316    args[1] = 2;
317    args[2] = 3;
318    result.SetI(0);
319    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
320    EXPECT_EQ(6, result.GetI());
321
322    args[0] = -1;
323    args[1] = 2;
324    args[2] = -3;
325    result.SetI(0);
326    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
327    EXPECT_EQ(-2, result.GetI());
328
329    args[0] = INT_MAX;
330    args[1] = INT_MIN;
331    args[2] = INT_MAX;
332    result.SetI(1234);
333    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
334    EXPECT_EQ(2147483646, result.GetI());
335
336    args[0] = INT_MAX;
337    args[1] = INT_MAX;
338    args[2] = INT_MAX;
339    result.SetI(INT_MIN);
340    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
341    EXPECT_EQ(2147483645, result.GetI());
342  }
343
344  void InvokeSumIntIntIntIntMethod(bool is_static)
345      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
346    mirror::ArtMethod* method;
347    mirror::Object* receiver;
348    DoCompile(method, receiver, is_static, "sum", "(IIII)I");
349
350    ArgArray arg_array(NULL, 0);
351    uint32_t* args = arg_array.GetArray();
352    JValue result;
353
354    if (!is_static) {
355      arg_array.Append(reinterpret_cast<uint32_t>(receiver));
356      args++;
357    }
358
359    arg_array.Append(0);
360    arg_array.Append(0);
361    arg_array.Append(0);
362    arg_array.Append(0);
363    result.SetI(-1);
364    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
365    EXPECT_EQ(0, result.GetI());
366
367    args[0] = 1;
368    args[1] = 2;
369    args[2] = 3;
370    args[3] = 4;
371    result.SetI(0);
372    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
373    EXPECT_EQ(10, result.GetI());
374
375    args[0] = -1;
376    args[1] = 2;
377    args[2] = -3;
378    args[3] = 4;
379    result.SetI(0);
380    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
381    EXPECT_EQ(2, result.GetI());
382
383    args[0] = INT_MAX;
384    args[1] = INT_MIN;
385    args[2] = INT_MAX;
386    args[3] = INT_MIN;
387    result.SetI(1234);
388    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
389    EXPECT_EQ(-2, result.GetI());
390
391    args[0] = INT_MAX;
392    args[1] = INT_MAX;
393    args[2] = INT_MAX;
394    args[3] = INT_MAX;
395    result.SetI(INT_MIN);
396    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
397    EXPECT_EQ(-4, result.GetI());
398  }
399
400  void InvokeSumIntIntIntIntIntMethod(bool is_static)
401      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
402    mirror::ArtMethod* method;
403    mirror::Object* receiver;
404    DoCompile(method, receiver, is_static, "sum", "(IIIII)I");
405
406    ArgArray arg_array(NULL, 0);
407    uint32_t* args = arg_array.GetArray();
408    JValue result;
409
410    if (!is_static) {
411      arg_array.Append(reinterpret_cast<uint32_t>(receiver));
412      args++;
413    }
414
415    arg_array.Append(0);
416    arg_array.Append(0);
417    arg_array.Append(0);
418    arg_array.Append(0);
419    arg_array.Append(0);
420    result.SetI(-1.0);
421    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
422    EXPECT_EQ(0, result.GetI());
423
424    args[0] = 1;
425    args[1] = 2;
426    args[2] = 3;
427    args[3] = 4;
428    args[4] = 5;
429    result.SetI(0);
430    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
431    EXPECT_EQ(15, result.GetI());
432
433    args[0] = -1;
434    args[1] = 2;
435    args[2] = -3;
436    args[3] = 4;
437    args[4] = -5;
438    result.SetI(0);
439    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
440    EXPECT_EQ(-3, result.GetI());
441
442    args[0] = INT_MAX;
443    args[1] = INT_MIN;
444    args[2] = INT_MAX;
445    args[3] = INT_MIN;
446    args[4] = INT_MAX;
447    result.SetI(1234);
448    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
449    EXPECT_EQ(2147483645, result.GetI());
450
451    args[0] = INT_MAX;
452    args[1] = INT_MAX;
453    args[2] = INT_MAX;
454    args[3] = INT_MAX;
455    args[4] = INT_MAX;
456    result.SetI(INT_MIN);
457    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'I');
458    EXPECT_EQ(2147483643, result.GetI());
459  }
460
461  void InvokeSumDoubleDoubleMethod(bool is_static)
462      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
463    mirror::ArtMethod* method;
464    mirror::Object* receiver;
465    DoCompile(method, receiver, is_static, "sum", "(DD)D");
466
467    ArgArray arg_array(NULL, 0);
468    uint32_t* args = arg_array.GetArray();
469    JValue value;
470    JValue value2;
471    JValue result;
472
473    if (!is_static) {
474      arg_array.Append(reinterpret_cast<uint32_t>(receiver));
475      args++;
476    }
477
478    value.SetD(0.0);
479    value2.SetD(0.0);
480    arg_array.AppendWide(value.GetJ());
481    arg_array.AppendWide(value2.GetJ());
482    result.SetD(-1.0);
483    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
484    EXPECT_EQ(0.0, result.GetD());
485
486    value.SetD(1.0);
487    value2.SetD(2.0);
488    args[0] = value.GetJ();
489    args[1] = value.GetJ() >> 32;
490    args[2] = value2.GetJ();
491    args[3] = value2.GetJ() >> 32;
492    result.SetD(0.0);
493    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
494    EXPECT_EQ(3.0, result.GetD());
495
496    value.SetD(1.0);
497    value2.SetD(-2.0);
498    args[0] = value.GetJ();
499    args[1] = value.GetJ() >> 32;
500    args[2] = value2.GetJ();
501    args[3] = value2.GetJ() >> 32;
502    result.SetD(0.0);
503    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
504    EXPECT_EQ(-1.0, result.GetD());
505
506    value.SetD(DBL_MAX);
507    value2.SetD(DBL_MIN);
508    args[0] = value.GetJ();
509    args[1] = value.GetJ() >> 32;
510    args[2] = value2.GetJ();
511    args[3] = value2.GetJ() >> 32;
512    result.SetD(0.0);
513    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
514    EXPECT_EQ(1.7976931348623157e308, result.GetD());
515
516    value.SetD(DBL_MAX);
517    value2.SetD(DBL_MAX);
518    args[0] = value.GetJ();
519    args[1] = value.GetJ() >> 32;
520    args[2] = value2.GetJ();
521    args[3] = value2.GetJ() >> 32;
522    result.SetD(0.0);
523    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
524    EXPECT_EQ(INFINITY, result.GetD());
525  }
526
527  void InvokeSumDoubleDoubleDoubleMethod(bool is_static)
528      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
529    mirror::ArtMethod* method;
530    mirror::Object* receiver;
531    DoCompile(method, receiver, is_static, "sum", "(DDD)D");
532
533    ArgArray arg_array(NULL, 0);
534    uint32_t* args = arg_array.GetArray();
535    JValue value;
536    JValue value2;
537    JValue value3;
538    JValue result;
539
540    if (!is_static) {
541      arg_array.Append(reinterpret_cast<uint32_t>(receiver));
542      args++;
543    }
544
545    value.SetD(0.0);
546    value2.SetD(0.0);
547    value3.SetD(0.0);
548    arg_array.AppendWide(value.GetJ());
549    arg_array.AppendWide(value2.GetJ());
550    arg_array.AppendWide(value3.GetJ());
551    result.SetD(-1.0);
552    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
553    EXPECT_EQ(0.0, result.GetD());
554
555    value.SetD(1.0);
556    value2.SetD(2.0);
557    value3.SetD(3.0);
558    args[0] = value.GetJ();
559    args[1] = value.GetJ() >> 32;
560    args[2] = value2.GetJ();
561    args[3] = value2.GetJ() >> 32;
562    args[4] = value3.GetJ();
563    args[5] = value3.GetJ() >> 32;
564    result.SetD(0.0);
565    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
566    EXPECT_EQ(6.0, result.GetD());
567
568    value.SetD(1.0);
569    value2.SetD(-2.0);
570    value3.SetD(3.0);
571    args[0] = value.GetJ();
572    args[1] = value.GetJ() >> 32;
573    args[2] = value2.GetJ();
574    args[3] = value2.GetJ() >> 32;
575    args[4] = value3.GetJ();
576    args[5] = value3.GetJ() >> 32;
577    result.SetD(0.0);
578    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
579    EXPECT_EQ(2.0, result.GetD());
580  }
581
582  void InvokeSumDoubleDoubleDoubleDoubleMethod(bool is_static)
583      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
584    mirror::ArtMethod* method;
585    mirror::Object* receiver;
586    DoCompile(method, receiver, is_static, "sum", "(DDDD)D");
587
588    ArgArray arg_array(NULL, 0);
589    uint32_t* args = arg_array.GetArray();
590    JValue value;
591    JValue value2;
592    JValue value3;
593    JValue value4;
594    JValue result;
595
596    if (!is_static) {
597      arg_array.Append(reinterpret_cast<uint32_t>(receiver));
598      args++;
599    }
600
601    value.SetD(0.0);
602    value2.SetD(0.0);
603    value3.SetD(0.0);
604    value4.SetD(0.0);
605    arg_array.AppendWide(value.GetJ());
606    arg_array.AppendWide(value2.GetJ());
607    arg_array.AppendWide(value3.GetJ());
608    arg_array.AppendWide(value4.GetJ());
609    result.SetD(-1.0);
610    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
611    EXPECT_EQ(0.0, result.GetD());
612
613    value.SetD(1.0);
614    value2.SetD(2.0);
615    value3.SetD(3.0);
616    value4.SetD(4.0);
617    args[0] = value.GetJ();
618    args[1] = value.GetJ() >> 32;
619    args[2] = value2.GetJ();
620    args[3] = value2.GetJ() >> 32;
621    args[4] = value3.GetJ();
622    args[5] = value3.GetJ() >> 32;
623    args[6] = value4.GetJ();
624    args[7] = value4.GetJ() >> 32;
625    result.SetD(0.0);
626    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
627    EXPECT_EQ(10.0, result.GetD());
628
629    value.SetD(1.0);
630    value2.SetD(-2.0);
631    value3.SetD(3.0);
632    value4.SetD(-4.0);
633    args[0] = value.GetJ();
634    args[1] = value.GetJ() >> 32;
635    args[2] = value2.GetJ();
636    args[3] = value2.GetJ() >> 32;
637    args[4] = value3.GetJ();
638    args[5] = value3.GetJ() >> 32;
639    args[6] = value4.GetJ();
640    args[7] = value4.GetJ() >> 32;
641    result.SetD(0.0);
642    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
643    EXPECT_EQ(-2.0, result.GetD());
644  }
645
646  void InvokeSumDoubleDoubleDoubleDoubleDoubleMethod(bool is_static)
647      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
648    mirror::ArtMethod* method;
649    mirror::Object* receiver;
650    DoCompile(method, receiver, is_static, "sum", "(DDDDD)D");
651
652    ArgArray arg_array(NULL, 0);
653    uint32_t* args = arg_array.GetArray();
654    JValue value;
655    JValue value2;
656    JValue value3;
657    JValue value4;
658    JValue value5;
659    JValue result;
660
661    if (!is_static) {
662      arg_array.Append(reinterpret_cast<uint32_t>(receiver));
663      args++;
664    }
665
666    value.SetD(0.0);
667    value2.SetD(0.0);
668    value3.SetD(0.0);
669    value4.SetD(0.0);
670    value5.SetD(0.0);
671    arg_array.AppendWide(value.GetJ());
672    arg_array.AppendWide(value2.GetJ());
673    arg_array.AppendWide(value3.GetJ());
674    arg_array.AppendWide(value4.GetJ());
675    arg_array.AppendWide(value5.GetJ());
676    result.SetD(-1.0);
677    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
678    EXPECT_EQ(0.0, result.GetD());
679
680    value.SetD(1.0);
681    value2.SetD(2.0);
682    value3.SetD(3.0);
683    value4.SetD(4.0);
684    value5.SetD(5.0);
685    args[0] = value.GetJ();
686    args[1] = value.GetJ() >> 32;
687    args[2] = value2.GetJ();
688    args[3] = value2.GetJ() >> 32;
689    args[4] = value3.GetJ();
690    args[5] = value3.GetJ() >> 32;
691    args[6] = value4.GetJ();
692    args[7] = value4.GetJ() >> 32;
693    args[8] = value5.GetJ();
694    args[9] = value5.GetJ() >> 32;
695    result.SetD(0.0);
696    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
697    EXPECT_EQ(15.0, result.GetD());
698
699    value.SetD(1.0);
700    value2.SetD(-2.0);
701    value3.SetD(3.0);
702    value4.SetD(-4.0);
703    value5.SetD(5.0);
704    args[0] = value.GetJ();
705    args[1] = value.GetJ() >> 32;
706    args[2] = value2.GetJ();
707    args[3] = value2.GetJ() >> 32;
708    args[4] = value3.GetJ();
709    args[5] = value3.GetJ() >> 32;
710    args[6] = value4.GetJ();
711    args[7] = value4.GetJ() >> 32;
712    args[8] = value5.GetJ();
713    args[9] = value5.GetJ() >> 32;
714    result.SetD(0.0);
715    method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'D');
716    EXPECT_EQ(3.0, result.GetD());
717  }
718
719  JavaVMExt* vm_;
720  JNIEnv* env_;
721  jclass aioobe_;
722  jclass ase_;
723  jclass sioobe_;
724};
725
726TEST_F(JniInternalTest, AllocObject) {
727  jclass c = env_->FindClass("java/lang/String");
728  ASSERT_TRUE(c != NULL);
729  jobject o = env_->AllocObject(c);
730  ASSERT_TRUE(o != NULL);
731
732  // We have an instance of the class we asked for...
733  ASSERT_TRUE(env_->IsInstanceOf(o, c));
734  // ...whose fields haven't been initialized because
735  // we didn't call a constructor.
736  ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "count", "I")));
737  ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "offset", "I")));
738  ASSERT_TRUE(env_->GetObjectField(o, env_->GetFieldID(c, "value", "[C")) == NULL);
739}
740
741TEST_F(JniInternalTest, GetVersion) {
742  ASSERT_EQ(JNI_VERSION_1_6, env_->GetVersion());
743}
744
745#define EXPECT_CLASS_FOUND(NAME) \
746  EXPECT_TRUE(env_->FindClass(NAME) != NULL); \
747  EXPECT_FALSE(env_->ExceptionCheck())
748
749#define EXPECT_CLASS_NOT_FOUND(NAME) \
750  EXPECT_TRUE(env_->FindClass(NAME) == NULL); \
751  EXPECT_TRUE(env_->ExceptionCheck()); \
752  env_->ExceptionClear()
753
754TEST_F(JniInternalTest, FindClass) {
755  // Reference types...
756  EXPECT_CLASS_FOUND("java/lang/String");
757  // ...for arrays too, where you must include "L;".
758  EXPECT_CLASS_FOUND("[Ljava/lang/String;");
759  // Primitive arrays are okay too, if the primitive type is valid.
760  EXPECT_CLASS_FOUND("[C");
761
762  {
763    // We support . as well as / for compatibility, if -Xcheck:jni is off.
764    CheckJniAbortCatcher check_jni_abort_catcher;
765    EXPECT_CLASS_FOUND("java.lang.String");
766    check_jni_abort_catcher.Check("illegal class name 'java.lang.String'");
767    EXPECT_CLASS_NOT_FOUND("Ljava.lang.String;");
768    check_jni_abort_catcher.Check("illegal class name 'Ljava.lang.String;'");
769    EXPECT_CLASS_FOUND("[Ljava.lang.String;");
770    check_jni_abort_catcher.Check("illegal class name '[Ljava.lang.String;'");
771    EXPECT_CLASS_NOT_FOUND("[java.lang.String");
772    check_jni_abort_catcher.Check("illegal class name '[java.lang.String'");
773
774    // You can't include the "L;" in a JNI class descriptor.
775    EXPECT_CLASS_NOT_FOUND("Ljava/lang/String;");
776    check_jni_abort_catcher.Check("illegal class name 'Ljava/lang/String;'");
777
778    // But you must include it for an array of any reference type.
779    EXPECT_CLASS_NOT_FOUND("[java/lang/String");
780    check_jni_abort_catcher.Check("illegal class name '[java/lang/String'");
781
782    EXPECT_CLASS_NOT_FOUND("[K");
783    check_jni_abort_catcher.Check("illegal class name '[K'");
784  }
785
786  // But primitive types aren't allowed...
787  EXPECT_CLASS_NOT_FOUND("C");
788  EXPECT_CLASS_NOT_FOUND("K");
789}
790
791#define EXPECT_EXCEPTION(exception_class) \
792  do { \
793    EXPECT_TRUE(env_->ExceptionCheck()); \
794    jthrowable exception = env_->ExceptionOccurred(); \
795    EXPECT_NE(static_cast<jthrowable>(NULL), exception); \
796    env_->ExceptionClear(); \
797    EXPECT_TRUE(env_->IsInstanceOf(exception, exception_class)); \
798  } while (false)
799
800TEST_F(JniInternalTest, GetFieldID) {
801  jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError");
802  ASSERT_TRUE(jlnsfe != NULL);
803  jclass c = env_->FindClass("java/lang/String");
804  ASSERT_TRUE(c != NULL);
805
806  // Wrong type.
807  jfieldID fid = env_->GetFieldID(c, "count", "J");
808  EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
809  EXPECT_EXCEPTION(jlnsfe);
810
811  // Wrong type where type doesn't exist.
812  fid = env_->GetFieldID(c, "count", "Lrod/jane/freddy;");
813  EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
814  EXPECT_EXCEPTION(jlnsfe);
815
816  // Wrong name.
817  fid = env_->GetFieldID(c, "Count", "I");
818  EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
819  EXPECT_EXCEPTION(jlnsfe);
820
821  // Good declared field lookup.
822  fid = env_->GetFieldID(c, "count", "I");
823  EXPECT_NE(static_cast<jfieldID>(NULL), fid);
824  EXPECT_TRUE(fid != NULL);
825  EXPECT_FALSE(env_->ExceptionCheck());
826
827  // Good superclass field lookup.
828  c = env_->FindClass("java/lang/StringBuilder");
829  fid = env_->GetFieldID(c, "count", "I");
830  EXPECT_NE(static_cast<jfieldID>(NULL), fid);
831  EXPECT_TRUE(fid != NULL);
832  EXPECT_FALSE(env_->ExceptionCheck());
833
834  // Not instance.
835  fid = env_->GetFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
836  EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
837  EXPECT_EXCEPTION(jlnsfe);
838}
839
840TEST_F(JniInternalTest, GetStaticFieldID) {
841  jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError");
842  ASSERT_TRUE(jlnsfe != NULL);
843  jclass c = env_->FindClass("java/lang/String");
844  ASSERT_TRUE(c != NULL);
845
846  // Wrong type.
847  jfieldID fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "J");
848  EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
849  EXPECT_EXCEPTION(jlnsfe);
850
851  // Wrong type where type doesn't exist.
852  fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Lrod/jane/freddy;");
853  EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
854  EXPECT_EXCEPTION(jlnsfe);
855
856  // Wrong name.
857  fid = env_->GetStaticFieldID(c, "cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
858  EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
859  EXPECT_EXCEPTION(jlnsfe);
860
861  // Good declared field lookup.
862  fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
863  EXPECT_NE(static_cast<jfieldID>(NULL), fid);
864  EXPECT_TRUE(fid != NULL);
865  EXPECT_FALSE(env_->ExceptionCheck());
866
867  // Not static.
868  fid = env_->GetStaticFieldID(c, "count", "I");
869  EXPECT_EQ(static_cast<jfieldID>(NULL), fid);
870  EXPECT_EXCEPTION(jlnsfe);
871}
872
873TEST_F(JniInternalTest, GetMethodID) {
874  jclass jlobject = env_->FindClass("java/lang/Object");
875  jclass jlstring = env_->FindClass("java/lang/String");
876  jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
877
878  // Sanity check that no exceptions are pending
879  ASSERT_FALSE(env_->ExceptionCheck());
880
881  // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
882  // a pending exception
883  jmethodID method = env_->GetMethodID(jlobject, "foo", "()V");
884  EXPECT_EQ(static_cast<jmethodID>(NULL), method);
885  EXPECT_EXCEPTION(jlnsme);
886
887  // Check that java.lang.Object.equals() does exist
888  method = env_->GetMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
889  EXPECT_NE(static_cast<jmethodID>(NULL), method);
890  EXPECT_FALSE(env_->ExceptionCheck());
891
892  // Check that GetMethodID for java.lang.String.valueOf(int) fails as the
893  // method is static
894  method = env_->GetMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;");
895  EXPECT_EQ(static_cast<jmethodID>(NULL), method);
896  EXPECT_EXCEPTION(jlnsme);
897
898  // Check that GetMethodID for java.lang.NoSuchMethodError.<init>(String) finds the constructor
899  method = env_->GetMethodID(jlnsme, "<init>", "(Ljava/lang/String;)V");
900  EXPECT_NE(static_cast<jmethodID>(NULL), method);
901  EXPECT_FALSE(env_->ExceptionCheck());
902}
903
904TEST_F(JniInternalTest, GetStaticMethodID) {
905  jclass jlobject = env_->FindClass("java/lang/Object");
906  jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
907
908  // Sanity check that no exceptions are pending
909  ASSERT_FALSE(env_->ExceptionCheck());
910
911  // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
912  // a pending exception
913  jmethodID method = env_->GetStaticMethodID(jlobject, "foo", "()V");
914  EXPECT_EQ(static_cast<jmethodID>(NULL), method);
915  EXPECT_EXCEPTION(jlnsme);
916
917  // Check that GetStaticMethodID for java.lang.Object.equals(Object) fails as
918  // the method is not static
919  method = env_->GetStaticMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
920  EXPECT_EQ(static_cast<jmethodID>(NULL), method);
921  EXPECT_EXCEPTION(jlnsme);
922
923  // Check that java.lang.String.valueOf(int) does exist
924  jclass jlstring = env_->FindClass("java/lang/String");
925  method = env_->GetStaticMethodID(jlstring, "valueOf",
926                                   "(I)Ljava/lang/String;");
927  EXPECT_NE(static_cast<jmethodID>(NULL), method);
928  EXPECT_FALSE(env_->ExceptionCheck());
929}
930
931TEST_F(JniInternalTest, FromReflectedField_ToReflectedField) {
932  jclass jlrField = env_->FindClass("java/lang/reflect/Field");
933  jclass c = env_->FindClass("java/lang/String");
934  ASSERT_TRUE(c != NULL);
935  jfieldID fid = env_->GetFieldID(c, "count", "I");
936  ASSERT_TRUE(fid != NULL);
937  // Turn the fid into a java.lang.reflect.Field...
938  jobject field = env_->ToReflectedField(c, fid, JNI_FALSE);
939  ASSERT_TRUE(c != NULL);
940  ASSERT_TRUE(env_->IsInstanceOf(field, jlrField));
941  // ...and back again.
942  jfieldID fid2 = env_->FromReflectedField(field);
943  ASSERT_TRUE(fid2 != NULL);
944  // Make sure we can actually use it.
945  jstring s = env_->NewStringUTF("poop");
946  ASSERT_EQ(4, env_->GetIntField(s, fid2));
947}
948
949TEST_F(JniInternalTest, FromReflectedMethod_ToReflectedMethod) {
950  jclass jlrMethod = env_->FindClass("java/lang/reflect/Method");
951  jclass c = env_->FindClass("java/lang/String");
952  ASSERT_TRUE(c != NULL);
953  jmethodID mid = env_->GetMethodID(c, "length", "()I");
954  ASSERT_TRUE(mid != NULL);
955  // Turn the mid into a java.lang.reflect.Method...
956  jobject method = env_->ToReflectedMethod(c, mid, JNI_FALSE);
957  ASSERT_TRUE(c != NULL);
958  ASSERT_TRUE(env_->IsInstanceOf(method, jlrMethod));
959  // ...and back again.
960  jmethodID mid2 = env_->FromReflectedMethod(method);
961  ASSERT_TRUE(mid2 != NULL);
962  // Make sure we can actually use it.
963  jstring s = env_->NewStringUTF("poop");
964  // TODO: this should return 4, but the runtime skips the method
965  // invoke because the runtime isn't started. In the future it would
966  // be nice to use interpretter for things like this. This still does
967  // validate that we have a sane jmethodID value.
968  ASSERT_EQ(0, env_->CallIntMethod(s, mid2));
969}
970
971void BogusMethod() {
972  // You can't pass NULL function pointers to RegisterNatives.
973}
974
975TEST_F(JniInternalTest, RegisterNatives) {
976  jclass jlobject = env_->FindClass("java/lang/Object");
977  jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
978
979  // Sanity check that no exceptions are pending
980  ASSERT_FALSE(env_->ExceptionCheck());
981
982  // Check that registering to a non-existent java.lang.Object.foo() causes a
983  // NoSuchMethodError
984  {
985    JNINativeMethod methods[] = { { "foo", "()V", NULL } };
986    env_->RegisterNatives(jlobject, methods, 1);
987  }
988  EXPECT_EXCEPTION(jlnsme);
989
990  // Check that registering non-native methods causes a NoSuchMethodError
991  {
992    JNINativeMethod methods[] = { { "equals", "(Ljava/lang/Object;)Z", NULL } };
993    env_->RegisterNatives(jlobject, methods, 1);
994  }
995  EXPECT_EXCEPTION(jlnsme);
996
997  // Check that registering native methods is successful
998  {
999    JNINativeMethod methods[] = { { "notify", "()V", reinterpret_cast<void*>(BogusMethod) } };
1000    env_->RegisterNatives(jlobject, methods, 1);
1001  }
1002  EXPECT_FALSE(env_->ExceptionCheck());
1003
1004  env_->UnregisterNatives(jlobject);
1005}
1006
1007#define EXPECT_PRIMITIVE_ARRAY(new_fn, \
1008                               get_region_fn, \
1009                               set_region_fn, \
1010                               get_elements_fn, \
1011                               release_elements_fn, \
1012                               scalar_type, \
1013                               expected_class_descriptor) \
1014  jsize size = 4; \
1015  /* Allocate an array and check it has the right type and length. */ \
1016  scalar_type ## Array a = env_->new_fn(size); \
1017  EXPECT_TRUE(a != NULL); \
1018  EXPECT_TRUE(env_->IsInstanceOf(a, env_->FindClass(expected_class_descriptor))); \
1019  EXPECT_EQ(size, env_->GetArrayLength(a)); \
1020  /* AIOOBE for negative start offset. */ \
1021  env_->get_region_fn(a, -1, 1, NULL); \
1022  EXPECT_EXCEPTION(aioobe_); \
1023  env_->set_region_fn(a, -1, 1, NULL); \
1024  EXPECT_EXCEPTION(aioobe_); \
1025  /* AIOOBE for negative length. */ \
1026  env_->get_region_fn(a, 0, -1, NULL); \
1027  EXPECT_EXCEPTION(aioobe_); \
1028  env_->set_region_fn(a, 0, -1, NULL); \
1029  EXPECT_EXCEPTION(aioobe_); \
1030  /* AIOOBE for buffer overrun. */ \
1031  env_->get_region_fn(a, size - 1, size, NULL); \
1032  EXPECT_EXCEPTION(aioobe_); \
1033  env_->set_region_fn(a, size - 1, size, NULL); \
1034  EXPECT_EXCEPTION(aioobe_); \
1035  /* Prepare a couple of buffers. */ \
1036  UniquePtr<scalar_type[]> src_buf(new scalar_type[size]); \
1037  UniquePtr<scalar_type[]> dst_buf(new scalar_type[size]); \
1038  for (jsize i = 0; i < size; ++i) { src_buf[i] = scalar_type(i); } \
1039  for (jsize i = 0; i < size; ++i) { dst_buf[i] = scalar_type(-1); } \
1040  /* Copy all of src_buf onto the heap. */ \
1041  env_->set_region_fn(a, 0, size, &src_buf[0]); \
1042  /* Copy back only part. */ \
1043  env_->get_region_fn(a, 1, size - 2, &dst_buf[1]); \
1044  EXPECT_NE(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \
1045    << "short copy equal"; \
1046  /* Copy the missing pieces. */ \
1047  env_->get_region_fn(a, 0, 1, &dst_buf[0]); \
1048  env_->get_region_fn(a, size - 1, 1, &dst_buf[size - 1]); \
1049  EXPECT_EQ(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \
1050    << "fixed copy not equal"; \
1051  /* Copy back the whole array. */ \
1052  env_->get_region_fn(a, 0, size, &dst_buf[0]); \
1053  EXPECT_EQ(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \
1054    << "full copy not equal"; \
1055  /* GetPrimitiveArrayCritical */ \
1056  void* v = env_->GetPrimitiveArrayCritical(a, NULL); \
1057  EXPECT_EQ(memcmp(&src_buf[0], v, size * sizeof(scalar_type)), 0) \
1058    << "GetPrimitiveArrayCritical not equal"; \
1059  env_->ReleasePrimitiveArrayCritical(a, v, 0); \
1060  /* GetXArrayElements */ \
1061  scalar_type* xs = env_->get_elements_fn(a, NULL); \
1062  EXPECT_EQ(memcmp(&src_buf[0], xs, size * sizeof(scalar_type)), 0) \
1063    << # get_elements_fn " not equal"; \
1064  env_->release_elements_fn(a, xs, 0); \
1065  EXPECT_EQ(reinterpret_cast<uintptr_t>(v), reinterpret_cast<uintptr_t>(xs))
1066
1067TEST_F(JniInternalTest, BooleanArrays) {
1068  EXPECT_PRIMITIVE_ARRAY(NewBooleanArray, GetBooleanArrayRegion, SetBooleanArrayRegion,
1069                         GetBooleanArrayElements, ReleaseBooleanArrayElements, jboolean, "[Z");
1070}
1071TEST_F(JniInternalTest, ByteArrays) {
1072  EXPECT_PRIMITIVE_ARRAY(NewByteArray, GetByteArrayRegion, SetByteArrayRegion,
1073                         GetByteArrayElements, ReleaseByteArrayElements, jbyte, "[B");
1074}
1075TEST_F(JniInternalTest, CharArrays) {
1076  EXPECT_PRIMITIVE_ARRAY(NewCharArray, GetCharArrayRegion, SetCharArrayRegion,
1077                         GetCharArrayElements, ReleaseCharArrayElements, jchar, "[C");
1078}
1079TEST_F(JniInternalTest, DoubleArrays) {
1080  EXPECT_PRIMITIVE_ARRAY(NewDoubleArray, GetDoubleArrayRegion, SetDoubleArrayRegion,
1081                         GetDoubleArrayElements, ReleaseDoubleArrayElements, jdouble, "[D");
1082}
1083TEST_F(JniInternalTest, FloatArrays) {
1084  EXPECT_PRIMITIVE_ARRAY(NewFloatArray, GetFloatArrayRegion, SetFloatArrayRegion,
1085                         GetFloatArrayElements, ReleaseFloatArrayElements, jfloat, "[F");
1086}
1087TEST_F(JniInternalTest, IntArrays) {
1088  EXPECT_PRIMITIVE_ARRAY(NewIntArray, GetIntArrayRegion, SetIntArrayRegion,
1089                         GetIntArrayElements, ReleaseIntArrayElements, jint, "[I");
1090}
1091TEST_F(JniInternalTest, LongArrays) {
1092  EXPECT_PRIMITIVE_ARRAY(NewLongArray, GetLongArrayRegion, SetLongArrayRegion,
1093                         GetLongArrayElements, ReleaseLongArrayElements, jlong, "[J");
1094}
1095TEST_F(JniInternalTest, ShortArrays) {
1096  EXPECT_PRIMITIVE_ARRAY(NewShortArray, GetShortArrayRegion, SetShortArrayRegion,
1097                         GetShortArrayElements, ReleaseShortArrayElements, jshort, "[S");
1098}
1099
1100TEST_F(JniInternalTest, NewObjectArray) {
1101  // TODO: death tests for negative array sizes.
1102
1103  // TODO: check non-NULL initial elements.
1104
1105  jclass element_class = env_->FindClass("java/lang/String");
1106  ASSERT_TRUE(element_class != NULL);
1107  jclass array_class = env_->FindClass("[Ljava/lang/String;");
1108  ASSERT_TRUE(array_class != NULL);
1109
1110  jobjectArray a;
1111
1112  a = env_->NewObjectArray(0, element_class, NULL);
1113  EXPECT_TRUE(a != NULL);
1114  EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
1115  EXPECT_EQ(0, env_->GetArrayLength(a));
1116
1117  a = env_->NewObjectArray(1, element_class, NULL);
1118  EXPECT_TRUE(a != NULL);
1119  EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
1120  EXPECT_EQ(1, env_->GetArrayLength(a));
1121  EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), NULL));
1122
1123  jstring s = env_->NewStringUTF("poop");
1124  a = env_->NewObjectArray(2, element_class, s);
1125  EXPECT_TRUE(a != NULL);
1126  EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
1127  EXPECT_EQ(2, env_->GetArrayLength(a));
1128  EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), s));
1129  EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 1), s));
1130}
1131
1132TEST_F(JniInternalTest, GetArrayLength) {
1133  // Already tested in NewObjectArray/NewPrimitiveArray.
1134}
1135
1136TEST_F(JniInternalTest, GetObjectClass) {
1137  jclass string_class = env_->FindClass("java/lang/String");
1138  ASSERT_TRUE(string_class != NULL);
1139  jclass class_class = env_->FindClass("java/lang/Class");
1140  ASSERT_TRUE(class_class != NULL);
1141
1142  jstring s = env_->NewStringUTF("poop");
1143  jclass c = env_->GetObjectClass(s);
1144  ASSERT_TRUE(env_->IsSameObject(string_class, c));
1145
1146  jclass c2 = env_->GetObjectClass(c);
1147  ASSERT_TRUE(env_->IsSameObject(class_class, env_->GetObjectClass(c2)));
1148}
1149
1150TEST_F(JniInternalTest, GetSuperclass) {
1151  jclass object_class = env_->FindClass("java/lang/Object");
1152  ASSERT_TRUE(object_class != NULL);
1153  jclass string_class = env_->FindClass("java/lang/String");
1154  ASSERT_TRUE(string_class != NULL);
1155  jclass runnable_interface = env_->FindClass("java/lang/Runnable");
1156  ASSERT_TRUE(runnable_interface != NULL);
1157  ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(string_class)));
1158  ASSERT_TRUE(env_->GetSuperclass(object_class) == NULL);
1159  ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(runnable_interface)));
1160}
1161
1162TEST_F(JniInternalTest, IsAssignableFrom) {
1163  jclass object_class = env_->FindClass("java/lang/Object");
1164  ASSERT_TRUE(object_class != NULL);
1165  jclass string_class = env_->FindClass("java/lang/String");
1166  ASSERT_TRUE(string_class != NULL);
1167
1168  ASSERT_TRUE(env_->IsAssignableFrom(object_class, string_class));
1169  ASSERT_FALSE(env_->IsAssignableFrom(string_class, object_class));
1170}
1171
1172TEST_F(JniInternalTest, GetObjectRefType) {
1173  jclass local = env_->FindClass("java/lang/Object");
1174  ASSERT_TRUE(local != NULL);
1175  EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(local));
1176
1177  jobject global = env_->NewGlobalRef(local);
1178  EXPECT_EQ(JNIGlobalRefType, env_->GetObjectRefType(global));
1179
1180  jweak weak_global = env_->NewWeakGlobalRef(local);
1181  EXPECT_EQ(JNIWeakGlobalRefType, env_->GetObjectRefType(weak_global));
1182
1183  jobject invalid = reinterpret_cast<jobject>(this);
1184  EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(invalid));
1185
1186  // TODO: invoke a native method and test that its arguments are considered local references.
1187}
1188
1189TEST_F(JniInternalTest, NewStringUTF) {
1190  EXPECT_TRUE(env_->NewStringUTF(NULL) == NULL);
1191  jstring s;
1192
1193  s = env_->NewStringUTF("");
1194  EXPECT_TRUE(s != NULL);
1195  EXPECT_EQ(0, env_->GetStringLength(s));
1196  EXPECT_EQ(0, env_->GetStringUTFLength(s));
1197  s = env_->NewStringUTF("hello");
1198  EXPECT_TRUE(s != NULL);
1199  EXPECT_EQ(5, env_->GetStringLength(s));
1200  EXPECT_EQ(5, env_->GetStringUTFLength(s));
1201
1202  // TODO: check some non-ASCII strings.
1203}
1204
1205TEST_F(JniInternalTest, NewString) {
1206  jchar chars[] = { 'h', 'i' };
1207  jstring s;
1208  s = env_->NewString(chars, 0);
1209  EXPECT_TRUE(s != NULL);
1210  EXPECT_EQ(0, env_->GetStringLength(s));
1211  EXPECT_EQ(0, env_->GetStringUTFLength(s));
1212  s = env_->NewString(chars, 2);
1213  EXPECT_TRUE(s != NULL);
1214  EXPECT_EQ(2, env_->GetStringLength(s));
1215  EXPECT_EQ(2, env_->GetStringUTFLength(s));
1216
1217  // TODO: check some non-ASCII strings.
1218}
1219
1220TEST_F(JniInternalTest, NewStringNullCharsZeroLength) {
1221  jstring s = env_->NewString(NULL, 0);
1222  EXPECT_TRUE(s != NULL);
1223  EXPECT_EQ(0, env_->GetStringLength(s));
1224}
1225
1226// TODO: fix gtest death tests on host http://b/5690440 (and target)
1227TEST_F(JniInternalTest, DISABLED_NewStringNullCharsNonzeroLength) {
1228  ASSERT_DEATH(env_->NewString(NULL, 1), "");
1229}
1230
1231TEST_F(JniInternalTest, GetStringLength_GetStringUTFLength) {
1232  // Already tested in the NewString/NewStringUTF tests.
1233}
1234
1235TEST_F(JniInternalTest, GetStringRegion_GetStringUTFRegion) {
1236  jstring s = env_->NewStringUTF("hello");
1237  ASSERT_TRUE(s != NULL);
1238
1239  env_->GetStringRegion(s, -1, 0, NULL);
1240  EXPECT_EXCEPTION(sioobe_);
1241  env_->GetStringRegion(s, 0, -1, NULL);
1242  EXPECT_EXCEPTION(sioobe_);
1243  env_->GetStringRegion(s, 0, 10, NULL);
1244  EXPECT_EXCEPTION(sioobe_);
1245  env_->GetStringRegion(s, 10, 1, NULL);
1246  EXPECT_EXCEPTION(sioobe_);
1247
1248  jchar chars[4] = { 'x', 'x', 'x', 'x' };
1249  env_->GetStringRegion(s, 1, 2, &chars[1]);
1250  EXPECT_EQ('x', chars[0]);
1251  EXPECT_EQ('e', chars[1]);
1252  EXPECT_EQ('l', chars[2]);
1253  EXPECT_EQ('x', chars[3]);
1254
1255  env_->GetStringUTFRegion(s, -1, 0, NULL);
1256  EXPECT_EXCEPTION(sioobe_);
1257  env_->GetStringUTFRegion(s, 0, -1, NULL);
1258  EXPECT_EXCEPTION(sioobe_);
1259  env_->GetStringUTFRegion(s, 0, 10, NULL);
1260  EXPECT_EXCEPTION(sioobe_);
1261  env_->GetStringUTFRegion(s, 10, 1, NULL);
1262  EXPECT_EXCEPTION(sioobe_);
1263
1264  char bytes[4] = { 'x', 'x', 'x', 'x' };
1265  env_->GetStringUTFRegion(s, 1, 2, &bytes[1]);
1266  EXPECT_EQ('x', bytes[0]);
1267  EXPECT_EQ('e', bytes[1]);
1268  EXPECT_EQ('l', bytes[2]);
1269  EXPECT_EQ('x', bytes[3]);
1270}
1271
1272TEST_F(JniInternalTest, GetStringUTFChars_ReleaseStringUTFChars) {
1273  // Passing in a NULL jstring is ignored normally, but caught by -Xcheck:jni.
1274  {
1275    CheckJniAbortCatcher check_jni_abort_catcher;
1276    EXPECT_TRUE(env_->GetStringUTFChars(NULL, NULL) == NULL);
1277    check_jni_abort_catcher.Check("GetStringUTFChars received null jstring");
1278  }
1279
1280  jstring s = env_->NewStringUTF("hello");
1281  ASSERT_TRUE(s != NULL);
1282
1283  const char* utf = env_->GetStringUTFChars(s, NULL);
1284  EXPECT_STREQ("hello", utf);
1285  env_->ReleaseStringUTFChars(s, utf);
1286
1287  jboolean is_copy = JNI_FALSE;
1288  utf = env_->GetStringUTFChars(s, &is_copy);
1289  EXPECT_EQ(JNI_TRUE, is_copy);
1290  EXPECT_STREQ("hello", utf);
1291  env_->ReleaseStringUTFChars(s, utf);
1292}
1293
1294TEST_F(JniInternalTest, GetStringChars_ReleaseStringChars) {
1295  jstring s = env_->NewStringUTF("hello");
1296  ASSERT_TRUE(s != NULL);
1297
1298  jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
1299  const jchar* chars = env_->GetStringChars(s, NULL);
1300  EXPECT_EQ(expected[0], chars[0]);
1301  EXPECT_EQ(expected[1], chars[1]);
1302  EXPECT_EQ(expected[2], chars[2]);
1303  EXPECT_EQ(expected[3], chars[3]);
1304  EXPECT_EQ(expected[4], chars[4]);
1305  env_->ReleaseStringChars(s, chars);
1306
1307  jboolean is_copy = JNI_FALSE;
1308  chars = env_->GetStringChars(s, &is_copy);
1309  EXPECT_EQ(JNI_FALSE, is_copy);
1310  EXPECT_EQ(expected[0], chars[0]);
1311  EXPECT_EQ(expected[1], chars[1]);
1312  EXPECT_EQ(expected[2], chars[2]);
1313  EXPECT_EQ(expected[3], chars[3]);
1314  EXPECT_EQ(expected[4], chars[4]);
1315  env_->ReleaseStringChars(s, chars);
1316}
1317
1318TEST_F(JniInternalTest, GetStringCritical_ReleaseStringCritical) {
1319  jstring s = env_->NewStringUTF("hello");
1320  ASSERT_TRUE(s != NULL);
1321
1322  jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
1323  const jchar* chars = env_->GetStringCritical(s, NULL);
1324  EXPECT_EQ(expected[0], chars[0]);
1325  EXPECT_EQ(expected[1], chars[1]);
1326  EXPECT_EQ(expected[2], chars[2]);
1327  EXPECT_EQ(expected[3], chars[3]);
1328  EXPECT_EQ(expected[4], chars[4]);
1329  env_->ReleaseStringCritical(s, chars);
1330
1331  jboolean is_copy = JNI_FALSE;
1332  chars = env_->GetStringCritical(s, &is_copy);
1333  EXPECT_EQ(JNI_FALSE, is_copy);
1334  EXPECT_EQ(expected[0], chars[0]);
1335  EXPECT_EQ(expected[1], chars[1]);
1336  EXPECT_EQ(expected[2], chars[2]);
1337  EXPECT_EQ(expected[3], chars[3]);
1338  EXPECT_EQ(expected[4], chars[4]);
1339  env_->ReleaseStringCritical(s, chars);
1340}
1341
1342TEST_F(JniInternalTest, GetObjectArrayElement_SetObjectArrayElement) {
1343  jclass java_lang_Class = env_->FindClass("java/lang/Class");
1344  ASSERT_TRUE(java_lang_Class != NULL);
1345
1346  jobjectArray array = env_->NewObjectArray(1, java_lang_Class, NULL);
1347  EXPECT_TRUE(array != NULL);
1348  EXPECT_TRUE(env_->GetObjectArrayElement(array, 0) == NULL);
1349  env_->SetObjectArrayElement(array, 0, java_lang_Class);
1350  EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(array, 0), java_lang_Class));
1351
1352  // ArrayIndexOutOfBounds for negative index.
1353  env_->SetObjectArrayElement(array, -1, java_lang_Class);
1354  EXPECT_EXCEPTION(aioobe_);
1355
1356  // ArrayIndexOutOfBounds for too-large index.
1357  env_->SetObjectArrayElement(array, 1, java_lang_Class);
1358  EXPECT_EXCEPTION(aioobe_);
1359
1360  // ArrayStoreException thrown for bad types.
1361  env_->SetObjectArrayElement(array, 0, env_->NewStringUTF("not a jclass!"));
1362  EXPECT_EXCEPTION(ase_);
1363}
1364
1365#define EXPECT_STATIC_PRIMITIVE_FIELD(type, field_name, sig, value1, value2) \
1366  do { \
1367    jfieldID fid = env_->GetStaticFieldID(c, field_name, sig); \
1368    EXPECT_TRUE(fid != NULL); \
1369    env_->SetStatic ## type ## Field(c, fid, value1); \
1370    EXPECT_TRUE(value1 == env_->GetStatic ## type ## Field(c, fid)); \
1371    env_->SetStatic ## type ## Field(c, fid, value2); \
1372    EXPECT_TRUE(value2 == env_->GetStatic ## type ## Field(c, fid)); \
1373  } while (false)
1374
1375#define EXPECT_PRIMITIVE_FIELD(instance, type, field_name, sig, value1, value2) \
1376  do { \
1377    jfieldID fid = env_->GetFieldID(c, field_name, sig); \
1378    EXPECT_TRUE(fid != NULL); \
1379    env_->Set ## type ## Field(instance, fid, value1); \
1380    EXPECT_TRUE(value1 == env_->Get ## type ## Field(instance, fid)); \
1381    env_->Set ## type ## Field(instance, fid, value2); \
1382    EXPECT_TRUE(value2 == env_->Get ## type ## Field(instance, fid)); \
1383  } while (false)
1384
1385
1386#if !defined(ART_USE_PORTABLE_COMPILER)
1387TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) {
1388  Thread::Current()->TransitionFromSuspendedToRunnable();
1389  LoadDex("AllFields");
1390  bool started = runtime_->Start();
1391  CHECK(started);
1392
1393  jclass c = env_->FindClass("AllFields");
1394  ASSERT_TRUE(c != NULL);
1395  jobject o = env_->AllocObject(c);
1396  ASSERT_TRUE(o != NULL);
1397
1398  EXPECT_STATIC_PRIMITIVE_FIELD(Boolean, "sZ", "Z", true, false);
1399  EXPECT_STATIC_PRIMITIVE_FIELD(Byte, "sB", "B", 1, 2);
1400  EXPECT_STATIC_PRIMITIVE_FIELD(Char, "sC", "C", 'a', 'b');
1401  EXPECT_STATIC_PRIMITIVE_FIELD(Double, "sD", "D", 1.0, 2.0);
1402  EXPECT_STATIC_PRIMITIVE_FIELD(Float, "sF", "F", 1.0, 2.0);
1403  EXPECT_STATIC_PRIMITIVE_FIELD(Int, "sI", "I", 1, 2);
1404  EXPECT_STATIC_PRIMITIVE_FIELD(Long, "sJ", "J", 1, 2);
1405  EXPECT_STATIC_PRIMITIVE_FIELD(Short, "sS", "S", 1, 2);
1406
1407  EXPECT_PRIMITIVE_FIELD(o, Boolean, "iZ", "Z", true, false);
1408  EXPECT_PRIMITIVE_FIELD(o, Byte, "iB", "B", 1, 2);
1409  EXPECT_PRIMITIVE_FIELD(o, Char, "iC", "C", 'a', 'b');
1410  EXPECT_PRIMITIVE_FIELD(o, Double, "iD", "D", 1.0, 2.0);
1411  EXPECT_PRIMITIVE_FIELD(o, Float, "iF", "F", 1.0, 2.0);
1412  EXPECT_PRIMITIVE_FIELD(o, Int, "iI", "I", 1, 2);
1413  EXPECT_PRIMITIVE_FIELD(o, Long, "iJ", "J", 1, 2);
1414  EXPECT_PRIMITIVE_FIELD(o, Short, "iS", "S", 1, 2);
1415}
1416
1417TEST_F(JniInternalTest, GetObjectField_SetObjectField) {
1418  Thread::Current()->TransitionFromSuspendedToRunnable();
1419  LoadDex("AllFields");
1420  runtime_->Start();
1421
1422  jclass c = env_->FindClass("AllFields");
1423  ASSERT_TRUE(c != NULL);
1424  jobject o = env_->AllocObject(c);
1425  ASSERT_TRUE(o != NULL);
1426
1427  jstring s1 = env_->NewStringUTF("hello");
1428  ASSERT_TRUE(s1 != NULL);
1429  jstring s2 = env_->NewStringUTF("world");
1430  ASSERT_TRUE(s2 != NULL);
1431
1432  jfieldID s_fid = env_->GetStaticFieldID(c, "sObject", "Ljava/lang/Object;");
1433  ASSERT_TRUE(s_fid != NULL);
1434  jfieldID i_fid = env_->GetFieldID(c, "iObject", "Ljava/lang/Object;");
1435  ASSERT_TRUE(i_fid != NULL);
1436
1437  env_->SetStaticObjectField(c, s_fid, s1);
1438  ASSERT_TRUE(env_->IsSameObject(s1, env_->GetStaticObjectField(c, s_fid)));
1439  env_->SetStaticObjectField(c, s_fid, s2);
1440  ASSERT_TRUE(env_->IsSameObject(s2, env_->GetStaticObjectField(c, s_fid)));
1441
1442  env_->SetObjectField(o, i_fid, s1);
1443  ASSERT_TRUE(env_->IsSameObject(s1, env_->GetObjectField(o, i_fid)));
1444  env_->SetObjectField(o, i_fid, s2);
1445  ASSERT_TRUE(env_->IsSameObject(s2, env_->GetObjectField(o, i_fid)));
1446}
1447#endif
1448
1449TEST_F(JniInternalTest, NewLocalRef_NULL) {
1450  EXPECT_TRUE(env_->NewLocalRef(NULL) == NULL);
1451}
1452
1453TEST_F(JniInternalTest, NewLocalRef) {
1454  jstring s = env_->NewStringUTF("");
1455  ASSERT_TRUE(s != NULL);
1456  jobject o = env_->NewLocalRef(s);
1457  EXPECT_TRUE(o != NULL);
1458  EXPECT_TRUE(o != s);
1459
1460  EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(o));
1461}
1462
1463TEST_F(JniInternalTest, DeleteLocalRef_NULL) {
1464  env_->DeleteLocalRef(NULL);
1465}
1466
1467TEST_F(JniInternalTest, DeleteLocalRef) {
1468  jstring s = env_->NewStringUTF("");
1469  ASSERT_TRUE(s != NULL);
1470  env_->DeleteLocalRef(s);
1471
1472  // Currently, deleting an already-deleted reference is just a CheckJNI warning.
1473  {
1474    CheckJniAbortCatcher check_jni_abort_catcher;
1475    env_->DeleteLocalRef(s);
1476
1477    std::string expected(StringPrintf("native code passing in reference to "
1478                                      "invalid local reference: %p", s));
1479    check_jni_abort_catcher.Check(expected.c_str());
1480  }
1481
1482  s = env_->NewStringUTF("");
1483  ASSERT_TRUE(s != NULL);
1484  jobject o = env_->NewLocalRef(s);
1485  ASSERT_TRUE(o != NULL);
1486
1487  env_->DeleteLocalRef(s);
1488  env_->DeleteLocalRef(o);
1489}
1490
1491TEST_F(JniInternalTest, PushLocalFrame_10395422) {
1492  // The JNI specification is ambiguous about whether the given capacity is to be interpreted as a
1493  // maximum or as a minimum, but it seems like it's supposed to be a minimum, and that's how
1494  // Android historically treated it, and it's how the RI treats it. It's also the more useful
1495  // interpretation!
1496  ASSERT_EQ(JNI_OK, env_->PushLocalFrame(0));
1497  env_->PopLocalFrame(NULL);
1498
1499  // Negative capacities are not allowed.
1500  ASSERT_EQ(JNI_ERR, env_->PushLocalFrame(-1));
1501
1502  // And it's okay to have an upper limit. Ours is currently 512.
1503  ASSERT_EQ(JNI_ERR, env_->PushLocalFrame(8192));
1504}
1505
1506TEST_F(JniInternalTest, PushLocalFrame_PopLocalFrame) {
1507  jobject original = env_->NewStringUTF("");
1508  ASSERT_TRUE(original != NULL);
1509
1510  jobject outer;
1511  jobject inner1, inner2;
1512  ScopedObjectAccess soa(env_);
1513  mirror::Object* inner2_direct_pointer;
1514  {
1515    ASSERT_EQ(JNI_OK, env_->PushLocalFrame(4));
1516    outer = env_->NewLocalRef(original);
1517
1518    {
1519      ASSERT_EQ(JNI_OK, env_->PushLocalFrame(4));
1520      inner1 = env_->NewLocalRef(outer);
1521      inner2 = env_->NewStringUTF("survivor");
1522      inner2_direct_pointer = soa.Decode<mirror::Object*>(inner2);
1523      env_->PopLocalFrame(inner2);
1524    }
1525
1526    EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original));
1527    EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(outer));
1528    EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1));
1529
1530    // Our local reference for the survivor is invalid because the survivor
1531    // gets a new local reference...
1532    EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
1533    // ...but the survivor should be in the local reference table.
1534    JNIEnvExt* env = reinterpret_cast<JNIEnvExt*>(env_);
1535    EXPECT_TRUE(env->locals.ContainsDirectPointer(inner2_direct_pointer));
1536
1537    env_->PopLocalFrame(NULL);
1538  }
1539  EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original));
1540  EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(outer));
1541  EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1));
1542  EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
1543}
1544
1545TEST_F(JniInternalTest, NewGlobalRef_NULL) {
1546  EXPECT_TRUE(env_->NewGlobalRef(NULL) == NULL);
1547}
1548
1549TEST_F(JniInternalTest, NewGlobalRef) {
1550  jstring s = env_->NewStringUTF("");
1551  ASSERT_TRUE(s != NULL);
1552  jobject o = env_->NewGlobalRef(s);
1553  EXPECT_TRUE(o != NULL);
1554  EXPECT_TRUE(o != s);
1555
1556  // TODO: check that o is a global reference.
1557}
1558
1559TEST_F(JniInternalTest, DeleteGlobalRef_NULL) {
1560  env_->DeleteGlobalRef(NULL);
1561}
1562
1563TEST_F(JniInternalTest, DeleteGlobalRef) {
1564  jstring s = env_->NewStringUTF("");
1565  ASSERT_TRUE(s != NULL);
1566
1567  jobject o = env_->NewGlobalRef(s);
1568  ASSERT_TRUE(o != NULL);
1569  env_->DeleteGlobalRef(o);
1570
1571  // Currently, deleting an already-deleted reference is just a CheckJNI warning.
1572  {
1573    CheckJniAbortCatcher check_jni_abort_catcher;
1574    env_->DeleteGlobalRef(o);
1575
1576    std::string expected(StringPrintf("native code passing in reference to "
1577                                      "invalid global reference: %p", o));
1578    check_jni_abort_catcher.Check(expected.c_str());
1579  }
1580
1581  jobject o1 = env_->NewGlobalRef(s);
1582  ASSERT_TRUE(o1 != NULL);
1583  jobject o2 = env_->NewGlobalRef(s);
1584  ASSERT_TRUE(o2 != NULL);
1585
1586  env_->DeleteGlobalRef(o1);
1587  env_->DeleteGlobalRef(o2);
1588}
1589
1590TEST_F(JniInternalTest, NewWeakGlobalRef_NULL) {
1591  EXPECT_TRUE(env_->NewWeakGlobalRef(NULL) == NULL);
1592}
1593
1594TEST_F(JniInternalTest, NewWeakGlobalRef) {
1595  jstring s = env_->NewStringUTF("");
1596  ASSERT_TRUE(s != NULL);
1597  jobject o = env_->NewWeakGlobalRef(s);
1598  EXPECT_TRUE(o != NULL);
1599  EXPECT_TRUE(o != s);
1600
1601  // TODO: check that o is a weak global reference.
1602}
1603
1604TEST_F(JniInternalTest, DeleteWeakGlobalRef_NULL) {
1605  env_->DeleteWeakGlobalRef(NULL);
1606}
1607
1608TEST_F(JniInternalTest, DeleteWeakGlobalRef) {
1609  jstring s = env_->NewStringUTF("");
1610  ASSERT_TRUE(s != NULL);
1611
1612  jobject o = env_->NewWeakGlobalRef(s);
1613  ASSERT_TRUE(o != NULL);
1614  env_->DeleteWeakGlobalRef(o);
1615
1616  // Currently, deleting an already-deleted reference is just a CheckJNI warning.
1617  {
1618    CheckJniAbortCatcher check_jni_abort_catcher;
1619    env_->DeleteWeakGlobalRef(o);
1620
1621    std::string expected(StringPrintf("native code passing in reference to "
1622                                      "invalid weak global reference: %p", o));
1623    check_jni_abort_catcher.Check(expected.c_str());
1624  }
1625
1626  jobject o1 = env_->NewWeakGlobalRef(s);
1627  ASSERT_TRUE(o1 != NULL);
1628  jobject o2 = env_->NewWeakGlobalRef(s);
1629  ASSERT_TRUE(o2 != NULL);
1630
1631  env_->DeleteWeakGlobalRef(o1);
1632  env_->DeleteWeakGlobalRef(o2);
1633}
1634
1635TEST_F(JniInternalTest, StaticMainMethod) {
1636  TEST_DISABLED_FOR_PORTABLE();
1637  ScopedObjectAccess soa(Thread::Current());
1638  jobject jclass_loader = LoadDex("Main");
1639  SirtRef<mirror::ClassLoader>
1640      class_loader(soa.Self(), soa.Decode<mirror::ClassLoader*>(jclass_loader));
1641  CompileDirectMethod(class_loader.get(), "Main", "main", "([Ljava/lang/String;)V");
1642
1643  mirror::Class* klass = class_linker_->FindClass("LMain;", class_loader.get());
1644  ASSERT_TRUE(klass != NULL);
1645
1646  mirror::ArtMethod* method = klass->FindDirectMethod("main", "([Ljava/lang/String;)V");
1647  ASSERT_TRUE(method != NULL);
1648
1649  ArgArray arg_array(NULL, 0);
1650  arg_array.Append(0);
1651  JValue result;
1652
1653  // Start runtime.
1654  bool started = runtime_->Start();
1655  CHECK(started);
1656  Thread::Current()->TransitionFromSuspendedToRunnable();
1657
1658  method->Invoke(Thread::Current(), arg_array.GetArray(), arg_array.GetNumBytes(), &result, 'V');
1659}
1660
1661TEST_F(JniInternalTest, StaticNopMethod) {
1662  TEST_DISABLED_FOR_PORTABLE();
1663  ScopedObjectAccess soa(Thread::Current());
1664  InvokeNopMethod(true);
1665}
1666
1667TEST_F(JniInternalTest, NonStaticNopMethod) {
1668  TEST_DISABLED_FOR_PORTABLE();
1669  ScopedObjectAccess soa(Thread::Current());
1670  InvokeNopMethod(false);
1671}
1672
1673TEST_F(JniInternalTest, StaticIdentityByteMethod) {
1674  TEST_DISABLED_FOR_PORTABLE();
1675  ScopedObjectAccess soa(Thread::Current());
1676  InvokeIdentityByteMethod(true);
1677}
1678
1679TEST_F(JniInternalTest, NonStaticIdentityByteMethod) {
1680  TEST_DISABLED_FOR_PORTABLE();
1681  ScopedObjectAccess soa(Thread::Current());
1682  InvokeIdentityByteMethod(false);
1683}
1684
1685TEST_F(JniInternalTest, StaticIdentityIntMethod) {
1686  TEST_DISABLED_FOR_PORTABLE();
1687  ScopedObjectAccess soa(Thread::Current());
1688  InvokeIdentityIntMethod(true);
1689}
1690
1691TEST_F(JniInternalTest, NonStaticIdentityIntMethod) {
1692  TEST_DISABLED_FOR_PORTABLE();
1693  ScopedObjectAccess soa(Thread::Current());
1694  InvokeIdentityIntMethod(false);
1695}
1696
1697TEST_F(JniInternalTest, StaticIdentityDoubleMethod) {
1698  TEST_DISABLED_FOR_PORTABLE();
1699  ScopedObjectAccess soa(Thread::Current());
1700  InvokeIdentityDoubleMethod(true);
1701}
1702
1703TEST_F(JniInternalTest, NonStaticIdentityDoubleMethod) {
1704  TEST_DISABLED_FOR_PORTABLE();
1705  ScopedObjectAccess soa(Thread::Current());
1706  InvokeIdentityDoubleMethod(false);
1707}
1708
1709TEST_F(JniInternalTest, StaticSumIntIntMethod) {
1710  TEST_DISABLED_FOR_PORTABLE();
1711  ScopedObjectAccess soa(Thread::Current());
1712  InvokeSumIntIntMethod(true);
1713}
1714
1715TEST_F(JniInternalTest, NonStaticSumIntIntMethod) {
1716  TEST_DISABLED_FOR_PORTABLE();
1717  ScopedObjectAccess soa(Thread::Current());
1718  InvokeSumIntIntMethod(false);
1719}
1720
1721TEST_F(JniInternalTest, StaticSumIntIntIntMethod) {
1722  TEST_DISABLED_FOR_PORTABLE();
1723  ScopedObjectAccess soa(Thread::Current());
1724  InvokeSumIntIntIntMethod(true);
1725}
1726
1727TEST_F(JniInternalTest, NonStaticSumIntIntIntMethod) {
1728  TEST_DISABLED_FOR_PORTABLE();
1729  ScopedObjectAccess soa(Thread::Current());
1730  InvokeSumIntIntIntMethod(false);
1731}
1732
1733TEST_F(JniInternalTest, StaticSumIntIntIntIntMethod) {
1734  TEST_DISABLED_FOR_PORTABLE();
1735  ScopedObjectAccess soa(Thread::Current());
1736  InvokeSumIntIntIntIntMethod(true);
1737}
1738
1739TEST_F(JniInternalTest, NonStaticSumIntIntIntIntMethod) {
1740  TEST_DISABLED_FOR_PORTABLE();
1741  ScopedObjectAccess soa(Thread::Current());
1742  InvokeSumIntIntIntIntMethod(false);
1743}
1744
1745TEST_F(JniInternalTest, StaticSumIntIntIntIntIntMethod) {
1746  TEST_DISABLED_FOR_PORTABLE();
1747  ScopedObjectAccess soa(Thread::Current());
1748  InvokeSumIntIntIntIntIntMethod(true);
1749}
1750
1751TEST_F(JniInternalTest, NonStaticSumIntIntIntIntIntMethod) {
1752  TEST_DISABLED_FOR_PORTABLE();
1753  ScopedObjectAccess soa(Thread::Current());
1754  InvokeSumIntIntIntIntIntMethod(false);
1755}
1756
1757TEST_F(JniInternalTest, StaticSumDoubleDoubleMethod) {
1758  TEST_DISABLED_FOR_PORTABLE();
1759  ScopedObjectAccess soa(Thread::Current());
1760  InvokeSumDoubleDoubleMethod(true);
1761}
1762
1763TEST_F(JniInternalTest, NonStaticSumDoubleDoubleMethod) {
1764  TEST_DISABLED_FOR_PORTABLE();
1765  ScopedObjectAccess soa(Thread::Current());
1766  InvokeSumDoubleDoubleMethod(false);
1767}
1768
1769TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleMethod) {
1770  TEST_DISABLED_FOR_PORTABLE();
1771  ScopedObjectAccess soa(Thread::Current());
1772  InvokeSumDoubleDoubleDoubleMethod(true);
1773}
1774
1775TEST_F(JniInternalTest, NonStaticSumDoubleDoubleDoubleMethod) {
1776  TEST_DISABLED_FOR_PORTABLE();
1777  ScopedObjectAccess soa(Thread::Current());
1778  InvokeSumDoubleDoubleDoubleMethod(false);
1779}
1780
1781TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleMethod) {
1782  TEST_DISABLED_FOR_PORTABLE();
1783  ScopedObjectAccess soa(Thread::Current());
1784  InvokeSumDoubleDoubleDoubleDoubleMethod(true);
1785}
1786
1787TEST_F(JniInternalTest, NonStaticSumDoubleDoubleDoubleDoubleMethod) {
1788  TEST_DISABLED_FOR_PORTABLE();
1789  ScopedObjectAccess soa(Thread::Current());
1790  InvokeSumDoubleDoubleDoubleDoubleMethod(false);
1791}
1792
1793TEST_F(JniInternalTest, StaticSumDoubleDoubleDoubleDoubleDoubleMethod) {
1794  TEST_DISABLED_FOR_PORTABLE();
1795  ScopedObjectAccess soa(Thread::Current());
1796  InvokeSumDoubleDoubleDoubleDoubleDoubleMethod(true);
1797}
1798
1799TEST_F(JniInternalTest, NonStaticSumDoubleDoubleDoubleDoubleDoubleMethod) {
1800  TEST_DISABLED_FOR_PORTABLE();
1801  ScopedObjectAccess soa(Thread::Current());
1802  InvokeSumDoubleDoubleDoubleDoubleDoubleMethod(false);
1803}
1804
1805TEST_F(JniInternalTest, Throw) {
1806  EXPECT_EQ(JNI_ERR, env_->Throw(NULL));
1807
1808  jclass exception_class = env_->FindClass("java/lang/RuntimeException");
1809  ASSERT_TRUE(exception_class != NULL);
1810  jthrowable exception = reinterpret_cast<jthrowable>(env_->AllocObject(exception_class));
1811  ASSERT_TRUE(exception != NULL);
1812
1813  EXPECT_EQ(JNI_OK, env_->Throw(exception));
1814  EXPECT_TRUE(env_->ExceptionCheck());
1815  jthrowable thrown_exception = env_->ExceptionOccurred();
1816  env_->ExceptionClear();
1817  EXPECT_TRUE(env_->IsSameObject(exception, thrown_exception));
1818}
1819
1820TEST_F(JniInternalTest, ThrowNew) {
1821  EXPECT_EQ(JNI_ERR, env_->Throw(NULL));
1822
1823  jclass exception_class = env_->FindClass("java/lang/RuntimeException");
1824  ASSERT_TRUE(exception_class != NULL);
1825
1826  jthrowable thrown_exception;
1827
1828  EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, "hello world"));
1829  EXPECT_TRUE(env_->ExceptionCheck());
1830  thrown_exception = env_->ExceptionOccurred();
1831  env_->ExceptionClear();
1832  EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class));
1833
1834  EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, NULL));
1835  EXPECT_TRUE(env_->ExceptionCheck());
1836  thrown_exception = env_->ExceptionOccurred();
1837  env_->ExceptionClear();
1838  EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class));
1839}
1840
1841// TODO: this test is DISABLED until we can actually run java.nio.Buffer's <init>.
1842TEST_F(JniInternalTest, DISABLED_NewDirectBuffer_GetDirectBufferAddress_GetDirectBufferCapacity) {
1843  jclass buffer_class = env_->FindClass("java/nio/Buffer");
1844  ASSERT_TRUE(buffer_class != NULL);
1845
1846  char bytes[1024];
1847  jobject buffer = env_->NewDirectByteBuffer(bytes, sizeof(bytes));
1848  ASSERT_TRUE(buffer != NULL);
1849  ASSERT_TRUE(env_->IsInstanceOf(buffer, buffer_class));
1850  ASSERT_TRUE(env_->GetDirectBufferAddress(buffer) == bytes);
1851  ASSERT_TRUE(env_->GetDirectBufferCapacity(buffer) == sizeof(bytes));
1852}
1853
1854TEST_F(JniInternalTest, MonitorEnterExit) {
1855  // Create an object to torture
1856  jclass object_class = env_->FindClass("java/lang/Object");
1857  ASSERT_TRUE(object_class != NULL);
1858  jobject object = env_->AllocObject(object_class);
1859  ASSERT_TRUE(object != NULL);
1860
1861  // Expected class of exceptions
1862  jclass imse_class = env_->FindClass("java/lang/IllegalMonitorStateException");
1863  ASSERT_TRUE(imse_class != NULL);
1864
1865  jthrowable thrown_exception;
1866
1867  // Unlock of unowned monitor
1868  env_->MonitorExit(object);
1869  EXPECT_TRUE(env_->ExceptionCheck());
1870  thrown_exception = env_->ExceptionOccurred();
1871  env_->ExceptionClear();
1872  EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class));
1873
1874  // Lock of unowned monitor
1875  env_->MonitorEnter(object);
1876  EXPECT_FALSE(env_->ExceptionCheck());
1877  // Regular unlock
1878  env_->MonitorExit(object);
1879  EXPECT_FALSE(env_->ExceptionCheck());
1880
1881  // Recursively lock a lot
1882  size_t max_recursive_lock = 1024;
1883  for (size_t i = 0; i < max_recursive_lock; i++) {
1884    env_->MonitorEnter(object);
1885    EXPECT_FALSE(env_->ExceptionCheck());
1886  }
1887  // Recursively unlock a lot
1888  for (size_t i = 0; i < max_recursive_lock; i++) {
1889    env_->MonitorExit(object);
1890    EXPECT_FALSE(env_->ExceptionCheck());
1891  }
1892
1893  // Unlock of unowned monitor
1894  env_->MonitorExit(object);
1895  EXPECT_TRUE(env_->ExceptionCheck());
1896  thrown_exception = env_->ExceptionOccurred();
1897  env_->ExceptionClear();
1898  EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class));
1899
1900  // It's an error to call MonitorEnter or MonitorExit on NULL.
1901  {
1902    CheckJniAbortCatcher check_jni_abort_catcher;
1903    env_->MonitorEnter(NULL);
1904    check_jni_abort_catcher.Check("in call to MonitorEnter");
1905
1906    env_->MonitorExit(NULL);
1907    check_jni_abort_catcher.Check("in call to MonitorExit");
1908  }
1909}
1910
1911TEST_F(JniInternalTest, DetachCurrentThread) {
1912  CleanUpJniEnv();  // cleanup now so TearDown won't have junk from wrong JNIEnv
1913  jint ok = vm_->DetachCurrentThread();
1914  EXPECT_EQ(JNI_OK, ok);
1915
1916  jint err = vm_->DetachCurrentThread();
1917  EXPECT_EQ(JNI_ERR, err);
1918  vm_->AttachCurrentThread(&env_, NULL);  // need attached thread for CommonTest::TearDown
1919}
1920
1921}  // namespace art
1922