// Copyright 2015 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 "base/containers/scoped_ptr_map.h" #include #include #include #include "base/bind.h" #include "base/callback.h" #include "base/memory/scoped_ptr.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { namespace { // A ScopedDestroyer sets a Boolean to true upon destruction. class ScopedDestroyer { public: ScopedDestroyer(bool* destroyed) : destroyed_(destroyed) { *destroyed_ = false; } ~ScopedDestroyer() { *destroyed_ = true; } private: bool* destroyed_; }; TEST(ScopedPtrMapTest, Insert) { bool destroyed1 = false; bool destroyed2 = false; { ScopedPtrMap> scoped_map; // Insert to new key. ScopedDestroyer* elem1 = new ScopedDestroyer(&destroyed1); EXPECT_FALSE(destroyed1); EXPECT_TRUE(scoped_map.insert(0, make_scoped_ptr(elem1)).second); EXPECT_EQ(elem1, scoped_map.find(0)->second); EXPECT_FALSE(destroyed1); // Insert to existing key. ScopedDestroyer* elem2 = new ScopedDestroyer(&destroyed2); EXPECT_FALSE(destroyed2); EXPECT_FALSE(scoped_map.insert(0, make_scoped_ptr(elem2)).second); EXPECT_EQ(elem1, scoped_map.find(0)->second); EXPECT_FALSE(destroyed1); EXPECT_TRUE(destroyed2); } EXPECT_TRUE(destroyed1); } TEST(ScopedPtrMapTest, Set) { bool destroyed1 = false; bool destroyed2 = false; { ScopedPtrMap> scoped_map; // Set a new key. ScopedDestroyer* elem1 = new ScopedDestroyer(&destroyed1); EXPECT_FALSE(destroyed1); scoped_map.set(0, make_scoped_ptr(elem1)); EXPECT_EQ(elem1, scoped_map.find(0)->second); EXPECT_FALSE(destroyed1); // Set to replace an existing key. ScopedDestroyer* elem2 = new ScopedDestroyer(&destroyed2); EXPECT_FALSE(destroyed2); scoped_map.set(0, make_scoped_ptr(elem2)); EXPECT_EQ(elem2, scoped_map.find(0)->second); EXPECT_TRUE(destroyed1); EXPECT_FALSE(destroyed2); } EXPECT_TRUE(destroyed1); EXPECT_TRUE(destroyed2); } TEST(ScopedPtrMapTest, EraseIterator) { bool destroyed = false; ScopedPtrMap> scoped_map; scoped_map.insert(0, make_scoped_ptr(new ScopedDestroyer(&destroyed))); EXPECT_FALSE(destroyed); scoped_map.erase(scoped_map.find(0)); EXPECT_TRUE(destroyed); EXPECT_TRUE(scoped_map.empty()); } TEST(ScopedPtrMapTest, EraseKey) { bool destroyed = false; ScopedPtrMap> scoped_map; scoped_map.insert(0, make_scoped_ptr(new ScopedDestroyer(&destroyed))); EXPECT_FALSE(destroyed); EXPECT_EQ(1u, scoped_map.erase(0)); EXPECT_TRUE(destroyed); EXPECT_TRUE(scoped_map.empty()); // Test erase of a non-existent key. EXPECT_EQ(0u, scoped_map.erase(7)); } TEST(ScopedPtrMapTest, EraseRange) { bool destroyed1 = false; bool destroyed2 = false; ScopedPtrMap> scoped_map; scoped_map.insert(0, make_scoped_ptr(new ScopedDestroyer(&destroyed1))); EXPECT_FALSE(destroyed1); scoped_map.insert(1, make_scoped_ptr(new ScopedDestroyer(&destroyed2))); EXPECT_FALSE(destroyed2); scoped_map.erase(scoped_map.find(0), scoped_map.end()); EXPECT_TRUE(destroyed1); EXPECT_TRUE(destroyed2); EXPECT_TRUE(scoped_map.empty()); } TEST(ScopedPtrMapTest, TakeAndErase) { bool destroyed = false; ScopedPtrMap> scoped_map; ScopedDestroyer* elem = new ScopedDestroyer(&destroyed); scoped_map.insert(0, make_scoped_ptr(elem)); EXPECT_EQ(elem, scoped_map.find(0)->second); EXPECT_FALSE(destroyed); scoped_ptr object = scoped_map.take_and_erase(0); EXPECT_EQ(elem, object.get()); EXPECT_FALSE(destroyed); EXPECT_TRUE(scoped_map.empty()); object.reset(); EXPECT_TRUE(destroyed); } TEST(ScopedPtrMapTest, Clear) { bool destroyed = false; ScopedPtrMap> scoped_map; scoped_map.insert(0, make_scoped_ptr(new ScopedDestroyer(&destroyed))); EXPECT_FALSE(destroyed); scoped_map.clear(); EXPECT_TRUE(destroyed); EXPECT_TRUE(scoped_map.empty()); } TEST(ScopedPtrMapTest, Compare) { // Construct a ScopedPtrMap with a custom comparison function. bool destroyed = false; ScopedPtrMap, std::greater> scoped_map; scoped_map.insert(0, make_scoped_ptr(new ScopedDestroyer(&destroyed))); scoped_map.insert(1, make_scoped_ptr(new ScopedDestroyer(&destroyed))); auto it = scoped_map.begin(); EXPECT_EQ(1, it->first); ++it; EXPECT_EQ(0, it->first); } TEST(ScopedPtrMapTest, Scope) { bool destroyed = false; { ScopedPtrMap> scoped_map; scoped_map.insert(0, make_scoped_ptr(new ScopedDestroyer(&destroyed))); EXPECT_FALSE(destroyed); } EXPECT_TRUE(destroyed); } TEST(ScopedPtrMapTest, MoveConstruct) { bool destroyed = false; { ScopedPtrMap> scoped_map; ScopedDestroyer* elem = new ScopedDestroyer(&destroyed); scoped_map.insert(0, make_scoped_ptr(elem)); EXPECT_EQ(elem, scoped_map.find(0)->second); EXPECT_FALSE(destroyed); EXPECT_FALSE(scoped_map.empty()); ScopedPtrMap> scoped_map_copy( scoped_map.Pass()); EXPECT_TRUE(scoped_map.empty()); EXPECT_FALSE(scoped_map_copy.empty()); EXPECT_EQ(elem, scoped_map_copy.find(0)->second); EXPECT_FALSE(destroyed); } EXPECT_TRUE(destroyed); } TEST(ScopedPtrMapTest, MoveAssign) { bool destroyed = false; { ScopedPtrMap> scoped_map; ScopedDestroyer* elem = new ScopedDestroyer(&destroyed); scoped_map.insert(0, make_scoped_ptr(elem)); EXPECT_EQ(elem, scoped_map.find(0)->second); EXPECT_FALSE(destroyed); EXPECT_FALSE(scoped_map.empty()); ScopedPtrMap> scoped_map_assign; scoped_map_assign = scoped_map.Pass(); EXPECT_TRUE(scoped_map.empty()); EXPECT_FALSE(scoped_map_assign.empty()); EXPECT_EQ(elem, scoped_map_assign.find(0)->second); EXPECT_FALSE(destroyed); } EXPECT_TRUE(destroyed); } template ScopedPtrMap PassThru(ScopedPtrMap scoper) { return scoper; } TEST(ScopedPtrMapTest, Passed) { bool destroyed = false; ScopedPtrMap> scoped_map; ScopedDestroyer* elem = new ScopedDestroyer(&destroyed); scoped_map.insert(0, make_scoped_ptr(elem)); EXPECT_EQ(elem, scoped_map.find(0)->second); EXPECT_FALSE(destroyed); base::Callback>(void)> callback = base::Bind(&PassThru>, base::Passed(&scoped_map)); EXPECT_TRUE(scoped_map.empty()); EXPECT_FALSE(destroyed); ScopedPtrMap> result = callback.Run(); EXPECT_TRUE(scoped_map.empty()); EXPECT_EQ(elem, result.find(0)->second); EXPECT_FALSE(destroyed); result.clear(); EXPECT_TRUE(destroyed); }; } // namespace } // namespace base