blob: 15fa259d20badc1cee8f5c4ff51532061177be63 [file] [log] [blame]
Elliott Hughes2faa5f12012-01-30 14:42:07 -08001/*
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 */
Brian Carlstrom7e93b502011-08-04 14:16:22 -070016
17#include "intern_table.h"
18
19#include "common_test.h"
20#include "object.h"
21
Brian Carlstrom7e93b502011-08-04 14:16:22 -070022namespace art {
23
Brian Carlstromf734cf52011-08-17 16:28:14 -070024class InternTableTest : public CommonTest {};
Brian Carlstrom7e93b502011-08-04 14:16:22 -070025
26TEST_F(InternTableTest, Intern) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070027 ScopedObjectAccess soa(Thread::Current());
Brian Carlstrom7e93b502011-08-04 14:16:22 -070028 InternTable intern_table;
Brian Carlstrom40381fb2011-10-19 14:13:40 -070029 SirtRef<String> foo_1(intern_table.InternStrong(3, "foo"));
30 SirtRef<String> foo_2(intern_table.InternStrong(3, "foo"));
31 SirtRef<String> foo_3(String::AllocFromModifiedUtf8("foo"));
32 SirtRef<String> bar(intern_table.InternStrong(3, "bar"));
Brian Carlstrom7e93b502011-08-04 14:16:22 -070033 EXPECT_TRUE(foo_1->Equals("foo"));
34 EXPECT_TRUE(foo_2->Equals("foo"));
35 EXPECT_TRUE(foo_3->Equals("foo"));
Brian Carlstrom40381fb2011-10-19 14:13:40 -070036 EXPECT_TRUE(foo_1.get() != NULL);
37 EXPECT_TRUE(foo_2.get() != NULL);
38 EXPECT_EQ(foo_1.get(), foo_2.get());
39 EXPECT_NE(foo_1.get(), bar.get());
40 EXPECT_NE(foo_2.get(), bar.get());
41 EXPECT_NE(foo_3.get(), bar.get());
Brian Carlstrom7e93b502011-08-04 14:16:22 -070042}
43
Elliott Hughescf4c6c42011-09-01 15:16:42 -070044TEST_F(InternTableTest, Size) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070045 ScopedObjectAccess soa(Thread::Current());
Elliott Hughescf4c6c42011-09-01 15:16:42 -070046 InternTable t;
47 EXPECT_EQ(0U, t.Size());
48 t.InternStrong(3, "foo");
Brian Carlstrom40381fb2011-10-19 14:13:40 -070049 SirtRef<String> foo(String::AllocFromModifiedUtf8("foo"));
50 t.InternWeak(foo.get());
Elliott Hughescf4c6c42011-09-01 15:16:42 -070051 EXPECT_EQ(1U, t.Size());
52 t.InternStrong(3, "bar");
53 EXPECT_EQ(2U, t.Size());
54}
55
Elliott Hughesc33a32b2011-10-11 18:18:07 -070056class TestPredicate {
Elliott Hughes410c0c82011-09-01 17:58:25 -070057 public:
Elliott Hughesc33a32b2011-10-11 18:18:07 -070058 bool IsMarked(const Object* s) const {
Elliott Hughes410c0c82011-09-01 17:58:25 -070059 bool erased = false;
60 typedef std::vector<const String*>::iterator It; // TODO: C++0x auto
61 for (It it = expected_.begin(), end = expected_.end(); it != end; ++it) {
62 if (*it == s) {
63 expected_.erase(it);
64 erased = true;
65 break;
66 }
Elliott Hughescf4c6c42011-09-01 15:16:42 -070067 }
Elliott Hughes410c0c82011-09-01 17:58:25 -070068 EXPECT_TRUE(erased);
Elliott Hughesc33a32b2011-10-11 18:18:07 -070069 return false;
Elliott Hughescf4c6c42011-09-01 15:16:42 -070070 }
Elliott Hughes410c0c82011-09-01 17:58:25 -070071
72 void Expect(const String* s) {
73 expected_.push_back(s);
74 }
75
76 ~TestPredicate() {
77 EXPECT_EQ(0U, expected_.size());
78 }
79
80 private:
81 mutable std::vector<const String*> expected_;
82};
Elliott Hughescf4c6c42011-09-01 15:16:42 -070083
Elliott Hughesc33a32b2011-10-11 18:18:07 -070084bool IsMarked(const Object* object, void* arg) {
85 return reinterpret_cast<TestPredicate*>(arg)->IsMarked(object);
86}
87
88TEST_F(InternTableTest, SweepInternTableWeaks) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070089 ScopedObjectAccess soa(Thread::Current());
Elliott Hughescf4c6c42011-09-01 15:16:42 -070090 InternTable t;
91 t.InternStrong(3, "foo");
92 t.InternStrong(3, "bar");
Brian Carlstrom40381fb2011-10-19 14:13:40 -070093 SirtRef<String> hello(String::AllocFromModifiedUtf8("hello"));
94 SirtRef<String> world(String::AllocFromModifiedUtf8("world"));
95 SirtRef<String> s0(t.InternWeak(hello.get()));
96 SirtRef<String> s1(t.InternWeak(world.get()));
Elliott Hughescf4c6c42011-09-01 15:16:42 -070097
98 EXPECT_EQ(4U, t.Size());
99
100 // We should traverse only the weaks...
Elliott Hughes410c0c82011-09-01 17:58:25 -0700101 TestPredicate p;
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700102 p.Expect(s0.get());
103 p.Expect(s1.get());
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700104 {
Ian Rogersb726dcb2012-09-05 08:57:23 -0700105 ReaderMutexLock mu(*Locks::heap_bitmap_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700106 t.SweepInternTableWeaks(IsMarked, &p);
107 }
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700108
109 EXPECT_EQ(2U, t.Size());
110
Elliott Hughese5448b52012-01-18 16:44:06 -0800111 // Just check that we didn't corrupt the map.
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700112 SirtRef<String> still_here(String::AllocFromModifiedUtf8("still here"));
113 t.InternWeak(still_here.get());
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700114 EXPECT_EQ(3U, t.Size());
115}
116
117TEST_F(InternTableTest, ContainsWeak) {
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700118 ScopedObjectAccess soa(Thread::Current());
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700119 {
120 // Strongs are never weak.
121 InternTable t;
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700122 SirtRef<String> interned_foo_1(t.InternStrong(3, "foo"));
123 EXPECT_FALSE(t.ContainsWeak(interned_foo_1.get()));
124 SirtRef<String> interned_foo_2(t.InternStrong(3, "foo"));
125 EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get()));
126 EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700127 }
128
129 {
130 // Weaks are always weak.
131 InternTable t;
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700132 SirtRef<String> foo_1(String::AllocFromModifiedUtf8("foo"));
133 SirtRef<String> foo_2(String::AllocFromModifiedUtf8("foo"));
134 EXPECT_NE(foo_1.get(), foo_2.get());
135 SirtRef<String> interned_foo_1(t.InternWeak(foo_1.get()));
136 SirtRef<String> interned_foo_2(t.InternWeak(foo_2.get()));
137 EXPECT_TRUE(t.ContainsWeak(interned_foo_2.get()));
138 EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700139 }
140
141 {
142 // A weak can be promoted to a strong.
143 InternTable t;
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700144 SirtRef<String> foo(String::AllocFromModifiedUtf8("foo"));
145 SirtRef<String> interned_foo_1(t.InternWeak(foo.get()));
146 EXPECT_TRUE(t.ContainsWeak(interned_foo_1.get()));
147 SirtRef<String> interned_foo_2(t.InternStrong(3, "foo"));
148 EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get()));
149 EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700150 }
151
152 {
153 // Interning a weak after a strong gets you the strong.
154 InternTable t;
Brian Carlstrom40381fb2011-10-19 14:13:40 -0700155 SirtRef<String> interned_foo_1(t.InternStrong(3, "foo"));
156 EXPECT_FALSE(t.ContainsWeak(interned_foo_1.get()));
157 SirtRef<String> foo(String::AllocFromModifiedUtf8("foo"));
158 SirtRef<String> interned_foo_2(t.InternWeak(foo.get()));
159 EXPECT_FALSE(t.ContainsWeak(interned_foo_2.get()));
160 EXPECT_EQ(interned_foo_1.get(), interned_foo_2.get());
Elliott Hughescf4c6c42011-09-01 15:16:42 -0700161 }
162}
163
Brian Carlstrom7e93b502011-08-04 14:16:22 -0700164} // namespace art