blob: ba151e37ebe645883175f58fcafb396cf001fc93 [file] [log] [blame]
// 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));
}
}