blob: 2e6ce4fe71f806149bf9044722cbcb773245f5f2 [file] [log] [blame]
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +01001/*
2 * Copyright (C) 2014 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
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080017#include "transaction.h"
18
19#include "common_runtime_test.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010020#include "invoke_arg_array_builder.h"
21#include "mirror/array-inl.h"
22#include "mirror/art_field-inl.h"
23#include "mirror/art_method-inl.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010024
25namespace art {
26
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080027class TransactionTest : public CommonRuntimeTest {};
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010028
29TEST_F(TransactionTest, Object_class) {
30 ScopedObjectAccess soa(Thread::Current());
31 SirtRef<mirror::Class> sirt_klass(soa.Self(),
Ian Rogers98379392014-02-24 16:53:16 -080032 class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;"));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010033 ASSERT_TRUE(sirt_klass.get() != nullptr);
34
35 Transaction transaction;
36 Runtime::Current()->EnterTransactionMode(&transaction);
37 SirtRef<mirror::Object> sirt_obj(soa.Self(), sirt_klass->AllocObject(soa.Self()));
38 ASSERT_TRUE(sirt_obj.get() != nullptr);
39 ASSERT_EQ(sirt_obj->GetClass(), sirt_klass.get());
40 Runtime::Current()->ExitTransactionMode();
41
42 // Aborting transaction must not clear the Object::class field.
43 transaction.Abort();
44 EXPECT_EQ(sirt_obj->GetClass(), sirt_klass.get());
45}
46
47TEST_F(TransactionTest, Object_monitor) {
48 ScopedObjectAccess soa(Thread::Current());
49 SirtRef<mirror::Class> sirt_klass(soa.Self(),
Ian Rogers98379392014-02-24 16:53:16 -080050 class_linker_->FindSystemClass(soa.Self(),
51 "Ljava/lang/Object;"));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010052 ASSERT_TRUE(sirt_klass.get() != nullptr);
53 SirtRef<mirror::Object> sirt_obj(soa.Self(), sirt_klass->AllocObject(soa.Self()));
54 ASSERT_TRUE(sirt_obj.get() != nullptr);
55 ASSERT_EQ(sirt_obj->GetClass(), sirt_klass.get());
56
57 // Lock object's monitor outside the transaction.
58 sirt_obj->MonitorEnter(soa.Self());
59 uint32_t old_lock_word = sirt_obj->GetLockWord().GetValue();
60
61 Transaction transaction;
62 Runtime::Current()->EnterTransactionMode(&transaction);
63 // Unlock object's monitor inside the transaction.
64 sirt_obj->MonitorExit(soa.Self());
65 uint32_t new_lock_word = sirt_obj->GetLockWord().GetValue();
66 Runtime::Current()->ExitTransactionMode();
67
68 // Aborting transaction must not clear the Object::class field.
69 transaction.Abort();
70 uint32_t aborted_lock_word = sirt_obj->GetLockWord().GetValue();
71 EXPECT_NE(old_lock_word, new_lock_word);
72 EXPECT_EQ(aborted_lock_word, new_lock_word);
73}
74
75TEST_F(TransactionTest, Array_length) {
76 ScopedObjectAccess soa(Thread::Current());
77 SirtRef<mirror::Class> sirt_klass(soa.Self(),
Ian Rogers98379392014-02-24 16:53:16 -080078 class_linker_->FindSystemClass(soa.Self(),
79 "[Ljava/lang/Object;"));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010080 ASSERT_TRUE(sirt_klass.get() != nullptr);
81
82 constexpr int32_t kArraySize = 2;
83
84 Transaction transaction;
85 Runtime::Current()->EnterTransactionMode(&transaction);
86
87 // Allocate an array during transaction.
88 SirtRef<mirror::Array> sirt_obj(soa.Self(),
Mathieu Chartier661974a2014-01-09 11:23:53 -080089 mirror::Array::Alloc<true>(soa.Self(), sirt_klass.get(),
90 kArraySize,
91 sirt_klass->GetComponentSize(),
92 Runtime::Current()->GetHeap()->GetCurrentAllocator()));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010093 ASSERT_TRUE(sirt_obj.get() != nullptr);
94 ASSERT_EQ(sirt_obj->GetClass(), sirt_klass.get());
95 Runtime::Current()->ExitTransactionMode();
96
97 // Aborting transaction must not clear the Object::class field.
98 transaction.Abort();
99 EXPECT_EQ(sirt_obj->GetLength(), kArraySize);
100}
101
102TEST_F(TransactionTest, StaticFieldsTest) {
103 ScopedObjectAccess soa(Thread::Current());
104 SirtRef<mirror::ClassLoader> class_loader(
105 soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction")));
106 ASSERT_TRUE(class_loader.get() != nullptr);
107
108 SirtRef<mirror::Class> sirt_klass(soa.Self(),
Ian Rogers98379392014-02-24 16:53:16 -0800109 class_linker_->FindClass(soa.Self(), "LStaticFieldsTest;",
110 class_loader));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100111 ASSERT_TRUE(sirt_klass.get() != nullptr);
112 class_linker_->EnsureInitialized(sirt_klass, true, true);
113 ASSERT_TRUE(sirt_klass->IsInitialized());
114
115 // Lookup fields.
116 mirror::ArtField* booleanField = sirt_klass->FindDeclaredStaticField("booleanField", "Z");
117 ASSERT_TRUE(booleanField != nullptr);
118 ASSERT_EQ(FieldHelper(booleanField).GetTypeAsPrimitiveType(), Primitive::kPrimBoolean);
119 ASSERT_EQ(booleanField->GetBoolean(sirt_klass.get()), false);
120
121 mirror::ArtField* byteField = sirt_klass->FindDeclaredStaticField("byteField", "B");
122 ASSERT_TRUE(byteField != nullptr);
123 ASSERT_EQ(FieldHelper(byteField).GetTypeAsPrimitiveType(), Primitive::kPrimByte);
124 ASSERT_EQ(byteField->GetByte(sirt_klass.get()), 0);
125
126 mirror::ArtField* charField = sirt_klass->FindDeclaredStaticField("charField", "C");
127 ASSERT_TRUE(charField != nullptr);
128 ASSERT_EQ(FieldHelper(charField).GetTypeAsPrimitiveType(), Primitive::kPrimChar);
129 ASSERT_EQ(charField->GetChar(sirt_klass.get()), 0u);
130
131 mirror::ArtField* shortField = sirt_klass->FindDeclaredStaticField("shortField", "S");
132 ASSERT_TRUE(shortField != nullptr);
133 ASSERT_EQ(FieldHelper(shortField).GetTypeAsPrimitiveType(), Primitive::kPrimShort);
134 ASSERT_EQ(shortField->GetShort(sirt_klass.get()), 0);
135
136 mirror::ArtField* intField = sirt_klass->FindDeclaredStaticField("intField", "I");
137 ASSERT_TRUE(intField != nullptr);
138 ASSERT_EQ(FieldHelper(intField).GetTypeAsPrimitiveType(), Primitive::kPrimInt);
139 ASSERT_EQ(intField->GetInt(sirt_klass.get()), 0);
140
141 mirror::ArtField* longField = sirt_klass->FindDeclaredStaticField("longField", "J");
142 ASSERT_TRUE(longField != nullptr);
143 ASSERT_EQ(FieldHelper(longField).GetTypeAsPrimitiveType(), Primitive::kPrimLong);
144 ASSERT_EQ(longField->GetLong(sirt_klass.get()), static_cast<int64_t>(0));
145
146 mirror::ArtField* floatField = sirt_klass->FindDeclaredStaticField("floatField", "F");
147 ASSERT_TRUE(floatField != nullptr);
148 ASSERT_EQ(FieldHelper(floatField).GetTypeAsPrimitiveType(), Primitive::kPrimFloat);
149 ASSERT_EQ(floatField->GetFloat(sirt_klass.get()), static_cast<float>(0.0f));
150
151 mirror::ArtField* doubleField = sirt_klass->FindDeclaredStaticField("doubleField", "D");
152 ASSERT_TRUE(doubleField != nullptr);
153 ASSERT_EQ(FieldHelper(doubleField).GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
154 ASSERT_EQ(doubleField->GetDouble(sirt_klass.get()), static_cast<double>(0.0));
155
Ian Rogers98379392014-02-24 16:53:16 -0800156 mirror::ArtField* objectField = sirt_klass->FindDeclaredStaticField("objectField",
157 "Ljava/lang/Object;");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100158 ASSERT_TRUE(objectField != nullptr);
159 ASSERT_EQ(FieldHelper(objectField).GetTypeAsPrimitiveType(), Primitive::kPrimNot);
160 ASSERT_EQ(objectField->GetObject(sirt_klass.get()), nullptr);
161
162 // Create a java.lang.Object instance to set objectField.
Ian Rogers98379392014-02-24 16:53:16 -0800163 SirtRef<mirror::Class> object_klass(soa.Self(),
164 class_linker_->FindSystemClass(soa.Self(),
165 "Ljava/lang/Object;"));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100166 ASSERT_TRUE(object_klass.get() != nullptr);
167 SirtRef<mirror::Object> sirt_obj(soa.Self(), sirt_klass->AllocObject(soa.Self()));
168 ASSERT_TRUE(sirt_obj.get() != nullptr);
169 ASSERT_EQ(sirt_obj->GetClass(), sirt_klass.get());
170
171 // Modify fields inside transaction and abort it.
172 Transaction transaction;
173 Runtime::Current()->EnterTransactionMode(&transaction);
174 booleanField->SetBoolean<true>(sirt_klass.get(), true);
175 byteField->SetByte<true>(sirt_klass.get(), 1);
176 charField->SetChar<true>(sirt_klass.get(), 1u);
177 shortField->SetShort<true>(sirt_klass.get(), 1);
178 intField->SetInt<true>(sirt_klass.get(), 1);
179 longField->SetLong<true>(sirt_klass.get(), 1);
180 floatField->SetFloat<true>(sirt_klass.get(), 1.0);
181 doubleField->SetDouble<true>(sirt_klass.get(), 1.0);
182 objectField->SetObject<true>(sirt_klass.get(), sirt_obj.get());
183 Runtime::Current()->ExitTransactionMode();
184 transaction.Abort();
185
186 // Check values have properly been restored to their original (default) value.
187 EXPECT_EQ(booleanField->GetBoolean(sirt_klass.get()), false);
188 EXPECT_EQ(byteField->GetByte(sirt_klass.get()), 0);
189 EXPECT_EQ(charField->GetChar(sirt_klass.get()), 0u);
190 EXPECT_EQ(shortField->GetShort(sirt_klass.get()), 0);
191 EXPECT_EQ(intField->GetInt(sirt_klass.get()), 0);
192 EXPECT_EQ(longField->GetLong(sirt_klass.get()), static_cast<int64_t>(0));
193 EXPECT_EQ(floatField->GetFloat(sirt_klass.get()), static_cast<float>(0.0f));
194 EXPECT_EQ(doubleField->GetDouble(sirt_klass.get()), static_cast<double>(0.0));
195 EXPECT_EQ(objectField->GetObject(sirt_klass.get()), nullptr);
196}
197
198TEST_F(TransactionTest, InstanceFieldsTest) {
199 ScopedObjectAccess soa(Thread::Current());
200 SirtRef<mirror::ClassLoader> class_loader(
201 soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction")));
202 ASSERT_TRUE(class_loader.get() != nullptr);
203
204 SirtRef<mirror::Class> sirt_klass(soa.Self(),
Ian Rogers98379392014-02-24 16:53:16 -0800205 class_linker_->FindClass(soa.Self(), "LInstanceFieldsTest;",
206 class_loader));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100207 ASSERT_TRUE(sirt_klass.get() != nullptr);
208 class_linker_->EnsureInitialized(sirt_klass, true, true);
209 ASSERT_TRUE(sirt_klass->IsInitialized());
210
211 // Allocate an InstanceFieldTest object.
212 SirtRef<mirror::Object> sirt_instance(soa.Self(), sirt_klass->AllocObject(soa.Self()));
213 ASSERT_TRUE(sirt_instance.get() != nullptr);
214
215 // Lookup fields.
216 mirror::ArtField* booleanField = sirt_klass->FindDeclaredInstanceField("booleanField", "Z");
217 ASSERT_TRUE(booleanField != nullptr);
218 ASSERT_EQ(FieldHelper(booleanField).GetTypeAsPrimitiveType(), Primitive::kPrimBoolean);
219 ASSERT_EQ(booleanField->GetBoolean(sirt_instance.get()), false);
220
221 mirror::ArtField* byteField = sirt_klass->FindDeclaredInstanceField("byteField", "B");
222 ASSERT_TRUE(byteField != nullptr);
223 ASSERT_EQ(FieldHelper(byteField).GetTypeAsPrimitiveType(), Primitive::kPrimByte);
224 ASSERT_EQ(byteField->GetByte(sirt_instance.get()), 0);
225
226 mirror::ArtField* charField = sirt_klass->FindDeclaredInstanceField("charField", "C");
227 ASSERT_TRUE(charField != nullptr);
228 ASSERT_EQ(FieldHelper(charField).GetTypeAsPrimitiveType(), Primitive::kPrimChar);
229 ASSERT_EQ(charField->GetChar(sirt_instance.get()), 0u);
230
231 mirror::ArtField* shortField = sirt_klass->FindDeclaredInstanceField("shortField", "S");
232 ASSERT_TRUE(shortField != nullptr);
233 ASSERT_EQ(FieldHelper(shortField).GetTypeAsPrimitiveType(), Primitive::kPrimShort);
234 ASSERT_EQ(shortField->GetShort(sirt_instance.get()), 0);
235
236 mirror::ArtField* intField = sirt_klass->FindDeclaredInstanceField("intField", "I");
237 ASSERT_TRUE(intField != nullptr);
238 ASSERT_EQ(FieldHelper(intField).GetTypeAsPrimitiveType(), Primitive::kPrimInt);
239 ASSERT_EQ(intField->GetInt(sirt_instance.get()), 0);
240
241 mirror::ArtField* longField = sirt_klass->FindDeclaredInstanceField("longField", "J");
242 ASSERT_TRUE(longField != nullptr);
243 ASSERT_EQ(FieldHelper(longField).GetTypeAsPrimitiveType(), Primitive::kPrimLong);
244 ASSERT_EQ(longField->GetLong(sirt_instance.get()), static_cast<int64_t>(0));
245
246 mirror::ArtField* floatField = sirt_klass->FindDeclaredInstanceField("floatField", "F");
247 ASSERT_TRUE(floatField != nullptr);
248 ASSERT_EQ(FieldHelper(floatField).GetTypeAsPrimitiveType(), Primitive::kPrimFloat);
249 ASSERT_EQ(floatField->GetFloat(sirt_instance.get()), static_cast<float>(0.0f));
250
251 mirror::ArtField* doubleField = sirt_klass->FindDeclaredInstanceField("doubleField", "D");
252 ASSERT_TRUE(doubleField != nullptr);
253 ASSERT_EQ(FieldHelper(doubleField).GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
254 ASSERT_EQ(doubleField->GetDouble(sirt_instance.get()), static_cast<double>(0.0));
255
Ian Rogers98379392014-02-24 16:53:16 -0800256 mirror::ArtField* objectField = sirt_klass->FindDeclaredInstanceField("objectField",
257 "Ljava/lang/Object;");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100258 ASSERT_TRUE(objectField != nullptr);
259 ASSERT_EQ(FieldHelper(objectField).GetTypeAsPrimitiveType(), Primitive::kPrimNot);
260 ASSERT_EQ(objectField->GetObject(sirt_instance.get()), nullptr);
261
262 // Create a java.lang.Object instance to set objectField.
Ian Rogers98379392014-02-24 16:53:16 -0800263 SirtRef<mirror::Class> object_klass(soa.Self(),
264 class_linker_->FindSystemClass(soa.Self(),
265 "Ljava/lang/Object;"));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100266 ASSERT_TRUE(object_klass.get() != nullptr);
267 SirtRef<mirror::Object> sirt_obj(soa.Self(), sirt_klass->AllocObject(soa.Self()));
268 ASSERT_TRUE(sirt_obj.get() != nullptr);
269 ASSERT_EQ(sirt_obj->GetClass(), sirt_klass.get());
270
271 // Modify fields inside transaction and abort it.
272 Transaction transaction;
273 Runtime::Current()->EnterTransactionMode(&transaction);
274 booleanField->SetBoolean<true>(sirt_instance.get(), true);
275 byteField->SetByte<true>(sirt_instance.get(), 1);
276 charField->SetChar<true>(sirt_instance.get(), 1u);
277 shortField->SetShort<true>(sirt_instance.get(), 1);
278 intField->SetInt<true>(sirt_instance.get(), 1);
279 longField->SetLong<true>(sirt_instance.get(), 1);
280 floatField->SetFloat<true>(sirt_instance.get(), 1.0);
281 doubleField->SetDouble<true>(sirt_instance.get(), 1.0);
282 objectField->SetObject<true>(sirt_instance.get(), sirt_obj.get());
283 Runtime::Current()->ExitTransactionMode();
284 transaction.Abort();
285
286 // Check values have properly been restored to their original (default) value.
287 EXPECT_EQ(booleanField->GetBoolean(sirt_instance.get()), false);
288 EXPECT_EQ(byteField->GetByte(sirt_instance.get()), 0);
289 EXPECT_EQ(charField->GetChar(sirt_instance.get()), 0u);
290 EXPECT_EQ(shortField->GetShort(sirt_instance.get()), 0);
291 EXPECT_EQ(intField->GetInt(sirt_instance.get()), 0);
292 EXPECT_EQ(longField->GetLong(sirt_instance.get()), static_cast<int64_t>(0));
293 EXPECT_EQ(floatField->GetFloat(sirt_instance.get()), static_cast<float>(0.0f));
294 EXPECT_EQ(doubleField->GetDouble(sirt_instance.get()), static_cast<double>(0.0));
295 EXPECT_EQ(objectField->GetObject(sirt_instance.get()), nullptr);
296}
297
298
299TEST_F(TransactionTest, StaticArrayFieldsTest) {
300 ScopedObjectAccess soa(Thread::Current());
301 SirtRef<mirror::ClassLoader> class_loader(
302 soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction")));
303 ASSERT_TRUE(class_loader.get() != nullptr);
304
305 SirtRef<mirror::Class> sirt_klass(soa.Self(),
Ian Rogers98379392014-02-24 16:53:16 -0800306 class_linker_->FindClass(soa.Self(), "LStaticArrayFieldsTest;",
307 class_loader));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100308 ASSERT_TRUE(sirt_klass.get() != nullptr);
309 class_linker_->EnsureInitialized(sirt_klass, true, true);
310 ASSERT_TRUE(sirt_klass->IsInitialized());
311
312 // Lookup fields.
313 mirror::ArtField* booleanArrayField = sirt_klass->FindDeclaredStaticField("booleanArrayField", "[Z");
314 ASSERT_TRUE(booleanArrayField != nullptr);
315 mirror::BooleanArray* booleanArray = booleanArrayField->GetObject(sirt_klass.get())->AsBooleanArray();
316 ASSERT_TRUE(booleanArray != nullptr);
317 ASSERT_EQ(booleanArray->GetLength(), 1);
318 ASSERT_EQ(booleanArray->GetWithoutChecks(0), false);
319
320 mirror::ArtField* byteArrayField = sirt_klass->FindDeclaredStaticField("byteArrayField", "[B");
321 ASSERT_TRUE(byteArrayField != nullptr);
322 mirror::ByteArray* byteArray = byteArrayField->GetObject(sirt_klass.get())->AsByteArray();
323 ASSERT_TRUE(byteArray != nullptr);
324 ASSERT_EQ(byteArray->GetLength(), 1);
325 ASSERT_EQ(byteArray->GetWithoutChecks(0), 0);
326
327 mirror::ArtField* charArrayField = sirt_klass->FindDeclaredStaticField("charArrayField", "[C");
328 ASSERT_TRUE(charArrayField != nullptr);
329 mirror::CharArray* charArray = charArrayField->GetObject(sirt_klass.get())->AsCharArray();
330 ASSERT_TRUE(charArray != nullptr);
331 ASSERT_EQ(charArray->GetLength(), 1);
332 ASSERT_EQ(charArray->GetWithoutChecks(0), 0u);
333
334 mirror::ArtField* shortArrayField = sirt_klass->FindDeclaredStaticField("shortArrayField", "[S");
335 ASSERT_TRUE(shortArrayField != nullptr);
336 mirror::ShortArray* shortArray = shortArrayField->GetObject(sirt_klass.get())->AsShortArray();
337 ASSERT_TRUE(shortArray != nullptr);
338 ASSERT_EQ(shortArray->GetLength(), 1);
339 ASSERT_EQ(shortArray->GetWithoutChecks(0), 0);
340
341 mirror::ArtField* intArrayField = sirt_klass->FindDeclaredStaticField("intArrayField", "[I");
342 ASSERT_TRUE(intArrayField != nullptr);
343 mirror::IntArray* intArray = intArrayField->GetObject(sirt_klass.get())->AsIntArray();
344 ASSERT_TRUE(intArray != nullptr);
345 ASSERT_EQ(intArray->GetLength(), 1);
346 ASSERT_EQ(intArray->GetWithoutChecks(0), 0);
347
348 mirror::ArtField* longArrayField = sirt_klass->FindDeclaredStaticField("longArrayField", "[J");
349 ASSERT_TRUE(longArrayField != nullptr);
350 mirror::LongArray* longArray = longArrayField->GetObject(sirt_klass.get())->AsLongArray();
351 ASSERT_TRUE(longArray != nullptr);
352 ASSERT_EQ(longArray->GetLength(), 1);
353 ASSERT_EQ(longArray->GetWithoutChecks(0), static_cast<int64_t>(0));
354
355 mirror::ArtField* floatArrayField = sirt_klass->FindDeclaredStaticField("floatArrayField", "[F");
356 ASSERT_TRUE(floatArrayField != nullptr);
357 mirror::FloatArray* floatArray = floatArrayField->GetObject(sirt_klass.get())->AsFloatArray();
358 ASSERT_TRUE(floatArray != nullptr);
359 ASSERT_EQ(floatArray->GetLength(), 1);
360 ASSERT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f));
361
362 mirror::ArtField* doubleArrayField = sirt_klass->FindDeclaredStaticField("doubleArrayField", "[D");
363 ASSERT_TRUE(doubleArrayField != nullptr);
364 mirror::DoubleArray* doubleArray = doubleArrayField->GetObject(sirt_klass.get())->AsDoubleArray();
365 ASSERT_TRUE(doubleArray != nullptr);
366 ASSERT_EQ(doubleArray->GetLength(), 1);
367 ASSERT_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f));
368
Ian Rogers98379392014-02-24 16:53:16 -0800369 mirror::ArtField* objectArrayField = sirt_klass->FindDeclaredStaticField("objectArrayField",
370 "[Ljava/lang/Object;");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100371 ASSERT_TRUE(objectArrayField != nullptr);
Ian Rogers98379392014-02-24 16:53:16 -0800372 mirror::ObjectArray<mirror::Object>* objectArray =
373 objectArrayField->GetObject(sirt_klass.get())->AsObjectArray<mirror::Object>();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100374 ASSERT_TRUE(objectArray != nullptr);
375 ASSERT_EQ(objectArray->GetLength(), 1);
376 ASSERT_EQ(objectArray->GetWithoutChecks(0), nullptr);
377
378 // Create a java.lang.Object instance to set objectField.
Ian Rogers98379392014-02-24 16:53:16 -0800379 SirtRef<mirror::Class> object_klass(soa.Self(),
380 class_linker_->FindSystemClass(soa.Self(),
381 "Ljava/lang/Object;"));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100382 ASSERT_TRUE(object_klass.get() != nullptr);
383 SirtRef<mirror::Object> sirt_obj(soa.Self(), sirt_klass->AllocObject(soa.Self()));
384 ASSERT_TRUE(sirt_obj.get() != nullptr);
385 ASSERT_EQ(sirt_obj->GetClass(), sirt_klass.get());
386
387 // Modify fields inside transaction and abort it.
388 Transaction transaction;
389 Runtime::Current()->EnterTransactionMode(&transaction);
390 booleanArray->SetWithoutChecks<true>(0, true);
391 byteArray->SetWithoutChecks<true>(0, 1);
392 charArray->SetWithoutChecks<true>(0, 1u);
393 shortArray->SetWithoutChecks<true>(0, 1);
394 intArray->SetWithoutChecks<true>(0, 1);
395 longArray->SetWithoutChecks<true>(0, 1);
396 floatArray->SetWithoutChecks<true>(0, 1.0);
397 doubleArray->SetWithoutChecks<true>(0, 1.0);
398 objectArray->SetWithoutChecks<true>(0, sirt_obj.get());
399 Runtime::Current()->ExitTransactionMode();
400 transaction.Abort();
401
402 // Check values have properly been restored to their original (default) value.
403 EXPECT_EQ(booleanArray->GetWithoutChecks(0), false);
404 EXPECT_EQ(byteArray->GetWithoutChecks(0), 0);
405 EXPECT_EQ(charArray->GetWithoutChecks(0), 0u);
406 EXPECT_EQ(shortArray->GetWithoutChecks(0), 0);
407 EXPECT_EQ(intArray->GetWithoutChecks(0), 0);
408 EXPECT_EQ(longArray->GetWithoutChecks(0), static_cast<int64_t>(0));
409 EXPECT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f));
410 EXPECT_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f));
411 EXPECT_EQ(objectArray->GetWithoutChecks(0), nullptr);
412}
413
414TEST_F(TransactionTest, EmptyClass) {
415 ScopedObjectAccess soa(Thread::Current());
416 SirtRef<mirror::ClassLoader> class_loader(
417 soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction")));
418 ASSERT_TRUE(class_loader.get() != nullptr);
419
420 SirtRef<mirror::Class> sirt_klass(soa.Self(),
Ian Rogers98379392014-02-24 16:53:16 -0800421 class_linker_->FindClass(soa.Self(),
422 "LTransaction$EmptyStatic;",
423 class_loader));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100424 ASSERT_TRUE(sirt_klass.get() != nullptr);
425 class_linker_->VerifyClass(sirt_klass);
426 ASSERT_TRUE(sirt_klass->IsVerified());
427
428 Transaction transaction;
429 Runtime::Current()->EnterTransactionMode(&transaction);
430 class_linker_->EnsureInitialized(sirt_klass, true, true);
431 Runtime::Current()->ExitTransactionMode();
432 ASSERT_FALSE(soa.Self()->IsExceptionPending());
433}
434
435TEST_F(TransactionTest, StaticFieldClass) {
436 ScopedObjectAccess soa(Thread::Current());
437 SirtRef<mirror::ClassLoader> class_loader(
438 soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction")));
439 ASSERT_TRUE(class_loader.get() != nullptr);
440
441 SirtRef<mirror::Class> sirt_klass(soa.Self(),
Ian Rogers98379392014-02-24 16:53:16 -0800442 class_linker_->FindClass(soa.Self(),
443 "LTransaction$StaticFieldClass;",
444 class_loader));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100445 ASSERT_TRUE(sirt_klass.get() != nullptr);
446 class_linker_->VerifyClass(sirt_klass);
447 ASSERT_TRUE(sirt_klass->IsVerified());
448
449 Transaction transaction;
450 Runtime::Current()->EnterTransactionMode(&transaction);
451 class_linker_->EnsureInitialized(sirt_klass, true, true);
452 Runtime::Current()->ExitTransactionMode();
453 ASSERT_FALSE(soa.Self()->IsExceptionPending());
454}
455
456TEST_F(TransactionTest, BlacklistedClass) {
457 ScopedObjectAccess soa(Thread::Current());
458 jobject jclass_loader = LoadDex("Transaction");
459 SirtRef<mirror::ClassLoader> class_loader(soa.Self(),
460 soa.Decode<mirror::ClassLoader*>(jclass_loader));
461 ASSERT_TRUE(class_loader.get() != nullptr);
462
463 // Load and verify java.lang.ExceptionInInitializerError and java.lang.InternalError which will
464 // be thrown by class initialization due to native call.
465 SirtRef<mirror::Class> sirt_klass(soa.Self(),
Ian Rogers98379392014-02-24 16:53:16 -0800466 class_linker_->FindSystemClass(soa.Self(),
467 "Ljava/lang/ExceptionInInitializerError;"));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100468 ASSERT_TRUE(sirt_klass.get() != nullptr);
469 class_linker_->VerifyClass(sirt_klass);
470 ASSERT_TRUE(sirt_klass->IsVerified());
Ian Rogers98379392014-02-24 16:53:16 -0800471 sirt_klass.reset(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/InternalError;"));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100472 ASSERT_TRUE(sirt_klass.get() != nullptr);
473 class_linker_->VerifyClass(sirt_klass);
474 ASSERT_TRUE(sirt_klass->IsVerified());
475
476 // Load and verify Transaction$NativeSupport used in class initialization.
Ian Rogers98379392014-02-24 16:53:16 -0800477 sirt_klass.reset(class_linker_->FindClass(soa.Self(), "LTransaction$NativeSupport;",
478 class_loader));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100479 ASSERT_TRUE(sirt_klass.get() != nullptr);
480 class_linker_->VerifyClass(sirt_klass);
481 ASSERT_TRUE(sirt_klass->IsVerified());
482
Ian Rogers98379392014-02-24 16:53:16 -0800483 sirt_klass.reset(class_linker_->FindClass(soa.Self(), "LTransaction$BlacklistedClass;",
484 class_loader));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100485 ASSERT_TRUE(sirt_klass.get() != nullptr);
486 class_linker_->VerifyClass(sirt_klass);
487 ASSERT_TRUE(sirt_klass->IsVerified());
488
489 Transaction transaction;
490 Runtime::Current()->EnterTransactionMode(&transaction);
491 class_linker_->EnsureInitialized(sirt_klass, true, true);
492 Runtime::Current()->ExitTransactionMode();
493 ASSERT_TRUE(soa.Self()->IsExceptionPending());
494}
495
496
497} // namespace art