blob: 77c2b76bbbd586094e845dbb4642e5d96e0c94d2 [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
Mathieu Chartierc7853442015-03-27 14:35:38 -070019#include "art_field-inl.h"
Mathieu Chartiere401d142015-04-22 13:56:20 -070020#include "art_method-inl.h"
Vladimir Marko3481ba22015-04-13 12:22:36 +010021#include "class_linker-inl.h"
Brian Carlstroma1ce1fe2014-02-24 23:23:58 -080022#include "common_runtime_test.h"
Mathieu Chartierbb816d62016-09-07 10:17:46 -070023#include "dex_file.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010024#include "mirror/array-inl.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070025#include "scoped_thread_state_change-inl.h"
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010026
27namespace art {
28
Mathieu Chartierbb816d62016-09-07 10:17:46 -070029static const size_t kDexNoIndex = DexFile::kDexNoIndex; // Make copy to prevent linking errors.
30
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010031class TransactionTest : public CommonRuntimeTest {
32 public:
33 // Tests failing class initialization due to native call with transaction rollback.
34 void testTransactionAbort(const char* tested_class_signature) {
35 ScopedObjectAccess soa(Thread::Current());
36 jobject jclass_loader = LoadDex("Transaction");
37 StackHandleScope<2> hs(soa.Self());
38 Handle<mirror::ClassLoader> class_loader(
Mathieu Chartier0795f232016-09-27 18:43:30 -070039 hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010040 ASSERT_TRUE(class_loader.Get() != nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010041
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020042 // Load and initialize java.lang.ExceptionInInitializerError and the exception class used
43 // to abort transaction so they can be thrown during class initialization if the transaction
44 // aborts.
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010045 MutableHandle<mirror::Class> h_klass(
46 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(),
47 "Ljava/lang/ExceptionInInitializerError;")));
48 ASSERT_TRUE(h_klass.Get() != nullptr);
49 class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
50 ASSERT_TRUE(h_klass->IsInitialized());
51
Sebastien Hertz2fd7e692015-04-02 11:11:19 +020052 h_klass.Assign(class_linker_->FindSystemClass(soa.Self(),
53 Transaction::kAbortExceptionSignature));
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010054 ASSERT_TRUE(h_klass.Get() != nullptr);
55 class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
56 ASSERT_TRUE(h_klass->IsInitialized());
57
58 // Load and verify utility class.
59 h_klass.Assign(class_linker_->FindClass(soa.Self(), "LTransaction$AbortHelperClass;",
60 class_loader));
61 ASSERT_TRUE(h_klass.Get() != nullptr);
62 class_linker_->VerifyClass(soa.Self(), h_klass);
63 ASSERT_TRUE(h_klass->IsVerified());
64
65 // Load and verify tested class.
66 h_klass.Assign(class_linker_->FindClass(soa.Self(), tested_class_signature, class_loader));
67 ASSERT_TRUE(h_klass.Get() != nullptr);
68 class_linker_->VerifyClass(soa.Self(), h_klass);
69 ASSERT_TRUE(h_klass->IsVerified());
70
71 mirror::Class::Status old_status = h_klass->GetStatus();
Hiroshi Yamauchie15ea082015-02-09 17:11:42 -080072 LockWord old_lock_word = h_klass->GetLockWord(false);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010073
74 Transaction transaction;
75 Runtime::Current()->EnterTransactionMode(&transaction);
76 bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
77 Runtime::Current()->ExitTransactionMode();
78 ASSERT_FALSE(success);
79 ASSERT_TRUE(h_klass->IsErroneous());
80 ASSERT_TRUE(soa.Self()->IsExceptionPending());
81 ASSERT_TRUE(transaction.IsAborted());
82
83 // Check class's monitor get back to its original state without rolling back changes.
Hiroshi Yamauchie15ea082015-02-09 17:11:42 -080084 LockWord new_lock_word = h_klass->GetLockWord(false);
85 EXPECT_TRUE(LockWord::Equal<false>(old_lock_word, new_lock_word));
Sebastien Hertz1c80bec2015-02-03 11:58:06 +010086
87 // Check class status is rolled back properly.
88 soa.Self()->ClearException();
89 transaction.Rollback();
90 ASSERT_EQ(old_status, h_klass->GetStatus());
91 }
92};
93
94// Tests object's class is preserved after transaction rollback.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +010095TEST_F(TransactionTest, Object_class) {
96 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070097 StackHandleScope<2> hs(soa.Self());
98 Handle<mirror::Class> h_klass(
99 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")));
100 ASSERT_TRUE(h_klass.Get() != nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100101
102 Transaction transaction;
103 Runtime::Current()->EnterTransactionMode(&transaction);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700104 Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self())));
105 ASSERT_TRUE(h_obj.Get() != nullptr);
106 ASSERT_EQ(h_obj->GetClass(), h_klass.Get());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100107 Runtime::Current()->ExitTransactionMode();
108
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100109 // Rolling back transaction's changes must not clear the Object::class field.
110 transaction.Rollback();
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700111 EXPECT_EQ(h_obj->GetClass(), h_klass.Get());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100112}
113
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100114// Tests object's monitor state is preserved after transaction rollback.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100115TEST_F(TransactionTest, Object_monitor) {
116 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700117 StackHandleScope<2> hs(soa.Self());
118 Handle<mirror::Class> h_klass(
119 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")));
120 ASSERT_TRUE(h_klass.Get() != nullptr);
121 Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self())));
122 ASSERT_TRUE(h_obj.Get() != nullptr);
123 ASSERT_EQ(h_obj->GetClass(), h_klass.Get());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100124
125 // Lock object's monitor outside the transaction.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700126 h_obj->MonitorEnter(soa.Self());
Hiroshi Yamauchie15ea082015-02-09 17:11:42 -0800127 LockWord old_lock_word = h_obj->GetLockWord(false);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100128
129 Transaction transaction;
130 Runtime::Current()->EnterTransactionMode(&transaction);
131 // Unlock object's monitor inside the transaction.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700132 h_obj->MonitorExit(soa.Self());
Hiroshi Yamauchie15ea082015-02-09 17:11:42 -0800133 LockWord new_lock_word = h_obj->GetLockWord(false);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100134 Runtime::Current()->ExitTransactionMode();
135
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100136 // Rolling back transaction's changes must not change monitor's state.
137 transaction.Rollback();
Hiroshi Yamauchie15ea082015-02-09 17:11:42 -0800138 LockWord aborted_lock_word = h_obj->GetLockWord(false);
139 EXPECT_FALSE(LockWord::Equal<false>(old_lock_word, new_lock_word));
140 EXPECT_TRUE(LockWord::Equal<false>(aborted_lock_word, new_lock_word));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100141}
142
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100143// Tests array's length is preserved after transaction rollback.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100144TEST_F(TransactionTest, Array_length) {
145 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700146 StackHandleScope<2> hs(soa.Self());
147 Handle<mirror::Class> h_klass(
148 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;")));
149 ASSERT_TRUE(h_klass.Get() != nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100150
151 constexpr int32_t kArraySize = 2;
152
153 Transaction transaction;
154 Runtime::Current()->EnterTransactionMode(&transaction);
155
156 // Allocate an array during transaction.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700157 Handle<mirror::Array> h_obj(
158 hs.NewHandle(
159 mirror::Array::Alloc<true>(soa.Self(), h_klass.Get(), kArraySize,
Hiroshi Yamauchif0edfc32014-09-25 11:46:46 -0700160 h_klass->GetComponentSizeShift(),
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700161 Runtime::Current()->GetHeap()->GetCurrentAllocator())));
162 ASSERT_TRUE(h_obj.Get() != nullptr);
163 ASSERT_EQ(h_obj->GetClass(), h_klass.Get());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100164 Runtime::Current()->ExitTransactionMode();
165
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100166 // Rolling back transaction's changes must not reset array's length.
167 transaction.Rollback();
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700168 EXPECT_EQ(h_obj->GetLength(), kArraySize);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100169}
170
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100171// Tests static fields are reset to their default value after transaction rollback.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100172TEST_F(TransactionTest, StaticFieldsTest) {
173 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700174 StackHandleScope<4> hs(soa.Self());
175 Handle<mirror::ClassLoader> class_loader(
Mathieu Chartier0795f232016-09-27 18:43:30 -0700176 hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700177 ASSERT_TRUE(class_loader.Get() != nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100178
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700179 Handle<mirror::Class> h_klass(
180 hs.NewHandle(class_linker_->FindClass(soa.Self(), "LStaticFieldsTest;", class_loader)));
181 ASSERT_TRUE(h_klass.Get() != nullptr);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100182 bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
183 ASSERT_TRUE(success);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700184 ASSERT_TRUE(h_klass->IsInitialized());
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100185 ASSERT_FALSE(soa.Self()->IsExceptionPending());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100186
187 // Lookup fields.
Mathieu Chartierc7853442015-03-27 14:35:38 -0700188 ArtField* booleanField = h_klass->FindDeclaredStaticField("booleanField", "Z");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100189 ASSERT_TRUE(booleanField != nullptr);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700190 ASSERT_EQ(booleanField->GetTypeAsPrimitiveType(), Primitive::kPrimBoolean);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700191 ASSERT_EQ(booleanField->GetBoolean(h_klass.Get()), false);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100192
Mathieu Chartierc7853442015-03-27 14:35:38 -0700193 ArtField* byteField = h_klass->FindDeclaredStaticField("byteField", "B");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100194 ASSERT_TRUE(byteField != nullptr);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700195 ASSERT_EQ(byteField->GetTypeAsPrimitiveType(), Primitive::kPrimByte);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700196 ASSERT_EQ(byteField->GetByte(h_klass.Get()), 0);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100197
Mathieu Chartierc7853442015-03-27 14:35:38 -0700198 ArtField* charField = h_klass->FindDeclaredStaticField("charField", "C");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100199 ASSERT_TRUE(charField != nullptr);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700200 ASSERT_EQ(charField->GetTypeAsPrimitiveType(), Primitive::kPrimChar);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700201 ASSERT_EQ(charField->GetChar(h_klass.Get()), 0u);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100202
Mathieu Chartierc7853442015-03-27 14:35:38 -0700203 ArtField* shortField = h_klass->FindDeclaredStaticField("shortField", "S");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100204 ASSERT_TRUE(shortField != nullptr);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700205 ASSERT_EQ(shortField->GetTypeAsPrimitiveType(), Primitive::kPrimShort);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700206 ASSERT_EQ(shortField->GetShort(h_klass.Get()), 0);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100207
Mathieu Chartierc7853442015-03-27 14:35:38 -0700208 ArtField* intField = h_klass->FindDeclaredStaticField("intField", "I");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100209 ASSERT_TRUE(intField != nullptr);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700210 ASSERT_EQ(intField->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700211 ASSERT_EQ(intField->GetInt(h_klass.Get()), 0);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100212
Mathieu Chartierc7853442015-03-27 14:35:38 -0700213 ArtField* longField = h_klass->FindDeclaredStaticField("longField", "J");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100214 ASSERT_TRUE(longField != nullptr);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700215 ASSERT_EQ(longField->GetTypeAsPrimitiveType(), Primitive::kPrimLong);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700216 ASSERT_EQ(longField->GetLong(h_klass.Get()), static_cast<int64_t>(0));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100217
Mathieu Chartierc7853442015-03-27 14:35:38 -0700218 ArtField* floatField = h_klass->FindDeclaredStaticField("floatField", "F");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100219 ASSERT_TRUE(floatField != nullptr);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700220 ASSERT_EQ(floatField->GetTypeAsPrimitiveType(), Primitive::kPrimFloat);
Ian Rogers647b1a82014-10-10 11:02:11 -0700221 ASSERT_FLOAT_EQ(floatField->GetFloat(h_klass.Get()), static_cast<float>(0.0f));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100222
Mathieu Chartierc7853442015-03-27 14:35:38 -0700223 ArtField* doubleField = h_klass->FindDeclaredStaticField("doubleField", "D");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100224 ASSERT_TRUE(doubleField != nullptr);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700225 ASSERT_EQ(doubleField->GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
Ian Rogers647b1a82014-10-10 11:02:11 -0700226 ASSERT_DOUBLE_EQ(doubleField->GetDouble(h_klass.Get()), static_cast<double>(0.0));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100227
Mathieu Chartierc7853442015-03-27 14:35:38 -0700228 ArtField* objectField = h_klass->FindDeclaredStaticField("objectField",
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100229 "Ljava/lang/Object;");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100230 ASSERT_TRUE(objectField != nullptr);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700231 ASSERT_EQ(objectField->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700232 ASSERT_EQ(objectField->GetObject(h_klass.Get()), nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100233
234 // Create a java.lang.Object instance to set objectField.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700235 Handle<mirror::Class> object_klass(
236 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")));
237 ASSERT_TRUE(object_klass.Get() != nullptr);
238 Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self())));
239 ASSERT_TRUE(h_obj.Get() != nullptr);
240 ASSERT_EQ(h_obj->GetClass(), h_klass.Get());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100241
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100242 // Modify fields inside transaction then rollback changes.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100243 Transaction transaction;
244 Runtime::Current()->EnterTransactionMode(&transaction);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700245 booleanField->SetBoolean<true>(h_klass.Get(), true);
246 byteField->SetByte<true>(h_klass.Get(), 1);
247 charField->SetChar<true>(h_klass.Get(), 1u);
248 shortField->SetShort<true>(h_klass.Get(), 1);
249 intField->SetInt<true>(h_klass.Get(), 1);
250 longField->SetLong<true>(h_klass.Get(), 1);
251 floatField->SetFloat<true>(h_klass.Get(), 1.0);
252 doubleField->SetDouble<true>(h_klass.Get(), 1.0);
253 objectField->SetObject<true>(h_klass.Get(), h_obj.Get());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100254 Runtime::Current()->ExitTransactionMode();
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100255 transaction.Rollback();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100256
257 // Check values have properly been restored to their original (default) value.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700258 EXPECT_EQ(booleanField->GetBoolean(h_klass.Get()), false);
259 EXPECT_EQ(byteField->GetByte(h_klass.Get()), 0);
260 EXPECT_EQ(charField->GetChar(h_klass.Get()), 0u);
261 EXPECT_EQ(shortField->GetShort(h_klass.Get()), 0);
262 EXPECT_EQ(intField->GetInt(h_klass.Get()), 0);
263 EXPECT_EQ(longField->GetLong(h_klass.Get()), static_cast<int64_t>(0));
Ian Rogers647b1a82014-10-10 11:02:11 -0700264 EXPECT_FLOAT_EQ(floatField->GetFloat(h_klass.Get()), static_cast<float>(0.0f));
265 EXPECT_DOUBLE_EQ(doubleField->GetDouble(h_klass.Get()), static_cast<double>(0.0));
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700266 EXPECT_EQ(objectField->GetObject(h_klass.Get()), nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100267}
268
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100269// Tests instance fields are reset to their default value after transaction rollback.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100270TEST_F(TransactionTest, InstanceFieldsTest) {
271 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700272 StackHandleScope<5> hs(soa.Self());
273 Handle<mirror::ClassLoader> class_loader(
Mathieu Chartier0795f232016-09-27 18:43:30 -0700274 hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700275 ASSERT_TRUE(class_loader.Get() != nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100276
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700277 Handle<mirror::Class> h_klass(
278 hs.NewHandle(class_linker_->FindClass(soa.Self(), "LInstanceFieldsTest;", class_loader)));
279 ASSERT_TRUE(h_klass.Get() != nullptr);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100280 bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
281 ASSERT_TRUE(success);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700282 ASSERT_TRUE(h_klass->IsInitialized());
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100283 ASSERT_FALSE(soa.Self()->IsExceptionPending());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100284
285 // Allocate an InstanceFieldTest object.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700286 Handle<mirror::Object> h_instance(hs.NewHandle(h_klass->AllocObject(soa.Self())));
287 ASSERT_TRUE(h_instance.Get() != nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100288
289 // Lookup fields.
Mathieu Chartierc7853442015-03-27 14:35:38 -0700290 ArtField* booleanField = h_klass->FindDeclaredInstanceField("booleanField", "Z");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100291 ASSERT_TRUE(booleanField != nullptr);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700292 ASSERT_EQ(booleanField->GetTypeAsPrimitiveType(), Primitive::kPrimBoolean);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700293 ASSERT_EQ(booleanField->GetBoolean(h_instance.Get()), false);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100294
Mathieu Chartierc7853442015-03-27 14:35:38 -0700295 ArtField* byteField = h_klass->FindDeclaredInstanceField("byteField", "B");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100296 ASSERT_TRUE(byteField != nullptr);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700297 ASSERT_EQ(byteField->GetTypeAsPrimitiveType(), Primitive::kPrimByte);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700298 ASSERT_EQ(byteField->GetByte(h_instance.Get()), 0);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100299
Mathieu Chartierc7853442015-03-27 14:35:38 -0700300 ArtField* charField = h_klass->FindDeclaredInstanceField("charField", "C");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100301 ASSERT_TRUE(charField != nullptr);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700302 ASSERT_EQ(charField->GetTypeAsPrimitiveType(), Primitive::kPrimChar);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700303 ASSERT_EQ(charField->GetChar(h_instance.Get()), 0u);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100304
Mathieu Chartierc7853442015-03-27 14:35:38 -0700305 ArtField* shortField = h_klass->FindDeclaredInstanceField("shortField", "S");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100306 ASSERT_TRUE(shortField != nullptr);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700307 ASSERT_EQ(shortField->GetTypeAsPrimitiveType(), Primitive::kPrimShort);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700308 ASSERT_EQ(shortField->GetShort(h_instance.Get()), 0);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100309
Mathieu Chartierc7853442015-03-27 14:35:38 -0700310 ArtField* intField = h_klass->FindDeclaredInstanceField("intField", "I");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100311 ASSERT_TRUE(intField != nullptr);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700312 ASSERT_EQ(intField->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700313 ASSERT_EQ(intField->GetInt(h_instance.Get()), 0);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100314
Mathieu Chartierc7853442015-03-27 14:35:38 -0700315 ArtField* longField = h_klass->FindDeclaredInstanceField("longField", "J");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100316 ASSERT_TRUE(longField != nullptr);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700317 ASSERT_EQ(longField->GetTypeAsPrimitiveType(), Primitive::kPrimLong);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700318 ASSERT_EQ(longField->GetLong(h_instance.Get()), static_cast<int64_t>(0));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100319
Mathieu Chartierc7853442015-03-27 14:35:38 -0700320 ArtField* floatField = h_klass->FindDeclaredInstanceField("floatField", "F");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100321 ASSERT_TRUE(floatField != nullptr);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700322 ASSERT_EQ(floatField->GetTypeAsPrimitiveType(), Primitive::kPrimFloat);
Ian Rogers647b1a82014-10-10 11:02:11 -0700323 ASSERT_FLOAT_EQ(floatField->GetFloat(h_instance.Get()), static_cast<float>(0.0f));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100324
Mathieu Chartierc7853442015-03-27 14:35:38 -0700325 ArtField* doubleField = h_klass->FindDeclaredInstanceField("doubleField", "D");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100326 ASSERT_TRUE(doubleField != nullptr);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700327 ASSERT_EQ(doubleField->GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
Ian Rogers647b1a82014-10-10 11:02:11 -0700328 ASSERT_DOUBLE_EQ(doubleField->GetDouble(h_instance.Get()), static_cast<double>(0.0));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100329
Mathieu Chartierc7853442015-03-27 14:35:38 -0700330 ArtField* objectField = h_klass->FindDeclaredInstanceField("objectField",
Ian Rogers98379392014-02-24 16:53:16 -0800331 "Ljava/lang/Object;");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100332 ASSERT_TRUE(objectField != nullptr);
Mathieu Chartier61c5ebc2014-06-05 17:42:53 -0700333 ASSERT_EQ(objectField->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700334 ASSERT_EQ(objectField->GetObject(h_instance.Get()), nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100335
336 // Create a java.lang.Object instance to set objectField.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700337 Handle<mirror::Class> object_klass(
338 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")));
339 ASSERT_TRUE(object_klass.Get() != nullptr);
340 Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self())));
341 ASSERT_TRUE(h_obj.Get() != nullptr);
342 ASSERT_EQ(h_obj->GetClass(), h_klass.Get());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100343
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100344 // Modify fields inside transaction then rollback changes.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100345 Transaction transaction;
346 Runtime::Current()->EnterTransactionMode(&transaction);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700347 booleanField->SetBoolean<true>(h_instance.Get(), true);
348 byteField->SetByte<true>(h_instance.Get(), 1);
349 charField->SetChar<true>(h_instance.Get(), 1u);
350 shortField->SetShort<true>(h_instance.Get(), 1);
351 intField->SetInt<true>(h_instance.Get(), 1);
352 longField->SetLong<true>(h_instance.Get(), 1);
353 floatField->SetFloat<true>(h_instance.Get(), 1.0);
354 doubleField->SetDouble<true>(h_instance.Get(), 1.0);
355 objectField->SetObject<true>(h_instance.Get(), h_obj.Get());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100356 Runtime::Current()->ExitTransactionMode();
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100357 transaction.Rollback();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100358
359 // Check values have properly been restored to their original (default) value.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700360 EXPECT_EQ(booleanField->GetBoolean(h_instance.Get()), false);
361 EXPECT_EQ(byteField->GetByte(h_instance.Get()), 0);
362 EXPECT_EQ(charField->GetChar(h_instance.Get()), 0u);
363 EXPECT_EQ(shortField->GetShort(h_instance.Get()), 0);
364 EXPECT_EQ(intField->GetInt(h_instance.Get()), 0);
365 EXPECT_EQ(longField->GetLong(h_instance.Get()), static_cast<int64_t>(0));
Ian Rogers647b1a82014-10-10 11:02:11 -0700366 EXPECT_FLOAT_EQ(floatField->GetFloat(h_instance.Get()), static_cast<float>(0.0f));
367 EXPECT_DOUBLE_EQ(doubleField->GetDouble(h_instance.Get()), static_cast<double>(0.0));
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700368 EXPECT_EQ(objectField->GetObject(h_instance.Get()), nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100369}
370
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100371// Tests static array fields are reset to their default value after transaction rollback.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100372TEST_F(TransactionTest, StaticArrayFieldsTest) {
373 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700374 StackHandleScope<4> hs(soa.Self());
375 Handle<mirror::ClassLoader> class_loader(
Mathieu Chartier0795f232016-09-27 18:43:30 -0700376 hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700377 ASSERT_TRUE(class_loader.Get() != nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100378
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700379 Handle<mirror::Class> h_klass(
380 hs.NewHandle(class_linker_->FindClass(soa.Self(), "LStaticArrayFieldsTest;", class_loader)));
381 ASSERT_TRUE(h_klass.Get() != nullptr);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100382 bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
383 ASSERT_TRUE(success);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700384 ASSERT_TRUE(h_klass->IsInitialized());
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100385 ASSERT_FALSE(soa.Self()->IsExceptionPending());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100386
387 // Lookup fields.
Mathieu Chartierc7853442015-03-27 14:35:38 -0700388 ArtField* booleanArrayField = h_klass->FindDeclaredStaticField("booleanArrayField", "[Z");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100389 ASSERT_TRUE(booleanArrayField != nullptr);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700390 mirror::BooleanArray* booleanArray = booleanArrayField->GetObject(h_klass.Get())->AsBooleanArray();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100391 ASSERT_TRUE(booleanArray != nullptr);
392 ASSERT_EQ(booleanArray->GetLength(), 1);
393 ASSERT_EQ(booleanArray->GetWithoutChecks(0), false);
394
Mathieu Chartierc7853442015-03-27 14:35:38 -0700395 ArtField* byteArrayField = h_klass->FindDeclaredStaticField("byteArrayField", "[B");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100396 ASSERT_TRUE(byteArrayField != nullptr);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700397 mirror::ByteArray* byteArray = byteArrayField->GetObject(h_klass.Get())->AsByteArray();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100398 ASSERT_TRUE(byteArray != nullptr);
399 ASSERT_EQ(byteArray->GetLength(), 1);
400 ASSERT_EQ(byteArray->GetWithoutChecks(0), 0);
401
Mathieu Chartierc7853442015-03-27 14:35:38 -0700402 ArtField* charArrayField = h_klass->FindDeclaredStaticField("charArrayField", "[C");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100403 ASSERT_TRUE(charArrayField != nullptr);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700404 mirror::CharArray* charArray = charArrayField->GetObject(h_klass.Get())->AsCharArray();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100405 ASSERT_TRUE(charArray != nullptr);
406 ASSERT_EQ(charArray->GetLength(), 1);
407 ASSERT_EQ(charArray->GetWithoutChecks(0), 0u);
408
Mathieu Chartierc7853442015-03-27 14:35:38 -0700409 ArtField* shortArrayField = h_klass->FindDeclaredStaticField("shortArrayField", "[S");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100410 ASSERT_TRUE(shortArrayField != nullptr);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700411 mirror::ShortArray* shortArray = shortArrayField->GetObject(h_klass.Get())->AsShortArray();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100412 ASSERT_TRUE(shortArray != nullptr);
413 ASSERT_EQ(shortArray->GetLength(), 1);
414 ASSERT_EQ(shortArray->GetWithoutChecks(0), 0);
415
Mathieu Chartierc7853442015-03-27 14:35:38 -0700416 ArtField* intArrayField = h_klass->FindDeclaredStaticField("intArrayField", "[I");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100417 ASSERT_TRUE(intArrayField != nullptr);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700418 mirror::IntArray* intArray = intArrayField->GetObject(h_klass.Get())->AsIntArray();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100419 ASSERT_TRUE(intArray != nullptr);
420 ASSERT_EQ(intArray->GetLength(), 1);
421 ASSERT_EQ(intArray->GetWithoutChecks(0), 0);
422
Mathieu Chartierc7853442015-03-27 14:35:38 -0700423 ArtField* longArrayField = h_klass->FindDeclaredStaticField("longArrayField", "[J");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100424 ASSERT_TRUE(longArrayField != nullptr);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700425 mirror::LongArray* longArray = longArrayField->GetObject(h_klass.Get())->AsLongArray();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100426 ASSERT_TRUE(longArray != nullptr);
427 ASSERT_EQ(longArray->GetLength(), 1);
428 ASSERT_EQ(longArray->GetWithoutChecks(0), static_cast<int64_t>(0));
429
Mathieu Chartierc7853442015-03-27 14:35:38 -0700430 ArtField* floatArrayField = h_klass->FindDeclaredStaticField("floatArrayField", "[F");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100431 ASSERT_TRUE(floatArrayField != nullptr);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700432 mirror::FloatArray* floatArray = floatArrayField->GetObject(h_klass.Get())->AsFloatArray();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100433 ASSERT_TRUE(floatArray != nullptr);
434 ASSERT_EQ(floatArray->GetLength(), 1);
Ian Rogers647b1a82014-10-10 11:02:11 -0700435 ASSERT_FLOAT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100436
Mathieu Chartierc7853442015-03-27 14:35:38 -0700437 ArtField* doubleArrayField = h_klass->FindDeclaredStaticField("doubleArrayField", "[D");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100438 ASSERT_TRUE(doubleArrayField != nullptr);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700439 mirror::DoubleArray* doubleArray = doubleArrayField->GetObject(h_klass.Get())->AsDoubleArray();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100440 ASSERT_TRUE(doubleArray != nullptr);
441 ASSERT_EQ(doubleArray->GetLength(), 1);
Ian Rogers647b1a82014-10-10 11:02:11 -0700442 ASSERT_DOUBLE_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100443
Mathieu Chartierc7853442015-03-27 14:35:38 -0700444 ArtField* objectArrayField = h_klass->FindDeclaredStaticField("objectArrayField",
Ian Rogers98379392014-02-24 16:53:16 -0800445 "[Ljava/lang/Object;");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100446 ASSERT_TRUE(objectArrayField != nullptr);
Ian Rogers98379392014-02-24 16:53:16 -0800447 mirror::ObjectArray<mirror::Object>* objectArray =
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700448 objectArrayField->GetObject(h_klass.Get())->AsObjectArray<mirror::Object>();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100449 ASSERT_TRUE(objectArray != nullptr);
450 ASSERT_EQ(objectArray->GetLength(), 1);
451 ASSERT_EQ(objectArray->GetWithoutChecks(0), nullptr);
452
453 // Create a java.lang.Object instance to set objectField.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700454 Handle<mirror::Class> object_klass(
455 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")));
456 ASSERT_TRUE(object_klass.Get() != nullptr);
457 Handle<mirror::Object> h_obj(hs.NewHandle(h_klass->AllocObject(soa.Self())));
458 ASSERT_TRUE(h_obj.Get() != nullptr);
459 ASSERT_EQ(h_obj->GetClass(), h_klass.Get());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100460
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100461 // Modify fields inside transaction then rollback changes.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100462 Transaction transaction;
463 Runtime::Current()->EnterTransactionMode(&transaction);
464 booleanArray->SetWithoutChecks<true>(0, true);
465 byteArray->SetWithoutChecks<true>(0, 1);
466 charArray->SetWithoutChecks<true>(0, 1u);
467 shortArray->SetWithoutChecks<true>(0, 1);
468 intArray->SetWithoutChecks<true>(0, 1);
469 longArray->SetWithoutChecks<true>(0, 1);
470 floatArray->SetWithoutChecks<true>(0, 1.0);
471 doubleArray->SetWithoutChecks<true>(0, 1.0);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700472 objectArray->SetWithoutChecks<true>(0, h_obj.Get());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100473 Runtime::Current()->ExitTransactionMode();
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100474 transaction.Rollback();
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100475
476 // Check values have properly been restored to their original (default) value.
477 EXPECT_EQ(booleanArray->GetWithoutChecks(0), false);
478 EXPECT_EQ(byteArray->GetWithoutChecks(0), 0);
479 EXPECT_EQ(charArray->GetWithoutChecks(0), 0u);
480 EXPECT_EQ(shortArray->GetWithoutChecks(0), 0);
481 EXPECT_EQ(intArray->GetWithoutChecks(0), 0);
482 EXPECT_EQ(longArray->GetWithoutChecks(0), static_cast<int64_t>(0));
Ian Rogers647b1a82014-10-10 11:02:11 -0700483 EXPECT_FLOAT_EQ(floatArray->GetWithoutChecks(0), static_cast<float>(0.0f));
484 EXPECT_DOUBLE_EQ(doubleArray->GetWithoutChecks(0), static_cast<double>(0.0f));
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100485 EXPECT_EQ(objectArray->GetWithoutChecks(0), nullptr);
486}
487
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700488// Tests rolling back interned strings and resolved strings.
489TEST_F(TransactionTest, ResolveString) {
490 ScopedObjectAccess soa(Thread::Current());
491 StackHandleScope<3> hs(soa.Self());
492 Handle<mirror::ClassLoader> class_loader(
Mathieu Chartier0795f232016-09-27 18:43:30 -0700493 hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
Mathieu Chartierbb816d62016-09-07 10:17:46 -0700494 ASSERT_TRUE(class_loader.Get() != nullptr);
495
496 Handle<mirror::Class> h_klass(
497 hs.NewHandle(class_linker_->FindClass(soa.Self(), "LTransaction$ResolveString;",
498 class_loader)));
499 ASSERT_TRUE(h_klass.Get() != nullptr);
500
501 Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(h_klass->GetDexCache()));
502 ASSERT_TRUE(h_dex_cache.Get() != nullptr);
503 const DexFile* const dex_file = h_dex_cache->GetDexFile();
504 ASSERT_TRUE(dex_file != nullptr);
505
506 // Go search the dex file to find the string id of our string.
507 static const char* kResolvedString = "ResolvedString";
508 const DexFile::StringId* string_id = dex_file->FindStringId(kResolvedString);
509 ASSERT_TRUE(string_id != nullptr);
510 uint32_t string_idx = dex_file->GetIndexForStringId(*string_id);
511 ASSERT_NE(string_idx, kDexNoIndex);
512 // String should only get resolved by the initializer.
513 EXPECT_TRUE(class_linker_->LookupString(*dex_file, string_idx, h_dex_cache) == nullptr);
514 EXPECT_TRUE(h_dex_cache->GetResolvedString(string_idx) == nullptr);
515 // Do the transaction, then roll back.
516 Transaction transaction;
517 Runtime::Current()->EnterTransactionMode(&transaction);
518 bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
519 ASSERT_TRUE(success);
520 ASSERT_TRUE(h_klass->IsInitialized());
521 // Make sure the string got resolved by the transaction.
522 {
523 mirror::String* s = class_linker_->LookupString(*dex_file, string_idx, h_dex_cache);
524 ASSERT_TRUE(s != nullptr);
525 EXPECT_STREQ(s->ToModifiedUtf8().c_str(), kResolvedString);
526 EXPECT_EQ(s, h_dex_cache->GetResolvedString(string_idx));
527 }
528 Runtime::Current()->ExitTransactionMode();
529 transaction.Rollback();
530 // Check that the string did not stay resolved.
531 EXPECT_TRUE(class_linker_->LookupString(*dex_file, string_idx, h_dex_cache) == nullptr);
532 EXPECT_TRUE(h_dex_cache->GetResolvedString(string_idx) == nullptr);
533 ASSERT_FALSE(h_klass->IsInitialized());
534 ASSERT_FALSE(soa.Self()->IsExceptionPending());
535}
536
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100537// Tests successful class initialization without class initializer.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100538TEST_F(TransactionTest, EmptyClass) {
539 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700540 StackHandleScope<2> hs(soa.Self());
541 Handle<mirror::ClassLoader> class_loader(
Mathieu Chartier0795f232016-09-27 18:43:30 -0700542 hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700543 ASSERT_TRUE(class_loader.Get() != nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100544
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700545 Handle<mirror::Class> h_klass(
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100546 hs.NewHandle(class_linker_->FindClass(soa.Self(), "LTransaction$EmptyStatic;",
547 class_loader)));
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700548 ASSERT_TRUE(h_klass.Get() != nullptr);
Ian Rogers7b078e82014-09-10 14:44:24 -0700549 class_linker_->VerifyClass(soa.Self(), h_klass);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700550 ASSERT_TRUE(h_klass->IsVerified());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100551
552 Transaction transaction;
553 Runtime::Current()->EnterTransactionMode(&transaction);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100554 bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100555 Runtime::Current()->ExitTransactionMode();
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100556 ASSERT_TRUE(success);
557 ASSERT_TRUE(h_klass->IsInitialized());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100558 ASSERT_FALSE(soa.Self()->IsExceptionPending());
559}
560
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100561// Tests successful class initialization with class initializer.
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100562TEST_F(TransactionTest, StaticFieldClass) {
563 ScopedObjectAccess soa(Thread::Current());
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700564 StackHandleScope<2> hs(soa.Self());
565 Handle<mirror::ClassLoader> class_loader(
Mathieu Chartier0795f232016-09-27 18:43:30 -0700566 hs.NewHandle(soa.Decode<mirror::ClassLoader>(LoadDex("Transaction"))));
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700567 ASSERT_TRUE(class_loader.Get() != nullptr);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100568
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700569 Handle<mirror::Class> h_klass(
570 hs.NewHandle(class_linker_->FindClass(soa.Self(), "LTransaction$StaticFieldClass;",
571 class_loader)));
572 ASSERT_TRUE(h_klass.Get() != nullptr);
Ian Rogers7b078e82014-09-10 14:44:24 -0700573 class_linker_->VerifyClass(soa.Self(), h_klass);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700574 ASSERT_TRUE(h_klass->IsVerified());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100575
576 Transaction transaction;
577 Runtime::Current()->EnterTransactionMode(&transaction);
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100578 bool success = class_linker_->EnsureInitialized(soa.Self(), h_klass, true, true);
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100579 Runtime::Current()->ExitTransactionMode();
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100580 ASSERT_TRUE(success);
581 ASSERT_TRUE(h_klass->IsInitialized());
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100582 ASSERT_FALSE(soa.Self()->IsExceptionPending());
583}
584
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100585// Tests failing class initialization due to native call.
586TEST_F(TransactionTest, NativeCallAbortClass) {
587 testTransactionAbort("LTransaction$NativeCallAbortClass;");
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100588}
589
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100590// Tests failing class initialization due to native call in a "synchronized" statement
591// (which must catch any exception, do the monitor-exit then re-throw the caught exception).
592TEST_F(TransactionTest, SynchronizedNativeCallAbortClass) {
593 testTransactionAbort("LTransaction$SynchronizedNativeCallAbortClass;");
594}
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100595
Sebastien Hertz1c80bec2015-02-03 11:58:06 +0100596// Tests failing class initialization due to native call, even if an "all" catch handler
597// catches the exception thrown when aborting the transaction.
598TEST_F(TransactionTest, CatchNativeCallAbortClass) {
599 testTransactionAbort("LTransaction$CatchNativeCallAbortClass;");
600}
601
602// Tests failing class initialization with multiple transaction aborts.
603TEST_F(TransactionTest, MultipleNativeCallAbortClass) {
604 testTransactionAbort("LTransaction$MultipleNativeCallAbortClass;");
605}
606
607// Tests failing class initialization due to allocating instance of finalizable class.
608TEST_F(TransactionTest, FinalizableAbortClass) {
609 testTransactionAbort("LTransaction$FinalizableAbortClass;");
610}
Sebastien Hertzd2fe10a2014-01-15 10:20:56 +0100611} // namespace art