• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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