1fd4e5da5Sopenharmony_ci// Copyright (c) 2017 Google Inc. 2fd4e5da5Sopenharmony_ci// 3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License. 5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at 6fd4e5da5Sopenharmony_ci// 7fd4e5da5Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8fd4e5da5Sopenharmony_ci// 9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and 13fd4e5da5Sopenharmony_ci// limitations under the License. 14fd4e5da5Sopenharmony_ci 15fd4e5da5Sopenharmony_ci#include <utility> 16fd4e5da5Sopenharmony_ci#include <vector> 17fd4e5da5Sopenharmony_ci 18fd4e5da5Sopenharmony_ci#include "gmock/gmock.h" 19fd4e5da5Sopenharmony_ci#include "source/util/ilist.h" 20fd4e5da5Sopenharmony_ci 21fd4e5da5Sopenharmony_cinamespace spvtools { 22fd4e5da5Sopenharmony_cinamespace utils { 23fd4e5da5Sopenharmony_cinamespace { 24fd4e5da5Sopenharmony_ci 25fd4e5da5Sopenharmony_ciusing ::testing::ElementsAre; 26fd4e5da5Sopenharmony_ciusing IListTest = ::testing::Test; 27fd4e5da5Sopenharmony_ci 28fd4e5da5Sopenharmony_ciclass TestNode : public IntrusiveNodeBase<TestNode> { 29fd4e5da5Sopenharmony_ci public: 30fd4e5da5Sopenharmony_ci TestNode() : IntrusiveNodeBase<TestNode>() {} 31fd4e5da5Sopenharmony_ci int data_; 32fd4e5da5Sopenharmony_ci}; 33fd4e5da5Sopenharmony_ci 34fd4e5da5Sopenharmony_ciclass TestList : public IntrusiveList<TestNode> { 35fd4e5da5Sopenharmony_ci public: 36fd4e5da5Sopenharmony_ci TestList() = default; 37fd4e5da5Sopenharmony_ci TestList(TestList&& that) : IntrusiveList<TestNode>(std::move(that)) {} 38fd4e5da5Sopenharmony_ci TestList& operator=(TestList&& that) { 39fd4e5da5Sopenharmony_ci static_cast<IntrusiveList<TestNode>&>(*this) = 40fd4e5da5Sopenharmony_ci static_cast<IntrusiveList<TestNode>&&>(that); 41fd4e5da5Sopenharmony_ci return *this; 42fd4e5da5Sopenharmony_ci } 43fd4e5da5Sopenharmony_ci}; 44fd4e5da5Sopenharmony_ci 45fd4e5da5Sopenharmony_ci// This test checks the push_back method, as well as using an iterator to 46fd4e5da5Sopenharmony_ci// traverse the list from begin() to end(). This implicitly test the 47fd4e5da5Sopenharmony_ci// PreviousNode and NextNode functions. 48fd4e5da5Sopenharmony_ciTEST(IListTest, PushBack) { 49fd4e5da5Sopenharmony_ci TestNode nodes[10]; 50fd4e5da5Sopenharmony_ci TestList list; 51fd4e5da5Sopenharmony_ci for (int i = 0; i < 10; i++) { 52fd4e5da5Sopenharmony_ci nodes[i].data_ = i; 53fd4e5da5Sopenharmony_ci list.push_back(&nodes[i]); 54fd4e5da5Sopenharmony_ci } 55fd4e5da5Sopenharmony_ci 56fd4e5da5Sopenharmony_ci std::vector<int> output; 57fd4e5da5Sopenharmony_ci for (auto& i : list) output.push_back(i.data_); 58fd4e5da5Sopenharmony_ci 59fd4e5da5Sopenharmony_ci EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); 60fd4e5da5Sopenharmony_ci} 61fd4e5da5Sopenharmony_ci 62fd4e5da5Sopenharmony_ci// Returns a list containing the values 0 to n-1 using the first n elements of 63fd4e5da5Sopenharmony_ci// nodes to build the list. 64fd4e5da5Sopenharmony_ciTestList BuildList(TestNode nodes[], int n) { 65fd4e5da5Sopenharmony_ci TestList list; 66fd4e5da5Sopenharmony_ci for (int i = 0; i < n; i++) { 67fd4e5da5Sopenharmony_ci nodes[i].data_ = i; 68fd4e5da5Sopenharmony_ci list.push_back(&nodes[i]); 69fd4e5da5Sopenharmony_ci } 70fd4e5da5Sopenharmony_ci return list; 71fd4e5da5Sopenharmony_ci} 72fd4e5da5Sopenharmony_ci 73fd4e5da5Sopenharmony_ci// Test decrementing begin() 74fd4e5da5Sopenharmony_ciTEST(IListTest, DecrementingBegin) { 75fd4e5da5Sopenharmony_ci TestNode nodes[10]; 76fd4e5da5Sopenharmony_ci TestList list = BuildList(nodes, 10); 77fd4e5da5Sopenharmony_ci EXPECT_EQ(--list.begin(), list.end()); 78fd4e5da5Sopenharmony_ci} 79fd4e5da5Sopenharmony_ci 80fd4e5da5Sopenharmony_ci// Test incrementing end() 81fd4e5da5Sopenharmony_ciTEST(IListTest, IncrementingEnd1) { 82fd4e5da5Sopenharmony_ci TestNode nodes[10]; 83fd4e5da5Sopenharmony_ci TestList list = BuildList(nodes, 10); 84fd4e5da5Sopenharmony_ci EXPECT_EQ((++list.end())->data_, 0); 85fd4e5da5Sopenharmony_ci} 86fd4e5da5Sopenharmony_ci 87fd4e5da5Sopenharmony_ci// Test incrementing end() should equal begin() 88fd4e5da5Sopenharmony_ciTEST(IListTest, IncrementingEnd2) { 89fd4e5da5Sopenharmony_ci TestNode nodes[10]; 90fd4e5da5Sopenharmony_ci TestList list = BuildList(nodes, 10); 91fd4e5da5Sopenharmony_ci EXPECT_EQ(++list.end(), list.begin()); 92fd4e5da5Sopenharmony_ci} 93fd4e5da5Sopenharmony_ci 94fd4e5da5Sopenharmony_ci// Test decrementing end() 95fd4e5da5Sopenharmony_ciTEST(IListTest, DecrementingEnd) { 96fd4e5da5Sopenharmony_ci TestNode nodes[10]; 97fd4e5da5Sopenharmony_ci TestList list = BuildList(nodes, 10); 98fd4e5da5Sopenharmony_ci EXPECT_EQ((--list.end())->data_, 9); 99fd4e5da5Sopenharmony_ci} 100fd4e5da5Sopenharmony_ci 101fd4e5da5Sopenharmony_ci// Test the move constructor for the list class. 102fd4e5da5Sopenharmony_ciTEST(IListTest, MoveConstructor) { 103fd4e5da5Sopenharmony_ci TestNode nodes[10]; 104fd4e5da5Sopenharmony_ci TestList list = BuildList(nodes, 10); 105fd4e5da5Sopenharmony_ci std::vector<int> output; 106fd4e5da5Sopenharmony_ci for (auto& i : list) output.push_back(i.data_); 107fd4e5da5Sopenharmony_ci 108fd4e5da5Sopenharmony_ci EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); 109fd4e5da5Sopenharmony_ci} 110fd4e5da5Sopenharmony_ci 111fd4e5da5Sopenharmony_ci// Using a const list so we can test the const_iterator. 112fd4e5da5Sopenharmony_ciTEST(IListTest, ConstIterator) { 113fd4e5da5Sopenharmony_ci TestNode nodes[10]; 114fd4e5da5Sopenharmony_ci const TestList list = BuildList(nodes, 10); 115fd4e5da5Sopenharmony_ci std::vector<int> output; 116fd4e5da5Sopenharmony_ci for (auto& i : list) output.push_back(i.data_); 117fd4e5da5Sopenharmony_ci 118fd4e5da5Sopenharmony_ci EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); 119fd4e5da5Sopenharmony_ci} 120fd4e5da5Sopenharmony_ci 121fd4e5da5Sopenharmony_ci// Uses the move assignement instead of the move constructor. 122fd4e5da5Sopenharmony_ciTEST(IListTest, MoveAssignment) { 123fd4e5da5Sopenharmony_ci TestNode nodes[10]; 124fd4e5da5Sopenharmony_ci TestList list; 125fd4e5da5Sopenharmony_ci list = BuildList(nodes, 10); 126fd4e5da5Sopenharmony_ci std::vector<int> output; 127fd4e5da5Sopenharmony_ci for (auto& i : list) output.push_back(i.data_); 128fd4e5da5Sopenharmony_ci 129fd4e5da5Sopenharmony_ci EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); 130fd4e5da5Sopenharmony_ci} 131fd4e5da5Sopenharmony_ci 132fd4e5da5Sopenharmony_ci// Test inserting a new element at the end of a list using the IntrusiveNodeBase 133fd4e5da5Sopenharmony_ci// "InsertAfter" function. 134fd4e5da5Sopenharmony_ciTEST(IListTest, InsertAfter1) { 135fd4e5da5Sopenharmony_ci TestNode nodes[10]; 136fd4e5da5Sopenharmony_ci TestList list = BuildList(nodes, 5); 137fd4e5da5Sopenharmony_ci 138fd4e5da5Sopenharmony_ci nodes[5].data_ = 5; 139fd4e5da5Sopenharmony_ci nodes[5].InsertAfter(&nodes[4]); 140fd4e5da5Sopenharmony_ci 141fd4e5da5Sopenharmony_ci std::vector<int> output; 142fd4e5da5Sopenharmony_ci for (auto& i : list) output.push_back(i.data_); 143fd4e5da5Sopenharmony_ci 144fd4e5da5Sopenharmony_ci EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5)); 145fd4e5da5Sopenharmony_ci} 146fd4e5da5Sopenharmony_ci 147fd4e5da5Sopenharmony_ci// Test inserting a new element in the middle of a list using the 148fd4e5da5Sopenharmony_ci// IntrusiveNodeBase "InsertAfter" function. 149fd4e5da5Sopenharmony_ciTEST(IListTest, InsertAfter2) { 150fd4e5da5Sopenharmony_ci TestNode nodes[10]; 151fd4e5da5Sopenharmony_ci TestList list = BuildList(nodes, 5); 152fd4e5da5Sopenharmony_ci 153fd4e5da5Sopenharmony_ci nodes[5].data_ = 5; 154fd4e5da5Sopenharmony_ci nodes[5].InsertAfter(&nodes[2]); 155fd4e5da5Sopenharmony_ci 156fd4e5da5Sopenharmony_ci std::vector<int> output; 157fd4e5da5Sopenharmony_ci for (auto& i : list) output.push_back(i.data_); 158fd4e5da5Sopenharmony_ci 159fd4e5da5Sopenharmony_ci EXPECT_THAT(output, ElementsAre(0, 1, 2, 5, 3, 4)); 160fd4e5da5Sopenharmony_ci} 161fd4e5da5Sopenharmony_ci 162fd4e5da5Sopenharmony_ci// Test moving an element already in the list in the middle of a list using the 163fd4e5da5Sopenharmony_ci// IntrusiveNodeBase "InsertAfter" function. 164fd4e5da5Sopenharmony_ciTEST(IListTest, MoveUsingInsertAfter1) { 165fd4e5da5Sopenharmony_ci TestNode nodes[10]; 166fd4e5da5Sopenharmony_ci TestList list = BuildList(nodes, 6); 167fd4e5da5Sopenharmony_ci 168fd4e5da5Sopenharmony_ci nodes[5].InsertAfter(&nodes[2]); 169fd4e5da5Sopenharmony_ci 170fd4e5da5Sopenharmony_ci std::vector<int> output; 171fd4e5da5Sopenharmony_ci for (auto& i : list) output.push_back(i.data_); 172fd4e5da5Sopenharmony_ci 173fd4e5da5Sopenharmony_ci EXPECT_THAT(output, ElementsAre(0, 1, 2, 5, 3, 4)); 174fd4e5da5Sopenharmony_ci} 175fd4e5da5Sopenharmony_ci 176fd4e5da5Sopenharmony_ci// Move the element at the start of the list into the middle. 177fd4e5da5Sopenharmony_ciTEST(IListTest, MoveUsingInsertAfter2) { 178fd4e5da5Sopenharmony_ci TestNode nodes[10]; 179fd4e5da5Sopenharmony_ci TestList list = BuildList(nodes, 6); 180fd4e5da5Sopenharmony_ci 181fd4e5da5Sopenharmony_ci nodes[0].InsertAfter(&nodes[2]); 182fd4e5da5Sopenharmony_ci 183fd4e5da5Sopenharmony_ci std::vector<int> output; 184fd4e5da5Sopenharmony_ci for (auto& i : list) output.push_back(i.data_); 185fd4e5da5Sopenharmony_ci 186fd4e5da5Sopenharmony_ci EXPECT_THAT(output, ElementsAre(1, 2, 0, 3, 4, 5)); 187fd4e5da5Sopenharmony_ci} 188fd4e5da5Sopenharmony_ci 189fd4e5da5Sopenharmony_ci// Move an element in the middle of the list to the end. 190fd4e5da5Sopenharmony_ciTEST(IListTest, MoveUsingInsertAfter3) { 191fd4e5da5Sopenharmony_ci TestNode nodes[10]; 192fd4e5da5Sopenharmony_ci TestList list = BuildList(nodes, 6); 193fd4e5da5Sopenharmony_ci 194fd4e5da5Sopenharmony_ci nodes[2].InsertAfter(&nodes[5]); 195fd4e5da5Sopenharmony_ci 196fd4e5da5Sopenharmony_ci std::vector<int> output; 197fd4e5da5Sopenharmony_ci for (auto& i : list) output.push_back(i.data_); 198fd4e5da5Sopenharmony_ci 199fd4e5da5Sopenharmony_ci EXPECT_THAT(output, ElementsAre(0, 1, 3, 4, 5, 2)); 200fd4e5da5Sopenharmony_ci} 201fd4e5da5Sopenharmony_ci 202fd4e5da5Sopenharmony_ci// Removing an element from the middle of a list. 203fd4e5da5Sopenharmony_ciTEST(IListTest, Remove1) { 204fd4e5da5Sopenharmony_ci TestNode nodes[10]; 205fd4e5da5Sopenharmony_ci TestList list = BuildList(nodes, 6); 206fd4e5da5Sopenharmony_ci 207fd4e5da5Sopenharmony_ci nodes[2].RemoveFromList(); 208fd4e5da5Sopenharmony_ci 209fd4e5da5Sopenharmony_ci std::vector<int> output; 210fd4e5da5Sopenharmony_ci for (auto& i : list) output.push_back(i.data_); 211fd4e5da5Sopenharmony_ci 212fd4e5da5Sopenharmony_ci EXPECT_THAT(output, ElementsAre(0, 1, 3, 4, 5)); 213fd4e5da5Sopenharmony_ci} 214fd4e5da5Sopenharmony_ci 215fd4e5da5Sopenharmony_ci// Removing an element from the beginning of the list. 216fd4e5da5Sopenharmony_ciTEST(IListTest, Remove2) { 217fd4e5da5Sopenharmony_ci TestNode nodes[10]; 218fd4e5da5Sopenharmony_ci TestList list = BuildList(nodes, 6); 219fd4e5da5Sopenharmony_ci 220fd4e5da5Sopenharmony_ci nodes[0].RemoveFromList(); 221fd4e5da5Sopenharmony_ci 222fd4e5da5Sopenharmony_ci std::vector<int> output; 223fd4e5da5Sopenharmony_ci for (auto& i : list) output.push_back(i.data_); 224fd4e5da5Sopenharmony_ci 225fd4e5da5Sopenharmony_ci EXPECT_THAT(output, ElementsAre(1, 2, 3, 4, 5)); 226fd4e5da5Sopenharmony_ci} 227fd4e5da5Sopenharmony_ci 228fd4e5da5Sopenharmony_ci// Removing the last element of a list. 229fd4e5da5Sopenharmony_ciTEST(IListTest, Remove3) { 230fd4e5da5Sopenharmony_ci TestNode nodes[10]; 231fd4e5da5Sopenharmony_ci TestList list = BuildList(nodes, 6); 232fd4e5da5Sopenharmony_ci 233fd4e5da5Sopenharmony_ci nodes[5].RemoveFromList(); 234fd4e5da5Sopenharmony_ci 235fd4e5da5Sopenharmony_ci std::vector<int> output; 236fd4e5da5Sopenharmony_ci for (auto& i : list) output.push_back(i.data_); 237fd4e5da5Sopenharmony_ci 238fd4e5da5Sopenharmony_ci EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4)); 239fd4e5da5Sopenharmony_ci} 240fd4e5da5Sopenharmony_ci 241fd4e5da5Sopenharmony_ci// Test that operator== and operator!= work properly for the iterator class. 242fd4e5da5Sopenharmony_ciTEST(IListTest, IteratorEqual) { 243fd4e5da5Sopenharmony_ci TestNode nodes[10]; 244fd4e5da5Sopenharmony_ci TestList list = BuildList(nodes, 6); 245fd4e5da5Sopenharmony_ci 246fd4e5da5Sopenharmony_ci std::vector<int> output; 247fd4e5da5Sopenharmony_ci for (auto i = list.begin(); i != list.end(); ++i) 248fd4e5da5Sopenharmony_ci for (auto j = list.begin(); j != list.end(); ++j) 249fd4e5da5Sopenharmony_ci if (i == j) output.push_back(i->data_); 250fd4e5da5Sopenharmony_ci 251fd4e5da5Sopenharmony_ci EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5)); 252fd4e5da5Sopenharmony_ci} 253fd4e5da5Sopenharmony_ci 254fd4e5da5Sopenharmony_ci// Test MoveBefore. Moving into middle of a list. 255fd4e5da5Sopenharmony_ciTEST(IListTest, MoveBefore1) { 256fd4e5da5Sopenharmony_ci TestNode nodes[10]; 257fd4e5da5Sopenharmony_ci TestList list1 = BuildList(nodes, 6); 258fd4e5da5Sopenharmony_ci TestList list2 = BuildList(nodes + 6, 3); 259fd4e5da5Sopenharmony_ci 260fd4e5da5Sopenharmony_ci TestList::iterator insertion_point = list1.begin(); 261fd4e5da5Sopenharmony_ci ++insertion_point; 262fd4e5da5Sopenharmony_ci insertion_point.MoveBefore(&list2); 263fd4e5da5Sopenharmony_ci 264fd4e5da5Sopenharmony_ci std::vector<int> output; 265fd4e5da5Sopenharmony_ci for (auto i = list1.begin(); i != list1.end(); ++i) { 266fd4e5da5Sopenharmony_ci output.push_back(i->data_); 267fd4e5da5Sopenharmony_ci } 268fd4e5da5Sopenharmony_ci 269fd4e5da5Sopenharmony_ci EXPECT_THAT(output, ElementsAre(0, 0, 1, 2, 1, 2, 3, 4, 5)); 270fd4e5da5Sopenharmony_ci} 271fd4e5da5Sopenharmony_ci 272fd4e5da5Sopenharmony_ci// Test MoveBefore. Moving to the start of a list. 273fd4e5da5Sopenharmony_ciTEST(IListTest, MoveBefore2) { 274fd4e5da5Sopenharmony_ci TestNode nodes[10]; 275fd4e5da5Sopenharmony_ci TestList list1 = BuildList(nodes, 6); 276fd4e5da5Sopenharmony_ci TestList list2 = BuildList(nodes + 6, 3); 277fd4e5da5Sopenharmony_ci 278fd4e5da5Sopenharmony_ci TestList::iterator insertion_point = list1.begin(); 279fd4e5da5Sopenharmony_ci insertion_point.MoveBefore(&list2); 280fd4e5da5Sopenharmony_ci 281fd4e5da5Sopenharmony_ci std::vector<int> output; 282fd4e5da5Sopenharmony_ci for (auto i = list1.begin(); i != list1.end(); ++i) { 283fd4e5da5Sopenharmony_ci output.push_back(i->data_); 284fd4e5da5Sopenharmony_ci } 285fd4e5da5Sopenharmony_ci 286fd4e5da5Sopenharmony_ci EXPECT_THAT(output, ElementsAre(0, 1, 2, 0, 1, 2, 3, 4, 5)); 287fd4e5da5Sopenharmony_ci} 288fd4e5da5Sopenharmony_ci 289fd4e5da5Sopenharmony_ci// Test MoveBefore. Moving to the end of a list. 290fd4e5da5Sopenharmony_ciTEST(IListTest, MoveBefore3) { 291fd4e5da5Sopenharmony_ci TestNode nodes[10]; 292fd4e5da5Sopenharmony_ci TestList list1 = BuildList(nodes, 6); 293fd4e5da5Sopenharmony_ci TestList list2 = BuildList(nodes + 6, 3); 294fd4e5da5Sopenharmony_ci 295fd4e5da5Sopenharmony_ci TestList::iterator insertion_point = list1.end(); 296fd4e5da5Sopenharmony_ci insertion_point.MoveBefore(&list2); 297fd4e5da5Sopenharmony_ci 298fd4e5da5Sopenharmony_ci std::vector<int> output; 299fd4e5da5Sopenharmony_ci for (auto i = list1.begin(); i != list1.end(); ++i) { 300fd4e5da5Sopenharmony_ci output.push_back(i->data_); 301fd4e5da5Sopenharmony_ci } 302fd4e5da5Sopenharmony_ci 303fd4e5da5Sopenharmony_ci EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5, 0, 1, 2)); 304fd4e5da5Sopenharmony_ci} 305fd4e5da5Sopenharmony_ci 306fd4e5da5Sopenharmony_ci// Test MoveBefore. Moving an empty list. 307fd4e5da5Sopenharmony_ciTEST(IListTest, MoveBefore4) { 308fd4e5da5Sopenharmony_ci TestNode nodes[10]; 309fd4e5da5Sopenharmony_ci TestList list1 = BuildList(nodes, 6); 310fd4e5da5Sopenharmony_ci TestList list2; 311fd4e5da5Sopenharmony_ci 312fd4e5da5Sopenharmony_ci TestList::iterator insertion_point = list1.end(); 313fd4e5da5Sopenharmony_ci insertion_point.MoveBefore(&list2); 314fd4e5da5Sopenharmony_ci 315fd4e5da5Sopenharmony_ci std::vector<int> output; 316fd4e5da5Sopenharmony_ci for (auto i = list1.begin(); i != list1.end(); ++i) { 317fd4e5da5Sopenharmony_ci output.push_back(i->data_); 318fd4e5da5Sopenharmony_ci } 319fd4e5da5Sopenharmony_ci 320fd4e5da5Sopenharmony_ci EXPECT_THAT(output, ElementsAre(0, 1, 2, 3, 4, 5)); 321fd4e5da5Sopenharmony_ci} 322fd4e5da5Sopenharmony_ci 323fd4e5da5Sopenharmony_ci} // namespace 324fd4e5da5Sopenharmony_ci} // namespace utils 325fd4e5da5Sopenharmony_ci} // namespace spvtools 326