text: // 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 <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"));
  
    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);
  
    // Fast sets are ordered according to the key pointer.
    // Because of the underlying bump allocator, addresses
    // for the first three inserts are in increasing order.
    auto it = set.begin();
    EXPECT_EQ(it, foo_ret.first);
    ++it;
  
    EXPECT_EQ(it, bar_ret.first);
    ++it;
  
    EXPECT_EQ(it, zoo_ret.first);
    ++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));
    }
  }
  