blob: 46843b3f2529f288ec3ef9cdef1884608cfa2524 [file] [log] [blame]
// 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 <functional>
#include <map>
#include <utility>
#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<int, scoped_ptr<ScopedDestroyer>> 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<int, scoped_ptr<ScopedDestroyer>> 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<int, scoped_ptr<ScopedDestroyer>> 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<int, scoped_ptr<ScopedDestroyer>> 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<int, scoped_ptr<ScopedDestroyer>> 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<int, scoped_ptr<ScopedDestroyer>> 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<ScopedDestroyer> 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<int, scoped_ptr<ScopedDestroyer>> 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<int, scoped_ptr<ScopedDestroyer>, std::greater<int>> 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<int, scoped_ptr<ScopedDestroyer>> 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<int, scoped_ptr<ScopedDestroyer>> 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<int, scoped_ptr<ScopedDestroyer>> 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<int, scoped_ptr<ScopedDestroyer>> 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<int, scoped_ptr<ScopedDestroyer>> 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 <typename Key, typename ScopedPtr>
ScopedPtrMap<Key, ScopedPtr> PassThru(ScopedPtrMap<Key, ScopedPtr> scoper) {
return scoper;
}
TEST(ScopedPtrMapTest, Passed) {
bool destroyed = false;
ScopedPtrMap<int, scoped_ptr<ScopedDestroyer>> 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<ScopedPtrMap<int, scoped_ptr<ScopedDestroyer>>(void)>
callback = base::Bind(&PassThru<int, scoped_ptr<ScopedDestroyer>>,
base::Passed(&scoped_map));
EXPECT_TRUE(scoped_map.empty());
EXPECT_FALSE(destroyed);
ScopedPtrMap<int, scoped_ptr<ScopedDestroyer>> 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