| // Copyright 2011 Google Inc. All Rights Reserved. |
| |
| #include "intern_table.h" |
| |
| #include "common_test.h" |
| #include "object.h" |
| |
| namespace art { |
| |
| class InternTableTest : public CommonTest {}; |
| |
| TEST_F(InternTableTest, Intern) { |
| InternTable intern_table; |
| const String* foo_1 = intern_table.InternStrong(3, "foo"); |
| const String* foo_2 = intern_table.InternStrong(3, "foo"); |
| const String* foo_3 = String::AllocFromModifiedUtf8("foo"); |
| const String* bar = intern_table.InternStrong(3, "bar"); |
| EXPECT_TRUE(foo_1->Equals("foo")); |
| EXPECT_TRUE(foo_2->Equals("foo")); |
| EXPECT_TRUE(foo_3->Equals("foo")); |
| EXPECT_TRUE(foo_1 != NULL); |
| EXPECT_TRUE(foo_2 != NULL); |
| EXPECT_EQ(foo_1, foo_2); |
| EXPECT_NE(foo_1, bar); |
| EXPECT_NE(foo_2, bar); |
| EXPECT_NE(foo_3, bar); |
| } |
| |
| TEST_F(InternTableTest, Size) { |
| InternTable t; |
| EXPECT_EQ(0U, t.Size()); |
| t.InternStrong(3, "foo"); |
| t.InternWeak(String::AllocFromModifiedUtf8("foo")); |
| EXPECT_EQ(1U, t.Size()); |
| t.InternStrong(3, "bar"); |
| EXPECT_EQ(2U, t.Size()); |
| } |
| |
| class TestPredicate { |
| public: |
| bool IsMarked(const Object* s) const { |
| bool erased = false; |
| typedef std::vector<const String*>::iterator It; // TODO: C++0x auto |
| for (It it = expected_.begin(), end = expected_.end(); it != end; ++it) { |
| if (*it == s) { |
| expected_.erase(it); |
| erased = true; |
| break; |
| } |
| } |
| EXPECT_TRUE(erased); |
| return false; |
| } |
| |
| void Expect(const String* s) { |
| expected_.push_back(s); |
| } |
| |
| ~TestPredicate() { |
| EXPECT_EQ(0U, expected_.size()); |
| } |
| |
| private: |
| mutable std::vector<const String*> expected_; |
| }; |
| |
| bool IsMarked(const Object* object, void* arg) { |
| return reinterpret_cast<TestPredicate*>(arg)->IsMarked(object); |
| } |
| |
| TEST_F(InternTableTest, SweepInternTableWeaks) { |
| InternTable t; |
| t.InternStrong(3, "foo"); |
| t.InternStrong(3, "bar"); |
| const String* s0 = t.InternWeak(String::AllocFromModifiedUtf8("hello")); |
| const String* s1 = t.InternWeak(String::AllocFromModifiedUtf8("world")); |
| |
| EXPECT_EQ(4U, t.Size()); |
| |
| // We should traverse only the weaks... |
| TestPredicate p; |
| p.Expect(s0); |
| p.Expect(s1); |
| t.SweepInternTableWeaks(IsMarked, &p); |
| |
| EXPECT_EQ(2U, t.Size()); |
| |
| // Just check that we didn't corrupt the unordered_multimap. |
| t.InternWeak(String::AllocFromModifiedUtf8("still here")); |
| EXPECT_EQ(3U, t.Size()); |
| } |
| |
| TEST_F(InternTableTest, ContainsWeak) { |
| { |
| // Strongs are never weak. |
| InternTable t; |
| String* foo_1 = t.InternStrong(3, "foo"); |
| EXPECT_FALSE(t.ContainsWeak(foo_1)); |
| String* foo_2 = t.InternStrong(3, "foo"); |
| EXPECT_FALSE(t.ContainsWeak(foo_2)); |
| EXPECT_EQ(foo_1, foo_2); |
| } |
| |
| { |
| // Weaks are always weak. |
| InternTable t; |
| String* foo_1 = t.InternWeak(String::AllocFromModifiedUtf8("foo")); |
| EXPECT_TRUE(t.ContainsWeak(foo_1)); |
| String* foo_2 = t.InternWeak(String::AllocFromModifiedUtf8("foo")); |
| EXPECT_TRUE(t.ContainsWeak(foo_2)); |
| EXPECT_EQ(foo_1, foo_2); |
| } |
| |
| { |
| // A weak can be promoted to a strong. |
| InternTable t; |
| String* foo_1 = t.InternWeak(String::AllocFromModifiedUtf8("foo")); |
| EXPECT_TRUE(t.ContainsWeak(foo_1)); |
| String* foo_2 = t.InternStrong(3, "foo"); |
| EXPECT_FALSE(t.ContainsWeak(foo_2)); |
| EXPECT_EQ(foo_1, foo_2); |
| } |
| |
| { |
| // Interning a weak after a strong gets you the strong. |
| InternTable t; |
| String* foo_1 = t.InternStrong(3, "foo"); |
| EXPECT_FALSE(t.ContainsWeak(foo_1)); |
| String* foo_2 = t.InternWeak(String::AllocFromModifiedUtf8("foo")); |
| EXPECT_FALSE(t.ContainsWeak(foo_2)); |
| EXPECT_EQ(foo_1, foo_2); |
| } |
| } |
| |
| } // namespace art |