blob: 3645ed20c919f860df5e5ae2fba5634fca156602 [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());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070030 StackHandleScope<2> hs(soa.Self());
31 Handle<mirror::Class> h_klass(
32 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")));
33 ASSERT_TRUE(h_klass.Get() != nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010034
35 Transaction transaction;
36 Runtime::Current()->EnterTransactionMode(&transaction);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070037 Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self())));
38 ASSERT_TRUE(h_obj.Get() != nullptr);
39 ASSERT_EQ(h_obj->GetClass(), h_klass.Get());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010040 Runtime::Current()->ExitTransactionMode();
41
42 // Aborting transaction must not clear the Object::class field.
43 transaction.Abort();
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070044 EXPECT_EQ(h_obj->GetClass(), h_klass.Get());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010045}
46
47TEST_F(TransactionTest, Object_monitor) {
48 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070049 StackHandleScope<2> hs(soa.Self());
50 Handle<mirror::Class> h_klass(
51 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")));
52 ASSERT_TRUE(h_klass.Get() != nullptr);
53 Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self())));
54 ASSERT_TRUE(h_obj.Get() != nullptr);
55 ASSERT_EQ(h_obj->GetClass(), h_klass.Get());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010056
57 // Lock object's monitor outside the transaction.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070058 h_obj->MonitorEnter(soa.Self());
59 uint32_t old_lock_word = h_obj->GetLockWord(false).GetValue();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010060
61 Transaction transaction;
62 Runtime::Current()->EnterTransactionMode(&transaction);
63 // Unlock object's monitor inside the transaction.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070064 h_obj->MonitorExit(soa.Self());
65 uint32_t new_lock_word = h_obj->GetLockWord(false).GetValue();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010066 Runtime::Current()->ExitTransactionMode();
67
68 // Aborting transaction must not clear the Object::class field.
69 transaction.Abort();
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070070 uint32_t aborted_lock_word = h_obj->GetLockWord(false).GetValue();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010071 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());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070077 StackHandleScope<2> hs(soa.Self());
78 Handle<mirror::Class> h_klass(
79 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;")));
80 ASSERT_TRUE(h_klass.Get() != nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010081
82 constexpr int32_t kArraySize = 2;
83
84 Transaction transaction;
85 Runtime::Current()->EnterTransactionMode(&transaction);
86
87 // Allocate an array during transaction.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070088 Handle<mirror::Array> h_obj(
89 hs.NewHandle(
90 mirror::Array::Alloc<true>(soa.Self(), h_klass.Get(), kArraySize,
91 h_klass->GetComponentSize(),
92 Runtime::Current()->GetHeap()->GetCurrentAllocator())));
93 ASSERT_TRUE(h_obj.Get() != nullptr);
94 ASSERT_EQ(h_obj->GetClass(), h_klass.Get());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010095 Runtime::Current()->ExitTransactionMode();
96
97 // Aborting transaction must not clear the Object::class field.
98 transaction.Abort();
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070099 EXPECT_EQ(h_obj->GetLength(), kArraySize);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100100}
101
102TEST_F(TransactionTest, StaticFieldsTest) {
103 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700104 StackHandleScope<4> hs(soa.Self());
105 Handle<mirror::ClassLoader> class_loader(
106 hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction"))));
107 ASSERT_TRUE(class_loader.Get() != nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100108
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700109 Handle<mirror::Class> h_klass(
110 hs.NewHandle(class_linker_->FindClass(soa.Self(), "LStaticFieldsTest;", class_loader)));
111 ASSERT_TRUE(h_klass.Get() != nullptr);
112 class_linker_->EnsureInitialized(h_klass, true, true);
113 ASSERT_TRUE(h_klass->IsInitialized());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100114
115 // Lookup fields.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700116 mirror::ArtField* booleanField = h_klass->FindDeclaredStaticField("booleanField", "Z");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100117 ASSERT_TRUE(booleanField != nullptr);
118 ASSERT_EQ(FieldHelper(booleanField).GetTypeAsPrimitiveType(), Primitive::kPrimBoolean);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700119 ASSERT_EQ(booleanField->GetBoolean(h_klass.Get()), false);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100120
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700121 mirror::ArtField* byteField = h_klass->FindDeclaredStaticField("byteField", "B");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100122 ASSERT_TRUE(byteField != nullptr);
123 ASSERT_EQ(FieldHelper(byteField).GetTypeAsPrimitiveType(), Primitive::kPrimByte);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700124 ASSERT_EQ(byteField->GetByte(h_klass.Get()), 0);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100125
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700126 mirror::ArtField* charField = h_klass->FindDeclaredStaticField("charField", "C");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100127 ASSERT_TRUE(charField != nullptr);
128 ASSERT_EQ(FieldHelper(charField).GetTypeAsPrimitiveType(), Primitive::kPrimChar);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700129 ASSERT_EQ(charField->GetChar(h_klass.Get()), 0u);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100130
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700131 mirror::ArtField* shortField = h_klass->FindDeclaredStaticField("shortField", "S");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100132 ASSERT_TRUE(shortField != nullptr);
133 ASSERT_EQ(FieldHelper(shortField).GetTypeAsPrimitiveType(), Primitive::kPrimShort);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700134 ASSERT_EQ(shortField->GetShort(h_klass.Get()), 0);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100135
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700136 mirror::ArtField* intField = h_klass->FindDeclaredStaticField("intField", "I");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100137 ASSERT_TRUE(intField != nullptr);
138 ASSERT_EQ(FieldHelper(intField).GetTypeAsPrimitiveType(), Primitive::kPrimInt);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700139 ASSERT_EQ(intField->GetInt(h_klass.Get()), 0);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100140
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700141 mirror::ArtField* longField = h_klass->FindDeclaredStaticField("longField", "J");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100142 ASSERT_TRUE(longField != nullptr);
143 ASSERT_EQ(FieldHelper(longField).GetTypeAsPrimitiveType(), Primitive::kPrimLong);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700144 ASSERT_EQ(longField->GetLong(h_klass.Get()), static_cast<int64_t>(0));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100145
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700146 mirror::ArtField* floatField = h_klass->FindDeclaredStaticField("floatField", "F");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100147 ASSERT_TRUE(floatField != nullptr);
148 ASSERT_EQ(FieldHelper(floatField).GetTypeAsPrimitiveType(), Primitive::kPrimFloat);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700149 ASSERT_EQ(floatField->GetFloat(h_klass.Get()), static_cast<float>(0.0f));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100150
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700151 mirror::ArtField* doubleField = h_klass->FindDeclaredStaticField("doubleField", "D");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100152 ASSERT_TRUE(doubleField != nullptr);
153 ASSERT_EQ(FieldHelper(doubleField).GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700154 ASSERT_EQ(doubleField->GetDouble(h_klass.Get()), static_cast<double>(0.0));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100155
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700156 mirror::ArtField* objectField = h_klass->FindDeclaredStaticField("objectField",
Ian Rogers98379392014-02-24 16:53:16 -0800157 "Ljava/lang/Object;");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100158 ASSERT_TRUE(objectField != nullptr);
159 ASSERT_EQ(FieldHelper(objectField).GetTypeAsPrimitiveType(), Primitive::kPrimNot);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700160 ASSERT_EQ(objectField->GetObject(h_klass.Get()), nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100161
162 // Create a java.lang.Object instance to set objectField.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700163 Handle<mirror::Class> object_klass(
164 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")));
165 ASSERT_TRUE(object_klass.Get() != nullptr);
166 Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self())));
167 ASSERT_TRUE(h_obj.Get() != nullptr);
168 ASSERT_EQ(h_obj->GetClass(), h_klass.Get());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100169
170 // Modify fields inside transaction and abort it.
171 Transaction transaction;
172 Runtime::Current()->EnterTransactionMode(&transaction);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700173 booleanField->SetBoolean<true>(h_klass.Get(), true);
174 byteField->SetByte<true>(h_klass.Get(), 1);
175 charField->SetChar<true>(h_klass.Get(), 1u);
176 shortField->SetShort<true>(h_klass.Get(), 1);
177 intField->SetInt<true>(h_klass.Get(), 1);
178 longField->SetLong<true>(h_klass.Get(), 1);
179 floatField->SetFloat<true>(h_klass.Get(), 1.0);
180 doubleField->SetDouble<true>(h_klass.Get(), 1.0);
181 objectField->SetObject<true>(h_klass.Get(), h_obj.Get());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100182 Runtime::Current()->ExitTransactionMode();
183 transaction.Abort();
184
185 // Check values have properly been restored to their original (default) value.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700186 EXPECT_EQ(booleanField->GetBoolean(h_klass.Get()), false);
187 EXPECT_EQ(byteField->GetByte(h_klass.Get()), 0);
188 EXPECT_EQ(charField->GetChar(h_klass.Get()), 0u);
189 EXPECT_EQ(shortField->GetShort(h_klass.Get()), 0);
190 EXPECT_EQ(intField->GetInt(h_klass.Get()), 0);
191 EXPECT_EQ(longField->GetLong(h_klass.Get()), static_cast<int64_t>(0));
192 EXPECT_EQ(floatField->GetFloat(h_klass.Get()), static_cast<float>(0.0f));
193 EXPECT_EQ(doubleField->GetDouble(h_klass.Get()), static_cast<double>(0.0));
194 EXPECT_EQ(objectField->GetObject(h_klass.Get()), nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100195}
196
197TEST_F(TransactionTest, InstanceFieldsTest) {
198 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700199 StackHandleScope<5> hs(soa.Self());
200 Handle<mirror::ClassLoader> class_loader(
201 hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction"))));
202 ASSERT_TRUE(class_loader.Get() != nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100203
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700204 Handle<mirror::Class> h_klass(
205 hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInstanceFieldsTest;", class_loader)));
206 ASSERT_TRUE(h_klass.Get() != nullptr);
207 class_linker_->EnsureInitialized(h_klass, true, true);
208 ASSERT_TRUE(h_klass->IsInitialized());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100209
210 // Allocate an InstanceFieldTest object.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700211 Handle<mirror::Object> h_instance(hs.NewHandle(h_klass->AllocObject(soa.Self())));
212 ASSERT_TRUE(h_instance.Get() != nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100213
214 // Lookup fields.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700215 mirror::ArtField* booleanField = h_klass->FindDeclaredInstanceField("booleanField", "Z");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100216 ASSERT_TRUE(booleanField != nullptr);
217 ASSERT_EQ(FieldHelper(booleanField).GetTypeAsPrimitiveType(), Primitive::kPrimBoolean);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700218 ASSERT_EQ(booleanField->GetBoolean(h_instance.Get()), false);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100219
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700220 mirror::ArtField* byteField = h_klass->FindDeclaredInstanceField("byteField", "B");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100221 ASSERT_TRUE(byteField != nullptr);
222 ASSERT_EQ(FieldHelper(byteField).GetTypeAsPrimitiveType(), Primitive::kPrimByte);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700223 ASSERT_EQ(byteField->GetByte(h_instance.Get()), 0);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100224
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700225 mirror::ArtField* charField = h_klass->FindDeclaredInstanceField("charField", "C");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100226 ASSERT_TRUE(charField != nullptr);
227 ASSERT_EQ(FieldHelper(charField).GetTypeAsPrimitiveType(), Primitive::kPrimChar);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700228 ASSERT_EQ(charField->GetChar(h_instance.Get()), 0u);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100229
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700230 mirror::ArtField* shortField = h_klass->FindDeclaredInstanceField("shortField", "S");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100231 ASSERT_TRUE(shortField != nullptr);
232 ASSERT_EQ(FieldHelper(shortField).GetTypeAsPrimitiveType(), Primitive::kPrimShort);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700233 ASSERT_EQ(shortField->GetShort(h_instance.Get()), 0);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100234
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700235 mirror::ArtField* intField = h_klass->FindDeclaredInstanceField("intField", "I");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100236 ASSERT_TRUE(intField != nullptr);
237 ASSERT_EQ(FieldHelper(intField).GetTypeAsPrimitiveType(), Primitive::kPrimInt);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700238 ASSERT_EQ(intField->GetInt(h_instance.Get()), 0);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100239
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700240 mirror::ArtField* longField = h_klass->FindDeclaredInstanceField("longField", "J");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100241 ASSERT_TRUE(longField != nullptr);
242 ASSERT_EQ(FieldHelper(longField).GetTypeAsPrimitiveType(), Primitive::kPrimLong);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700243 ASSERT_EQ(longField->GetLong(h_instance.Get()), static_cast<int64_t>(0));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100244
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700245 mirror::ArtField* floatField = h_klass->FindDeclaredInstanceField("floatField", "F");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100246 ASSERT_TRUE(floatField != nullptr);
247 ASSERT_EQ(FieldHelper(floatField).GetTypeAsPrimitiveType(), Primitive::kPrimFloat);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700248 ASSERT_EQ(floatField->GetFloat(h_instance.Get()), static_cast<float>(0.0f));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100249
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700250 mirror::ArtField* doubleField = h_klass->FindDeclaredInstanceField("doubleField", "D");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100251 ASSERT_TRUE(doubleField != nullptr);
252 ASSERT_EQ(FieldHelper(doubleField).GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700253 ASSERT_EQ(doubleField->GetDouble(h_instance.Get()), static_cast<double>(0.0));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100254
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700255 mirror::ArtField* objectField = h_klass->FindDeclaredInstanceField("objectField",
Ian Rogers98379392014-02-24 16:53:16 -0800256 "Ljava/lang/Object;");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100257 ASSERT_TRUE(objectField != nullptr);
258 ASSERT_EQ(FieldHelper(objectField).GetTypeAsPrimitiveType(), Primitive::kPrimNot);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700259 ASSERT_EQ(objectField->GetObject(h_instance.Get()), nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100260
261 // Create a java.lang.Object instance to set objectField.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700262 Handle<mirror::Class> object_klass(
263 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")));
264 ASSERT_TRUE(object_klass.Get() != nullptr);
265 Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self())));
266 ASSERT_TRUE(h_obj.Get() != nullptr);
267 ASSERT_EQ(h_obj->GetClass(), h_klass.Get());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100268
269 // Modify fields inside transaction and abort it.
270 Transaction transaction;
271 Runtime::Current()->EnterTransactionMode(&transaction);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700272 booleanField->SetBoolean<true>(h_instance.Get(), true);
273 byteField->SetByte<true>(h_instance.Get(), 1);
274 charField->SetChar<true>(h_instance.Get(), 1u);
275 shortField->SetShort<true>(h_instance.Get(), 1);
276 intField->SetInt<true>(h_instance.Get(), 1);
277 longField->SetLong<true>(h_instance.Get(), 1);
278 floatField->SetFloat<true>(h_instance.Get(), 1.0);
279 doubleField->SetDouble<true>(h_instance.Get(), 1.0);
280 objectField->SetObject<true>(h_instance.Get(), h_obj.Get());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100281 Runtime::Current()->ExitTransactionMode();
282 transaction.Abort();
283
284 // Check values have properly been restored to their original (default) value.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700285 EXPECT_EQ(booleanField->GetBoolean(h_instance.Get()), false);
286 EXPECT_EQ(byteField->GetByte(h_instance.Get()), 0);
287 EXPECT_EQ(charField->GetChar(h_instance.Get()), 0u);
288 EXPECT_EQ(shortField->GetShort(h_instance.Get()), 0);
289 EXPECT_EQ(intField->GetInt(h_instance.Get()), 0);
290 EXPECT_EQ(longField->GetLong(h_instance.Get()), static_cast<int64_t>(0));
291 EXPECT_EQ(floatField->GetFloat(h_instance.Get()), static_cast<float>(0.0f));
292 EXPECT_EQ(doubleField->GetDouble(h_instance.Get()), static_cast<double>(0.0));
293 EXPECT_EQ(objectField->GetObject(h_instance.Get()), nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100294}
295
296
297TEST_F(TransactionTest, StaticArrayFieldsTest) {
298 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700299 StackHandleScope<4> hs(soa.Self());
300 Handle<mirror::ClassLoader> class_loader(
301 hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction"))));
302 ASSERT_TRUE(class_loader.Get() != nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100303
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700304 Handle<mirror::Class> h_klass(
305 hs.NewHandle(class_linker_->FindClass(soa.Self(), "LStaticArrayFieldsTest;", class_loader)));
306 ASSERT_TRUE(h_klass.Get() != nullptr);
307 class_linker_->EnsureInitialized(h_klass, true, true);
308 ASSERT_TRUE(h_klass->IsInitialized());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100309
310 // Lookup fields.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700311 mirror::ArtField* booleanArrayField = h_klass->FindDeclaredStaticField("booleanArrayField", "[Z");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100312 ASSERT_TRUE(booleanArrayField != nullptr);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700313 mirror::BooleanArray* booleanArray = booleanArrayField->GetObject(h_klass.Get())->AsBooleanArray();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100314 ASSERT_TRUE(booleanArray != nullptr);
315 ASSERT_EQ(booleanArray->GetLength(), 1);
316 ASSERT_EQ(booleanArray->GetWithoutChecks(0), false);
317
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700318 mirror::ArtField* byteArrayField = h_klass->FindDeclaredStaticField("byteArrayField", "[B");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100319 ASSERT_TRUE(byteArrayField != nullptr);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700320 mirror::ByteArray* byteArray = byteArrayField->GetObject(h_klass.Get())->AsByteArray();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100321 ASSERT_TRUE(byteArray != nullptr);
322 ASSERT_EQ(byteArray->GetLength(), 1);
323 ASSERT_EQ(byteArray->GetWithoutChecks(0), 0);
324
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700325 mirror::ArtField* charArrayField = h_klass->FindDeclaredStaticField("charArrayField", "[C");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100326 ASSERT_TRUE(charArrayField != nullptr);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700327 mirror::CharArray* charArray = charArrayField->GetObject(h_klass.Get())->AsCharArray();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100328 ASSERT_TRUE(charArray != nullptr);
329 ASSERT_EQ(charArray->GetLength(), 1);
330 ASSERT_EQ(charArray->GetWithoutChecks(0), 0u);
331
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700332 mirror::ArtField* shortArrayField = h_klass->FindDeclaredStaticField("shortArrayField", "[S");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100333 ASSERT_TRUE(shortArrayField != nullptr);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700334 mirror::ShortArray* shortArray = shortArrayField->GetObject(h_klass.Get())->AsShortArray();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100335 ASSERT_TRUE(shortArray != nullptr);
336 ASSERT_EQ(shortArray->GetLength(), 1);
337 ASSERT_EQ(shortArray->GetWithoutChecks(0), 0);
338
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700339 mirror::ArtField* intArrayField = h_klass->FindDeclaredStaticField("intArrayField", "[I");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100340 ASSERT_TRUE(intArrayField != nullptr);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700341 mirror::IntArray* intArray = intArrayField->GetObject(h_klass.Get())->AsIntArray();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100342 ASSERT_TRUE(intArray != nullptr);
343 ASSERT_EQ(intArray->GetLength(), 1);
344 ASSERT_EQ(intArray->GetWithoutChecks(0), 0);
345
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700346 mirror::ArtField* longArrayField = h_klass->FindDeclaredStaticField("longArrayField", "[J");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100347 ASSERT_TRUE(longArrayField != nullptr);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700348 mirror::LongArray* longArray = longArrayField->GetObject(h_klass.Get())->AsLongArray();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100349 ASSERT_TRUE(longArray != nullptr);
350 ASSERT_EQ(longArray->GetLength(), 1);
351 ASSERT_EQ(longArray->GetWithoutChecks(0), static_cast<int64_t>(0));
352
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700353 mirror::ArtField* floatArrayField = h_klass->FindDeclaredStaticField("floatArrayField", "[F");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100354 ASSERT_TRUE(floatArrayField != nullptr);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700355 mirror::FloatArray* floatArray = floatArrayField->GetObject(h_klass.Get())->AsFloatArray();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100356 ASSERT_TRUE(floatArray != nullptr);
357 ASSERT_EQ(floatArray->GetLength(), 1);
358 ASSERT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f));
359
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700360 mirror::ArtField* doubleArrayField = h_klass->FindDeclaredStaticField("doubleArrayField", "[D");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100361 ASSERT_TRUE(doubleArrayField != nullptr);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700362 mirror::DoubleArray* doubleArray = doubleArrayField->GetObject(h_klass.Get())->AsDoubleArray();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100363 ASSERT_TRUE(doubleArray != nullptr);
364 ASSERT_EQ(doubleArray->GetLength(), 1);
365 ASSERT_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f));
366
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700367 mirror::ArtField* objectArrayField = h_klass->FindDeclaredStaticField("objectArrayField",
Ian Rogers98379392014-02-24 16:53:16 -0800368 "[Ljava/lang/Object;");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100369 ASSERT_TRUE(objectArrayField != nullptr);
Ian Rogers98379392014-02-24 16:53:16 -0800370 mirror::ObjectArray<mirror::Object>* objectArray =
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700371 objectArrayField->GetObject(h_klass.Get())->AsObjectArray<mirror::Object>();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100372 ASSERT_TRUE(objectArray != nullptr);
373 ASSERT_EQ(objectArray->GetLength(), 1);
374 ASSERT_EQ(objectArray->GetWithoutChecks(0), nullptr);
375
376 // Create a java.lang.Object instance to set objectField.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700377 Handle<mirror::Class> object_klass(
378 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")));
379 ASSERT_TRUE(object_klass.Get() != nullptr);
380 Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self())));
381 ASSERT_TRUE(h_obj.Get() != nullptr);
382 ASSERT_EQ(h_obj->GetClass(), h_klass.Get());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100383
384 // Modify fields inside transaction and abort it.
385 Transaction transaction;
386 Runtime::Current()->EnterTransactionMode(&transaction);
387 booleanArray->SetWithoutChecks<true>(0, true);
388 byteArray->SetWithoutChecks<true>(0, 1);
389 charArray->SetWithoutChecks<true>(0, 1u);
390 shortArray->SetWithoutChecks<true>(0, 1);
391 intArray->SetWithoutChecks<true>(0, 1);
392 longArray->SetWithoutChecks<true>(0, 1);
393 floatArray->SetWithoutChecks<true>(0, 1.0);
394 doubleArray->SetWithoutChecks<true>(0, 1.0);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700395 objectArray->SetWithoutChecks<true>(0, h_obj.Get());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100396 Runtime::Current()->ExitTransactionMode();
397 transaction.Abort();
398
399 // Check values have properly been restored to their original (default) value.
400 EXPECT_EQ(booleanArray->GetWithoutChecks(0), false);
401 EXPECT_EQ(byteArray->GetWithoutChecks(0), 0);
402 EXPECT_EQ(charArray->GetWithoutChecks(0), 0u);
403 EXPECT_EQ(shortArray->GetWithoutChecks(0), 0);
404 EXPECT_EQ(intArray->GetWithoutChecks(0), 0);
405 EXPECT_EQ(longArray->GetWithoutChecks(0), static_cast<int64_t>(0));
406 EXPECT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f));
407 EXPECT_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f));
408 EXPECT_EQ(objectArray->GetWithoutChecks(0), nullptr);
409}
410
411TEST_F(TransactionTest, EmptyClass) {
412 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700413 StackHandleScope<2> hs(soa.Self());
414 Handle<mirror::ClassLoader> class_loader(
415 hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction"))));
416 ASSERT_TRUE(class_loader.Get() != nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100417
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700418 Handle<mirror::Class> h_klass(
419 hs.NewHandle(class_linker_->FindClass(soa.Self(), "LTransaction$EmptyStatic;", class_loader)));
420 ASSERT_TRUE(h_klass.Get() != nullptr);
421 class_linker_->VerifyClass(h_klass);
422 ASSERT_TRUE(h_klass->IsVerified());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100423
424 Transaction transaction;
425 Runtime::Current()->EnterTransactionMode(&transaction);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700426 class_linker_->EnsureInitialized(h_klass, true, true);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100427 Runtime::Current()->ExitTransactionMode();
428 ASSERT_FALSE(soa.Self()->IsExceptionPending());
429}
430
431TEST_F(TransactionTest, StaticFieldClass) {
432 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700433 StackHandleScope<2> hs(soa.Self());
434 Handle<mirror::ClassLoader> class_loader(
435 hs.NewHandle(soa.Decode<mirror::ClassLoader*>(LoadDex("Transaction"))));
436 ASSERT_TRUE(class_loader.Get() != nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100437
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700438 Handle<mirror::Class> h_klass(
439 hs.NewHandle(class_linker_->FindClass(soa.Self(), "LTransaction$StaticFieldClass;",
440 class_loader)));
441 ASSERT_TRUE(h_klass.Get() != nullptr);
442 class_linker_->VerifyClass(h_klass);
443 ASSERT_TRUE(h_klass->IsVerified());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100444
445 Transaction transaction;
446 Runtime::Current()->EnterTransactionMode(&transaction);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700447 class_linker_->EnsureInitialized(h_klass, true, true);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100448 Runtime::Current()->ExitTransactionMode();
449 ASSERT_FALSE(soa.Self()->IsExceptionPending());
450}
451
452TEST_F(TransactionTest, BlacklistedClass) {
453 ScopedObjectAccess soa(Thread::Current());
454 jobject jclass_loader = LoadDex("Transaction");
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700455 StackHandleScope<2> hs(soa.Self());
456 Handle<mirror::ClassLoader> class_loader(
457 hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
458 ASSERT_TRUE(class_loader.Get() != nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100459
460 // Load and verify java.lang.ExceptionInInitializerError and java.lang.InternalError which will
461 // be thrown by class initialization due to native call.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700462 Handle<mirror::Class> h_klass(
463 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(),
464 "Ljava/lang/ExceptionInInitializerError;")));
465 ASSERT_TRUE(h_klass.Get() != nullptr);
466 class_linker_->VerifyClass(h_klass);
467 ASSERT_TRUE(h_klass->IsVerified());
468 h_klass.Assign(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/InternalError;"));
469 ASSERT_TRUE(h_klass.Get() != nullptr);
470 class_linker_->VerifyClass(h_klass);
471 ASSERT_TRUE(h_klass->IsVerified());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100472
473 // Load and verify Transaction$NativeSupport used in class initialization.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700474 h_klass.Assign(class_linker_->FindClass(soa.Self(), "LTransaction$NativeSupport;",
475 class_loader));
476 ASSERT_TRUE(h_klass.Get() != nullptr);
477 class_linker_->VerifyClass(h_klass);
478 ASSERT_TRUE(h_klass->IsVerified());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100479
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700480 h_klass.Assign(class_linker_->FindClass(soa.Self(), "LTransaction$BlacklistedClass;",
481 class_loader));
482 ASSERT_TRUE(h_klass.Get() != nullptr);
483 class_linker_->VerifyClass(h_klass);
484 ASSERT_TRUE(h_klass->IsVerified());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100485
486 Transaction transaction;
487 Runtime::Current()->EnterTransactionMode(&transaction);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700488 class_linker_->EnsureInitialized(h_klass, true, true);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100489 Runtime::Current()->ExitTransactionMode();
490 ASSERT_TRUE(soa.Self()->IsExceptionPending());
491}
492
493
494} // namespace art