mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
721 lines
18 KiB
C++
721 lines
18 KiB
C++
/*
|
|
* Copyright (C) 2012 Apple Inc. All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
|
|
#include <gtest/gtest.h>
|
|
#include "flutter/sky/engine/wtf/LinkedHashSet.h"
|
|
#include "flutter/sky/engine/wtf/ListHashSet.h"
|
|
#include "flutter/sky/engine/wtf/PassRefPtr.h"
|
|
#include "flutter/sky/engine/wtf/RefCounted.h"
|
|
#include "flutter/sky/engine/wtf/RefPtr.h"
|
|
|
|
namespace {
|
|
|
|
template<typename Set>
|
|
void removeFirstHelper()
|
|
{
|
|
Set list;
|
|
list.add(-1);
|
|
list.add(0);
|
|
list.add(1);
|
|
list.add(2);
|
|
list.add(3);
|
|
|
|
EXPECT_EQ(-1, list.first());
|
|
EXPECT_EQ(3, list.last());
|
|
|
|
list.removeFirst();
|
|
EXPECT_EQ(0, list.first());
|
|
|
|
list.removeLast();
|
|
EXPECT_EQ(2, list.last());
|
|
|
|
list.removeFirst();
|
|
EXPECT_EQ(1, list.first());
|
|
|
|
list.removeFirst();
|
|
EXPECT_EQ(2, list.first());
|
|
|
|
list.removeFirst();
|
|
EXPECT_TRUE(list.isEmpty());
|
|
}
|
|
|
|
TEST(ListHashSetTest, RemoveFirst)
|
|
{
|
|
removeFirstHelper<ListHashSet<int> >();
|
|
removeFirstHelper<ListHashSet<int, 1> >();
|
|
}
|
|
|
|
TEST(LinkedHashSetTest, RemoveFirst)
|
|
{
|
|
removeFirstHelper<LinkedHashSet<int> >();
|
|
}
|
|
|
|
template<typename Set>
|
|
void appendOrMoveToLastNewItems()
|
|
{
|
|
Set list;
|
|
typename Set::AddResult result = list.appendOrMoveToLast(1);
|
|
EXPECT_TRUE(result.isNewEntry);
|
|
result = list.add(2);
|
|
EXPECT_TRUE(result.isNewEntry);
|
|
result = list.appendOrMoveToLast(3);
|
|
EXPECT_TRUE(result.isNewEntry);
|
|
|
|
EXPECT_EQ(list.size(), 3UL);
|
|
|
|
// The list should be in order 1, 2, 3.
|
|
typename Set::iterator iterator = list.begin();
|
|
EXPECT_EQ(1, *iterator);
|
|
++iterator;
|
|
EXPECT_EQ(2, *iterator);
|
|
++iterator;
|
|
EXPECT_EQ(3, *iterator);
|
|
++iterator;
|
|
}
|
|
|
|
TEST(ListHashSetTest, AppendOrMoveToLastNewItems)
|
|
{
|
|
appendOrMoveToLastNewItems<ListHashSet<int> >();
|
|
appendOrMoveToLastNewItems<ListHashSet<int, 1> >();
|
|
}
|
|
|
|
TEST(LinkedHashSetTest, AppendOrMoveToLastNewItems)
|
|
{
|
|
appendOrMoveToLastNewItems<LinkedHashSet<int> >();
|
|
}
|
|
|
|
template<typename Set>
|
|
void appendOrMoveToLastWithDuplicates()
|
|
{
|
|
Set list;
|
|
|
|
// Add a single element twice.
|
|
typename Set::AddResult result = list.add(1);
|
|
EXPECT_TRUE(result.isNewEntry);
|
|
result = list.appendOrMoveToLast(1);
|
|
EXPECT_FALSE(result.isNewEntry);
|
|
EXPECT_EQ(1UL, list.size());
|
|
|
|
list.add(2);
|
|
list.add(3);
|
|
EXPECT_EQ(3UL, list.size());
|
|
|
|
// Appending 2 move it to the end.
|
|
EXPECT_EQ(3, list.last());
|
|
result = list.appendOrMoveToLast(2);
|
|
EXPECT_FALSE(result.isNewEntry);
|
|
EXPECT_EQ(2, list.last());
|
|
|
|
// Inverse the list by moving each element to end end.
|
|
result = list.appendOrMoveToLast(3);
|
|
EXPECT_FALSE(result.isNewEntry);
|
|
result = list.appendOrMoveToLast(2);
|
|
EXPECT_FALSE(result.isNewEntry);
|
|
result = list.appendOrMoveToLast(1);
|
|
EXPECT_FALSE(result.isNewEntry);
|
|
EXPECT_EQ(3UL, list.size());
|
|
|
|
typename Set::iterator iterator = list.begin();
|
|
EXPECT_EQ(3, *iterator);
|
|
++iterator;
|
|
EXPECT_EQ(2, *iterator);
|
|
++iterator;
|
|
EXPECT_EQ(1, *iterator);
|
|
++iterator;
|
|
}
|
|
|
|
TEST(ListHashSetTest, AppendOrMoveToLastWithDuplicates)
|
|
{
|
|
appendOrMoveToLastWithDuplicates<ListHashSet<int> >();
|
|
appendOrMoveToLastWithDuplicates<ListHashSet<int, 1> >();
|
|
}
|
|
|
|
TEST(LinkedHashSetTest, AppendOrMoveToLastWithDuplicates)
|
|
{
|
|
appendOrMoveToLastWithDuplicates<LinkedHashSet<int> >();
|
|
}
|
|
|
|
template<typename Set>
|
|
void prependOrMoveToFirstNewItems()
|
|
{
|
|
Set list;
|
|
typename Set::AddResult result = list.prependOrMoveToFirst(1);
|
|
EXPECT_TRUE(result.isNewEntry);
|
|
result = list.add(2);
|
|
EXPECT_TRUE(result.isNewEntry);
|
|
result = list.prependOrMoveToFirst(3);
|
|
EXPECT_TRUE(result.isNewEntry);
|
|
|
|
EXPECT_EQ(list.size(), 3UL);
|
|
|
|
// The list should be in order 3, 1, 2.
|
|
typename Set::iterator iterator = list.begin();
|
|
EXPECT_EQ(3, *iterator);
|
|
++iterator;
|
|
EXPECT_EQ(1, *iterator);
|
|
++iterator;
|
|
EXPECT_EQ(2, *iterator);
|
|
++iterator;
|
|
}
|
|
|
|
TEST(ListHashSetTest, PrependOrMoveToFirstNewItems)
|
|
{
|
|
prependOrMoveToFirstNewItems<ListHashSet<int> >();
|
|
prependOrMoveToFirstNewItems<ListHashSet<int, 1> >();
|
|
}
|
|
|
|
TEST(LinkedHashSetTest, PrependOrMoveToFirstNewItems)
|
|
{
|
|
prependOrMoveToFirstNewItems<LinkedHashSet<int> >();
|
|
}
|
|
|
|
template<typename Set>
|
|
void prependOrMoveToLastWithDuplicates()
|
|
{
|
|
Set list;
|
|
|
|
// Add a single element twice.
|
|
typename Set::AddResult result = list.add(1);
|
|
EXPECT_TRUE(result.isNewEntry);
|
|
result = list.prependOrMoveToFirst(1);
|
|
EXPECT_FALSE(result.isNewEntry);
|
|
EXPECT_EQ(1UL, list.size());
|
|
|
|
list.add(2);
|
|
list.add(3);
|
|
EXPECT_EQ(3UL, list.size());
|
|
|
|
// Prepending 2 move it to the beginning.
|
|
EXPECT_EQ(1, list.first());
|
|
result = list.prependOrMoveToFirst(2);
|
|
EXPECT_FALSE(result.isNewEntry);
|
|
EXPECT_EQ(2, list.first());
|
|
|
|
// Inverse the list by moving each element to the first position.
|
|
result = list.prependOrMoveToFirst(1);
|
|
EXPECT_FALSE(result.isNewEntry);
|
|
result = list.prependOrMoveToFirst(2);
|
|
EXPECT_FALSE(result.isNewEntry);
|
|
result = list.prependOrMoveToFirst(3);
|
|
EXPECT_FALSE(result.isNewEntry);
|
|
EXPECT_EQ(3UL, list.size());
|
|
|
|
typename Set::iterator iterator = list.begin();
|
|
EXPECT_EQ(3, *iterator);
|
|
++iterator;
|
|
EXPECT_EQ(2, *iterator);
|
|
++iterator;
|
|
EXPECT_EQ(1, *iterator);
|
|
++iterator;
|
|
}
|
|
|
|
TEST(ListHashSetTest, PrependOrMoveToLastWithDuplicates)
|
|
{
|
|
prependOrMoveToLastWithDuplicates<ListHashSet<int> >();
|
|
prependOrMoveToLastWithDuplicates<ListHashSet<int, 1> >();
|
|
}
|
|
|
|
TEST(LinkedHashSetTest, PrependOrMoveToLastWithDuplicates)
|
|
{
|
|
prependOrMoveToLastWithDuplicates<LinkedHashSet<int> >();
|
|
}
|
|
|
|
class DummyRefCounted: public WTF::RefCounted<DummyRefCounted> {
|
|
public:
|
|
DummyRefCounted(bool& isDeleted) : m_isDeleted(isDeleted) { m_isDeleted = false; }
|
|
~DummyRefCounted() { m_isDeleted = true; }
|
|
void ref()
|
|
{
|
|
WTF::RefCounted<DummyRefCounted>::ref();
|
|
++m_refInvokesCount;
|
|
}
|
|
|
|
static int m_refInvokesCount;
|
|
|
|
private:
|
|
bool& m_isDeleted;
|
|
};
|
|
|
|
int DummyRefCounted::m_refInvokesCount = 0;
|
|
|
|
template<typename Set>
|
|
void withRefPtr()
|
|
{
|
|
bool isDeleted = false;
|
|
DummyRefCounted::m_refInvokesCount = 0;
|
|
RefPtr<DummyRefCounted> ptr = adoptRef(new DummyRefCounted(isDeleted));
|
|
EXPECT_EQ(0, DummyRefCounted::m_refInvokesCount);
|
|
|
|
Set set;
|
|
set.add(ptr);
|
|
// Referenced only once (to store a copy in the container).
|
|
EXPECT_EQ(1, DummyRefCounted::m_refInvokesCount);
|
|
EXPECT_EQ(ptr, set.first());
|
|
EXPECT_EQ(1, DummyRefCounted::m_refInvokesCount);
|
|
|
|
DummyRefCounted* rawPtr = ptr.get();
|
|
|
|
EXPECT_TRUE(set.contains(ptr));
|
|
EXPECT_TRUE(set.contains(rawPtr));
|
|
EXPECT_EQ(1, DummyRefCounted::m_refInvokesCount);
|
|
|
|
ptr.clear();
|
|
EXPECT_FALSE(isDeleted);
|
|
EXPECT_EQ(1, DummyRefCounted::m_refInvokesCount);
|
|
|
|
set.remove(rawPtr);
|
|
EXPECT_TRUE(isDeleted);
|
|
|
|
EXPECT_EQ(1, DummyRefCounted::m_refInvokesCount);
|
|
}
|
|
|
|
TEST(ListHashSetTest, WithRefPtr)
|
|
{
|
|
withRefPtr<ListHashSet<RefPtr<DummyRefCounted> > >();
|
|
withRefPtr<ListHashSet<RefPtr<DummyRefCounted>, 1> >();
|
|
}
|
|
|
|
TEST(LinkedHashSetTest, WithRefPtr)
|
|
{
|
|
withRefPtr<LinkedHashSet<RefPtr<DummyRefCounted> > >();
|
|
}
|
|
|
|
template<typename Set, typename SetRef, typename Iterator>
|
|
void findHelper()
|
|
{
|
|
Set set;
|
|
set.add(-1);
|
|
set.add(0);
|
|
set.add(1);
|
|
set.add(2);
|
|
set.add(3);
|
|
|
|
SetRef ref = set;
|
|
Iterator it = ref.find(2);
|
|
EXPECT_EQ(2, *it);
|
|
++it;
|
|
EXPECT_EQ(3, *it);
|
|
--it;
|
|
--it;
|
|
EXPECT_EQ(1, *it);
|
|
}
|
|
|
|
TEST(ListHashSetTest, Find)
|
|
{
|
|
findHelper<ListHashSet<int>, const ListHashSet<int>&, ListHashSet<int>::const_iterator>();
|
|
findHelper<ListHashSet<int>, ListHashSet<int>&, ListHashSet<int>::iterator>();
|
|
findHelper<ListHashSet<int, 1>, const ListHashSet<int, 1>&, ListHashSet<int, 1>::const_iterator>();
|
|
findHelper<ListHashSet<int, 1>, ListHashSet<int, 1>&, ListHashSet<int, 1>::iterator>();
|
|
}
|
|
|
|
TEST(LinkedHashSetTest, Find)
|
|
{
|
|
findHelper<LinkedHashSet<int>, const LinkedHashSet<int>&, LinkedHashSet<int>::const_iterator>();
|
|
findHelper<LinkedHashSet<int>, LinkedHashSet<int>&, LinkedHashSet<int>::iterator>();
|
|
}
|
|
|
|
template<typename Set>
|
|
void insertBeforeHelper(bool canModifyWhileIterating)
|
|
{
|
|
Set set;
|
|
set.add(-1);
|
|
set.add(0);
|
|
set.add(2);
|
|
set.add(3);
|
|
|
|
typename Set::iterator it = set.find(2);
|
|
EXPECT_EQ(2, *it);
|
|
set.insertBefore(it, 1);
|
|
if (!canModifyWhileIterating)
|
|
it = set.find(2);
|
|
++it;
|
|
EXPECT_EQ(3, *it);
|
|
EXPECT_EQ(5u, set.size());
|
|
--it;
|
|
--it;
|
|
EXPECT_EQ(1, *it);
|
|
if (canModifyWhileIterating) {
|
|
set.remove(-1);
|
|
set.remove(0);
|
|
set.remove(2);
|
|
set.remove(3);
|
|
EXPECT_EQ(1u, set.size());
|
|
EXPECT_EQ(1, *it);
|
|
++it;
|
|
EXPECT_EQ(it, set.end());
|
|
--it;
|
|
EXPECT_EQ(1, *it);
|
|
set.insertBefore(it, -1);
|
|
set.insertBefore(it, 0);
|
|
set.add(2);
|
|
set.add(3);
|
|
}
|
|
set.insertBefore(2, 42);
|
|
set.insertBefore(-1, 103);
|
|
EXPECT_EQ(103, set.first());
|
|
if (!canModifyWhileIterating)
|
|
it = set.find(1);
|
|
++it;
|
|
EXPECT_EQ(42, *it);
|
|
EXPECT_EQ(7u, set.size());
|
|
}
|
|
|
|
TEST(ListHashSetTest, InsertBefore)
|
|
{
|
|
insertBeforeHelper<ListHashSet<int> >(true);
|
|
insertBeforeHelper<ListHashSet<int, 1> >(true);
|
|
}
|
|
|
|
TEST(LinkedHashSetTest, InsertBefore)
|
|
{
|
|
insertBeforeHelper<LinkedHashSet<int> >(false);
|
|
}
|
|
|
|
template<typename Set>
|
|
void addReturnIterator(bool canModifyWhileIterating)
|
|
{
|
|
Set set;
|
|
set.add(-1);
|
|
set.add(0);
|
|
set.add(1);
|
|
set.add(2);
|
|
|
|
typename Set::iterator it = set.addReturnIterator(3);
|
|
EXPECT_EQ(3, *it);
|
|
--it;
|
|
EXPECT_EQ(2, *it);
|
|
EXPECT_EQ(5u, set.size());
|
|
--it;
|
|
EXPECT_EQ(1, *it);
|
|
--it;
|
|
EXPECT_EQ(0, *it);
|
|
it = set.addReturnIterator(4);
|
|
if (canModifyWhileIterating) {
|
|
set.remove(3);
|
|
set.remove(2);
|
|
set.remove(1);
|
|
set.remove(0);
|
|
set.remove(-1);
|
|
EXPECT_EQ(1u, set.size());
|
|
}
|
|
EXPECT_EQ(4, *it);
|
|
++it;
|
|
EXPECT_EQ(it, set.end());
|
|
--it;
|
|
EXPECT_EQ(4, *it);
|
|
if (canModifyWhileIterating) {
|
|
set.insertBefore(it, -1);
|
|
set.insertBefore(it, 0);
|
|
set.insertBefore(it, 1);
|
|
set.insertBefore(it, 2);
|
|
set.insertBefore(it, 3);
|
|
}
|
|
EXPECT_EQ(6u, set.size());
|
|
it = set.addReturnIterator(5);
|
|
EXPECT_EQ(7u, set.size());
|
|
set.remove(it);
|
|
EXPECT_EQ(6u, set.size());
|
|
EXPECT_EQ(4, set.last());
|
|
}
|
|
|
|
TEST(ListHashSetTest, AddReturnIterator)
|
|
{
|
|
addReturnIterator<ListHashSet<int> >(true);
|
|
addReturnIterator<ListHashSet<int, 1> >(true);
|
|
}
|
|
|
|
TEST(LinkedHashSetTest, AddReturnIterator)
|
|
{
|
|
addReturnIterator<LinkedHashSet<int> >(false);
|
|
}
|
|
|
|
template<typename Set>
|
|
void excerciseValuePeekInType()
|
|
{
|
|
Set set;
|
|
bool isDeleted = false;
|
|
bool isDeleted2 = false;
|
|
|
|
RefPtr<DummyRefCounted> ptr = adoptRef(new DummyRefCounted(isDeleted));
|
|
RefPtr<DummyRefCounted> ptr2 = adoptRef(new DummyRefCounted(isDeleted2));
|
|
|
|
typename Set::AddResult addResult = set.add(ptr);
|
|
EXPECT_TRUE(addResult.isNewEntry);
|
|
set.find(ptr);
|
|
const Set& constSet(set);
|
|
constSet.find(ptr);
|
|
EXPECT_TRUE(set.contains(ptr));
|
|
typename Set::iterator it = set.addReturnIterator(ptr);
|
|
set.appendOrMoveToLast(ptr);
|
|
set.prependOrMoveToFirst(ptr);
|
|
set.insertBefore(ptr, ptr);
|
|
set.insertBefore(it, ptr);
|
|
EXPECT_EQ(1u, set.size());
|
|
set.add(ptr2);
|
|
ptr2.clear();
|
|
set.remove(ptr);
|
|
|
|
EXPECT_FALSE(isDeleted);
|
|
ptr.clear();
|
|
EXPECT_TRUE(isDeleted);
|
|
|
|
EXPECT_FALSE(isDeleted2);
|
|
set.removeFirst();
|
|
EXPECT_TRUE(isDeleted2);
|
|
|
|
EXPECT_EQ(0u, set.size());
|
|
}
|
|
|
|
TEST(ListHashSetTest, ExcerciseValuePeekInType)
|
|
{
|
|
excerciseValuePeekInType<ListHashSet<RefPtr<DummyRefCounted> > >();
|
|
excerciseValuePeekInType<ListHashSet<RefPtr<DummyRefCounted>, 1> >();
|
|
}
|
|
|
|
TEST(LinkedHashSetTest, ExcerciseValuePeekInType)
|
|
{
|
|
excerciseValuePeekInType<LinkedHashSet<RefPtr<DummyRefCounted> > >();
|
|
}
|
|
|
|
struct Simple {
|
|
Simple(int value) : m_value(value) { };
|
|
int m_value;
|
|
};
|
|
|
|
struct Complicated {
|
|
Complicated(int value) : m_simple(value)
|
|
{
|
|
s_objectsConstructed++;
|
|
}
|
|
|
|
Complicated(const Complicated& other) : m_simple(other.m_simple)
|
|
{
|
|
s_objectsConstructed++;
|
|
}
|
|
|
|
Simple m_simple;
|
|
static int s_objectsConstructed;
|
|
|
|
private:
|
|
Complicated();
|
|
};
|
|
|
|
int Complicated::s_objectsConstructed = 0;
|
|
|
|
struct ComplicatedHashFunctions {
|
|
static unsigned hash(const Complicated& key) { return key.m_simple.m_value; }
|
|
static bool equal(const Complicated& a, const Complicated& b) { return a.m_simple.m_value == b.m_simple.m_value; }
|
|
};
|
|
struct ComplexityTranslator {
|
|
static unsigned hash(const Simple& key) { return key.m_value; }
|
|
static bool equal(const Complicated& a, const Simple& b) { return a.m_simple.m_value == b.m_value; }
|
|
};
|
|
|
|
template<typename Set>
|
|
void translatorTest()
|
|
{
|
|
Set set;
|
|
set.add(Complicated(42));
|
|
int baseLine = Complicated::s_objectsConstructed;
|
|
|
|
typename Set::iterator it = set.template find<ComplexityTranslator>(Simple(42));
|
|
EXPECT_NE(it, set.end());
|
|
EXPECT_EQ(baseLine, Complicated::s_objectsConstructed);
|
|
|
|
it = set.template find<ComplexityTranslator>(Simple(103));
|
|
EXPECT_EQ(it, set.end());
|
|
EXPECT_EQ(baseLine, Complicated::s_objectsConstructed);
|
|
|
|
const Set& constSet(set);
|
|
|
|
typename Set::const_iterator constIterator = constSet.template find<ComplexityTranslator>(Simple(42));
|
|
EXPECT_NE(constIterator, constSet.end());
|
|
EXPECT_EQ(baseLine, Complicated::s_objectsConstructed);
|
|
|
|
constIterator = constSet.template find<ComplexityTranslator>(Simple(103));
|
|
EXPECT_EQ(constIterator, constSet.end());
|
|
EXPECT_EQ(baseLine, Complicated::s_objectsConstructed);
|
|
}
|
|
|
|
TEST(ListHashSetTest, ComplexityTranslator)
|
|
{
|
|
translatorTest<ListHashSet<Complicated, 256, ComplicatedHashFunctions> >();
|
|
translatorTest<ListHashSet<Complicated, 1, ComplicatedHashFunctions> >();
|
|
}
|
|
|
|
TEST(LinkedHashSetTest, ComplexityTranslator)
|
|
{
|
|
translatorTest<LinkedHashSet<Complicated, ComplicatedHashFunctions> >();
|
|
}
|
|
|
|
struct Dummy {
|
|
Dummy(bool& deleted) : deleted(deleted) { }
|
|
|
|
~Dummy()
|
|
{
|
|
deleted = true;
|
|
}
|
|
|
|
bool& deleted;
|
|
};
|
|
|
|
TEST(ListHashSetTest, WithOwnPtr)
|
|
{
|
|
bool deleted1 = false, deleted2 = false;
|
|
|
|
typedef ListHashSet<OwnPtr<Dummy> > OwnPtrSet;
|
|
OwnPtrSet set;
|
|
|
|
Dummy* ptr1 = new Dummy(deleted1);
|
|
{
|
|
// AddResult in a separate scope to avoid assertion hit,
|
|
// since we modify the container further.
|
|
OwnPtrSet::AddResult res1 = set.add(adoptPtr(ptr1));
|
|
EXPECT_EQ(res1.storedValue->m_value.get(), ptr1);
|
|
}
|
|
|
|
EXPECT_FALSE(deleted1);
|
|
EXPECT_EQ(1UL, set.size());
|
|
OwnPtrSet::iterator it1 = set.find(ptr1);
|
|
EXPECT_NE(set.end(), it1);
|
|
EXPECT_EQ(ptr1, (*it1));
|
|
|
|
Dummy* ptr2 = new Dummy(deleted2);
|
|
{
|
|
OwnPtrSet::AddResult res2 = set.add(adoptPtr(ptr2));
|
|
EXPECT_EQ(res2.storedValue->m_value.get(), ptr2);
|
|
}
|
|
|
|
EXPECT_FALSE(deleted2);
|
|
EXPECT_EQ(2UL, set.size());
|
|
OwnPtrSet::iterator it2 = set.find(ptr2);
|
|
EXPECT_NE(set.end(), it2);
|
|
EXPECT_EQ(ptr2, (*it2));
|
|
|
|
set.remove(ptr1);
|
|
EXPECT_TRUE(deleted1);
|
|
|
|
set.clear();
|
|
EXPECT_TRUE(deleted2);
|
|
EXPECT_TRUE(set.isEmpty());
|
|
|
|
deleted1 = false;
|
|
deleted2 = false;
|
|
{
|
|
OwnPtrSet set;
|
|
set.add(adoptPtr(new Dummy(deleted1)));
|
|
set.add(adoptPtr(new Dummy(deleted2)));
|
|
}
|
|
EXPECT_TRUE(deleted1);
|
|
EXPECT_TRUE(deleted2);
|
|
|
|
|
|
deleted1 = false;
|
|
deleted2 = false;
|
|
OwnPtr<Dummy> ownPtr1;
|
|
OwnPtr<Dummy> ownPtr2;
|
|
ptr1 = new Dummy(deleted1);
|
|
ptr2 = new Dummy(deleted2);
|
|
{
|
|
OwnPtrSet set;
|
|
set.add(adoptPtr(ptr1));
|
|
set.add(adoptPtr(ptr2));
|
|
ownPtr1 = set.takeFirst();
|
|
EXPECT_EQ(1UL, set.size());
|
|
ownPtr2 = set.take(ptr2);
|
|
EXPECT_TRUE(set.isEmpty());
|
|
}
|
|
EXPECT_FALSE(deleted1);
|
|
EXPECT_FALSE(deleted2);
|
|
|
|
EXPECT_EQ(ptr1, ownPtr1);
|
|
EXPECT_EQ(ptr2, ownPtr2);
|
|
}
|
|
|
|
template<typename Set>
|
|
void swapTestHelper()
|
|
{
|
|
int num = 10;
|
|
Set set0;
|
|
Set set1;
|
|
Set set2;
|
|
for (int i = 0; i < num; ++i) {
|
|
set1.add(i + 1);
|
|
set2.add(num - i);
|
|
}
|
|
|
|
typename Set::iterator it1 = set1.begin();
|
|
typename Set::iterator it2 = set2.begin();
|
|
for (int i = 0; i < num; ++i, ++it1, ++it2) {
|
|
EXPECT_EQ(*it1, i + 1);
|
|
EXPECT_EQ(*it2, num - i);
|
|
}
|
|
EXPECT_EQ(set0.begin(), set0.end());
|
|
EXPECT_EQ(it1, set1.end());
|
|
EXPECT_EQ(it2, set2.end());
|
|
|
|
// Shift sets: 2->1, 1->0, 0->2
|
|
set1.swap(set2); // Swap with non-empty sets.
|
|
set0.swap(set2); // Swap with an empty set.
|
|
|
|
it1 = set0.begin();
|
|
it2 = set1.begin();
|
|
for (int i = 0; i < num; ++i, ++it1, ++it2) {
|
|
EXPECT_EQ(*it1, i + 1);
|
|
EXPECT_EQ(*it2, num - i);
|
|
}
|
|
EXPECT_EQ(it1, set0.end());
|
|
EXPECT_EQ(it2, set1.end());
|
|
EXPECT_EQ(set2.begin(), set2.end());
|
|
|
|
int removedIndex = num >> 1;
|
|
set0.remove(removedIndex + 1);
|
|
set1.remove(num - removedIndex);
|
|
|
|
it1 = set0.begin();
|
|
it2 = set1.begin();
|
|
for (int i = 0; i < num; ++i, ++it1, ++it2) {
|
|
if (i == removedIndex)
|
|
++i;
|
|
EXPECT_EQ(*it1, i + 1);
|
|
EXPECT_EQ(*it2, num - i);
|
|
}
|
|
EXPECT_EQ(it1, set0.end());
|
|
EXPECT_EQ(it2, set1.end());
|
|
}
|
|
|
|
TEST(ListHashSetTest, Swap)
|
|
{
|
|
swapTestHelper<ListHashSet<int> >();
|
|
}
|
|
|
|
TEST(LinkedHashSetTest, Swap)
|
|
{
|
|
swapTestHelper<LinkedHashSet<int> >();
|
|
}
|
|
|
|
} // namespace
|