| // Copyright (c) 2020 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "gn/string_atom.h" |
| |
| #include "util/test/test.h" |
| |
| #include <algorithm> |
| #include <array> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| TEST(StringAtomTest, EmptyString) { |
| StringAtom key1; |
| StringAtom key2(""); |
| |
| ASSERT_STREQ(key1.str().c_str(), ""); |
| ASSERT_STREQ(key2.str().c_str(), ""); |
| ASSERT_EQ(&key1.str(), &key2.str()); |
| } |
| |
| TEST(StringAtomTest, Find) { |
| StringAtom empty; |
| EXPECT_EQ(empty.str(), std::string()); |
| |
| StringAtom foo("foo"); |
| EXPECT_EQ(foo.str(), std::string("foo")); |
| |
| StringAtom foo2("foo"); |
| EXPECT_EQ(&foo.str(), &foo2.str()); |
| } |
| |
| // Default compare should always be ordered. |
| TEST(StringAtomTest, DefaultCompare) { |
| auto foo = StringAtom("foo"); |
| auto bar = StringAtom("bar"); |
| auto zoo = StringAtom("zoo"); |
| |
| EXPECT_TRUE(bar < foo); |
| EXPECT_TRUE(foo < zoo); |
| EXPECT_TRUE(bar < zoo); |
| } |
| |
| TEST(StringAtomTest, NormalSet) { |
| std::set<StringAtom> set; |
| auto foo_ret = set.insert(std::string_view("foo")); |
| auto bar_ret = set.insert(std::string_view("bar")); |
| auto zoo_ret = set.insert(std::string_view("zoo")); |
| |
| StringAtom foo_key("foo"); |
| EXPECT_EQ(*foo_ret.first, foo_key); |
| |
| auto foo_it = set.find(foo_key); |
| EXPECT_NE(foo_it, set.end()); |
| EXPECT_EQ(*foo_it, foo_key); |
| |
| EXPECT_EQ(set.find(std::string_view("bar")), bar_ret.first); |
| EXPECT_EQ(set.find(std::string_view("zoo")), zoo_ret.first); |
| |
| // Normal sets are always ordered according to the key value. |
| auto it = set.begin(); |
| EXPECT_EQ(it, bar_ret.first); |
| ++it; |
| |
| EXPECT_EQ(it, foo_ret.first); |
| ++it; |
| |
| EXPECT_EQ(it, zoo_ret.first); |
| ++it; |
| |
| EXPECT_EQ(it, set.end()); |
| } |
| |
| TEST(StringAtomTest, FastSet) { |
| std::set<StringAtom, StringAtom::PtrCompare> set; |
| |
| auto foo_ret = set.insert(std::string_view("foo")); |
| auto bar_ret = set.insert(std::string_view("bar")); |
| auto zoo_ret = set.insert(std::string_view("zoo")); |
| |
| auto atom_to_ptr = [](const StringAtom& atom) -> const std::string* { |
| return &atom.str(); |
| }; |
| |
| EXPECT_TRUE(foo_ret.second); |
| EXPECT_TRUE(bar_ret.second); |
| EXPECT_TRUE(zoo_ret.second); |
| |
| const std::string* foo_ptr = atom_to_ptr(*foo_ret.first); |
| const std::string* bar_ptr = atom_to_ptr(*bar_ret.first); |
| const std::string* zoo_ptr = atom_to_ptr(*zoo_ret.first); |
| |
| StringAtom foo_key("foo"); |
| EXPECT_EQ(foo_ptr, atom_to_ptr(foo_key)); |
| |
| auto foo_it = set.find(foo_key); |
| EXPECT_NE(foo_it, set.end()); |
| EXPECT_EQ(*foo_it, foo_key); |
| |
| EXPECT_EQ(set.find(std::string_view("bar")), bar_ret.first); |
| EXPECT_EQ(set.find(std::string_view("zoo")), zoo_ret.first); |
| |
| // Fast sets are ordered according to the key pointer. |
| // Even though a bump allocator is used to allocate AtomString |
| // strings, there is no guarantee that the global StringAtom |
| // set was not already populated by a different test previously, |
| // which means the pointers value need to be sorted before |
| // iterating over the set for comparison. |
| std::array<const std::string*, 3> ptrs = { |
| foo_ptr, |
| bar_ptr, |
| zoo_ptr, |
| }; |
| std::sort(ptrs.begin(), ptrs.end()); |
| |
| auto it = set.begin(); |
| EXPECT_EQ(atom_to_ptr(*it), ptrs[0]); |
| ++it; |
| |
| EXPECT_EQ(atom_to_ptr(*it), ptrs[1]); |
| ++it; |
| |
| EXPECT_EQ(atom_to_ptr(*it), ptrs[2]); |
| ++it; |
| |
| EXPECT_EQ(it, set.end()); |
| } |
| |
| TEST(StringAtom, AllocMoreThanASingleSlabOfKeys) { |
| // Verify that allocating more than 128 string keys works properly. |
| const size_t kMaxCount = 16384; |
| std::vector<StringAtom> keys; |
| |
| // Small lambda to create a string for the n-th key. |
| auto string_for = [](size_t index) -> std::string { |
| return std::to_string(index) + "_key"; |
| }; |
| |
| for (size_t nn = 0; nn < kMaxCount; ++nn) { |
| keys.push_back(StringAtom(string_for(nn))); |
| } |
| |
| for (size_t nn = 0; nn < kMaxCount; ++nn) { |
| ASSERT_EQ(keys[nn].str(), string_for(nn)); |
| } |
| } |