1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "intern_table.h"
18
19 #include "common_test.h"
20 #include "mirror/object.h"
21 #include "sirt_ref.h"
22
23 namespace art {
24
25 class InternTableTest : public CommonTest {};
26
TEST_F(InternTableTest,Intern)27 TEST_F(InternTableTest, Intern) {
28 ScopedObjectAccess soa(Thread::Current());
29 InternTable intern_table;
30 SirtRef<mirror::String> foo_1(soa.Self(), intern_table.InternStrong(3, "foo"));
31 SirtRef<mirror::String> foo_2(soa.Self(), intern_table.InternStrong(3, "foo"));
32 SirtRef<mirror::String> foo_3(soa.Self(), mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"));
33 SirtRef<mirror::String> bar(soa.Self(), intern_table.InternStrong(3, "bar"));
34 EXPECT_TRUE(foo_1->Equals("foo"));
35 EXPECT_TRUE(foo_2->Equals("foo"));
36 EXPECT_TRUE(foo_3->Equals("foo"));
37 EXPECT_TRUE(foo_1.get() != NULL);
38 EXPECT_TRUE(foo_2.get() != NULL);
39 EXPECT_EQ(foo_1.get(), foo_2.get());
40 EXPECT_NE(foo_1.get(), bar.get());
41 EXPECT_NE(foo_2.get(), bar.get());
42 EXPECT_NE(foo_3.get(), bar.get());
43 }
44
TEST_F(InternTableTest,Size)45 TEST_F(InternTableTest, Size) {
46 ScopedObjectAccess soa(Thread::Current());
47 InternTable t;
48 EXPECT_EQ(0U, t.Size());
49 t.InternStrong(3, "foo");
50 SirtRef<mirror::String> foo(soa.Self(), mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"));
51 t.InternWeak(foo.get());
52 EXPECT_EQ(1U, t.Size());
53 t.InternStrong(3, "bar");
54 EXPECT_EQ(2U, t.Size());
55 }
56
57 class TestPredicate {
58 public:
IsMarked(const mirror::Object * s) const59 bool IsMarked(const mirror::Object* s) const {
60 bool erased = false;
61 for (auto it = expected_.begin(), end = expected_.end(); it != end; ++it) {
62 if (*it == s) {
63 expected_.erase(it);
64 erased = true;
65 break;
66 }
67 }
68 EXPECT_TRUE(erased);
69 return false;
70 }
71
Expect(const mirror::String * s)72 void Expect(const mirror::String* s) {
73 expected_.push_back(s);
74 }
75
~TestPredicate()76 ~TestPredicate() {
77 EXPECT_EQ(0U, expected_.size());
78 }
79
80 private:
81 mutable std::vector<const mirror::String*> expected_;
82 };
83
IsMarked(const mirror::Object * object,void * arg)84 bool IsMarked(const mirror::Object* object, void* arg) {
85 return reinterpret_cast<TestPredicate*>(arg)->IsMarked(object);
86 }
87
TEST_F(InternTableTest,SweepInternTableWeaks)88 TEST_F(InternTableTest, SweepInternTableWeaks) {
89 ScopedObjectAccess soa(Thread::Current());
90 InternTable t;
91 t.InternStrong(3, "foo");
92 t.InternStrong(3, "bar");
93 SirtRef<mirror::String> hello(soa.Self(),
94 mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello"));
95 SirtRef<mirror::String> world(soa.Self(),
96 mirror::String::AllocFromModifiedUtf8(soa.Self(), "world"));
97 SirtRef<mirror::String> s0(soa.Self(), t.InternWeak(hello.get()));
98 SirtRef<mirror::String> s1(soa.Self(), t.InternWeak(world.get()));
99
100 EXPECT_EQ(4U, t.Size());
101
102 // We should traverse only the weaks...
103 TestPredicate p;
104 p.Expect(s0.get());
105 p.Expect(s1.get());
106 {
107 ReaderMutexLock mu(soa.Self(), *Locks::heap_bitmap_lock_);
108 t.SweepInternTableWeaks(IsMarked, &p);
109 }
110
111 EXPECT_EQ(2U, t.Size());
112
113 // Just check that we didn't corrupt the map.
114 SirtRef<mirror::String> still_here(soa.Self(),
115 mirror::String::AllocFromModifiedUtf8(soa.Self(), "still here"));
116 t.InternWeak(still_here.get());
117 EXPECT_EQ(3U, t.Size());
118 }
119
TEST_F(InternTableTest,ContainsWeak)120 TEST_F(InternTableTest, ContainsWeak) {
121 ScopedObjectAccess soa(Thread::Current());
122 {
123 // Strongs are never weak.
124 InternTable t;
125 SirtRef<mirror::String> interned_foo_1(soa.Self(), t.InternStrong(3, "foo"));
126 EXPECT_FALSE(t.ContainsWeak(interned_foo_1.get()));
127 SirtRef<mirror::String> interned_foo_2(soa.Self(), t.InternStrong(3, "foo"));
128 EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get()));
129 EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
130 }
131
132 {
133 // Weaks are always weak.
134 InternTable t;
135 SirtRef<mirror::String> foo_1(soa.Self(),
136 mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"));
137 SirtRef<mirror::String> foo_2(soa.Self(),
138 mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"));
139 EXPECT_NE(foo_1.get(), foo_2.get());
140 SirtRef<mirror::String> interned_foo_1(soa.Self(), t.InternWeak(foo_1.get()));
141 SirtRef<mirror::String> interned_foo_2(soa.Self(), t.InternWeak(foo_2.get()));
142 EXPECT_TRUE(t.ContainsWeak(interned_foo_2.get()));
143 EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
144 }
145
146 {
147 // A weak can be promoted to a strong.
148 InternTable t;
149 SirtRef<mirror::String> foo(soa.Self(), mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"));
150 SirtRef<mirror::String> interned_foo_1(soa.Self(), t.InternWeak(foo.get()));
151 EXPECT_TRUE(t.ContainsWeak(interned_foo_1.get()));
152 SirtRef<mirror::String> interned_foo_2(soa.Self(), t.InternStrong(3, "foo"));
153 EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get()));
154 EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
155 }
156
157 {
158 // Interning a weak after a strong gets you the strong.
159 InternTable t;
160 SirtRef<mirror::String> interned_foo_1(soa.Self(), t.InternStrong(3, "foo"));
161 EXPECT_FALSE(t.ContainsWeak(interned_foo_1.get()));
162 SirtRef<mirror::String> foo(soa.Self(),
163 mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"));
164 SirtRef<mirror::String> interned_foo_2(soa.Self(), t.InternWeak(foo.get()));
165 EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get()));
166 EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
167 }
168 }
169
170 } // namespace art
171