Fully implement string interning.
Also, more const.
Change-Id: I09cae88d677e8e6e42d0fa9b5d1093c79d225e66
diff --git a/src/intern_table_test.cc b/src/intern_table_test.cc
index a01c6dd..d230a01 100644
--- a/src/intern_table_test.cc
+++ b/src/intern_table_test.cc
@@ -11,10 +11,10 @@
TEST_F(InternTableTest, Intern) {
InternTable intern_table;
- String* foo_1 = intern_table.Intern(3, "foo");
- String* foo_2 = intern_table.Intern(3, "foo");
- String* foo_3 = String::AllocFromModifiedUtf8("foo");
- String* bar = intern_table.Intern(3, "bar");
+ 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"));
@@ -26,4 +26,94 @@
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());
+}
+
+std::vector<const String*> gExpectedWeakStrings;
+bool TestPredicate(const String* s) {
+ bool erased = false;
+ typedef std::vector<const String*>::iterator It; // TODO: C++0x auto
+ for (It it = gExpectedWeakStrings.begin(), end = gExpectedWeakStrings.end(); it != end; ++it) {
+ if (*it == s) {
+ gExpectedWeakStrings.erase(it);
+ erased = true;
+ break;
+ }
+ }
+ EXPECT_TRUE(erased);
+ return true;
+}
+
+TEST_F(InternTableTest, RemoveWeakIf) {
+ 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...
+ gExpectedWeakStrings.clear();
+ gExpectedWeakStrings.push_back(s0);
+ gExpectedWeakStrings.push_back(s1);
+ t.RemoveWeakIf(TestPredicate);
+ EXPECT_EQ(0U, gExpectedWeakStrings.size());
+
+ 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;
+ const String* foo_1 = t.InternStrong(3, "foo");
+ EXPECT_FALSE(t.ContainsWeak(foo_1));
+ const 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;
+ const String* foo_1 = t.InternWeak(String::AllocFromModifiedUtf8("foo"));
+ EXPECT_TRUE(t.ContainsWeak(foo_1));
+ const 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;
+ const String* foo_1 = t.InternWeak(String::AllocFromModifiedUtf8("foo"));
+ EXPECT_TRUE(t.ContainsWeak(foo_1));
+ const 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;
+ const String* foo_1 = t.InternStrong(3, "foo");
+ EXPECT_FALSE(t.ContainsWeak(foo_1));
+ const String* foo_2 = t.InternWeak(String::AllocFromModifiedUtf8("foo"));
+ EXPECT_FALSE(t.ContainsWeak(foo_2));
+ EXPECT_EQ(foo_1, foo_2);
+ }
+}
+
} // namespace art