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 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 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: 59 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 72 void Expect(const mirror::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 mirror::String*> expected_; 82 }; 83 84 bool IsMarked(const mirror::Object* object, void* arg) { 85 return reinterpret_cast<TestPredicate*>(arg)->IsMarked(object); 86 } 87 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 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