blob: 83e9b1028a267f11a1c9b7f5d99fea076247e183 [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
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080019#include "common_compiler_test.h"
Brian Carlstromea46f952013-07-30 01:26:50 -070020#include "mirror/art_method-inl.h"
Elliott Hughes726079d2011-10-07 18:43:44 -070021#include "ScopedLocalRef.h"
Elliott Hughes0c9cd562011-08-12 10:59:29 -070022
23namespace art {
24
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080025// TODO: Convert to CommonRuntimeTest. Currently MakeExecutable is used.
26class JniInternalTest : public CommonCompilerTest {
Elliott Hughesc7ac37f2011-08-12 12:21:58 -070027 protected:
28 virtual void SetUp() {
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080029 CommonCompilerTest::SetUp();
Elliott Hughes5174fe62011-08-23 15:12:35 -070030
Elliott Hughesa2501992011-08-26 19:39:54 -070031 vm_ = Runtime::Current()->GetJavaVM();
32
Elliott Hughes5174fe62011-08-23 15:12:35 -070033 // Turn on -verbose:jni for the JNI tests.
Ian Rogers79713632013-08-21 19:06:15 -070034 // gLogVerbosity.jni = true;
Elliott Hughes5174fe62011-08-23 15:12:35 -070035
Ian Rogers2d10b202014-05-12 19:15:18 -070036 vm_->AttachCurrentThread(&env_, nullptr);
Elliott Hughesb465ab02011-08-24 11:21:21 -070037
Brian Carlstromea46f952013-07-30 01:26:50 -070038 ScopedLocalRef<jclass> aioobe(env_,
39 env_->FindClass("java/lang/ArrayIndexOutOfBoundsException"));
Ian Rogers2d10b202014-05-12 19:15:18 -070040 CHECK(aioobe.get() != nullptr);
Elliott Hughes726079d2011-10-07 18:43:44 -070041 aioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(aioobe.get()));
Elliott Hughesb465ab02011-08-24 11:21:21 -070042
Elliott Hughesb264f082012-04-06 17:10:10 -070043 ScopedLocalRef<jclass> ase(env_, env_->FindClass("java/lang/ArrayStoreException"));
Ian Rogers2d10b202014-05-12 19:15:18 -070044 CHECK(ase.get() != nullptr);
Elliott Hughesb264f082012-04-06 17:10:10 -070045 ase_ = reinterpret_cast<jclass>(env_->NewGlobalRef(ase.get()));
46
Brian Carlstromea46f952013-07-30 01:26:50 -070047 ScopedLocalRef<jclass> sioobe(env_,
48 env_->FindClass("java/lang/StringIndexOutOfBoundsException"));
Ian Rogers2d10b202014-05-12 19:15:18 -070049 CHECK(sioobe.get() != nullptr);
Elliott Hughes726079d2011-10-07 18:43:44 -070050 sioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(sioobe.get()));
51 }
52
Ian Rogers2d10b202014-05-12 19:15:18 -070053 void ExpectException(jclass exception_class) {
54 EXPECT_TRUE(env_->ExceptionCheck());
55 jthrowable exception = env_->ExceptionOccurred();
56 EXPECT_NE(nullptr, exception);
57 env_->ExceptionClear();
58 EXPECT_TRUE(env_->IsInstanceOf(exception, exception_class));
59 }
60
61 void ExpectClassFound(const char* name) {
62 EXPECT_NE(env_->FindClass(name), nullptr) << name;
63 EXPECT_FALSE(env_->ExceptionCheck()) << name;
64 }
65
66 void ExpectClassNotFound(const char* name) {
67 EXPECT_EQ(env_->FindClass(name), nullptr) << name;
68 EXPECT_TRUE(env_->ExceptionCheck()) << name;
69 env_->ExceptionClear();
70 }
71
Brian Carlstrom4d571432012-05-16 00:21:41 -070072 void CleanUpJniEnv() {
Ian Rogers2d10b202014-05-12 19:15:18 -070073 if (aioobe_ != nullptr) {
Brian Carlstrom4d571432012-05-16 00:21:41 -070074 env_->DeleteGlobalRef(aioobe_);
Ian Rogers2d10b202014-05-12 19:15:18 -070075 aioobe_ = nullptr;
Brian Carlstrom4d571432012-05-16 00:21:41 -070076 }
Ian Rogers2d10b202014-05-12 19:15:18 -070077 if (ase_ != nullptr) {
Brian Carlstrom4d571432012-05-16 00:21:41 -070078 env_->DeleteGlobalRef(ase_);
Ian Rogers2d10b202014-05-12 19:15:18 -070079 ase_ = nullptr;
Brian Carlstrom4d571432012-05-16 00:21:41 -070080 }
Ian Rogers2d10b202014-05-12 19:15:18 -070081 if (sioobe_ != nullptr) {
Brian Carlstrom4d571432012-05-16 00:21:41 -070082 env_->DeleteGlobalRef(sioobe_);
Ian Rogers2d10b202014-05-12 19:15:18 -070083 sioobe_ = nullptr;
Brian Carlstrom4d571432012-05-16 00:21:41 -070084 }
85 }
86
Ian Rogers53b8b092014-03-13 23:45:53 -070087 virtual void TearDown() OVERRIDE {
Brian Carlstrom4d571432012-05-16 00:21:41 -070088 CleanUpJniEnv();
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080089 CommonCompilerTest::TearDown();
Elliott Hughesc7ac37f2011-08-12 12:21:58 -070090 }
Elliott Hughesb465ab02011-08-24 11:21:21 -070091
Ian Rogers1d99e452014-01-02 17:36:41 -080092 jclass GetPrimitiveClass(char descriptor) {
93 ScopedObjectAccess soa(env_);
94 mirror::Class* c = class_linker_->FindPrimitiveClass(descriptor);
95 CHECK(c != nullptr);
96 return soa.AddLocalReference<jclass>(c);
97 }
98
Elliott Hughesa2501992011-08-26 19:39:54 -070099 JavaVMExt* vm_;
Brian Carlstrom4d571432012-05-16 00:21:41 -0700100 JNIEnv* env_;
Elliott Hughes814e4032011-08-23 12:07:56 -0700101 jclass aioobe_;
Elliott Hughesb264f082012-04-06 17:10:10 -0700102 jclass ase_;
Elliott Hughesb465ab02011-08-24 11:21:21 -0700103 jclass sioobe_;
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700104};
105
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700106TEST_F(JniInternalTest, AllocObject) {
107 jclass c = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -0700108 ASSERT_NE(c, nullptr);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700109 jobject o = env_->AllocObject(c);
Ian Rogers2d10b202014-05-12 19:15:18 -0700110 ASSERT_NE(o, nullptr);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700111
112 // We have an instance of the class we asked for...
113 ASSERT_TRUE(env_->IsInstanceOf(o, c));
114 // ...whose fields haven't been initialized because
115 // we didn't call a constructor.
116 ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "count", "I")));
117 ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "offset", "I")));
Ian Rogers2d10b202014-05-12 19:15:18 -0700118 ASSERT_TRUE(env_->GetObjectField(o, env_->GetFieldID(c, "value", "[C")) == nullptr);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700119}
120
Elliott Hughesc7ac37f2011-08-12 12:21:58 -0700121TEST_F(JniInternalTest, GetVersion) {
122 ASSERT_EQ(JNI_VERSION_1_6, env_->GetVersion());
123}
124
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700125TEST_F(JniInternalTest, FindClass) {
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700126 // Reference types...
Ian Rogers2d10b202014-05-12 19:15:18 -0700127 ExpectClassFound("java/lang/String");
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700128 // ...for arrays too, where you must include "L;".
Ian Rogers2d10b202014-05-12 19:15:18 -0700129 ExpectClassFound("[Ljava/lang/String;");
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700130 // Primitive arrays are okay too, if the primitive type is valid.
Ian Rogers2d10b202014-05-12 19:15:18 -0700131 ExpectClassFound("[C");
Elliott Hughesa2501992011-08-26 19:39:54 -0700132
Elliott Hughesb264f082012-04-06 17:10:10 -0700133 {
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700134 CheckJniAbortCatcher check_jni_abort_catcher;
Ian Rogers2d10b202014-05-12 19:15:18 -0700135 env_->FindClass(nullptr);
136 check_jni_abort_catcher.Check("name == null");
137
138 // We support . as well as / for compatibility, if -Xcheck:jni is off.
139 ExpectClassFound("java.lang.String");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700140 check_jni_abort_catcher.Check("illegal class name 'java.lang.String'");
Ian Rogers2d10b202014-05-12 19:15:18 -0700141 ExpectClassNotFound("Ljava.lang.String;");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700142 check_jni_abort_catcher.Check("illegal class name 'Ljava.lang.String;'");
Ian Rogers2d10b202014-05-12 19:15:18 -0700143 ExpectClassFound("[Ljava.lang.String;");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700144 check_jni_abort_catcher.Check("illegal class name '[Ljava.lang.String;'");
Ian Rogers2d10b202014-05-12 19:15:18 -0700145 ExpectClassNotFound("[java.lang.String");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700146 check_jni_abort_catcher.Check("illegal class name '[java.lang.String'");
Elliott Hughesb264f082012-04-06 17:10:10 -0700147
148 // You can't include the "L;" in a JNI class descriptor.
Ian Rogers2d10b202014-05-12 19:15:18 -0700149 ExpectClassNotFound("Ljava/lang/String;");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700150 check_jni_abort_catcher.Check("illegal class name 'Ljava/lang/String;'");
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700151
Elliott Hughesb264f082012-04-06 17:10:10 -0700152 // But you must include it for an array of any reference type.
Ian Rogers2d10b202014-05-12 19:15:18 -0700153 ExpectClassNotFound("[java/lang/String");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700154 check_jni_abort_catcher.Check("illegal class name '[java/lang/String'");
Elliott Hughes3f6635a2012-06-19 13:37:49 -0700155
Ian Rogers2d10b202014-05-12 19:15:18 -0700156 ExpectClassNotFound("[K");
Elliott Hughes56ef0422012-06-19 14:35:04 -0700157 check_jni_abort_catcher.Check("illegal class name '[K'");
Ian Rogers2d10b202014-05-12 19:15:18 -0700158
159 // Void arrays aren't allowed.
160 ExpectClassNotFound("[V");
161 check_jni_abort_catcher.Check("illegal class name '[V'");
Elliott Hughesb264f082012-04-06 17:10:10 -0700162 }
Elliott Hughesa2501992011-08-26 19:39:54 -0700163
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700164 // But primitive types aren't allowed...
Ian Rogers2d10b202014-05-12 19:15:18 -0700165 ExpectClassNotFound("C");
166 ExpectClassNotFound("V");
167 ExpectClassNotFound("K");
Elliott Hughes0c9cd562011-08-12 10:59:29 -0700168}
169
Elliott Hughescdf53122011-08-19 15:46:09 -0700170TEST_F(JniInternalTest, GetFieldID) {
171 jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError");
Ian Rogers2d10b202014-05-12 19:15:18 -0700172 ASSERT_NE(jlnsfe, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700173 jclass c = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -0700174 ASSERT_NE(c, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700175
176 // Wrong type.
177 jfieldID fid = env_->GetFieldID(c, "count", "J");
Ian Rogers2d10b202014-05-12 19:15:18 -0700178 EXPECT_EQ(nullptr, fid);
179 ExpectException(jlnsfe);
Elliott Hughescdf53122011-08-19 15:46:09 -0700180
Ian Rogersb17d08b2011-09-02 16:16:49 -0700181 // Wrong type where type doesn't exist.
182 fid = env_->GetFieldID(c, "count", "Lrod/jane/freddy;");
Ian Rogers2d10b202014-05-12 19:15:18 -0700183 EXPECT_EQ(nullptr, fid);
184 ExpectException(jlnsfe);
Ian Rogersb17d08b2011-09-02 16:16:49 -0700185
Elliott Hughescdf53122011-08-19 15:46:09 -0700186 // Wrong name.
187 fid = env_->GetFieldID(c, "Count", "I");
Ian Rogers2d10b202014-05-12 19:15:18 -0700188 EXPECT_EQ(nullptr, fid);
189 ExpectException(jlnsfe);
Elliott Hughescdf53122011-08-19 15:46:09 -0700190
191 // Good declared field lookup.
192 fid = env_->GetFieldID(c, "count", "I");
Ian Rogers2d10b202014-05-12 19:15:18 -0700193 EXPECT_NE(nullptr, fid);
Elliott Hughescdf53122011-08-19 15:46:09 -0700194 EXPECT_FALSE(env_->ExceptionCheck());
195
196 // Good superclass field lookup.
197 c = env_->FindClass("java/lang/StringBuilder");
198 fid = env_->GetFieldID(c, "count", "I");
Ian Rogers2d10b202014-05-12 19:15:18 -0700199 EXPECT_NE(nullptr, fid);
200 EXPECT_NE(fid, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700201 EXPECT_FALSE(env_->ExceptionCheck());
202
203 // Not instance.
204 fid = env_->GetFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
Ian Rogers2d10b202014-05-12 19:15:18 -0700205 EXPECT_EQ(nullptr, fid);
206 ExpectException(jlnsfe);
207
208 // Bad arguments.
209 CheckJniAbortCatcher check_jni_abort_catcher;
210 fid = env_->GetFieldID(nullptr, "count", "I");
211 EXPECT_EQ(nullptr, fid);
212 check_jni_abort_catcher.Check("java_class == null");
213 fid = env_->GetFieldID(c, nullptr, "I");
214 EXPECT_EQ(nullptr, fid);
215 check_jni_abort_catcher.Check("name == null");
216 fid = env_->GetFieldID(c, "count", nullptr);
217 EXPECT_EQ(nullptr, fid);
218 check_jni_abort_catcher.Check("sig == null");
Elliott Hughescdf53122011-08-19 15:46:09 -0700219}
220
221TEST_F(JniInternalTest, GetStaticFieldID) {
222 jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError");
Ian Rogers2d10b202014-05-12 19:15:18 -0700223 ASSERT_NE(jlnsfe, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700224 jclass c = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -0700225 ASSERT_NE(c, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700226
227 // Wrong type.
228 jfieldID fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "J");
Ian Rogers2d10b202014-05-12 19:15:18 -0700229 EXPECT_EQ(nullptr, fid);
230 ExpectException(jlnsfe);
Elliott Hughescdf53122011-08-19 15:46:09 -0700231
Ian Rogersb17d08b2011-09-02 16:16:49 -0700232 // Wrong type where type doesn't exist.
233 fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Lrod/jane/freddy;");
Ian Rogers2d10b202014-05-12 19:15:18 -0700234 EXPECT_EQ(nullptr, fid);
235 ExpectException(jlnsfe);
Ian Rogersb17d08b2011-09-02 16:16:49 -0700236
Elliott Hughescdf53122011-08-19 15:46:09 -0700237 // Wrong name.
238 fid = env_->GetStaticFieldID(c, "cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
Ian Rogers2d10b202014-05-12 19:15:18 -0700239 EXPECT_EQ(nullptr, fid);
240 ExpectException(jlnsfe);
Elliott Hughescdf53122011-08-19 15:46:09 -0700241
242 // Good declared field lookup.
243 fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
Ian Rogers2d10b202014-05-12 19:15:18 -0700244 EXPECT_NE(nullptr, fid);
245 EXPECT_NE(fid, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700246 EXPECT_FALSE(env_->ExceptionCheck());
247
248 // Not static.
249 fid = env_->GetStaticFieldID(c, "count", "I");
Ian Rogers2d10b202014-05-12 19:15:18 -0700250 EXPECT_EQ(nullptr, fid);
251 ExpectException(jlnsfe);
252
253 // Bad arguments.
254 CheckJniAbortCatcher check_jni_abort_catcher;
255 fid = env_->GetStaticFieldID(nullptr, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
256 EXPECT_EQ(nullptr, fid);
257 check_jni_abort_catcher.Check("java_class == null");
258 fid = env_->GetStaticFieldID(c, nullptr, "Ljava/util/Comparator;");
259 EXPECT_EQ(nullptr, fid);
260 check_jni_abort_catcher.Check("name == null");
261 fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", nullptr);
262 EXPECT_EQ(nullptr, fid);
263 check_jni_abort_catcher.Check("sig == null");
Elliott Hughescdf53122011-08-19 15:46:09 -0700264}
265
Ian Rogers4dd71f12011-08-16 14:16:02 -0700266TEST_F(JniInternalTest, GetMethodID) {
267 jclass jlobject = env_->FindClass("java/lang/Object");
268 jclass jlstring = env_->FindClass("java/lang/String");
269 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
270
271 // Sanity check that no exceptions are pending
Elliott Hughescdf53122011-08-19 15:46:09 -0700272 ASSERT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700273
274 // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
275 // a pending exception
276 jmethodID method = env_->GetMethodID(jlobject, "foo", "()V");
Ian Rogers2d10b202014-05-12 19:15:18 -0700277 EXPECT_EQ(nullptr, method);
278 ExpectException(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700279
280 // Check that java.lang.Object.equals() does exist
Ian Rogers4dd71f12011-08-16 14:16:02 -0700281 method = env_->GetMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
Ian Rogers2d10b202014-05-12 19:15:18 -0700282 EXPECT_NE(nullptr, method);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700283 EXPECT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700284
285 // Check that GetMethodID for java.lang.String.valueOf(int) fails as the
286 // method is static
287 method = env_->GetMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;");
Ian Rogers2d10b202014-05-12 19:15:18 -0700288 EXPECT_EQ(nullptr, method);
289 ExpectException(jlnsme);
Brian Carlstromea46f952013-07-30 01:26:50 -0700290
291 // Check that GetMethodID for java.lang.NoSuchMethodError.<init>(String) finds the constructor
292 method = env_->GetMethodID(jlnsme, "<init>", "(Ljava/lang/String;)V");
Ian Rogers2d10b202014-05-12 19:15:18 -0700293 EXPECT_NE(nullptr, method);
Brian Carlstromea46f952013-07-30 01:26:50 -0700294 EXPECT_FALSE(env_->ExceptionCheck());
Ian Rogers2d10b202014-05-12 19:15:18 -0700295
296 // Bad arguments.
297 CheckJniAbortCatcher check_jni_abort_catcher;
298 method = env_->GetMethodID(nullptr, "<init>", "(Ljava/lang/String;)V");
299 EXPECT_EQ(nullptr, method);
300 check_jni_abort_catcher.Check("java_class == null");
301 method = env_->GetMethodID(jlnsme, nullptr, "(Ljava/lang/String;)V");
302 EXPECT_EQ(nullptr, method);
303 check_jni_abort_catcher.Check("name == null");
304 method = env_->GetMethodID(jlnsme, "<init>", nullptr);
305 EXPECT_EQ(nullptr, method);
306 check_jni_abort_catcher.Check("sig == null");
Ian Rogers4dd71f12011-08-16 14:16:02 -0700307}
308
309TEST_F(JniInternalTest, GetStaticMethodID) {
310 jclass jlobject = env_->FindClass("java/lang/Object");
311 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
312
313 // Sanity check that no exceptions are pending
Elliott Hughescdf53122011-08-19 15:46:09 -0700314 ASSERT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700315
316 // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is
317 // a pending exception
318 jmethodID method = env_->GetStaticMethodID(jlobject, "foo", "()V");
Ian Rogers2d10b202014-05-12 19:15:18 -0700319 EXPECT_EQ(nullptr, method);
320 ExpectException(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700321
322 // Check that GetStaticMethodID for java.lang.Object.equals(Object) fails as
323 // the method is not static
324 method = env_->GetStaticMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z");
Ian Rogers2d10b202014-05-12 19:15:18 -0700325 EXPECT_EQ(nullptr, method);
326 ExpectException(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700327
328 // Check that java.lang.String.valueOf(int) does exist
Ian Rogers4dd71f12011-08-16 14:16:02 -0700329 jclass jlstring = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -0700330 method = env_->GetStaticMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;");
331 EXPECT_NE(nullptr, method);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700332 EXPECT_FALSE(env_->ExceptionCheck());
Ian Rogers2d10b202014-05-12 19:15:18 -0700333
334 // Bad arguments.
335 CheckJniAbortCatcher check_jni_abort_catcher;
336 method = env_->GetStaticMethodID(nullptr, "valueOf", "(I)Ljava/lang/String;");
337 EXPECT_EQ(nullptr, method);
338 check_jni_abort_catcher.Check("java_class == null");
339 method = env_->GetStaticMethodID(jlstring, nullptr, "(I)Ljava/lang/String;");
340 EXPECT_EQ(nullptr, method);
341 check_jni_abort_catcher.Check("name == null");
342 method = env_->GetStaticMethodID(jlstring, "valueOf", nullptr);
343 EXPECT_EQ(nullptr, method);
344 check_jni_abort_catcher.Check("sig == null");
Ian Rogers4dd71f12011-08-16 14:16:02 -0700345}
346
Elliott Hughescdf53122011-08-19 15:46:09 -0700347TEST_F(JniInternalTest, FromReflectedField_ToReflectedField) {
348 jclass jlrField = env_->FindClass("java/lang/reflect/Field");
349 jclass c = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -0700350 ASSERT_NE(c, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700351 jfieldID fid = env_->GetFieldID(c, "count", "I");
Ian Rogers2d10b202014-05-12 19:15:18 -0700352 ASSERT_NE(fid, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700353 // Turn the fid into a java.lang.reflect.Field...
354 jobject field = env_->ToReflectedField(c, fid, JNI_FALSE);
Ian Rogers2d10b202014-05-12 19:15:18 -0700355 ASSERT_NE(c, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700356 ASSERT_TRUE(env_->IsInstanceOf(field, jlrField));
357 // ...and back again.
358 jfieldID fid2 = env_->FromReflectedField(field);
Ian Rogers2d10b202014-05-12 19:15:18 -0700359 ASSERT_NE(fid2, nullptr);
Brian Carlstromea46f952013-07-30 01:26:50 -0700360 // Make sure we can actually use it.
361 jstring s = env_->NewStringUTF("poop");
362 ASSERT_EQ(4, env_->GetIntField(s, fid2));
Ian Rogers2d10b202014-05-12 19:15:18 -0700363
364 // Bad arguments.
365 CheckJniAbortCatcher check_jni_abort_catcher;
366 field = env_->ToReflectedField(c, nullptr, JNI_FALSE);
367 EXPECT_EQ(field, nullptr);
368 check_jni_abort_catcher.Check("fid == null");
369 fid2 = env_->FromReflectedField(nullptr);
370 ASSERT_EQ(fid2, nullptr);
371 check_jni_abort_catcher.Check("jlr_field == null");
Elliott Hughescdf53122011-08-19 15:46:09 -0700372}
373
374TEST_F(JniInternalTest, FromReflectedMethod_ToReflectedMethod) {
375 jclass jlrMethod = env_->FindClass("java/lang/reflect/Method");
376 jclass c = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -0700377 ASSERT_NE(c, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700378 jmethodID mid = env_->GetMethodID(c, "length", "()I");
Ian Rogers2d10b202014-05-12 19:15:18 -0700379 ASSERT_NE(mid, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700380 // Turn the mid into a java.lang.reflect.Method...
381 jobject method = env_->ToReflectedMethod(c, mid, JNI_FALSE);
Ian Rogers2d10b202014-05-12 19:15:18 -0700382 ASSERT_NE(c, nullptr);
Elliott Hughescdf53122011-08-19 15:46:09 -0700383 ASSERT_TRUE(env_->IsInstanceOf(method, jlrMethod));
384 // ...and back again.
385 jmethodID mid2 = env_->FromReflectedMethod(method);
Ian Rogers2d10b202014-05-12 19:15:18 -0700386 ASSERT_NE(mid2, nullptr);
Brian Carlstromea46f952013-07-30 01:26:50 -0700387 // Make sure we can actually use it.
388 jstring s = env_->NewStringUTF("poop");
Ian Rogers5d27faf2014-05-02 17:17:18 -0700389 ASSERT_EQ(4, env_->CallIntMethod(s, mid2));
Ian Rogers2d10b202014-05-12 19:15:18 -0700390
391 // Bad arguments.
392 CheckJniAbortCatcher check_jni_abort_catcher;
393 method = env_->ToReflectedMethod(c, nullptr, JNI_FALSE);
394 EXPECT_EQ(method, nullptr);
395 check_jni_abort_catcher.Check("mid == null");
396 mid2 = env_->FromReflectedMethod(method);
397 ASSERT_EQ(mid2, nullptr);
398 check_jni_abort_catcher.Check("jlr_method == null");
Elliott Hughescdf53122011-08-19 15:46:09 -0700399}
400
Ian Rogers2d10b202014-05-12 19:15:18 -0700401static void BogusMethod() {
402 // You can't pass nullptr function pointers to RegisterNatives.
Elliott Hughes5174fe62011-08-23 15:12:35 -0700403}
404
Ian Rogers2d10b202014-05-12 19:15:18 -0700405TEST_F(JniInternalTest, RegisterAndUnregisterNatives) {
Ian Rogers4dd71f12011-08-16 14:16:02 -0700406 jclass jlobject = env_->FindClass("java/lang/Object");
407 jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError");
408
Ian Rogers2d10b202014-05-12 19:15:18 -0700409 // Sanity check that no exceptions are pending.
Elliott Hughescdf53122011-08-19 15:46:09 -0700410 ASSERT_FALSE(env_->ExceptionCheck());
Ian Rogers4dd71f12011-08-16 14:16:02 -0700411
Ian Rogers2d10b202014-05-12 19:15:18 -0700412 // Check that registering to a non-existent java.lang.Object.foo() causes a NoSuchMethodError.
Ian Rogers4dd71f12011-08-16 14:16:02 -0700413 {
Ian Rogers2d10b202014-05-12 19:15:18 -0700414 JNINativeMethod methods[] = { { "foo", "()V", nullptr } };
415 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700416 }
Ian Rogers2d10b202014-05-12 19:15:18 -0700417 ExpectException(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700418
Ian Rogers2d10b202014-05-12 19:15:18 -0700419 // Check that registering non-native methods causes a NoSuchMethodError.
Ian Rogers4dd71f12011-08-16 14:16:02 -0700420 {
Ian Rogers2d10b202014-05-12 19:15:18 -0700421 JNINativeMethod methods[] = { { "equals", "(Ljava/lang/Object;)Z", nullptr } };
422 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700423 }
Ian Rogers2d10b202014-05-12 19:15:18 -0700424 ExpectException(jlnsme);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700425
Ian Rogers2d10b202014-05-12 19:15:18 -0700426 // Check that registering native methods is successful.
Ian Rogers4dd71f12011-08-16 14:16:02 -0700427 {
Elliott Hughesb25c3f62012-03-26 16:35:06 -0700428 JNINativeMethod methods[] = { { "notify", "()V", reinterpret_cast<void*>(BogusMethod) } };
Ian Rogers2d10b202014-05-12 19:15:18 -0700429 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_OK);
430 }
431 EXPECT_FALSE(env_->ExceptionCheck());
432 EXPECT_EQ(env_->UnregisterNatives(jlobject), JNI_OK);
433
434 // Check that registering no methods isn't a failure.
435 {
436 JNINativeMethod methods[] = { };
437 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 0), JNI_OK);
438 }
439 EXPECT_FALSE(env_->ExceptionCheck());
440 EXPECT_EQ(env_->UnregisterNatives(jlobject), JNI_OK);
441
442 // Check that registering a -ve number of methods is a failure.
443 CheckJniAbortCatcher check_jni_abort_catcher;
444 for (int i = -10; i < 0; ++i) {
445 JNINativeMethod methods[] = { };
446 EXPECT_EQ(env_->RegisterNatives(jlobject, methods, i), JNI_ERR);
447 check_jni_abort_catcher.Check("negative method count: ");
Ian Rogers4dd71f12011-08-16 14:16:02 -0700448 }
449 EXPECT_FALSE(env_->ExceptionCheck());
Elliott Hughes5174fe62011-08-23 15:12:35 -0700450
Ian Rogers2d10b202014-05-12 19:15:18 -0700451 // Passing a class of null is a failure.
452 {
453 JNINativeMethod methods[] = { };
454 EXPECT_EQ(env_->RegisterNatives(nullptr, methods, 0), JNI_ERR);
455 check_jni_abort_catcher.Check("java_class == null");
456 }
457
458 // Passing methods as null is a failure.
459 EXPECT_EQ(env_->RegisterNatives(jlobject, nullptr, 1), JNI_ERR);
460 check_jni_abort_catcher.Check("methods == null");
461
462 // Unregisters null is a failure.
463 EXPECT_EQ(env_->UnregisterNatives(nullptr), JNI_ERR);
464 check_jni_abort_catcher.Check("java_class == null");
465
466 // Unregistering a class with no natives is a warning.
467 EXPECT_EQ(env_->UnregisterNatives(jlnsme), JNI_OK);
Ian Rogers4dd71f12011-08-16 14:16:02 -0700468}
469
Brian Carlstromea46f952013-07-30 01:26:50 -0700470#define EXPECT_PRIMITIVE_ARRAY(new_fn, \
471 get_region_fn, \
472 set_region_fn, \
473 get_elements_fn, \
474 release_elements_fn, \
475 scalar_type, \
476 expected_class_descriptor) \
Ian Rogers2d10b202014-05-12 19:15:18 -0700477 jsize size = 4; \
478 \
Ian Rogers1d99e452014-01-02 17:36:41 -0800479 { \
480 CheckJniAbortCatcher jni_abort_catcher; \
481 /* Allocate an negative sized array and check it has the right failure type. */ \
Ian Rogers2d10b202014-05-12 19:15:18 -0700482 EXPECT_EQ(env_->new_fn(-1), nullptr); \
Ian Rogers1d99e452014-01-02 17:36:41 -0800483 jni_abort_catcher.Check("negative array length: -1"); \
Ian Rogers2d10b202014-05-12 19:15:18 -0700484 EXPECT_EQ(env_->new_fn(std::numeric_limits<jint>::min()), nullptr); \
Ian Rogers1d99e452014-01-02 17:36:41 -0800485 jni_abort_catcher.Check("negative array length: -2147483648"); \
Ian Rogers2d10b202014-05-12 19:15:18 -0700486 /* Pass the array as null. */ \
487 EXPECT_EQ(0, env_->GetArrayLength(nullptr)); \
488 jni_abort_catcher.Check("java_array == null"); \
489 env_->get_region_fn(nullptr, 0, 0, nullptr); \
490 jni_abort_catcher.Check("java_array == null"); \
491 env_->set_region_fn(nullptr, 0, 0, nullptr); \
492 jni_abort_catcher.Check("java_array == null"); \
493 env_->get_elements_fn(nullptr, nullptr); \
494 jni_abort_catcher.Check("java_array == null"); \
495 env_->release_elements_fn(nullptr, nullptr, 0); \
496 jni_abort_catcher.Check("java_array == null"); \
497 /* Pass the elements for region as null. */ \
498 scalar_type ## Array a = env_->new_fn(size); \
499 env_->get_region_fn(a, 0, size, nullptr); \
500 jni_abort_catcher.Check("buf == null"); \
501 env_->set_region_fn(a, 0, size, nullptr); \
502 jni_abort_catcher.Check("buf == null"); \
Ian Rogers1d99e452014-01-02 17:36:41 -0800503 } \
Elliott Hughes814e4032011-08-23 12:07:56 -0700504 /* Allocate an array and check it has the right type and length. */ \
505 scalar_type ## Array a = env_->new_fn(size); \
Ian Rogers2d10b202014-05-12 19:15:18 -0700506 EXPECT_NE(a, nullptr); \
Elliott Hughes814e4032011-08-23 12:07:56 -0700507 EXPECT_TRUE(env_->IsInstanceOf(a, env_->FindClass(expected_class_descriptor))); \
508 EXPECT_EQ(size, env_->GetArrayLength(a)); \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -0700509 \
510 /* GetPrimitiveArrayRegion/SetPrimitiveArrayRegion */ \
Elliott Hughes814e4032011-08-23 12:07:56 -0700511 /* AIOOBE for negative start offset. */ \
Ian Rogers2d10b202014-05-12 19:15:18 -0700512 env_->get_region_fn(a, -1, 1, nullptr); \
513 ExpectException(aioobe_); \
514 env_->set_region_fn(a, -1, 1, nullptr); \
515 ExpectException(aioobe_); \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -0700516 \
Elliott Hughes814e4032011-08-23 12:07:56 -0700517 /* AIOOBE for negative length. */ \
Ian Rogers2d10b202014-05-12 19:15:18 -0700518 env_->get_region_fn(a, 0, -1, nullptr); \
519 ExpectException(aioobe_); \
520 env_->set_region_fn(a, 0, -1, nullptr); \
521 ExpectException(aioobe_); \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -0700522 \
Elliott Hughes814e4032011-08-23 12:07:56 -0700523 /* AIOOBE for buffer overrun. */ \
Ian Rogers2d10b202014-05-12 19:15:18 -0700524 env_->get_region_fn(a, size - 1, size, nullptr); \
525 ExpectException(aioobe_); \
526 env_->set_region_fn(a, size - 1, size, nullptr); \
527 ExpectException(aioobe_); \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -0700528 \
Ian Rogers2d10b202014-05-12 19:15:18 -0700529 /* It's okay for the buffer to be nullptr as long as the length is 0. */ \
530 env_->get_region_fn(a, 2, 0, nullptr); \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -0700531 /* Even if the offset is invalid... */ \
Ian Rogers2d10b202014-05-12 19:15:18 -0700532 env_->get_region_fn(a, 123, 0, nullptr); \
533 ExpectException(aioobe_); \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -0700534 \
Ian Rogers2d10b202014-05-12 19:15:18 -0700535 /* It's okay for the buffer to be nullptr as long as the length is 0. */ \
536 env_->set_region_fn(a, 2, 0, nullptr); \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -0700537 /* Even if the offset is invalid... */ \
Ian Rogers2d10b202014-05-12 19:15:18 -0700538 env_->set_region_fn(a, 123, 0, nullptr); \
539 ExpectException(aioobe_); \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -0700540 \
Elliott Hughes814e4032011-08-23 12:07:56 -0700541 /* Prepare a couple of buffers. */ \
Elliott Hughesee0fa762012-03-26 17:12:41 -0700542 UniquePtr<scalar_type[]> src_buf(new scalar_type[size]); \
543 UniquePtr<scalar_type[]> dst_buf(new scalar_type[size]); \
Elliott Hughes814e4032011-08-23 12:07:56 -0700544 for (jsize i = 0; i < size; ++i) { src_buf[i] = scalar_type(i); } \
545 for (jsize i = 0; i < size; ++i) { dst_buf[i] = scalar_type(-1); } \
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -0700546 \
Elliott Hughes814e4032011-08-23 12:07:56 -0700547 /* Copy all of src_buf onto the heap. */ \
Elliott Hughesee0fa762012-03-26 17:12:41 -0700548 env_->set_region_fn(a, 0, size, &src_buf[0]); \
Elliott Hughes814e4032011-08-23 12:07:56 -0700549 /* Copy back only part. */ \
550 env_->get_region_fn(a, 1, size - 2, &dst_buf[1]); \
Brian Carlstromea46f952013-07-30 01:26:50 -0700551 EXPECT_NE(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \
552 << "short copy equal"; \
Elliott Hughes814e4032011-08-23 12:07:56 -0700553 /* Copy the missing pieces. */ \
Elliott Hughesee0fa762012-03-26 17:12:41 -0700554 env_->get_region_fn(a, 0, 1, &dst_buf[0]); \
Elliott Hughes814e4032011-08-23 12:07:56 -0700555 env_->get_region_fn(a, size - 1, 1, &dst_buf[size - 1]); \
Brian Carlstromea46f952013-07-30 01:26:50 -0700556 EXPECT_EQ(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \
557 << "fixed copy not equal"; \
Elliott Hughes814e4032011-08-23 12:07:56 -0700558 /* Copy back the whole array. */ \
Elliott Hughesee0fa762012-03-26 17:12:41 -0700559 env_->get_region_fn(a, 0, size, &dst_buf[0]); \
Brian Carlstromea46f952013-07-30 01:26:50 -0700560 EXPECT_EQ(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \
561 << "full copy not equal"; \
Elliott Hughes75770752011-08-24 17:52:38 -0700562 /* GetPrimitiveArrayCritical */ \
Ian Rogers2d10b202014-05-12 19:15:18 -0700563 void* v = env_->GetPrimitiveArrayCritical(a, nullptr); \
Brian Carlstromea46f952013-07-30 01:26:50 -0700564 EXPECT_EQ(memcmp(&src_buf[0], v, size * sizeof(scalar_type)), 0) \
565 << "GetPrimitiveArrayCritical not equal"; \
Elliott Hughes75770752011-08-24 17:52:38 -0700566 env_->ReleasePrimitiveArrayCritical(a, v, 0); \
567 /* GetXArrayElements */ \
Ian Rogers2d10b202014-05-12 19:15:18 -0700568 scalar_type* xs = env_->get_elements_fn(a, nullptr); \
Brian Carlstromea46f952013-07-30 01:26:50 -0700569 EXPECT_EQ(memcmp(&src_buf[0], xs, size * sizeof(scalar_type)), 0) \
570 << # get_elements_fn " not equal"; \
Elliott Hughes75770752011-08-24 17:52:38 -0700571 env_->release_elements_fn(a, xs, 0); \
Elliott Hughesbd935992011-08-22 11:59:34 -0700572
Elliott Hughes814e4032011-08-23 12:07:56 -0700573TEST_F(JniInternalTest, BooleanArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -0700574 EXPECT_PRIMITIVE_ARRAY(NewBooleanArray, GetBooleanArrayRegion, SetBooleanArrayRegion,
575 GetBooleanArrayElements, ReleaseBooleanArrayElements, jboolean, "[Z");
Elliott Hughes814e4032011-08-23 12:07:56 -0700576}
577TEST_F(JniInternalTest, ByteArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -0700578 EXPECT_PRIMITIVE_ARRAY(NewByteArray, GetByteArrayRegion, SetByteArrayRegion,
579 GetByteArrayElements, ReleaseByteArrayElements, jbyte, "[B");
Elliott Hughes814e4032011-08-23 12:07:56 -0700580}
581TEST_F(JniInternalTest, CharArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -0700582 EXPECT_PRIMITIVE_ARRAY(NewCharArray, GetCharArrayRegion, SetCharArrayRegion,
583 GetCharArrayElements, ReleaseCharArrayElements, jchar, "[C");
Elliott Hughes814e4032011-08-23 12:07:56 -0700584}
585TEST_F(JniInternalTest, DoubleArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -0700586 EXPECT_PRIMITIVE_ARRAY(NewDoubleArray, GetDoubleArrayRegion, SetDoubleArrayRegion,
587 GetDoubleArrayElements, ReleaseDoubleArrayElements, jdouble, "[D");
Elliott Hughes814e4032011-08-23 12:07:56 -0700588}
589TEST_F(JniInternalTest, FloatArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -0700590 EXPECT_PRIMITIVE_ARRAY(NewFloatArray, GetFloatArrayRegion, SetFloatArrayRegion,
591 GetFloatArrayElements, ReleaseFloatArrayElements, jfloat, "[F");
Elliott Hughes814e4032011-08-23 12:07:56 -0700592}
593TEST_F(JniInternalTest, IntArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -0700594 EXPECT_PRIMITIVE_ARRAY(NewIntArray, GetIntArrayRegion, SetIntArrayRegion,
595 GetIntArrayElements, ReleaseIntArrayElements, jint, "[I");
Elliott Hughes814e4032011-08-23 12:07:56 -0700596}
597TEST_F(JniInternalTest, LongArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -0700598 EXPECT_PRIMITIVE_ARRAY(NewLongArray, GetLongArrayRegion, SetLongArrayRegion,
599 GetLongArrayElements, ReleaseLongArrayElements, jlong, "[J");
Elliott Hughes814e4032011-08-23 12:07:56 -0700600}
601TEST_F(JniInternalTest, ShortArrays) {
Brian Carlstromea46f952013-07-30 01:26:50 -0700602 EXPECT_PRIMITIVE_ARRAY(NewShortArray, GetShortArrayRegion, SetShortArrayRegion,
603 GetShortArrayElements, ReleaseShortArrayElements, jshort, "[S");
Elliott Hughesd8ddfd52011-08-15 14:32:53 -0700604}
605
Ian Rogers2d10b202014-05-12 19:15:18 -0700606TEST_F(JniInternalTest, GetPrimitiveArrayElementsOfWrongType) {
607 CheckJniAbortCatcher jni_abort_catcher;
608 jbooleanArray array = env_->NewBooleanArray(10);
609 jboolean is_copy;
610 EXPECT_EQ(env_->GetByteArrayElements(reinterpret_cast<jbyteArray>(array), &is_copy), nullptr);
611 jni_abort_catcher.Check(
612 "attempt to get byte primitive array elements with an object of type boolean[]");
613 EXPECT_EQ(env_->GetShortArrayElements(reinterpret_cast<jshortArray>(array), &is_copy), nullptr);
614 jni_abort_catcher.Check(
615 "attempt to get short primitive array elements with an object of type boolean[]");
616 EXPECT_EQ(env_->GetCharArrayElements(reinterpret_cast<jcharArray>(array), &is_copy), nullptr);
617 jni_abort_catcher.Check(
618 "attempt to get char primitive array elements with an object of type boolean[]");
619 EXPECT_EQ(env_->GetIntArrayElements(reinterpret_cast<jintArray>(array), &is_copy), nullptr);
620 jni_abort_catcher.Check(
621 "attempt to get int primitive array elements with an object of type boolean[]");
622 EXPECT_EQ(env_->GetLongArrayElements(reinterpret_cast<jlongArray>(array), &is_copy), nullptr);
623 jni_abort_catcher.Check(
624 "attempt to get long primitive array elements with an object of type boolean[]");
625 EXPECT_EQ(env_->GetFloatArrayElements(reinterpret_cast<jfloatArray>(array), &is_copy), nullptr);
626 jni_abort_catcher.Check(
627 "attempt to get float primitive array elements with an object of type boolean[]");
628 EXPECT_EQ(env_->GetDoubleArrayElements(reinterpret_cast<jdoubleArray>(array), &is_copy), nullptr);
629 jni_abort_catcher.Check(
630 "attempt to get double primitive array elements with an object of type boolean[]");
631 jbyteArray array2 = env_->NewByteArray(10);
632 EXPECT_EQ(env_->GetBooleanArrayElements(reinterpret_cast<jbooleanArray>(array2), &is_copy), nullptr);
633 jni_abort_catcher.Check(
634 "attempt to get boolean primitive array elements with an object of type byte[]");
635 jobject object = env_->NewStringUTF("Test String");
636 EXPECT_EQ(env_->GetBooleanArrayElements(reinterpret_cast<jbooleanArray>(object), &is_copy), nullptr);
637 jni_abort_catcher.Check(
638 "attempt to get boolean primitive array elements with an object of type java.lang.String");
639}
640
641TEST_F(JniInternalTest, ReleasePrimitiveArrayElementsOfWrongType) {
642 CheckJniAbortCatcher jni_abort_catcher;
643 jbooleanArray array = env_->NewBooleanArray(10);
644 ASSERT_TRUE(array != nullptr);
645 jboolean is_copy;
646 jboolean* elements = env_->GetBooleanArrayElements(array, &is_copy);
647 ASSERT_TRUE(elements != nullptr);
648 env_->ReleaseByteArrayElements(reinterpret_cast<jbyteArray>(array),
649 reinterpret_cast<jbyte*>(elements), 0);
650 jni_abort_catcher.Check(
651 "attempt to release byte primitive array elements with an object of type boolean[]");
652 env_->ReleaseShortArrayElements(reinterpret_cast<jshortArray>(array),
653 reinterpret_cast<jshort*>(elements), 0);
654 jni_abort_catcher.Check(
655 "attempt to release short primitive array elements with an object of type boolean[]");
656 env_->ReleaseCharArrayElements(reinterpret_cast<jcharArray>(array),
657 reinterpret_cast<jchar*>(elements), 0);
658 jni_abort_catcher.Check(
659 "attempt to release char primitive array elements with an object of type boolean[]");
660 env_->ReleaseIntArrayElements(reinterpret_cast<jintArray>(array),
661 reinterpret_cast<jint*>(elements), 0);
662 jni_abort_catcher.Check(
663 "attempt to release int primitive array elements with an object of type boolean[]");
664 env_->ReleaseLongArrayElements(reinterpret_cast<jlongArray>(array),
665 reinterpret_cast<jlong*>(elements), 0);
666 jni_abort_catcher.Check(
667 "attempt to release long primitive array elements with an object of type boolean[]");
668 env_->ReleaseFloatArrayElements(reinterpret_cast<jfloatArray>(array),
669 reinterpret_cast<jfloat*>(elements), 0);
670 jni_abort_catcher.Check(
671 "attempt to release float primitive array elements with an object of type boolean[]");
672 env_->ReleaseDoubleArrayElements(reinterpret_cast<jdoubleArray>(array),
673 reinterpret_cast<jdouble*>(elements), 0);
674 jni_abort_catcher.Check(
675 "attempt to release double primitive array elements with an object of type boolean[]");
676 jbyteArray array2 = env_->NewByteArray(10);
677 env_->ReleaseBooleanArrayElements(reinterpret_cast<jbooleanArray>(array2), elements, 0);
678 jni_abort_catcher.Check(
679 "attempt to release boolean primitive array elements with an object of type byte[]");
680 jobject object = env_->NewStringUTF("Test String");
681 env_->ReleaseBooleanArrayElements(reinterpret_cast<jbooleanArray>(object), elements, 0);
682 jni_abort_catcher.Check(
683 "attempt to release boolean primitive array elements with an object of type java.lang.String");
684}
685TEST_F(JniInternalTest, GetReleasePrimitiveArrayCriticalOfWrongType) {
686 CheckJniAbortCatcher jni_abort_catcher;
687 jobject object = env_->NewStringUTF("Test String");
688 jboolean is_copy;
689 void* elements = env_->GetPrimitiveArrayCritical(reinterpret_cast<jarray>(object), &is_copy);
690 jni_abort_catcher.Check("expected primitive array, given java.lang.String");
691 env_->ReleasePrimitiveArrayCritical(reinterpret_cast<jarray>(object), elements, 0);
692 jni_abort_catcher.Check("expected primitive array, given java.lang.String");
693}
694
695TEST_F(JniInternalTest, GetPrimitiveArrayRegionElementsOfWrongType) {
696 CheckJniAbortCatcher jni_abort_catcher;
697 constexpr size_t kLength = 10;
698 jbooleanArray array = env_->NewBooleanArray(kLength);
699 ASSERT_TRUE(array != nullptr);
700 jboolean elements[kLength];
701 env_->GetByteArrayRegion(reinterpret_cast<jbyteArray>(array), 0, kLength,
702 reinterpret_cast<jbyte*>(elements));
703 jni_abort_catcher.Check(
704 "attempt to get region of byte primitive array elements with an object of type boolean[]");
705 env_->GetShortArrayRegion(reinterpret_cast<jshortArray>(array), 0, kLength,
706 reinterpret_cast<jshort*>(elements));
707 jni_abort_catcher.Check(
708 "attempt to get region of short primitive array elements with an object of type boolean[]");
709 env_->GetCharArrayRegion(reinterpret_cast<jcharArray>(array), 0, kLength,
710 reinterpret_cast<jchar*>(elements));
711 jni_abort_catcher.Check(
712 "attempt to get region of char primitive array elements with an object of type boolean[]");
713 env_->GetIntArrayRegion(reinterpret_cast<jintArray>(array), 0, kLength,
714 reinterpret_cast<jint*>(elements));
715 jni_abort_catcher.Check(
716 "attempt to get region of int primitive array elements with an object of type boolean[]");
717 env_->GetLongArrayRegion(reinterpret_cast<jlongArray>(array), 0, kLength,
718 reinterpret_cast<jlong*>(elements));
719 jni_abort_catcher.Check(
720 "attempt to get region of long primitive array elements with an object of type boolean[]");
721 env_->GetFloatArrayRegion(reinterpret_cast<jfloatArray>(array), 0, kLength,
722 reinterpret_cast<jfloat*>(elements));
723 jni_abort_catcher.Check(
724 "attempt to get region of float primitive array elements with an object of type boolean[]");
725 env_->GetDoubleArrayRegion(reinterpret_cast<jdoubleArray>(array), 0, kLength,
726 reinterpret_cast<jdouble*>(elements));
727 jni_abort_catcher.Check(
728 "attempt to get region of double primitive array elements with an object of type boolean[]");
729 jbyteArray array2 = env_->NewByteArray(10);
730 env_->GetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(array2), 0, kLength,
731 reinterpret_cast<jboolean*>(elements));
732 jni_abort_catcher.Check(
733 "attempt to get region of boolean primitive array elements with an object of type byte[]");
734 jobject object = env_->NewStringUTF("Test String");
735 env_->GetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(object), 0, kLength,
736 reinterpret_cast<jboolean*>(elements));
737 jni_abort_catcher.Check(
738 "attempt to get region of boolean primitive array elements with an object of type java.lang.String");
739}
740
741TEST_F(JniInternalTest, SetPrimitiveArrayRegionElementsOfWrongType) {
742 CheckJniAbortCatcher jni_abort_catcher;
743 constexpr size_t kLength = 10;
744 jbooleanArray array = env_->NewBooleanArray(kLength);
745 ASSERT_TRUE(array != nullptr);
746 jboolean elements[kLength];
747 env_->SetByteArrayRegion(reinterpret_cast<jbyteArray>(array), 0, kLength,
748 reinterpret_cast<jbyte*>(elements));
749 jni_abort_catcher.Check(
750 "attempt to set region of byte primitive array elements with an object of type boolean[]");
751 env_->SetShortArrayRegion(reinterpret_cast<jshortArray>(array), 0, kLength,
752 reinterpret_cast<jshort*>(elements));
753 jni_abort_catcher.Check(
754 "attempt to set region of short primitive array elements with an object of type boolean[]");
755 env_->SetCharArrayRegion(reinterpret_cast<jcharArray>(array), 0, kLength,
756 reinterpret_cast<jchar*>(elements));
757 jni_abort_catcher.Check(
758 "attempt to set region of char primitive array elements with an object of type boolean[]");
759 env_->SetIntArrayRegion(reinterpret_cast<jintArray>(array), 0, kLength,
760 reinterpret_cast<jint*>(elements));
761 jni_abort_catcher.Check(
762 "attempt to set region of int primitive array elements with an object of type boolean[]");
763 env_->SetLongArrayRegion(reinterpret_cast<jlongArray>(array), 0, kLength,
764 reinterpret_cast<jlong*>(elements));
765 jni_abort_catcher.Check(
766 "attempt to set region of long primitive array elements with an object of type boolean[]");
767 env_->SetFloatArrayRegion(reinterpret_cast<jfloatArray>(array), 0, kLength,
768 reinterpret_cast<jfloat*>(elements));
769 jni_abort_catcher.Check(
770 "attempt to set region of float primitive array elements with an object of type boolean[]");
771 env_->SetDoubleArrayRegion(reinterpret_cast<jdoubleArray>(array), 0, kLength,
772 reinterpret_cast<jdouble*>(elements));
773 jni_abort_catcher.Check(
774 "attempt to set region of double primitive array elements with an object of type boolean[]");
775 jbyteArray array2 = env_->NewByteArray(10);
776 env_->SetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(array2), 0, kLength,
777 reinterpret_cast<jboolean*>(elements));
778 jni_abort_catcher.Check(
779 "attempt to set region of boolean primitive array elements with an object of type byte[]");
780 jobject object = env_->NewStringUTF("Test String");
781 env_->SetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(object), 0, kLength,
782 reinterpret_cast<jboolean*>(elements));
783 jni_abort_catcher.Check(
784 "attempt to set region of boolean primitive array elements with an object of type java.lang.String");
785}
786
Elliott Hughesf2682d52011-08-15 16:37:04 -0700787TEST_F(JniInternalTest, NewObjectArray) {
Elliott Hughesbd935992011-08-22 11:59:34 -0700788 jclass element_class = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -0700789 ASSERT_NE(element_class, nullptr);
Elliott Hughesbd935992011-08-22 11:59:34 -0700790 jclass array_class = env_->FindClass("[Ljava/lang/String;");
Ian Rogers2d10b202014-05-12 19:15:18 -0700791 ASSERT_NE(array_class, nullptr);
Elliott Hughesf2682d52011-08-15 16:37:04 -0700792
Ian Rogers1d99e452014-01-02 17:36:41 -0800793 jobjectArray a = env_->NewObjectArray(0, element_class, nullptr);
Ian Rogers2d10b202014-05-12 19:15:18 -0700794 EXPECT_NE(a, nullptr);
Elliott Hughesbd935992011-08-22 11:59:34 -0700795 EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
796 EXPECT_EQ(0, env_->GetArrayLength(a));
797
Ian Rogers1d99e452014-01-02 17:36:41 -0800798 a = env_->NewObjectArray(1, element_class, nullptr);
Ian Rogers2d10b202014-05-12 19:15:18 -0700799 EXPECT_NE(a, nullptr);
Elliott Hughesbd935992011-08-22 11:59:34 -0700800 EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
801 EXPECT_EQ(1, env_->GetArrayLength(a));
Ian Rogers1d99e452014-01-02 17:36:41 -0800802 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), nullptr));
Ian Rogers1d99e452014-01-02 17:36:41 -0800803
Ian Rogers2d10b202014-05-12 19:15:18 -0700804 // Negative array length checks.
Ian Rogers1d99e452014-01-02 17:36:41 -0800805 CheckJniAbortCatcher jni_abort_catcher;
Ian Rogers1d99e452014-01-02 17:36:41 -0800806 env_->NewObjectArray(-1, element_class, nullptr);
807 jni_abort_catcher.Check("negative array length: -1");
808
809 env_->NewObjectArray(std::numeric_limits<jint>::min(), element_class, nullptr);
810 jni_abort_catcher.Check("negative array length: -2147483648");
811}
812
813TEST_F(JniInternalTest, NewObjectArrayWithPrimitiveClasses) {
814 const char* primitive_descriptors = "VZBSCIJFD";
815 const char* primitive_names[] = {
816 "void", "boolean", "byte", "short", "char", "int", "long", "float", "double"
817 };
818 ASSERT_EQ(strlen(primitive_descriptors), arraysize(primitive_names));
819
820 CheckJniAbortCatcher jni_abort_catcher;
821 for (size_t i = 0; i < strlen(primitive_descriptors); ++i) {
Ian Rogers2d10b202014-05-12 19:15:18 -0700822 env_->NewObjectArray(0, nullptr, nullptr);
823 jni_abort_catcher.Check("element_jclass == null");
Ian Rogers1d99e452014-01-02 17:36:41 -0800824 jclass primitive_class = GetPrimitiveClass(primitive_descriptors[i]);
825 env_->NewObjectArray(1, primitive_class, nullptr);
826 std::string error_msg(StringPrintf("not an object type: %s", primitive_names[i]));
827 jni_abort_catcher.Check(error_msg.c_str());
828 }
829}
830
831TEST_F(JniInternalTest, NewObjectArrayWithInitialValue) {
832 jclass element_class = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -0700833 ASSERT_NE(element_class, nullptr);
Ian Rogers1d99e452014-01-02 17:36:41 -0800834 jclass array_class = env_->FindClass("[Ljava/lang/String;");
Ian Rogers2d10b202014-05-12 19:15:18 -0700835 ASSERT_NE(array_class, nullptr);
Elliott Hughes75770752011-08-24 17:52:38 -0700836
837 jstring s = env_->NewStringUTF("poop");
Ian Rogers1d99e452014-01-02 17:36:41 -0800838 jobjectArray a = env_->NewObjectArray(2, element_class, s);
Ian Rogers2d10b202014-05-12 19:15:18 -0700839 EXPECT_NE(a, nullptr);
Elliott Hughes75770752011-08-24 17:52:38 -0700840 EXPECT_TRUE(env_->IsInstanceOf(a, array_class));
841 EXPECT_EQ(2, env_->GetArrayLength(a));
842 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), s));
843 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 1), s));
Ian Rogers1d99e452014-01-02 17:36:41 -0800844
845 // Attempt to incorrect create an array of strings with initial value of string arrays.
846 CheckJniAbortCatcher jni_abort_catcher;
847 env_->NewObjectArray(2, element_class, a);
848 jni_abort_catcher.Check("cannot assign object of type 'java.lang.String[]' to array with element "
849 "type of 'java.lang.String'");
Elliott Hughesbd935992011-08-22 11:59:34 -0700850}
851
852TEST_F(JniInternalTest, GetArrayLength) {
853 // Already tested in NewObjectArray/NewPrimitiveArray.
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700854}
855
Elliott Hughes37f7a402011-08-22 18:56:01 -0700856TEST_F(JniInternalTest, GetObjectClass) {
857 jclass string_class = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -0700858 ASSERT_NE(string_class, nullptr);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700859 jclass class_class = env_->FindClass("java/lang/Class");
Ian Rogers2d10b202014-05-12 19:15:18 -0700860 ASSERT_NE(class_class, nullptr);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700861
862 jstring s = env_->NewStringUTF("poop");
863 jclass c = env_->GetObjectClass(s);
864 ASSERT_TRUE(env_->IsSameObject(string_class, c));
865
866 jclass c2 = env_->GetObjectClass(c);
867 ASSERT_TRUE(env_->IsSameObject(class_class, env_->GetObjectClass(c2)));
Ian Rogers2d10b202014-05-12 19:15:18 -0700868
869 // Null as object should fail.
870 CheckJniAbortCatcher jni_abort_catcher;
871 EXPECT_EQ(env_->GetObjectClass(nullptr), nullptr);
872 jni_abort_catcher.Check("java_object == null");
Elliott Hughes37f7a402011-08-22 18:56:01 -0700873}
874
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700875TEST_F(JniInternalTest, GetSuperclass) {
876 jclass object_class = env_->FindClass("java/lang/Object");
Ian Rogers2d10b202014-05-12 19:15:18 -0700877 ASSERT_NE(object_class, nullptr);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700878 jclass string_class = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -0700879 ASSERT_NE(string_class, nullptr);
Ian Rogersdc180202012-01-29 14:47:29 -0800880 jclass runnable_interface = env_->FindClass("java/lang/Runnable");
Ian Rogers2d10b202014-05-12 19:15:18 -0700881 ASSERT_NE(runnable_interface, nullptr);
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700882 ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(string_class)));
Ian Rogers2d10b202014-05-12 19:15:18 -0700883 ASSERT_EQ(env_->GetSuperclass(object_class), nullptr);
Ian Rogersdc180202012-01-29 14:47:29 -0800884 ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(runnable_interface)));
Ian Rogers2d10b202014-05-12 19:15:18 -0700885
886 // Null as class should fail.
887 CheckJniAbortCatcher jni_abort_catcher;
888 EXPECT_EQ(env_->GetSuperclass(nullptr), nullptr);
889 jni_abort_catcher.Check("java_class == null");
Elliott Hughes885c3bd2011-08-22 16:59:20 -0700890}
891
Elliott Hughes37f7a402011-08-22 18:56:01 -0700892TEST_F(JniInternalTest, IsAssignableFrom) {
893 jclass object_class = env_->FindClass("java/lang/Object");
Ian Rogers2d10b202014-05-12 19:15:18 -0700894 ASSERT_NE(object_class, nullptr);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700895 jclass string_class = env_->FindClass("java/lang/String");
Ian Rogers2d10b202014-05-12 19:15:18 -0700896 ASSERT_NE(string_class, nullptr);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700897
898 ASSERT_TRUE(env_->IsAssignableFrom(object_class, string_class));
899 ASSERT_FALSE(env_->IsAssignableFrom(string_class, object_class));
Ian Rogers2d10b202014-05-12 19:15:18 -0700900
901 // Null as either class should fail.
902 CheckJniAbortCatcher jni_abort_catcher;
903 EXPECT_EQ(env_->IsAssignableFrom(nullptr, string_class), JNI_FALSE);
904 jni_abort_catcher.Check("java_class1 == null");
905 EXPECT_EQ(env_->IsAssignableFrom(object_class, nullptr), JNI_FALSE);
906 jni_abort_catcher.Check("java_class2 == null");
Elliott Hughes37f7a402011-08-22 18:56:01 -0700907}
908
Elliott Hughesb465ab02011-08-24 11:21:21 -0700909TEST_F(JniInternalTest, GetObjectRefType) {
910 jclass local = env_->FindClass("java/lang/Object");
Ian Rogers2d10b202014-05-12 19:15:18 -0700911 ASSERT_TRUE(local != nullptr);
Elliott Hughesb465ab02011-08-24 11:21:21 -0700912 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(local));
913
914 jobject global = env_->NewGlobalRef(local);
915 EXPECT_EQ(JNIGlobalRefType, env_->GetObjectRefType(global));
916
917 jweak weak_global = env_->NewWeakGlobalRef(local);
918 EXPECT_EQ(JNIWeakGlobalRefType, env_->GetObjectRefType(weak_global));
919
920 jobject invalid = reinterpret_cast<jobject>(this);
921 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(invalid));
922
923 // TODO: invoke a native method and test that its arguments are considered local references.
Ian Rogers2d10b202014-05-12 19:15:18 -0700924
925 // Null as object should fail.
926 CheckJniAbortCatcher jni_abort_catcher;
927 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(nullptr));
928 jni_abort_catcher.Check("java_object == null");
Elliott Hughesb465ab02011-08-24 11:21:21 -0700929}
930
Mathieu Chartier08599992013-12-20 17:17:55 -0800931TEST_F(JniInternalTest, StaleWeakGlobal) {
932 jclass java_lang_Class = env_->FindClass("java/lang/Class");
Ian Rogers2d10b202014-05-12 19:15:18 -0700933 ASSERT_NE(java_lang_Class, nullptr);
934 jobjectArray local_ref = env_->NewObjectArray(1, java_lang_Class, nullptr);
935 ASSERT_NE(local_ref, nullptr);
Mathieu Chartier08599992013-12-20 17:17:55 -0800936 jweak weak_global = env_->NewWeakGlobalRef(local_ref);
Ian Rogers2d10b202014-05-12 19:15:18 -0700937 ASSERT_NE(weak_global, nullptr);
Mathieu Chartier08599992013-12-20 17:17:55 -0800938 env_->DeleteLocalRef(local_ref);
939 Runtime::Current()->GetHeap()->CollectGarbage(false); // GC should clear the weak global.
940 jobject new_global_ref = env_->NewGlobalRef(weak_global);
Ian Rogers2d10b202014-05-12 19:15:18 -0700941 EXPECT_EQ(new_global_ref, nullptr);
Mathieu Chartier08599992013-12-20 17:17:55 -0800942 jobject new_local_ref = env_->NewLocalRef(weak_global);
Ian Rogers2d10b202014-05-12 19:15:18 -0700943 EXPECT_EQ(new_local_ref, nullptr);
Mathieu Chartier08599992013-12-20 17:17:55 -0800944}
945
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700946TEST_F(JniInternalTest, NewStringUTF) {
Ian Rogers2d10b202014-05-12 19:15:18 -0700947 EXPECT_EQ(env_->NewStringUTF(nullptr), nullptr);
Elliott Hughes814e4032011-08-23 12:07:56 -0700948 jstring s;
949
950 s = env_->NewStringUTF("");
Ian Rogers2d10b202014-05-12 19:15:18 -0700951 EXPECT_NE(s, nullptr);
Elliott Hughes814e4032011-08-23 12:07:56 -0700952 EXPECT_EQ(0, env_->GetStringLength(s));
953 EXPECT_EQ(0, env_->GetStringUTFLength(s));
954 s = env_->NewStringUTF("hello");
Ian Rogers2d10b202014-05-12 19:15:18 -0700955 EXPECT_NE(s, nullptr);
Elliott Hughes814e4032011-08-23 12:07:56 -0700956 EXPECT_EQ(5, env_->GetStringLength(s));
957 EXPECT_EQ(5, env_->GetStringUTFLength(s));
958
Elliott Hughes8a26c5c2011-08-15 18:35:43 -0700959 // TODO: check some non-ASCII strings.
Elliott Hughesf2682d52011-08-15 16:37:04 -0700960}
961
Elliott Hughes814e4032011-08-23 12:07:56 -0700962TEST_F(JniInternalTest, NewString) {
Elliott Hughes814e4032011-08-23 12:07:56 -0700963 jchar chars[] = { 'h', 'i' };
964 jstring s;
965 s = env_->NewString(chars, 0);
Ian Rogers2d10b202014-05-12 19:15:18 -0700966 EXPECT_NE(s, nullptr);
Elliott Hughes814e4032011-08-23 12:07:56 -0700967 EXPECT_EQ(0, env_->GetStringLength(s));
968 EXPECT_EQ(0, env_->GetStringUTFLength(s));
969 s = env_->NewString(chars, 2);
Ian Rogers2d10b202014-05-12 19:15:18 -0700970 EXPECT_NE(s, nullptr);
Elliott Hughes814e4032011-08-23 12:07:56 -0700971 EXPECT_EQ(2, env_->GetStringLength(s));
972 EXPECT_EQ(2, env_->GetStringUTFLength(s));
973
974 // TODO: check some non-ASCII strings.
975}
976
Jesse Wilson25e79a52011-11-18 15:31:58 -0500977TEST_F(JniInternalTest, NewStringNullCharsZeroLength) {
Ian Rogers1d99e452014-01-02 17:36:41 -0800978 jstring s = env_->NewString(nullptr, 0);
Ian Rogers2d10b202014-05-12 19:15:18 -0700979 EXPECT_NE(s, nullptr);
Jesse Wilson25e79a52011-11-18 15:31:58 -0500980 EXPECT_EQ(0, env_->GetStringLength(s));
981}
982
Ian Rogers1d99e452014-01-02 17:36:41 -0800983TEST_F(JniInternalTest, NewStringNullCharsNonzeroLength) {
984 CheckJniAbortCatcher jni_abort_catcher;
985 env_->NewString(nullptr, 1);
986 jni_abort_catcher.Check("chars == null && char_count > 0");
987}
988
989TEST_F(JniInternalTest, NewStringNegativeLength) {
990 CheckJniAbortCatcher jni_abort_catcher;
991 env_->NewString(nullptr, -1);
992 jni_abort_catcher.Check("char_count < 0: -1");
993 env_->NewString(nullptr, std::numeric_limits<jint>::min());
994 jni_abort_catcher.Check("char_count < 0: -2147483648");
Jesse Wilson25e79a52011-11-18 15:31:58 -0500995}
996
Elliott Hughesb465ab02011-08-24 11:21:21 -0700997TEST_F(JniInternalTest, GetStringLength_GetStringUTFLength) {
998 // Already tested in the NewString/NewStringUTF tests.
999}
1000
1001TEST_F(JniInternalTest, GetStringRegion_GetStringUTFRegion) {
1002 jstring s = env_->NewStringUTF("hello");
Ian Rogers2d10b202014-05-12 19:15:18 -07001003 ASSERT_TRUE(s != nullptr);
Elliott Hughesb465ab02011-08-24 11:21:21 -07001004
Ian Rogers2d10b202014-05-12 19:15:18 -07001005 env_->GetStringRegion(s, -1, 0, nullptr);
1006 ExpectException(sioobe_);
1007 env_->GetStringRegion(s, 0, -1, nullptr);
1008 ExpectException(sioobe_);
1009 env_->GetStringRegion(s, 0, 10, nullptr);
1010 ExpectException(sioobe_);
1011 env_->GetStringRegion(s, 10, 1, nullptr);
1012 ExpectException(sioobe_);
Elliott Hughesb465ab02011-08-24 11:21:21 -07001013
1014 jchar chars[4] = { 'x', 'x', 'x', 'x' };
1015 env_->GetStringRegion(s, 1, 2, &chars[1]);
1016 EXPECT_EQ('x', chars[0]);
1017 EXPECT_EQ('e', chars[1]);
1018 EXPECT_EQ('l', chars[2]);
1019 EXPECT_EQ('x', chars[3]);
1020
Ian Rogers2d10b202014-05-12 19:15:18 -07001021 // It's okay for the buffer to be nullptr as long as the length is 0.
1022 env_->GetStringRegion(s, 2, 0, nullptr);
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -07001023 // Even if the offset is invalid...
Ian Rogers2d10b202014-05-12 19:15:18 -07001024 env_->GetStringRegion(s, 123, 0, nullptr);
1025 ExpectException(sioobe_);
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -07001026
Ian Rogers2d10b202014-05-12 19:15:18 -07001027 env_->GetStringUTFRegion(s, -1, 0, nullptr);
1028 ExpectException(sioobe_);
1029 env_->GetStringUTFRegion(s, 0, -1, nullptr);
1030 ExpectException(sioobe_);
1031 env_->GetStringUTFRegion(s, 0, 10, nullptr);
1032 ExpectException(sioobe_);
1033 env_->GetStringUTFRegion(s, 10, 1, nullptr);
1034 ExpectException(sioobe_);
Elliott Hughesb465ab02011-08-24 11:21:21 -07001035
1036 char bytes[4] = { 'x', 'x', 'x', 'x' };
1037 env_->GetStringUTFRegion(s, 1, 2, &bytes[1]);
1038 EXPECT_EQ('x', bytes[0]);
1039 EXPECT_EQ('e', bytes[1]);
1040 EXPECT_EQ('l', bytes[2]);
1041 EXPECT_EQ('x', bytes[3]);
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -07001042
Ian Rogers2d10b202014-05-12 19:15:18 -07001043 // It's okay for the buffer to be nullptr as long as the length is 0.
1044 env_->GetStringUTFRegion(s, 2, 0, nullptr);
Elliott Hughesd7d7f6e2013-09-18 12:00:45 -07001045 // Even if the offset is invalid...
Ian Rogers2d10b202014-05-12 19:15:18 -07001046 env_->GetStringUTFRegion(s, 123, 0, nullptr);
1047 ExpectException(sioobe_);
Elliott Hughesb465ab02011-08-24 11:21:21 -07001048}
1049
Elliott Hughes75770752011-08-24 17:52:38 -07001050TEST_F(JniInternalTest, GetStringUTFChars_ReleaseStringUTFChars) {
Ian Rogers2d10b202014-05-12 19:15:18 -07001051 // Passing in a nullptr jstring is ignored normally, but caught by -Xcheck:jni.
Elliott Hughesb264f082012-04-06 17:10:10 -07001052 {
Elliott Hughesb264f082012-04-06 17:10:10 -07001053 CheckJniAbortCatcher check_jni_abort_catcher;
Ian Rogers2d10b202014-05-12 19:15:18 -07001054 EXPECT_EQ(env_->GetStringUTFChars(nullptr, nullptr), nullptr);
Elliott Hughes56ef0422012-06-19 14:35:04 -07001055 check_jni_abort_catcher.Check("GetStringUTFChars received null jstring");
Elliott Hughesb264f082012-04-06 17:10:10 -07001056 }
Elliott Hughes75770752011-08-24 17:52:38 -07001057
1058 jstring s = env_->NewStringUTF("hello");
Ian Rogers2d10b202014-05-12 19:15:18 -07001059 ASSERT_TRUE(s != nullptr);
Elliott Hughes75770752011-08-24 17:52:38 -07001060
Ian Rogers2d10b202014-05-12 19:15:18 -07001061 const char* utf = env_->GetStringUTFChars(s, nullptr);
Elliott Hughes75770752011-08-24 17:52:38 -07001062 EXPECT_STREQ("hello", utf);
1063 env_->ReleaseStringUTFChars(s, utf);
1064
1065 jboolean is_copy = JNI_FALSE;
1066 utf = env_->GetStringUTFChars(s, &is_copy);
1067 EXPECT_EQ(JNI_TRUE, is_copy);
1068 EXPECT_STREQ("hello", utf);
1069 env_->ReleaseStringUTFChars(s, utf);
1070}
1071
1072TEST_F(JniInternalTest, GetStringChars_ReleaseStringChars) {
1073 jstring s = env_->NewStringUTF("hello");
Ian Rogers2d10b202014-05-12 19:15:18 -07001074 ASSERT_TRUE(s != nullptr);
Elliott Hughes75770752011-08-24 17:52:38 -07001075
1076 jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
Ian Rogers2d10b202014-05-12 19:15:18 -07001077 const jchar* chars = env_->GetStringChars(s, nullptr);
Elliott Hughes75770752011-08-24 17:52:38 -07001078 EXPECT_EQ(expected[0], chars[0]);
1079 EXPECT_EQ(expected[1], chars[1]);
1080 EXPECT_EQ(expected[2], chars[2]);
1081 EXPECT_EQ(expected[3], chars[3]);
1082 EXPECT_EQ(expected[4], chars[4]);
1083 env_->ReleaseStringChars(s, chars);
1084
1085 jboolean is_copy = JNI_FALSE;
1086 chars = env_->GetStringChars(s, &is_copy);
Mathieu Chartier590fee92013-09-13 13:46:47 -07001087 EXPECT_EQ(JNI_TRUE, is_copy);
Elliott Hughes75770752011-08-24 17:52:38 -07001088 EXPECT_EQ(expected[0], chars[0]);
1089 EXPECT_EQ(expected[1], chars[1]);
1090 EXPECT_EQ(expected[2], chars[2]);
1091 EXPECT_EQ(expected[3], chars[3]);
1092 EXPECT_EQ(expected[4], chars[4]);
1093 env_->ReleaseStringChars(s, chars);
1094}
1095
1096TEST_F(JniInternalTest, GetStringCritical_ReleaseStringCritical) {
1097 jstring s = env_->NewStringUTF("hello");
Ian Rogers2d10b202014-05-12 19:15:18 -07001098 ASSERT_TRUE(s != nullptr);
Elliott Hughes75770752011-08-24 17:52:38 -07001099
1100 jchar expected[] = { 'h', 'e', 'l', 'l', 'o' };
Ian Rogers2d10b202014-05-12 19:15:18 -07001101 const jchar* chars = env_->GetStringCritical(s, nullptr);
Elliott Hughes75770752011-08-24 17:52:38 -07001102 EXPECT_EQ(expected[0], chars[0]);
1103 EXPECT_EQ(expected[1], chars[1]);
1104 EXPECT_EQ(expected[2], chars[2]);
1105 EXPECT_EQ(expected[3], chars[3]);
1106 EXPECT_EQ(expected[4], chars[4]);
1107 env_->ReleaseStringCritical(s, chars);
1108
1109 jboolean is_copy = JNI_FALSE;
1110 chars = env_->GetStringCritical(s, &is_copy);
Mathieu Chartier590fee92013-09-13 13:46:47 -07001111 // TODO: Fix GetStringCritical to use the same mechanism as GetPrimitiveArrayElementsCritical.
1112 EXPECT_EQ(JNI_TRUE, is_copy);
Elliott Hughes75770752011-08-24 17:52:38 -07001113 EXPECT_EQ(expected[0], chars[0]);
1114 EXPECT_EQ(expected[1], chars[1]);
1115 EXPECT_EQ(expected[2], chars[2]);
1116 EXPECT_EQ(expected[3], chars[3]);
1117 EXPECT_EQ(expected[4], chars[4]);
1118 env_->ReleaseStringCritical(s, chars);
1119}
1120
Elliott Hughes814e4032011-08-23 12:07:56 -07001121TEST_F(JniInternalTest, GetObjectArrayElement_SetObjectArrayElement) {
Elliott Hughesb264f082012-04-06 17:10:10 -07001122 jclass java_lang_Class = env_->FindClass("java/lang/Class");
Ian Rogers2d10b202014-05-12 19:15:18 -07001123 ASSERT_TRUE(java_lang_Class != nullptr);
Elliott Hughes289da822011-08-16 10:11:20 -07001124
Ian Rogers2d10b202014-05-12 19:15:18 -07001125 jobjectArray array = env_->NewObjectArray(1, java_lang_Class, nullptr);
1126 EXPECT_NE(array, nullptr);
1127 EXPECT_EQ(env_->GetObjectArrayElement(array, 0), nullptr);
Elliott Hughesb264f082012-04-06 17:10:10 -07001128 env_->SetObjectArrayElement(array, 0, java_lang_Class);
1129 EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(array, 0), java_lang_Class));
Elliott Hughesa5b897e2011-08-16 11:33:06 -07001130
1131 // ArrayIndexOutOfBounds for negative index.
Elliott Hughesb264f082012-04-06 17:10:10 -07001132 env_->SetObjectArrayElement(array, -1, java_lang_Class);
Ian Rogers2d10b202014-05-12 19:15:18 -07001133 ExpectException(aioobe_);
Elliott Hughesa5b897e2011-08-16 11:33:06 -07001134
1135 // ArrayIndexOutOfBounds for too-large index.
Elliott Hughesb264f082012-04-06 17:10:10 -07001136 env_->SetObjectArrayElement(array, 1, java_lang_Class);
Ian Rogers2d10b202014-05-12 19:15:18 -07001137 ExpectException(aioobe_);
Elliott Hughesa5b897e2011-08-16 11:33:06 -07001138
Elliott Hughesb264f082012-04-06 17:10:10 -07001139 // ArrayStoreException thrown for bad types.
1140 env_->SetObjectArrayElement(array, 0, env_->NewStringUTF("not a jclass!"));
Ian Rogers2d10b202014-05-12 19:15:18 -07001141 ExpectException(ase_);
1142
1143 // Null as array should fail.
1144 CheckJniAbortCatcher jni_abort_catcher;
1145 EXPECT_EQ(nullptr, env_->GetObjectArrayElement(nullptr, 0));
1146 jni_abort_catcher.Check("java_array == null");
1147 env_->SetObjectArrayElement(nullptr, 0, nullptr);
1148 jni_abort_catcher.Check("java_array == null");
Elliott Hughes289da822011-08-16 10:11:20 -07001149}
1150
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001151#define EXPECT_STATIC_PRIMITIVE_FIELD(type, field_name, sig, value1, value2) \
1152 do { \
1153 jfieldID fid = env_->GetStaticFieldID(c, field_name, sig); \
Ian Rogers2d10b202014-05-12 19:15:18 -07001154 EXPECT_NE(fid, nullptr); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001155 env_->SetStatic ## type ## Field(c, fid, value1); \
Ian Rogers2d10b202014-05-12 19:15:18 -07001156 EXPECT_EQ(value1, env_->GetStatic ## type ## Field(c, fid)); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001157 env_->SetStatic ## type ## Field(c, fid, value2); \
Ian Rogers2d10b202014-05-12 19:15:18 -07001158 EXPECT_EQ(value2, env_->GetStatic ## type ## Field(c, fid)); \
1159 \
1160 CheckJniAbortCatcher jni_abort_catcher; \
1161 env_->GetStatic ## type ## Field(nullptr, fid); \
1162 jni_abort_catcher.Check("received null jclass"); \
1163 env_->SetStatic ## type ## Field(nullptr, fid, value1); \
1164 jni_abort_catcher.Check("received null jclass"); \
1165 env_->GetStatic ## type ## Field(c, nullptr); \
1166 jni_abort_catcher.Check("fid == null"); \
1167 env_->SetStatic ## type ## Field(c, nullptr, value1); \
1168 jni_abort_catcher.Check("fid == null"); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001169 } while (false)
1170
1171#define EXPECT_PRIMITIVE_FIELD(instance, type, field_name, sig, value1, value2) \
1172 do { \
1173 jfieldID fid = env_->GetFieldID(c, field_name, sig); \
Ian Rogers2d10b202014-05-12 19:15:18 -07001174 EXPECT_NE(fid, nullptr); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001175 env_->Set ## type ## Field(instance, fid, value1); \
Ian Rogers2d10b202014-05-12 19:15:18 -07001176 EXPECT_EQ(value1, env_->Get ## type ## Field(instance, fid)); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001177 env_->Set ## type ## Field(instance, fid, value2); \
Ian Rogers2d10b202014-05-12 19:15:18 -07001178 EXPECT_EQ(value2, env_->Get ## type ## Field(instance, fid)); \
1179 \
1180 CheckJniAbortCatcher jni_abort_catcher; \
1181 env_->Get ## type ## Field(nullptr, fid); \
1182 jni_abort_catcher.Check("obj == null"); \
1183 env_->Set ## type ## Field(nullptr, fid, value1); \
1184 jni_abort_catcher.Check("obj == null"); \
1185 env_->Get ## type ## Field(instance, nullptr); \
1186 jni_abort_catcher.Check("fid == null"); \
1187 env_->Set ## type ## Field(instance, nullptr, value1); \
1188 jni_abort_catcher.Check("fid == null"); \
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001189 } while (false)
1190
1191
1192TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001193 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001194 Thread::Current()->TransitionFromSuspendedToRunnable();
1195 LoadDex("AllFields");
Brian Carlstrombd86bcc2013-03-10 20:26:16 -07001196 bool started = runtime_->Start();
Ian Rogers2d10b202014-05-12 19:15:18 -07001197 ASSERT_TRUE(started);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001198
1199 jclass c = env_->FindClass("AllFields");
Ian Rogers2d10b202014-05-12 19:15:18 -07001200 ASSERT_NE(c, nullptr);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001201 jobject o = env_->AllocObject(c);
Ian Rogers2d10b202014-05-12 19:15:18 -07001202 ASSERT_NE(o, nullptr);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001203
Ian Rogers2d10b202014-05-12 19:15:18 -07001204 EXPECT_STATIC_PRIMITIVE_FIELD(Boolean, "sZ", "Z", JNI_TRUE, JNI_FALSE);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001205 EXPECT_STATIC_PRIMITIVE_FIELD(Byte, "sB", "B", 1, 2);
1206 EXPECT_STATIC_PRIMITIVE_FIELD(Char, "sC", "C", 'a', 'b');
1207 EXPECT_STATIC_PRIMITIVE_FIELD(Double, "sD", "D", 1.0, 2.0);
1208 EXPECT_STATIC_PRIMITIVE_FIELD(Float, "sF", "F", 1.0, 2.0);
1209 EXPECT_STATIC_PRIMITIVE_FIELD(Int, "sI", "I", 1, 2);
1210 EXPECT_STATIC_PRIMITIVE_FIELD(Long, "sJ", "J", 1, 2);
1211 EXPECT_STATIC_PRIMITIVE_FIELD(Short, "sS", "S", 1, 2);
1212
Ian Rogers2d10b202014-05-12 19:15:18 -07001213 EXPECT_PRIMITIVE_FIELD(o, Boolean, "iZ", "Z", JNI_TRUE, JNI_FALSE);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001214 EXPECT_PRIMITIVE_FIELD(o, Byte, "iB", "B", 1, 2);
1215 EXPECT_PRIMITIVE_FIELD(o, Char, "iC", "C", 'a', 'b');
1216 EXPECT_PRIMITIVE_FIELD(o, Double, "iD", "D", 1.0, 2.0);
1217 EXPECT_PRIMITIVE_FIELD(o, Float, "iF", "F", 1.0, 2.0);
1218 EXPECT_PRIMITIVE_FIELD(o, Int, "iI", "I", 1, 2);
1219 EXPECT_PRIMITIVE_FIELD(o, Long, "iJ", "J", 1, 2);
1220 EXPECT_PRIMITIVE_FIELD(o, Short, "iS", "S", 1, 2);
1221}
1222
1223TEST_F(JniInternalTest, GetObjectField_SetObjectField) {
Ian Rogersef7d42f2014-01-06 12:55:46 -08001224 TEST_DISABLED_FOR_PORTABLE();
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001225 Thread::Current()->TransitionFromSuspendedToRunnable();
1226 LoadDex("AllFields");
Brian Carlstrom25c33252011-09-18 15:58:35 -07001227 runtime_->Start();
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001228
1229 jclass c = env_->FindClass("AllFields");
Ian Rogers2d10b202014-05-12 19:15:18 -07001230 ASSERT_NE(c, nullptr);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001231 jobject o = env_->AllocObject(c);
Ian Rogers2d10b202014-05-12 19:15:18 -07001232 ASSERT_NE(o, nullptr);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001233
1234 jstring s1 = env_->NewStringUTF("hello");
Ian Rogers2d10b202014-05-12 19:15:18 -07001235 ASSERT_NE(s1, nullptr);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001236 jstring s2 = env_->NewStringUTF("world");
Ian Rogers2d10b202014-05-12 19:15:18 -07001237 ASSERT_NE(s2, nullptr);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001238
1239 jfieldID s_fid = env_->GetStaticFieldID(c, "sObject", "Ljava/lang/Object;");
Ian Rogers2d10b202014-05-12 19:15:18 -07001240 ASSERT_NE(s_fid, nullptr);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001241 jfieldID i_fid = env_->GetFieldID(c, "iObject", "Ljava/lang/Object;");
Ian Rogers2d10b202014-05-12 19:15:18 -07001242 ASSERT_NE(i_fid, nullptr);
Elliott Hughes885c3bd2011-08-22 16:59:20 -07001243
1244 env_->SetStaticObjectField(c, s_fid, s1);
1245 ASSERT_TRUE(env_->IsSameObject(s1, env_->GetStaticObjectField(c, s_fid)));
1246 env_->SetStaticObjectField(c, s_fid, s2);
1247 ASSERT_TRUE(env_->IsSameObject(s2, env_->GetStaticObjectField(c, s_fid)));
1248
1249 env_->SetObjectField(o, i_fid, s1);
1250 ASSERT_TRUE(env_->IsSameObject(s1, env_->GetObjectField(o, i_fid)));
1251 env_->SetObjectField(o, i_fid, s2);
1252 ASSERT_TRUE(env_->IsSameObject(s2, env_->GetObjectField(o, i_fid)));
1253}
1254
Ian Rogers2d10b202014-05-12 19:15:18 -07001255TEST_F(JniInternalTest, NewLocalRef_nullptr) {
1256 EXPECT_EQ(env_->NewLocalRef(nullptr), nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001257}
1258
1259TEST_F(JniInternalTest, NewLocalRef) {
1260 jstring s = env_->NewStringUTF("");
Ian Rogers2d10b202014-05-12 19:15:18 -07001261 ASSERT_NE(s, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001262 jobject o = env_->NewLocalRef(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07001263 EXPECT_NE(o, nullptr);
1264 EXPECT_NE(o, s);
Elliott Hughes18c07532011-08-18 15:50:51 -07001265
Elliott Hughes2ced6a52011-10-16 18:44:48 -07001266 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(o));
Elliott Hughes18c07532011-08-18 15:50:51 -07001267}
1268
Ian Rogers2d10b202014-05-12 19:15:18 -07001269TEST_F(JniInternalTest, DeleteLocalRef_nullptr) {
1270 env_->DeleteLocalRef(nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001271}
1272
1273TEST_F(JniInternalTest, DeleteLocalRef) {
1274 jstring s = env_->NewStringUTF("");
Ian Rogers2d10b202014-05-12 19:15:18 -07001275 ASSERT_NE(s, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001276 env_->DeleteLocalRef(s);
1277
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001278 // Currently, deleting an already-deleted reference is just a CheckJNI warning.
Elliott Hughesb264f082012-04-06 17:10:10 -07001279 {
Elliott Hughesb264f082012-04-06 17:10:10 -07001280 CheckJniAbortCatcher check_jni_abort_catcher;
1281 env_->DeleteLocalRef(s);
Elliott Hughesa9137c62013-01-09 10:55:21 -08001282
Brian Carlstromea46f952013-07-30 01:26:50 -07001283 std::string expected(StringPrintf("native code passing in reference to "
1284 "invalid local reference: %p", s));
Elliott Hughesa9137c62013-01-09 10:55:21 -08001285 check_jni_abort_catcher.Check(expected.c_str());
Elliott Hughesb264f082012-04-06 17:10:10 -07001286 }
Elliott Hughes18c07532011-08-18 15:50:51 -07001287
1288 s = env_->NewStringUTF("");
Ian Rogers2d10b202014-05-12 19:15:18 -07001289 ASSERT_NE(s, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001290 jobject o = env_->NewLocalRef(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07001291 ASSERT_NE(o, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001292
1293 env_->DeleteLocalRef(s);
1294 env_->DeleteLocalRef(o);
1295}
1296
Elliott Hughesaa836f72013-08-20 16:57:23 -07001297TEST_F(JniInternalTest, PushLocalFrame_10395422) {
1298 // The JNI specification is ambiguous about whether the given capacity is to be interpreted as a
1299 // maximum or as a minimum, but it seems like it's supposed to be a minimum, and that's how
1300 // Android historically treated it, and it's how the RI treats it. It's also the more useful
1301 // interpretation!
1302 ASSERT_EQ(JNI_OK, env_->PushLocalFrame(0));
Ian Rogers2d10b202014-05-12 19:15:18 -07001303 env_->PopLocalFrame(nullptr);
Elliott Hughesaa836f72013-08-20 16:57:23 -07001304
1305 // Negative capacities are not allowed.
1306 ASSERT_EQ(JNI_ERR, env_->PushLocalFrame(-1));
1307
1308 // And it's okay to have an upper limit. Ours is currently 512.
1309 ASSERT_EQ(JNI_ERR, env_->PushLocalFrame(8192));
1310}
1311
Elliott Hughes2ced6a52011-10-16 18:44:48 -07001312TEST_F(JniInternalTest, PushLocalFrame_PopLocalFrame) {
1313 jobject original = env_->NewStringUTF("");
Ian Rogers2d10b202014-05-12 19:15:18 -07001314 ASSERT_NE(original, nullptr);
Elliott Hughes2ced6a52011-10-16 18:44:48 -07001315
1316 jobject outer;
1317 jobject inner1, inner2;
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001318 ScopedObjectAccess soa(env_);
Ian Rogers2dd0e2c2013-01-24 12:42:14 -08001319 mirror::Object* inner2_direct_pointer;
Elliott Hughes2ced6a52011-10-16 18:44:48 -07001320 {
Elliott Hughesaa836f72013-08-20 16:57:23 -07001321 ASSERT_EQ(JNI_OK, env_->PushLocalFrame(4));
Elliott Hughes2ced6a52011-10-16 18:44:48 -07001322 outer = env_->NewLocalRef(original);
1323
1324 {
Elliott Hughesaa836f72013-08-20 16:57:23 -07001325 ASSERT_EQ(JNI_OK, env_->PushLocalFrame(4));
Elliott Hughes2ced6a52011-10-16 18:44:48 -07001326 inner1 = env_->NewLocalRef(outer);
1327 inner2 = env_->NewStringUTF("survivor");
Ian Rogers2dd0e2c2013-01-24 12:42:14 -08001328 inner2_direct_pointer = soa.Decode<mirror::Object*>(inner2);
Elliott Hughes2ced6a52011-10-16 18:44:48 -07001329 env_->PopLocalFrame(inner2);
1330 }
1331
1332 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original));
1333 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(outer));
1334 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1));
1335
1336 // Our local reference for the survivor is invalid because the survivor
1337 // gets a new local reference...
1338 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
Elliott Hughes2ced6a52011-10-16 18:44:48 -07001339
Ian Rogers2d10b202014-05-12 19:15:18 -07001340 env_->PopLocalFrame(nullptr);
Elliott Hughes2ced6a52011-10-16 18:44:48 -07001341 }
1342 EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original));
1343 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(outer));
1344 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner1));
1345 EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2));
1346}
1347
Ian Rogers2d10b202014-05-12 19:15:18 -07001348TEST_F(JniInternalTest, NewGlobalRef_nullptr) {
1349 EXPECT_EQ(env_->NewGlobalRef(nullptr), nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001350}
1351
1352TEST_F(JniInternalTest, NewGlobalRef) {
1353 jstring s = env_->NewStringUTF("");
Ian Rogers2d10b202014-05-12 19:15:18 -07001354 ASSERT_NE(s, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001355 jobject o = env_->NewGlobalRef(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07001356 EXPECT_NE(o, nullptr);
1357 EXPECT_NE(o, s);
Elliott Hughes18c07532011-08-18 15:50:51 -07001358
Ian Rogers2d10b202014-05-12 19:15:18 -07001359 EXPECT_EQ(env_->GetObjectRefType(o), JNIGlobalRefType);
Elliott Hughes18c07532011-08-18 15:50:51 -07001360}
1361
Ian Rogers2d10b202014-05-12 19:15:18 -07001362TEST_F(JniInternalTest, DeleteGlobalRef_nullptr) {
1363 env_->DeleteGlobalRef(nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001364}
1365
1366TEST_F(JniInternalTest, DeleteGlobalRef) {
1367 jstring s = env_->NewStringUTF("");
Ian Rogers2d10b202014-05-12 19:15:18 -07001368 ASSERT_NE(s, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001369
1370 jobject o = env_->NewGlobalRef(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07001371 ASSERT_NE(o, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001372 env_->DeleteGlobalRef(o);
1373
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001374 // Currently, deleting an already-deleted reference is just a CheckJNI warning.
Elliott Hughesb264f082012-04-06 17:10:10 -07001375 {
Elliott Hughesb264f082012-04-06 17:10:10 -07001376 CheckJniAbortCatcher check_jni_abort_catcher;
1377 env_->DeleteGlobalRef(o);
Elliott Hughesa9137c62013-01-09 10:55:21 -08001378
Brian Carlstromea46f952013-07-30 01:26:50 -07001379 std::string expected(StringPrintf("native code passing in reference to "
1380 "invalid global reference: %p", o));
Elliott Hughesa9137c62013-01-09 10:55:21 -08001381 check_jni_abort_catcher.Check(expected.c_str());
Elliott Hughesb264f082012-04-06 17:10:10 -07001382 }
Elliott Hughes18c07532011-08-18 15:50:51 -07001383
1384 jobject o1 = env_->NewGlobalRef(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07001385 ASSERT_NE(o1, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001386 jobject o2 = env_->NewGlobalRef(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07001387 ASSERT_NE(o2, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001388
1389 env_->DeleteGlobalRef(o1);
1390 env_->DeleteGlobalRef(o2);
1391}
1392
Ian Rogers2d10b202014-05-12 19:15:18 -07001393TEST_F(JniInternalTest, NewWeakGlobalRef_nullptr) {
1394 EXPECT_EQ(env_->NewWeakGlobalRef(nullptr), nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001395}
1396
1397TEST_F(JniInternalTest, NewWeakGlobalRef) {
1398 jstring s = env_->NewStringUTF("");
Ian Rogers2d10b202014-05-12 19:15:18 -07001399 ASSERT_NE(s, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001400 jobject o = env_->NewWeakGlobalRef(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07001401 EXPECT_NE(o, nullptr);
1402 EXPECT_NE(o, s);
Elliott Hughes18c07532011-08-18 15:50:51 -07001403
Ian Rogers2d10b202014-05-12 19:15:18 -07001404 EXPECT_EQ(env_->GetObjectRefType(o), JNIWeakGlobalRefType);
Elliott Hughes18c07532011-08-18 15:50:51 -07001405}
1406
Ian Rogers2d10b202014-05-12 19:15:18 -07001407TEST_F(JniInternalTest, DeleteWeakGlobalRef_nullptr) {
1408 env_->DeleteWeakGlobalRef(nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001409}
1410
1411TEST_F(JniInternalTest, DeleteWeakGlobalRef) {
1412 jstring s = env_->NewStringUTF("");
Ian Rogers2d10b202014-05-12 19:15:18 -07001413 ASSERT_NE(s, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001414
1415 jobject o = env_->NewWeakGlobalRef(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07001416 ASSERT_NE(o, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001417 env_->DeleteWeakGlobalRef(o);
1418
Elliott Hughes3f6635a2012-06-19 13:37:49 -07001419 // Currently, deleting an already-deleted reference is just a CheckJNI warning.
Elliott Hughesb264f082012-04-06 17:10:10 -07001420 {
Elliott Hughesb264f082012-04-06 17:10:10 -07001421 CheckJniAbortCatcher check_jni_abort_catcher;
1422 env_->DeleteWeakGlobalRef(o);
Elliott Hughesa9137c62013-01-09 10:55:21 -08001423
Brian Carlstromea46f952013-07-30 01:26:50 -07001424 std::string expected(StringPrintf("native code passing in reference to "
1425 "invalid weak global reference: %p", o));
Elliott Hughesa9137c62013-01-09 10:55:21 -08001426 check_jni_abort_catcher.Check(expected.c_str());
Elliott Hughesb264f082012-04-06 17:10:10 -07001427 }
Elliott Hughes18c07532011-08-18 15:50:51 -07001428
1429 jobject o1 = env_->NewWeakGlobalRef(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07001430 ASSERT_NE(o1, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001431 jobject o2 = env_->NewWeakGlobalRef(s);
Ian Rogers2d10b202014-05-12 19:15:18 -07001432 ASSERT_NE(o2, nullptr);
Elliott Hughes18c07532011-08-18 15:50:51 -07001433
1434 env_->DeleteWeakGlobalRef(o1);
1435 env_->DeleteWeakGlobalRef(o2);
1436}
1437
Elliott Hughes37f7a402011-08-22 18:56:01 -07001438TEST_F(JniInternalTest, Throw) {
Ian Rogers2d10b202014-05-12 19:15:18 -07001439 EXPECT_EQ(JNI_ERR, env_->Throw(nullptr));
Elliott Hughes37f7a402011-08-22 18:56:01 -07001440
1441 jclass exception_class = env_->FindClass("java/lang/RuntimeException");
Ian Rogers2d10b202014-05-12 19:15:18 -07001442 ASSERT_TRUE(exception_class != nullptr);
Elliott Hughes37f7a402011-08-22 18:56:01 -07001443 jthrowable exception = reinterpret_cast<jthrowable>(env_->AllocObject(exception_class));
Ian Rogers2d10b202014-05-12 19:15:18 -07001444 ASSERT_TRUE(exception != nullptr);
Elliott Hughes37f7a402011-08-22 18:56:01 -07001445
1446 EXPECT_EQ(JNI_OK, env_->Throw(exception));
1447 EXPECT_TRUE(env_->ExceptionCheck());
Elliott Hughesa2501992011-08-26 19:39:54 -07001448 jthrowable thrown_exception = env_->ExceptionOccurred();
Elliott Hughes37f7a402011-08-22 18:56:01 -07001449 env_->ExceptionClear();
Elliott Hughesa2501992011-08-26 19:39:54 -07001450 EXPECT_TRUE(env_->IsSameObject(exception, thrown_exception));
Elliott Hughes37f7a402011-08-22 18:56:01 -07001451}
1452
1453TEST_F(JniInternalTest, ThrowNew) {
Ian Rogers2d10b202014-05-12 19:15:18 -07001454 EXPECT_EQ(JNI_ERR, env_->Throw(nullptr));
Elliott Hughes37f7a402011-08-22 18:56:01 -07001455
1456 jclass exception_class = env_->FindClass("java/lang/RuntimeException");
Ian Rogers2d10b202014-05-12 19:15:18 -07001457 ASSERT_TRUE(exception_class != nullptr);
Elliott Hughes37f7a402011-08-22 18:56:01 -07001458
Elliott Hughes5cb5ad22011-10-02 12:13:39 -07001459 jthrowable thrown_exception;
1460
Elliott Hughes37f7a402011-08-22 18:56:01 -07001461 EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, "hello world"));
1462 EXPECT_TRUE(env_->ExceptionCheck());
Elliott Hughes5cb5ad22011-10-02 12:13:39 -07001463 thrown_exception = env_->ExceptionOccurred();
1464 env_->ExceptionClear();
1465 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class));
1466
Ian Rogers2d10b202014-05-12 19:15:18 -07001467 EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, nullptr));
Elliott Hughes5cb5ad22011-10-02 12:13:39 -07001468 EXPECT_TRUE(env_->ExceptionCheck());
1469 thrown_exception = env_->ExceptionOccurred();
Elliott Hughes37f7a402011-08-22 18:56:01 -07001470 env_->ExceptionClear();
Elliott Hughesa2501992011-08-26 19:39:54 -07001471 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class));
Elliott Hughes37f7a402011-08-22 18:56:01 -07001472}
1473
Ian Rogers1d99e452014-01-02 17:36:41 -08001474TEST_F(JniInternalTest, NewDirectBuffer_GetDirectBufferAddress_GetDirectBufferCapacity) {
1475 // Start runtime.
1476 Thread* self = Thread::Current();
1477 self->TransitionFromSuspendedToRunnable();
1478 MakeExecutable(nullptr, "java.lang.Class");
1479 MakeExecutable(nullptr, "java.lang.Object");
1480 MakeExecutable(nullptr, "java.nio.DirectByteBuffer");
1481 MakeExecutable(nullptr, "java.nio.MemoryBlock");
1482 MakeExecutable(nullptr, "java.nio.MemoryBlock$UnmanagedBlock");
1483 MakeExecutable(nullptr, "java.nio.MappedByteBuffer");
1484 MakeExecutable(nullptr, "java.nio.ByteBuffer");
1485 MakeExecutable(nullptr, "java.nio.Buffer");
1486 // TODO: we only load a dex file here as starting the runtime relies upon it.
1487 const char* class_name = "StaticLeafMethods";
1488 LoadDex(class_name);
1489 bool started = runtime_->Start();
1490 ASSERT_TRUE(started);
1491
Elliott Hughesb465ab02011-08-24 11:21:21 -07001492 jclass buffer_class = env_->FindClass("java/nio/Buffer");
Ian Rogers2d10b202014-05-12 19:15:18 -07001493 ASSERT_NE(buffer_class, nullptr);
Elliott Hughesb465ab02011-08-24 11:21:21 -07001494
1495 char bytes[1024];
1496 jobject buffer = env_->NewDirectByteBuffer(bytes, sizeof(bytes));
Ian Rogers2d10b202014-05-12 19:15:18 -07001497 ASSERT_NE(buffer, nullptr);
Elliott Hughesb465ab02011-08-24 11:21:21 -07001498 ASSERT_TRUE(env_->IsInstanceOf(buffer, buffer_class));
Ian Rogers2d10b202014-05-12 19:15:18 -07001499 ASSERT_EQ(env_->GetDirectBufferAddress(buffer), bytes);
Ian Rogers1ee99352014-05-14 14:38:16 -07001500 ASSERT_EQ(env_->GetDirectBufferCapacity(buffer), static_cast<jlong>(sizeof(bytes)));
Elliott Hughesb465ab02011-08-24 11:21:21 -07001501}
1502
Ian Rogers6d0b13e2012-02-07 09:25:29 -08001503TEST_F(JniInternalTest, MonitorEnterExit) {
Ian Rogers2d10b202014-05-12 19:15:18 -07001504 // Create an object to torture.
Ian Rogers6d0b13e2012-02-07 09:25:29 -08001505 jclass object_class = env_->FindClass("java/lang/Object");
Ian Rogers2d10b202014-05-12 19:15:18 -07001506 ASSERT_NE(object_class, nullptr);
Ian Rogers6d0b13e2012-02-07 09:25:29 -08001507 jobject object = env_->AllocObject(object_class);
Ian Rogers2d10b202014-05-12 19:15:18 -07001508 ASSERT_NE(object, nullptr);
Ian Rogers6d0b13e2012-02-07 09:25:29 -08001509
1510 // Expected class of exceptions
1511 jclass imse_class = env_->FindClass("java/lang/IllegalMonitorStateException");
Ian Rogers2d10b202014-05-12 19:15:18 -07001512 ASSERT_NE(imse_class, nullptr);
Ian Rogers6d0b13e2012-02-07 09:25:29 -08001513
1514 jthrowable thrown_exception;
1515
1516 // Unlock of unowned monitor
1517 env_->MonitorExit(object);
1518 EXPECT_TRUE(env_->ExceptionCheck());
1519 thrown_exception = env_->ExceptionOccurred();
1520 env_->ExceptionClear();
1521 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class));
1522
1523 // Lock of unowned monitor
1524 env_->MonitorEnter(object);
1525 EXPECT_FALSE(env_->ExceptionCheck());
1526 // Regular unlock
1527 env_->MonitorExit(object);
1528 EXPECT_FALSE(env_->ExceptionCheck());
1529
1530 // Recursively lock a lot
1531 size_t max_recursive_lock = 1024;
1532 for (size_t i = 0; i < max_recursive_lock; i++) {
1533 env_->MonitorEnter(object);
1534 EXPECT_FALSE(env_->ExceptionCheck());
1535 }
1536 // Recursively unlock a lot
1537 for (size_t i = 0; i < max_recursive_lock; i++) {
1538 env_->MonitorExit(object);
1539 EXPECT_FALSE(env_->ExceptionCheck());
1540 }
1541
1542 // Unlock of unowned monitor
1543 env_->MonitorExit(object);
1544 EXPECT_TRUE(env_->ExceptionCheck());
1545 thrown_exception = env_->ExceptionOccurred();
1546 env_->ExceptionClear();
1547 EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class));
Elliott Hughesa92853e2012-02-07 16:09:27 -08001548
Ian Rogers2d10b202014-05-12 19:15:18 -07001549 // It's an error to call MonitorEnter or MonitorExit on nullptr.
Elliott Hughesb264f082012-04-06 17:10:10 -07001550 {
1551 CheckJniAbortCatcher check_jni_abort_catcher;
Ian Rogers2d10b202014-05-12 19:15:18 -07001552 env_->MonitorEnter(nullptr);
Elliott Hughesb264f082012-04-06 17:10:10 -07001553 check_jni_abort_catcher.Check("in call to MonitorEnter");
Elliott Hughesb264f082012-04-06 17:10:10 -07001554
Ian Rogers2d10b202014-05-12 19:15:18 -07001555 env_->MonitorExit(nullptr);
Elliott Hughesb264f082012-04-06 17:10:10 -07001556 check_jni_abort_catcher.Check("in call to MonitorExit");
1557 }
Ian Rogers6d0b13e2012-02-07 09:25:29 -08001558}
1559
Brian Carlstrom4d571432012-05-16 00:21:41 -07001560TEST_F(JniInternalTest, DetachCurrentThread) {
1561 CleanUpJniEnv(); // cleanup now so TearDown won't have junk from wrong JNIEnv
1562 jint ok = vm_->DetachCurrentThread();
1563 EXPECT_EQ(JNI_OK, ok);
1564
1565 jint err = vm_->DetachCurrentThread();
1566 EXPECT_EQ(JNI_ERR, err);
Ian Rogers2d10b202014-05-12 19:15:18 -07001567 vm_->AttachCurrentThread(&env_, nullptr); // need attached thread for CommonRuntimeTest::TearDown
Brian Carlstrom4d571432012-05-16 00:21:41 -07001568}
1569
Ian Rogers0cfe1fb2011-08-26 03:29:44 -07001570} // namespace art