pcsx-redux/tests/support/list.cc
Nicolas 'Pixel' Noble 0980fd3b1a Adding multilist test
2020-11-17 22:15:08 -08:00

359 lines
9.9 KiB
C++

/***************************************************************************
* Copyright (C) 2020 PCSX-Redux authors *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
***************************************************************************/
#include "support/list.h"
#include <algorithm>
#include "gtest/gtest.h"
struct ListElement;
typedef PCSX::Intrusive::List<ListElement> ListType;
struct ListElement : public ListType::Node {
ListElement(int tag = 0) : m_tag(tag) {}
int m_tag = 0;
};
TEST(BasicList, EmptyList) {
ListType list;
EXPECT_TRUE(list.empty());
}
TEST(BasicList, PushBackIterator) {
ListType list;
list.push_back(new ListElement(1));
list.push_back(new ListElement(2));
list.push_back(new ListElement(3));
EXPECT_FALSE(list.empty());
EXPECT_EQ(list.size(), 3);
ListType::iterator i = list.begin();
EXPECT_EQ(i->m_tag, 1);
i++;
EXPECT_EQ(i->m_tag, 2);
i++;
EXPECT_EQ(i->m_tag, 3);
EXPECT_TRUE(++i == list.end());
list.destroyAll();
EXPECT_TRUE(list.empty());
}
TEST(BasicList, PushFrontIterator) {
ListType list;
list.push_front(new ListElement(1));
list.push_front(new ListElement(2));
list.push_front(new ListElement(3));
EXPECT_FALSE(list.empty());
EXPECT_EQ(list.size(), 3);
ListType::iterator i = list.end();
i--;
EXPECT_EQ(i->m_tag, 1);
i--;
EXPECT_EQ(i->m_tag, 2);
i--;
EXPECT_EQ(i->m_tag, 3);
EXPECT_TRUE(i == list.begin());
list.destroyAll();
EXPECT_TRUE(list.empty());
}
TEST(BasicList, UseAfterDestroy) {
ListType list;
list.push_front(new ListElement(1));
list.push_front(new ListElement(2));
list.push_front(new ListElement(3));
list.destroyAll();
list.push_front(new ListElement(4));
list.push_front(new ListElement(5));
list.push_front(new ListElement(6));
EXPECT_FALSE(list.empty());
EXPECT_EQ(list.size(), 3);
ListType::iterator i = list.end();
i--;
EXPECT_EQ(i->m_tag, 4);
i--;
EXPECT_EQ(i->m_tag, 5);
i--;
EXPECT_EQ(i->m_tag, 6);
EXPECT_TRUE(i == list.begin());
list.destroyAll();
EXPECT_TRUE(list.empty());
}
TEST(AdvancedList, MoveElement) {
ListType list;
list.push_back(new ListElement(1));
list.push_back(new ListElement(2));
list.push_back(new ListElement(3));
auto i = std::find_if(list.begin(), list.end(), [](ListElement& e) { return e.m_tag == 2; });
list.push_front(&*i);
EXPECT_EQ(list.size(), 3);
i = list.begin();
EXPECT_EQ(i->m_tag, 2);
i++;
EXPECT_EQ(i->m_tag, 1);
i++;
EXPECT_EQ(i->m_tag, 3);
EXPECT_TRUE(++i == list.end());
list.destroyAll();
}
TEST(AdvancedList, TwoListsExclusive) {
ListType list1;
ListType list2;
ListElement *e1, *e2, *e3;
list1.push_back(e1 = new ListElement(1));
list1.push_back(e2 = new ListElement(2));
list1.push_back(e3 = new ListElement(3));
auto i = std::find_if(list1.begin(), list1.end(), [](ListElement& e) { return e.m_tag == 2; });
list2.push_front(&*i);
EXPECT_EQ(list1.size(), 2);
i = list1.begin();
EXPECT_EQ(i->m_tag, 1);
i++;
EXPECT_EQ(i->m_tag, 3);
EXPECT_TRUE(++i == list1.end());
EXPECT_EQ(list2.size(), 1);
i = list2.begin();
EXPECT_EQ(i->m_tag, 2);
EXPECT_TRUE(++i == list2.end());
EXPECT_TRUE(e1->isLinked());
EXPECT_TRUE(e2->isLinked());
EXPECT_TRUE(e3->isLinked());
EXPECT_TRUE(list1.contains(e1));
EXPECT_FALSE(list1.contains(e2));
EXPECT_TRUE(list1.contains(e3));
EXPECT_FALSE(list2.contains(e1));
EXPECT_TRUE(list2.contains(e2));
EXPECT_FALSE(list2.contains(e3));
list1.destroyAll();
list2.destroyAll();
}
TEST(AdvancedList, ListSwap) {
ListType list1, list2;
ListElement *e1, *e2, *e3;
list1.push_back(e1 = new ListElement(1));
list2.push_back(e2 = new ListElement(2));
list1.push_back(e3 = new ListElement(3));
EXPECT_EQ(list1.size(), 2);
auto i = list1.begin();
EXPECT_EQ(i->m_tag, 1);
i++;
EXPECT_EQ(i->m_tag, 3);
EXPECT_TRUE(++i == list1.end());
EXPECT_EQ(list2.size(), 1);
i = list2.begin();
EXPECT_EQ(i->m_tag, 2);
EXPECT_TRUE(++i == list2.end());
EXPECT_TRUE(list1.contains(e1));
EXPECT_FALSE(list1.contains(e2));
EXPECT_TRUE(list1.contains(e3));
EXPECT_FALSE(list2.contains(e1));
EXPECT_TRUE(list2.contains(e2));
EXPECT_FALSE(list2.contains(e3));
list1.swap(list2);
EXPECT_EQ(list2.size(), 2);
i = list2.begin();
EXPECT_EQ(i->m_tag, 1);
i++;
EXPECT_EQ(i->m_tag, 3);
EXPECT_TRUE(++i == list2.end());
EXPECT_EQ(list1.size(), 1);
i = list1.begin();
EXPECT_EQ(i->m_tag, 2);
EXPECT_TRUE(++i == list1.end());
EXPECT_TRUE(list2.contains(e1));
EXPECT_FALSE(list2.contains(e2));
EXPECT_TRUE(list2.contains(e3));
EXPECT_FALSE(list1.contains(e1));
EXPECT_TRUE(list1.contains(e2));
EXPECT_FALSE(list1.contains(e3));
list1.destroyAll();
list2.destroyAll();
}
TEST(AdvancedList, Append) {
ListType list1, list2;
ListElement *e1, *e2, *e3;
list1.push_back(e1 = new ListElement(1));
list2.push_back(e2 = new ListElement(2));
list1.push_back(e3 = new ListElement(3));
ListType swap;
swap.append(list1);
list1.append(list2);
list2.append(swap);
EXPECT_EQ(list2.size(), 2);
auto i = list2.begin();
EXPECT_EQ(i->m_tag, 1);
i++;
EXPECT_EQ(i->m_tag, 3);
EXPECT_TRUE(++i == list2.end());
EXPECT_EQ(list1.size(), 1);
i = list1.begin();
EXPECT_EQ(i->m_tag, 2);
EXPECT_TRUE(++i == list1.end());
EXPECT_TRUE(list2.contains(e1));
EXPECT_FALSE(list2.contains(e2));
EXPECT_TRUE(list2.contains(e3));
EXPECT_FALSE(list1.contains(e1));
EXPECT_TRUE(list1.contains(e2));
EXPECT_FALSE(list1.contains(e3));
list1.destroyAll();
list2.destroyAll();
}
TEST(AdvancedList, Prepend) {
ListType list1, list2;
ListElement *e1, *e2, *e3;
list1.push_back(e1 = new ListElement(1));
list2.push_back(e2 = new ListElement(2));
list1.push_back(e3 = new ListElement(3));
ListType swap;
swap.prepend(list1);
list1.prepend(list2);
list2.prepend(swap);
EXPECT_EQ(list2.size(), 2);
auto i = list2.begin();
EXPECT_EQ(i->m_tag, 1);
i++;
EXPECT_EQ(i->m_tag, 3);
EXPECT_TRUE(++i == list2.end());
EXPECT_EQ(list1.size(), 1);
i = list1.begin();
EXPECT_EQ(i->m_tag, 2);
EXPECT_TRUE(++i == list1.end());
EXPECT_TRUE(list2.contains(e1));
EXPECT_FALSE(list2.contains(e2));
EXPECT_TRUE(list2.contains(e3));
EXPECT_FALSE(list1.contains(e1));
EXPECT_TRUE(list1.contains(e2));
EXPECT_FALSE(list1.contains(e3));
list1.destroyAll();
list2.destroyAll();
}
TEST(AlgorithmList, FindIf) {
ListType list;
list.push_back(new ListElement(1));
auto e1 = --list.end();
list.push_back(new ListElement(2));
auto e2 = --list.end();
list.push_back(new ListElement(3));
auto e3 = --list.end();
auto i = list.begin();
auto f = std::find_if(list.begin(), list.end(), [](ListElement& e) { return e.m_tag == 1; });
EXPECT_TRUE(f == i);
EXPECT_TRUE(f == e1);
EXPECT_EQ(f->m_tag, 1);
i++;
f = std::find_if(list.begin(), list.end(), [](ListElement& e) { return e.m_tag == 2; });
EXPECT_TRUE(f == i);
EXPECT_TRUE(f == e2);
EXPECT_EQ(f->m_tag, 2);
i++;
f = std::find_if(list.begin(), list.end(), [](ListElement& e) { return e.m_tag == 3; });
EXPECT_TRUE(f == i);
EXPECT_TRUE(f == e3);
EXPECT_EQ(f->m_tag, 3);
list.destroyAll();
EXPECT_TRUE(list.empty());
}
struct MultiListElement;
struct List1 {};
struct List2 {};
typedef PCSX::Intrusive::List<MultiListElement> MultiListType;
typedef PCSX::Intrusive::List<MultiListElement, List1> MultiListType1;
typedef PCSX::Intrusive::List<MultiListElement, List2> MultiListType2;
struct MultiListElement : public MultiListType::Node, public MultiListType1::Node, public MultiListType2::Node {
MultiListElement(int tag = 0) : m_tag(tag) {}
int m_tag = 0;
};
TEST(MultiList, BasicMulti) {
MultiListType list;
MultiListType1 list1;
MultiListType2 list2;
{
MultiListElement e;
list.push_back(&e);
list1.push_back(&e);
list2.push_back(&e);
EXPECT_EQ(list.size(), 1);
EXPECT_EQ(list1.size(), 1);
EXPECT_EQ(list2.size(), 1);
EXPECT_TRUE(list.contains(&e));
EXPECT_TRUE(list1.contains(&e));
EXPECT_TRUE(list2.contains(&e));
list.clear();
EXPECT_EQ(list.size(), 0);
EXPECT_EQ(list1.size(), 1);
EXPECT_EQ(list2.size(), 1);
EXPECT_FALSE(list.contains(&e));
EXPECT_TRUE(list1.contains(&e));
EXPECT_TRUE(list2.contains(&e));
}
EXPECT_EQ(list.size(), 0);
EXPECT_EQ(list1.size(), 0);
EXPECT_EQ(list2.size(), 0);
}