blob: 1dc2da0c8b2b3b06a3a9ce23c3d21bea3f459124 [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 "mirror/array-inl.h"
21#include "mirror/art_field-inl.h"
22#include "mirror/art_method-inl.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010023
24namespace art {
25
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080026class TransactionTest : public CommonRuntimeTest {};
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010027
28TEST_F(TransactionTest, Object_class) {
29 ScopedObjectAccess soa(Thread::Current());
30 SirtRef<mirror::Class> sirt_klass(soa.Self(),
Ian Rogers98379392014-02-24 16:53:16 -080031 class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;"));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010032 ASSERT_TRUE(sirt_klass.get() != nullptr);
33
34 Transaction transaction;
35 Runtime::Current()->EnterTransactionMode(&transaction);
36 SirtRef<mirror::Object> sirt_obj(soa.Self(), sirt_klass->AllocObject(soa.Self()));
37 ASSERT_TRUE(sirt_obj.get() != nullptr);
38 ASSERT_EQ(sirt_obj->GetClass(), sirt_klass.get());
39 Runtime::Current()->ExitTransactionMode();
40
41 // Aborting transaction must not clear the Object::class field.
42 transaction.Abort();
43 EXPECT_EQ(sirt_obj->GetClass(), sirt_klass.get());
44}
45
46TEST_F(TransactionTest, Object_monitor) {
47 ScopedObjectAccess soa(Thread::Current());
48 SirtRef<mirror::Class> sirt_klass(soa.Self(),
Ian Rogers98379392014-02-24 16:53:16 -080049 class_linker_->FindSystemClass(soa.Self(),
50 "Ljava/lang/Object;"));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010051 ASSERT_TRUE(sirt_klass.get() != nullptr);
52 SirtRef<mirror::Object> sirt_obj(soa.Self(), sirt_klass->AllocObject(soa.Self()));
53 ASSERT_TRUE(sirt_obj.get() != nullptr);
54 ASSERT_EQ(sirt_obj->GetClass(), sirt_klass.get());
55
56 // Lock object's monitor outside the transaction.
57 sirt_obj->MonitorEnter(soa.Self());
Mathieu Chartier4d7f61d2014-04-17 14:43:39 -070058 uint32_t old_lock_word = sirt_obj->GetLockWord(false).GetValue();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010059
60 Transaction transaction;
61 Runtime::Current()->EnterTransactionMode(&transaction);
62 // Unlock object's monitor inside the transaction.
63 sirt_obj->MonitorExit(soa.Self());
Mathieu Chartier4d7f61d2014-04-17 14:43:39 -070064 uint32_t new_lock_word = sirt_obj->GetLockWord(false).GetValue();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010065 Runtime::Current()->ExitTransactionMode();
66
67 // Aborting transaction must not clear the Object::class field.
68 transaction.Abort();
Mathieu Chartier4d7f61d2014-04-17 14:43:39 -070069 uint32_t aborted_lock_word = sirt_obj->GetLockWord(false).GetValue();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010070 EXPECT_NE(old_lock_word, new_lock_word);
71 EXPECT_EQ(aborted_lock_word, new_lock_word);
72}
73
74TEST_F(TransactionTest, Array_length) {
75 ScopedObjectAccess soa(Thread::Current());
76 SirtRef<mirror::Class> sirt_klass(soa.Self(),
Ian Rogers98379392014-02-24 16:53:16 -080077 class_linker_->FindSystemClass(soa.Self(),
78 "[Ljava/lang/Object;"));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010079 ASSERT_TRUE(sirt_klass.get() != nullptr);
80
81 constexpr int32_t kArraySize = 2;
82
83 Transaction transaction;
84 Runtime::Current()->EnterTransactionMode(&transaction);
85
86 // Allocate an array during transaction.
87 SirtRef<mirror::Array> sirt_obj(soa.Self(),
Mathieu Chartier661974a2014-01-09 11:23:53 -080088 mirror::Array::Alloc<true>(soa.Self(), sirt_klass.get(),
89 kArraySize,
90 sirt_klass->GetComponentSize(),
91 Runtime::Current()->GetHeap()->GetCurrentAllocator()));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010092 ASSERT_TRUE(sirt_obj.get() != nullptr);
93 ASSERT_EQ(sirt_obj->GetClass(), sirt_klass.get());
94 Runtime::Current()->ExitTransactionMode();
95
96 // Aborting transaction must not clear the Object::class field.
97 transaction.Abort();
98 EXPECT_EQ(sirt_obj->GetLength(), kArraySize);
99}
100
101TEST_F(TransactionTest, StaticFieldsTest) {
102 ScopedObjectAccess soa(Thread::Current());
103 SirtRef<mirror::ClassLoader> class_loader(
104 soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction")));
105 ASSERT_TRUE(class_loader.get() != nullptr);
106
107 SirtRef<mirror::Class> sirt_klass(soa.Self(),
Ian Rogers98379392014-02-24 16:53:16 -0800108 class_linker_->FindClass(soa.Self(), "LStaticFieldsTest;",
109 class_loader));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100110 ASSERT_TRUE(sirt_klass.get() != nullptr);
111 class_linker_->EnsureInitialized(sirt_klass, true, true);
112 ASSERT_TRUE(sirt_klass->IsInitialized());
113
114 // Lookup fields.
115 mirror::ArtField* booleanField = sirt_klass->FindDeclaredStaticField("booleanField", "Z");
116 ASSERT_TRUE(booleanField != nullptr);
117 ASSERT_EQ(FieldHelper(booleanField).GetTypeAsPrimitiveType(), Primitive::kPrimBoolean);
118 ASSERT_EQ(booleanField->GetBoolean(sirt_klass.get()), false);
119
120 mirror::ArtField* byteField = sirt_klass->FindDeclaredStaticField("byteField", "B");
121 ASSERT_TRUE(byteField != nullptr);
122 ASSERT_EQ(FieldHelper(byteField).GetTypeAsPrimitiveType(), Primitive::kPrimByte);
123 ASSERT_EQ(byteField->GetByte(sirt_klass.get()), 0);
124
125 mirror::ArtField* charField = sirt_klass->FindDeclaredStaticField("charField", "C");
126 ASSERT_TRUE(charField != nullptr);
127 ASSERT_EQ(FieldHelper(charField).GetTypeAsPrimitiveType(), Primitive::kPrimChar);
128 ASSERT_EQ(charField->GetChar(sirt_klass.get()), 0u);
129
130 mirror::ArtField* shortField = sirt_klass->FindDeclaredStaticField("shortField", "S");
131 ASSERT_TRUE(shortField != nullptr);
132 ASSERT_EQ(FieldHelper(shortField).GetTypeAsPrimitiveType(), Primitive::kPrimShort);
133 ASSERT_EQ(shortField->GetShort(sirt_klass.get()), 0);
134
135 mirror::ArtField* intField = sirt_klass->FindDeclaredStaticField("intField", "I");
136 ASSERT_TRUE(intField != nullptr);
137 ASSERT_EQ(FieldHelper(intField).GetTypeAsPrimitiveType(), Primitive::kPrimInt);
138 ASSERT_EQ(intField->GetInt(sirt_klass.get()), 0);
139
140 mirror::ArtField* longField = sirt_klass->FindDeclaredStaticField("longField", "J");
141 ASSERT_TRUE(longField != nullptr);
142 ASSERT_EQ(FieldHelper(longField).GetTypeAsPrimitiveType(), Primitive::kPrimLong);
143 ASSERT_EQ(longField->GetLong(sirt_klass.get()), static_cast<int64_t>(0));
144
145 mirror::ArtField* floatField = sirt_klass->FindDeclaredStaticField("floatField", "F");
146 ASSERT_TRUE(floatField != nullptr);
147 ASSERT_EQ(FieldHelper(floatField).GetTypeAsPrimitiveType(), Primitive::kPrimFloat);
148 ASSERT_EQ(floatField->GetFloat(sirt_klass.get()), static_cast<float>(0.0f));
149
150 mirror::ArtField* doubleField = sirt_klass->FindDeclaredStaticField("doubleField", "D");
151 ASSERT_TRUE(doubleField != nullptr);
152 ASSERT_EQ(FieldHelper(doubleField).GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
153 ASSERT_EQ(doubleField->GetDouble(sirt_klass.get()), static_cast<double>(0.0));
154
Ian Rogers98379392014-02-24 16:53:16 -0800155 mirror::ArtField* objectField = sirt_klass->FindDeclaredStaticField("objectField",
156 "Ljava/lang/Object;");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100157 ASSERT_TRUE(objectField != nullptr);
158 ASSERT_EQ(FieldHelper(objectField).GetTypeAsPrimitiveType(), Primitive::kPrimNot);
159 ASSERT_EQ(objectField->GetObject(sirt_klass.get()), nullptr);
160
161 // Create a java.lang.Object instance to set objectField.
Ian Rogers98379392014-02-24 16:53:16 -0800162 SirtRef<mirror::Class> object_klass(soa.Self(),
163 class_linker_->FindSystemClass(soa.Self(),
164 "Ljava/lang/Object;"));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100165 ASSERT_TRUE(object_klass.get() != nullptr);
166 SirtRef<mirror::Object> sirt_obj(soa.Self(), sirt_klass->AllocObject(soa.Self()));
167 ASSERT_TRUE(sirt_obj.get() != nullptr);
168 ASSERT_EQ(sirt_obj->GetClass(), sirt_klass.get());
169
170 // Modify fields inside transaction and abort it.
171 Transaction transaction;
172 Runtime::Current()->EnterTransactionMode(&transaction);
173 booleanField->SetBoolean<true>(sirt_klass.get(), true);
174 byteField->SetByte<true>(sirt_klass.get(), 1);
175 charField->SetChar<true>(sirt_klass.get(), 1u);
176 shortField->SetShort<true>(sirt_klass.get(), 1);
177 intField->SetInt<true>(sirt_klass.get(), 1);
178 longField->SetLong<true>(sirt_klass.get(), 1);
179 floatField->SetFloat<true>(sirt_klass.get(), 1.0);
180 doubleField->SetDouble<true>(sirt_klass.get(), 1.0);
181 objectField->SetObject<true>(sirt_klass.get(), sirt_obj.get());
182 Runtime::Current()->ExitTransactionMode();
183 transaction.Abort();
184
185 // Check values have properly been restored to their original (default) value.
186 EXPECT_EQ(booleanField->GetBoolean(sirt_klass.get()), false);
187 EXPECT_EQ(byteField->GetByte(sirt_klass.get()), 0);
188 EXPECT_EQ(charField->GetChar(sirt_klass.get()), 0u);
189 EXPECT_EQ(shortField->GetShort(sirt_klass.get()), 0);
190 EXPECT_EQ(intField->GetInt(sirt_klass.get()), 0);
191 EXPECT_EQ(longField->GetLong(sirt_klass.get()), static_cast<int64_t>(0));
192 EXPECT_EQ(floatField->GetFloat(sirt_klass.get()), static_cast<float>(0.0f));
193 EXPECT_EQ(doubleField->GetDouble(sirt_klass.get()), static_cast<double>(0.0));
194 EXPECT_EQ(objectField->GetObject(sirt_klass.get()), nullptr);
195}
196
197TEST_F(TransactionTest, InstanceFieldsTest) {
198 ScopedObjectAccess soa(Thread::Current());
199 SirtRef<mirror::ClassLoader> class_loader(
200 soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction")));
201 ASSERT_TRUE(class_loader.get() != nullptr);
202
203 SirtRef<mirror::Class> sirt_klass(soa.Self(),
Ian Rogers98379392014-02-24 16:53:16 -0800204 class_linker_->FindClass(soa.Self(), "LInstanceFieldsTest;",
205 class_loader));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100206 ASSERT_TRUE(sirt_klass.get() != nullptr);
207 class_linker_->EnsureInitialized(sirt_klass, true, true);
208 ASSERT_TRUE(sirt_klass->IsInitialized());
209
210 // Allocate an InstanceFieldTest object.
211 SirtRef<mirror::Object> sirt_instance(soa.Self(), sirt_klass->AllocObject(soa.Self()));
212 ASSERT_TRUE(sirt_instance.get() != nullptr);
213
214 // Lookup fields.
215 mirror::ArtField* booleanField = sirt_klass->FindDeclaredInstanceField("booleanField", "Z");
216 ASSERT_TRUE(booleanField != nullptr);
217 ASSERT_EQ(FieldHelper(booleanField).GetTypeAsPrimitiveType(), Primitive::kPrimBoolean);
218 ASSERT_EQ(booleanField->GetBoolean(sirt_instance.get()), false);
219
220 mirror::ArtField* byteField = sirt_klass->FindDeclaredInstanceField("byteField", "B");
221 ASSERT_TRUE(byteField != nullptr);
222 ASSERT_EQ(FieldHelper(byteField).GetTypeAsPrimitiveType(), Primitive::kPrimByte);
223 ASSERT_EQ(byteField->GetByte(sirt_instance.get()), 0);
224
225 mirror::ArtField* charField = sirt_klass->FindDeclaredInstanceField("charField", "C");
226 ASSERT_TRUE(charField != nullptr);
227 ASSERT_EQ(FieldHelper(charField).GetTypeAsPrimitiveType(), Primitive::kPrimChar);
228 ASSERT_EQ(charField->GetChar(sirt_instance.get()), 0u);
229
230 mirror::ArtField* shortField = sirt_klass->FindDeclaredInstanceField("shortField", "S");
231 ASSERT_TRUE(shortField != nullptr);
232 ASSERT_EQ(FieldHelper(shortField).GetTypeAsPrimitiveType(), Primitive::kPrimShort);
233 ASSERT_EQ(shortField->GetShort(sirt_instance.get()), 0);
234
235 mirror::ArtField* intField = sirt_klass->FindDeclaredInstanceField("intField", "I");
236 ASSERT_TRUE(intField != nullptr);
237 ASSERT_EQ(FieldHelper(intField).GetTypeAsPrimitiveType(), Primitive::kPrimInt);
238 ASSERT_EQ(intField->GetInt(sirt_instance.get()), 0);
239
240 mirror::ArtField* longField = sirt_klass->FindDeclaredInstanceField("longField", "J");
241 ASSERT_TRUE(longField != nullptr);
242 ASSERT_EQ(FieldHelper(longField).GetTypeAsPrimitiveType(), Primitive::kPrimLong);
243 ASSERT_EQ(longField->GetLong(sirt_instance.get()), static_cast<int64_t>(0));
244
245 mirror::ArtField* floatField = sirt_klass->FindDeclaredInstanceField("floatField", "F");
246 ASSERT_TRUE(floatField != nullptr);
247 ASSERT_EQ(FieldHelper(floatField).GetTypeAsPrimitiveType(), Primitive::kPrimFloat);
248 ASSERT_EQ(floatField->GetFloat(sirt_instance.get()), static_cast<float>(0.0f));
249
250 mirror::ArtField* doubleField = sirt_klass->FindDeclaredInstanceField("doubleField", "D");
251 ASSERT_TRUE(doubleField != nullptr);
252 ASSERT_EQ(FieldHelper(doubleField).GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
253 ASSERT_EQ(doubleField->GetDouble(sirt_instance.get()), static_cast<double>(0.0));
254
Ian Rogers98379392014-02-24 16:53:16 -0800255 mirror::ArtField* objectField = sirt_klass->FindDeclaredInstanceField("objectField",
256 "Ljava/lang/Object;");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100257 ASSERT_TRUE(objectField != nullptr);
258 ASSERT_EQ(FieldHelper(objectField).GetTypeAsPrimitiveType(), Primitive::kPrimNot);
259 ASSERT_EQ(objectField->GetObject(sirt_instance.get()), nullptr);
260
261 // Create a java.lang.Object instance to set objectField.
Ian Rogers98379392014-02-24 16:53:16 -0800262 SirtRef<mirror::Class> object_klass(soa.Self(),
263 class_linker_->FindSystemClass(soa.Self(),
264 "Ljava/lang/Object;"));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100265 ASSERT_TRUE(object_klass.get() != nullptr);
266 SirtRef<mirror::Object> sirt_obj(soa.Self(), sirt_klass->AllocObject(soa.Self()));
267 ASSERT_TRUE(sirt_obj.get() != nullptr);
268 ASSERT_EQ(sirt_obj->GetClass(), sirt_klass.get());
269
270 // Modify fields inside transaction and abort it.
271 Transaction transaction;
272 Runtime::Current()->EnterTransactionMode(&transaction);
273 booleanField->SetBoolean<true>(sirt_instance.get(), true);
274 byteField->SetByte<true>(sirt_instance.get(), 1);
275 charField->SetChar<true>(sirt_instance.get(), 1u);
276 shortField->SetShort<true>(sirt_instance.get(), 1);
277 intField->SetInt<true>(sirt_instance.get(), 1);
278 longField->SetLong<true>(sirt_instance.get(), 1);
279 floatField->SetFloat<true>(sirt_instance.get(), 1.0);
280 doubleField->SetDouble<true>(sirt_instance.get(), 1.0);
281 objectField->SetObject<true>(sirt_instance.get(), sirt_obj.get());
282 Runtime::Current()->ExitTransactionMode();
283 transaction.Abort();
284
285 // Check values have properly been restored to their original (default) value.
286 EXPECT_EQ(booleanField->GetBoolean(sirt_instance.get()), false);
287 EXPECT_EQ(byteField->GetByte(sirt_instance.get()), 0);
288 EXPECT_EQ(charField->GetChar(sirt_instance.get()), 0u);
289 EXPECT_EQ(shortField->GetShort(sirt_instance.get()), 0);
290 EXPECT_EQ(intField->GetInt(sirt_instance.get()), 0);
291 EXPECT_EQ(longField->GetLong(sirt_instance.get()), static_cast<int64_t>(0));
292 EXPECT_EQ(floatField->GetFloat(sirt_instance.get()), static_cast<float>(0.0f));
293 EXPECT_EQ(doubleField->GetDouble(sirt_instance.get()), static_cast<double>(0.0));
294 EXPECT_EQ(objectField->GetObject(sirt_instance.get()), nullptr);
295}
296
297
298TEST_F(TransactionTest, StaticArrayFieldsTest) {
299 ScopedObjectAccess soa(Thread::Current());
300 SirtRef<mirror::ClassLoader> class_loader(
301 soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction")));
302 ASSERT_TRUE(class_loader.get() != nullptr);
303
304 SirtRef<mirror::Class> sirt_klass(soa.Self(),
Ian Rogers98379392014-02-24 16:53:16 -0800305 class_linker_->FindClass(soa.Self(), "LStaticArrayFieldsTest;",
306 class_loader));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100307 ASSERT_TRUE(sirt_klass.get() != nullptr);
308 class_linker_->EnsureInitialized(sirt_klass, true, true);
309 ASSERT_TRUE(sirt_klass->IsInitialized());
310
311 // Lookup fields.
312 mirror::ArtField* booleanArrayField = sirt_klass->FindDeclaredStaticField("booleanArrayField", "[Z");
313 ASSERT_TRUE(booleanArrayField != nullptr);
314 mirror::BooleanArray* booleanArray = booleanArrayField->GetObject(sirt_klass.get())->AsBooleanArray();
315 ASSERT_TRUE(booleanArray != nullptr);
316 ASSERT_EQ(booleanArray->GetLength(), 1);
317 ASSERT_EQ(booleanArray->GetWithoutChecks(0), false);
318
319 mirror::ArtField* byteArrayField = sirt_klass->FindDeclaredStaticField("byteArrayField", "[B");
320 ASSERT_TRUE(byteArrayField != nullptr);
321 mirror::ByteArray* byteArray = byteArrayField->GetObject(sirt_klass.get())->AsByteArray();
322 ASSERT_TRUE(byteArray != nullptr);
323 ASSERT_EQ(byteArray->GetLength(), 1);
324 ASSERT_EQ(byteArray->GetWithoutChecks(0), 0);
325
326 mirror::ArtField* charArrayField = sirt_klass->FindDeclaredStaticField("charArrayField", "[C");
327 ASSERT_TRUE(charArrayField != nullptr);
328 mirror::CharArray* charArray = charArrayField->GetObject(sirt_klass.get())->AsCharArray();
329 ASSERT_TRUE(charArray != nullptr);
330 ASSERT_EQ(charArray->GetLength(), 1);
331 ASSERT_EQ(charArray->GetWithoutChecks(0), 0u);
332
333 mirror::ArtField* shortArrayField = sirt_klass->FindDeclaredStaticField("shortArrayField", "[S");
334 ASSERT_TRUE(shortArrayField != nullptr);
335 mirror::ShortArray* shortArray = shortArrayField->GetObject(sirt_klass.get())->AsShortArray();
336 ASSERT_TRUE(shortArray != nullptr);
337 ASSERT_EQ(shortArray->GetLength(), 1);
338 ASSERT_EQ(shortArray->GetWithoutChecks(0), 0);
339
340 mirror::ArtField* intArrayField = sirt_klass->FindDeclaredStaticField("intArrayField", "[I");
341 ASSERT_TRUE(intArrayField != nullptr);
342 mirror::IntArray* intArray = intArrayField->GetObject(sirt_klass.get())->AsIntArray();
343 ASSERT_TRUE(intArray != nullptr);
344 ASSERT_EQ(intArray->GetLength(), 1);
345 ASSERT_EQ(intArray->GetWithoutChecks(0), 0);
346
347 mirror::ArtField* longArrayField = sirt_klass->FindDeclaredStaticField("longArrayField", "[J");
348 ASSERT_TRUE(longArrayField != nullptr);
349 mirror::LongArray* longArray = longArrayField->GetObject(sirt_klass.get())->AsLongArray();
350 ASSERT_TRUE(longArray != nullptr);
351 ASSERT_EQ(longArray->GetLength(), 1);
352 ASSERT_EQ(longArray->GetWithoutChecks(0), static_cast<int64_t>(0));
353
354 mirror::ArtField* floatArrayField = sirt_klass->FindDeclaredStaticField("floatArrayField", "[F");
355 ASSERT_TRUE(floatArrayField != nullptr);
356 mirror::FloatArray* floatArray = floatArrayField->GetObject(sirt_klass.get())->AsFloatArray();
357 ASSERT_TRUE(floatArray != nullptr);
358 ASSERT_EQ(floatArray->GetLength(), 1);
359 ASSERT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f));
360
361 mirror::ArtField* doubleArrayField = sirt_klass->FindDeclaredStaticField("doubleArrayField", "[D");
362 ASSERT_TRUE(doubleArrayField != nullptr);
363 mirror::DoubleArray* doubleArray = doubleArrayField->GetObject(sirt_klass.get())->AsDoubleArray();
364 ASSERT_TRUE(doubleArray != nullptr);
365 ASSERT_EQ(doubleArray->GetLength(), 1);
366 ASSERT_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f));
367
Ian Rogers98379392014-02-24 16:53:16 -0800368 mirror::ArtField* objectArrayField = sirt_klass->FindDeclaredStaticField("objectArrayField",
369 "[Ljava/lang/Object;");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100370 ASSERT_TRUE(objectArrayField != nullptr);
Ian Rogers98379392014-02-24 16:53:16 -0800371 mirror::ObjectArray<mirror::Object>* objectArray =
372 objectArrayField->GetObject(sirt_klass.get())->AsObjectArray<mirror::Object>();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100373 ASSERT_TRUE(objectArray != nullptr);
374 ASSERT_EQ(objectArray->GetLength(), 1);
375 ASSERT_EQ(objectArray->GetWithoutChecks(0), nullptr);
376
377 // Create a java.lang.Object instance to set objectField.
Ian Rogers98379392014-02-24 16:53:16 -0800378 SirtRef<mirror::Class> object_klass(soa.Self(),
379 class_linker_->FindSystemClass(soa.Self(),
380 "Ljava/lang/Object;"));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100381 ASSERT_TRUE(object_klass.get() != nullptr);
382 SirtRef<mirror::Object> sirt_obj(soa.Self(), sirt_klass->AllocObject(soa.Self()));
383 ASSERT_TRUE(sirt_obj.get() != nullptr);
384 ASSERT_EQ(sirt_obj->GetClass(), sirt_klass.get());
385
386 // Modify fields inside transaction and abort it.
387 Transaction transaction;
388 Runtime::Current()->EnterTransactionMode(&transaction);
389 booleanArray->SetWithoutChecks<true>(0, true);
390 byteArray->SetWithoutChecks<true>(0, 1);
391 charArray->SetWithoutChecks<true>(0, 1u);
392 shortArray->SetWithoutChecks<true>(0, 1);
393 intArray->SetWithoutChecks<true>(0, 1);
394 longArray->SetWithoutChecks<true>(0, 1);
395 floatArray->SetWithoutChecks<true>(0, 1.0);
396 doubleArray->SetWithoutChecks<true>(0, 1.0);
397 objectArray->SetWithoutChecks<true>(0, sirt_obj.get());
398 Runtime::Current()->ExitTransactionMode();
399 transaction.Abort();
400
401 // Check values have properly been restored to their original (default) value.
402 EXPECT_EQ(booleanArray->GetWithoutChecks(0), false);
403 EXPECT_EQ(byteArray->GetWithoutChecks(0), 0);
404 EXPECT_EQ(charArray->GetWithoutChecks(0), 0u);
405 EXPECT_EQ(shortArray->GetWithoutChecks(0), 0);
406 EXPECT_EQ(intArray->GetWithoutChecks(0), 0);
407 EXPECT_EQ(longArray->GetWithoutChecks(0), static_cast<int64_t>(0));
408 EXPECT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f));
409 EXPECT_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f));
410 EXPECT_EQ(objectArray->GetWithoutChecks(0), nullptr);
411}
412
413TEST_F(TransactionTest, EmptyClass) {
414 ScopedObjectAccess soa(Thread::Current());
415 SirtRef<mirror::ClassLoader> class_loader(
416 soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction")));
417 ASSERT_TRUE(class_loader.get() != nullptr);
418
419 SirtRef<mirror::Class> sirt_klass(soa.Self(),
Ian Rogers98379392014-02-24 16:53:16 -0800420 class_linker_->FindClass(soa.Self(),
421 "LTransaction$EmptyStatic;",
422 class_loader));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100423 ASSERT_TRUE(sirt_klass.get() != nullptr);
424 class_linker_->VerifyClass(sirt_klass);
425 ASSERT_TRUE(sirt_klass->IsVerified());
426
427 Transaction transaction;
428 Runtime::Current()->EnterTransactionMode(&transaction);
429 class_linker_->EnsureInitialized(sirt_klass, true, true);
430 Runtime::Current()->ExitTransactionMode();
431 ASSERT_FALSE(soa.Self()->IsExceptionPending());
432}
433
434TEST_F(TransactionTest, StaticFieldClass) {
435 ScopedObjectAccess soa(Thread::Current());
436 SirtRef<mirror::ClassLoader> class_loader(
437 soa.Self(), soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction")));
438 ASSERT_TRUE(class_loader.get() != nullptr);
439
440 SirtRef<mirror::Class> sirt_klass(soa.Self(),
Ian Rogers98379392014-02-24 16:53:16 -0800441 class_linker_->FindClass(soa.Self(),
442 "LTransaction$StaticFieldClass;",
443 class_loader));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100444 ASSERT_TRUE(sirt_klass.get() != nullptr);
445 class_linker_->VerifyClass(sirt_klass);
446 ASSERT_TRUE(sirt_klass->IsVerified());
447
448 Transaction transaction;
449 Runtime::Current()->EnterTransactionMode(&transaction);
450 class_linker_->EnsureInitialized(sirt_klass, true, true);
451 Runtime::Current()->ExitTransactionMode();
452 ASSERT_FALSE(soa.Self()->IsExceptionPending());
453}
454
455TEST_F(TransactionTest, BlacklistedClass) {
456 ScopedObjectAccess soa(Thread::Current());
457 jobject jclass_loader = LoadDex("Transaction");
458 SirtRef<mirror::ClassLoader> class_loader(soa.Self(),
459 soa.Decode<mirror::ClassLoader*>(jclass_loader));
460 ASSERT_TRUE(class_loader.get() != nullptr);
461
462 // Load and verify java.lang.ExceptionInInitializerError and java.lang.InternalError which will
463 // be thrown by class initialization due to native call.
464 SirtRef<mirror::Class> sirt_klass(soa.Self(),
Ian Rogers98379392014-02-24 16:53:16 -0800465 class_linker_->FindSystemClass(soa.Self(),
466 "Ljava/lang/ExceptionInInitializerError;"));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100467 ASSERT_TRUE(sirt_klass.get() != nullptr);
468 class_linker_->VerifyClass(sirt_klass);
469 ASSERT_TRUE(sirt_klass->IsVerified());
Ian Rogers98379392014-02-24 16:53:16 -0800470 sirt_klass.reset(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/InternalError;"));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100471 ASSERT_TRUE(sirt_klass.get() != nullptr);
472 class_linker_->VerifyClass(sirt_klass);
473 ASSERT_TRUE(sirt_klass->IsVerified());
474
475 // Load and verify Transaction$NativeSupport used in class initialization.
Ian Rogers98379392014-02-24 16:53:16 -0800476 sirt_klass.reset(class_linker_->FindClass(soa.Self(), "LTransaction$NativeSupport;",
477 class_loader));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100478 ASSERT_TRUE(sirt_klass.get() != nullptr);
479 class_linker_->VerifyClass(sirt_klass);
480 ASSERT_TRUE(sirt_klass->IsVerified());
481
Ian Rogers98379392014-02-24 16:53:16 -0800482 sirt_klass.reset(class_linker_->FindClass(soa.Self(), "LTransaction$BlacklistedClass;",
483 class_loader));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100484 ASSERT_TRUE(sirt_klass.get() != nullptr);
485 class_linker_->VerifyClass(sirt_klass);
486 ASSERT_TRUE(sirt_klass->IsVerified());
487
488 Transaction transaction;
489 Runtime::Current()->EnterTransactionMode(&transaction);
490 class_linker_->EnsureInitialized(sirt_klass, true, true);
491 Runtime::Current()->ExitTransactionMode();
492 ASSERT_TRUE(soa.Self()->IsExceptionPending());
493}
494
495
496} // namespace art