// Copyright 2007 Google Inc. All Rights Reserved. // Author: jmacd@google.com (Josh MacDonald) // Author: pmattis@google.com (Peter Mattis) #include "base/arena-inl.h" #include "base/init_google.h" #include "base/integral_types.h" #include "base/logging.h" #include "strings/stringpiece.h" #include "testing/base/public/gunit.h" #include "util/btree/btree_map.h" #include "util/btree/btree_set.h" #include "util/btree/btree_test.h" namespace util { namespace btree { namespace { template void SetTest() { typedef ArenaAllocator ArenaAlloc; CHECK_EQ(sizeof(btree_set), sizeof(void*)); BtreeTest, allocator, N>, set >(); BtreeArenaTest, ArenaAlloc, N> >(); } template void MapTest() { typedef ArenaAllocator ArenaAlloc; CHECK_EQ(sizeof(btree_map), sizeof(void*)); BtreeTest, allocator, N>, map >(); BtreeArenaTest, ArenaAlloc, N> >(); BtreeMapTest, allocator, N> >(); } TEST(Btree, set_int32_32) { SetTest(); } TEST(Btree, set_int32_64) { SetTest(); } TEST(Btree, set_int32_128) { SetTest(); } TEST(Btree, set_int32_256) { SetTest(); } TEST(Btree, set_int64_256) { SetTest(); } TEST(Btree, set_string_256) { SetTest(); } TEST(Btree, set_cord_256) { SetTest(); } TEST(Btree, set_pair_256) { SetTest, 256>(); } TEST(Btree, map_int32_256) { MapTest(); } TEST(Btree, map_int64_256) { MapTest(); } TEST(Btree, map_string_256) { MapTest(); } TEST(Btree, map_cord_256) { MapTest(); } TEST(Btree, map_pair_256) { MapTest, 256>(); } // Large-node tests TEST(Btree, map_int32_1024) { MapTest(); } TEST(Btree, map_int32_1032) { MapTest(); } TEST(Btree, map_int32_1040) { MapTest(); } TEST(Btree, map_int32_1048) { MapTest(); } TEST(Btree, map_int32_1056) { MapTest(); } TEST(Btree, map_int32_2048) { MapTest(); } TEST(Btree, map_int32_4096) { MapTest(); } TEST(Btree, set_int32_1024) { SetTest(); } TEST(Btree, set_int32_2048) { SetTest(); } TEST(Btree, set_int32_4096) { SetTest(); } TEST(Btree, map_string_1024) { MapTest(); } TEST(Btree, map_string_2048) { MapTest(); } TEST(Btree, map_string_4096) { MapTest(); } TEST(Btree, set_string_1024) { SetTest(); } TEST(Btree, set_string_2048) { SetTest(); } TEST(Btree, set_string_4096) { SetTest(); } template void MultiSetTest() { typedef ArenaAllocator ArenaAlloc; CHECK_EQ(sizeof(btree_multiset), sizeof(void*)); BtreeMultiTest, allocator, N>, multiset >(); BtreeArenaTest, ArenaAlloc, N> >(); } template void MultiMapTest() { typedef ArenaAllocator ArenaAlloc; CHECK_EQ(sizeof(btree_multimap), sizeof(void*)); BtreeMultiTest, allocator, N>, multimap >(); BtreeMultiMapTest, allocator, N> >(); BtreeArenaTest, ArenaAlloc, N> >(); } TEST(Btree, multiset_int32_256) { MultiSetTest(); } TEST(Btree, multiset_int64_256) { MultiSetTest(); } TEST(Btree, multiset_string_256) { MultiSetTest(); } TEST(Btree, multiset_cord_256) { MultiSetTest(); } TEST(Btree, multiset_pair_256) { MultiSetTest, 256>(); } TEST(Btree, multimap_int32_256) { MultiMapTest(); } TEST(Btree, multimap_int64_256) { MultiMapTest(); } TEST(Btree, multimap_string_256) { MultiMapTest(); } TEST(Btree, multimap_cord_256) { MultiMapTest(); } TEST(Btree, multimap_pair_256) { MultiMapTest, 256>(); } // Large-node tests TEST(Btree, multimap_int32_1024) { MultiMapTest(); } TEST(Btree, multimap_int32_2048) { MultiMapTest(); } TEST(Btree, multimap_int32_4096) { MultiMapTest(); } TEST(Btree, multiset_int32_1024) { MultiSetTest(); } TEST(Btree, multiset_int32_2048) { MultiSetTest(); } TEST(Btree, multiset_int32_4096) { MultiSetTest(); } TEST(Btree, multimap_string_1024) { MultiMapTest(); } TEST(Btree, multimap_string_2048) { MultiMapTest(); } TEST(Btree, multimap_string_4096) { MultiMapTest(); } TEST(Btree, multiset_string_1024) { MultiSetTest(); } TEST(Btree, multiset_string_2048) { MultiSetTest(); } TEST(Btree, multiset_string_4096) { MultiSetTest(); } // Verify that swapping btrees swaps the key comparision functors. struct SubstringLess { SubstringLess() : n(2) {} SubstringLess(int length) : n(length) { } bool operator()(const string &a, const string &b) const { return StringPiece(a).substr(0, n) < StringPiece(b).substr(0, n); } int n; }; TEST(Btree, SwapKeyCompare) { typedef btree_set SubstringSet; SubstringSet s1(SubstringLess(1), SubstringSet::allocator_type()); SubstringSet s2(SubstringLess(2), SubstringSet::allocator_type()); ASSERT_TRUE(s1.insert("a").second); ASSERT_FALSE(s1.insert("aa").second); ASSERT_TRUE(s2.insert("a").second); ASSERT_TRUE(s2.insert("aa").second); ASSERT_FALSE(s2.insert("aaa").second); swap(s1, s2); ASSERT_TRUE(s1.insert("b").second); ASSERT_TRUE(s1.insert("bb").second); ASSERT_FALSE(s1.insert("bbb").second); ASSERT_TRUE(s2.insert("b").second); ASSERT_FALSE(s2.insert("bb").second); } TEST(Btree, UpperBoundRegression) { // Regress a bug where upper_bound would default-construct a new key_compare // instead of copying the existing one. typedef btree_set SubstringSet; SubstringSet my_set(SubstringLess(3)); my_set.insert("aab"); my_set.insert("abb"); // We call upper_bound("aaa"). If this correctly uses the length 3 // comparator, aaa < aab < abb, so we should get aab as the result. // If it instead uses the default-constructed length 2 comparator, // aa == aa < ab, so we'll get abb as our result. SubstringSet::iterator it = my_set.upper_bound("aaa"); ASSERT_TRUE(it != my_set.end()); EXPECT_EQ("aab", *it); } TEST(Btree, IteratorIncrementBy) { // Test that increment_by returns the same position as increment. const int kSetSize = 2341; btree_set my_set; for (int i = 0; i < kSetSize; ++i) { my_set.insert(i); } { // Simple increment vs. increment by. btree_set::iterator a = my_set.begin(); btree_set::iterator b = my_set.begin(); a.increment(); b.increment_by(1); EXPECT_EQ(*a, *b); } btree_set::iterator a = my_set.begin(); for (int i = 1; i < kSetSize; ++i) { ++a; // increment_by btree_set::iterator b = my_set.begin(); b.increment_by(i); EXPECT_EQ(*a, *b) << ": i=" << i; } } TEST(Btree, Comparison) { const int kSetSize = 1201; btree_set my_set; for (int i = 0; i < kSetSize; ++i) { my_set.insert(i); } btree_set my_set_copy(my_set); EXPECT_TRUE(my_set_copy == my_set); EXPECT_TRUE(my_set == my_set_copy); EXPECT_FALSE(my_set_copy != my_set); EXPECT_FALSE(my_set != my_set_copy); my_set.insert(kSetSize); EXPECT_FALSE(my_set_copy == my_set); EXPECT_FALSE(my_set == my_set_copy); EXPECT_TRUE(my_set_copy != my_set); EXPECT_TRUE(my_set != my_set_copy); my_set.erase(kSetSize - 1); EXPECT_FALSE(my_set_copy == my_set); EXPECT_FALSE(my_set == my_set_copy); EXPECT_TRUE(my_set_copy != my_set); EXPECT_TRUE(my_set != my_set_copy); btree_map my_map; for (int i = 0; i < kSetSize; ++i) { my_map[string(i, 'a')] = i; } btree_map my_map_copy(my_map); EXPECT_TRUE(my_map_copy == my_map); EXPECT_TRUE(my_map == my_map_copy); EXPECT_FALSE(my_map_copy != my_map); EXPECT_FALSE(my_map != my_map_copy); ++my_map_copy[string(7, 'a')]; EXPECT_FALSE(my_map_copy == my_map); EXPECT_FALSE(my_map == my_map_copy); EXPECT_TRUE(my_map_copy != my_map); EXPECT_TRUE(my_map != my_map_copy); my_map_copy = my_map; my_map["hello"] = kSetSize; EXPECT_FALSE(my_map_copy == my_map); EXPECT_FALSE(my_map == my_map_copy); EXPECT_TRUE(my_map_copy != my_map); EXPECT_TRUE(my_map != my_map_copy); my_map.erase(string(kSetSize - 1, 'a')); EXPECT_FALSE(my_map_copy == my_map); EXPECT_FALSE(my_map == my_map_copy); EXPECT_TRUE(my_map_copy != my_map); EXPECT_TRUE(my_map != my_map_copy); } } // namespace } // namespace btree } // namespace util int main(int argc, char **argv) { FLAGS_logtostderr = true; InitGoogle(argv[0], &argc, &argv, true); return RUN_ALL_TESTS(); }