blob: d7cf980d1dd696324e0f58162112b2532332d615 [file] [log] [blame]
Duncan P. N. Exon Smithfbdb2012016-08-30 00:18:43 +00001//===- unittests/ADT/IListTest.cpp - ilist unit tests ---------------------===//
Daniel Dunbar959ae592010-05-12 21:35:19 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Daniel Dunbar959ae592010-05-12 21:35:19 +000010#include "llvm/ADT/ilist.h"
Jakob Stoklund Olesenb8d29bf2012-12-18 19:28:37 +000011#include "llvm/ADT/STLExtras.h"
Chandler Carruthb034cb72013-01-02 10:26:28 +000012#include "llvm/ADT/ilist_node.h"
Chandler Carruth130cec22012-12-04 10:23:08 +000013#include "gtest/gtest.h"
14#include <ostream>
Daniel Dunbar959ae592010-05-12 21:35:19 +000015
16using namespace llvm;
17
18namespace {
19
20struct Node : ilist_node<Node> {
21 int Value;
22
23 Node() {}
David Blaikie0bc56da2015-03-04 17:01:18 +000024 Node(int Value) : Value(Value) {}
25 Node(const Node&) = default;
Jakob Stoklund Olesen4ccabc12013-01-04 22:35:42 +000026 ~Node() { Value = -1; }
Daniel Dunbar959ae592010-05-12 21:35:19 +000027};
28
Duncan P. N. Exon Smithfbdb2012016-08-30 00:18:43 +000029TEST(IListTest, Basic) {
Daniel Dunbar959ae592010-05-12 21:35:19 +000030 ilist<Node> List;
31 List.push_back(Node(1));
32 EXPECT_EQ(1, List.back().Value);
Duncan P. N. Exon Smith4042d912015-11-11 02:26:42 +000033 EXPECT_EQ(nullptr, List.getPrevNode(List.back()));
34 EXPECT_EQ(nullptr, List.getNextNode(List.back()));
Daniel Dunbar959ae592010-05-12 21:35:19 +000035
36 List.push_back(Node(2));
37 EXPECT_EQ(2, List.back().Value);
Duncan P. N. Exon Smith4042d912015-11-11 02:26:42 +000038 EXPECT_EQ(2, List.getNextNode(List.front())->Value);
39 EXPECT_EQ(1, List.getPrevNode(List.back())->Value);
Daniel Dunbar2842f252010-05-13 18:35:02 +000040
41 const ilist<Node> &ConstList = List;
42 EXPECT_EQ(2, ConstList.back().Value);
Duncan P. N. Exon Smith4042d912015-11-11 02:26:42 +000043 EXPECT_EQ(2, ConstList.getNextNode(ConstList.front())->Value);
44 EXPECT_EQ(1, ConstList.getPrevNode(ConstList.back())->Value);
Daniel Dunbar959ae592010-05-12 21:35:19 +000045}
46
Duncan P. N. Exon Smithfbdb2012016-08-30 00:18:43 +000047TEST(IListTest, SpliceOne) {
Jakob Stoklund Olesenb8d29bf2012-12-18 19:28:37 +000048 ilist<Node> List;
49 List.push_back(1);
50
51 // The single-element splice operation supports noops.
52 List.splice(List.begin(), List, List.begin());
53 EXPECT_EQ(1u, List.size());
54 EXPECT_EQ(1, List.front().Value);
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +000055 EXPECT_TRUE(std::next(List.begin()) == List.end());
Jakob Stoklund Olesenb8d29bf2012-12-18 19:28:37 +000056
57 // Altenative noop. Move the first element behind itself.
58 List.push_back(2);
59 List.push_back(3);
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +000060 List.splice(std::next(List.begin()), List, List.begin());
Jakob Stoklund Olesenb8d29bf2012-12-18 19:28:37 +000061 EXPECT_EQ(3u, List.size());
62 EXPECT_EQ(1, List.front().Value);
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +000063 EXPECT_EQ(2, std::next(List.begin())->Value);
Jakob Stoklund Olesenb8d29bf2012-12-18 19:28:37 +000064 EXPECT_EQ(3, List.back().Value);
65}
66
Duncan P. N. Exon Smithfbdb2012016-08-30 00:18:43 +000067TEST(IListTest, SpliceSwap) {
Duncan P. N. Exon Smith47416612016-08-17 02:08:08 +000068 ilist<Node> L;
69 Node N0(0);
70 Node N1(1);
71 L.insert(L.end(), &N0);
72 L.insert(L.end(), &N1);
73 EXPECT_EQ(0, L.front().Value);
74 EXPECT_EQ(1, L.back().Value);
75
76 L.splice(L.begin(), L, ++L.begin());
77 EXPECT_EQ(1, L.front().Value);
78 EXPECT_EQ(0, L.back().Value);
79
80 L.clearAndLeakNodesUnsafely();
81}
82
Duncan P. N. Exon Smithfbdb2012016-08-30 00:18:43 +000083TEST(IListTest, SpliceSwapOtherWay) {
Duncan P. N. Exon Smith47416612016-08-17 02:08:08 +000084 ilist<Node> L;
85 Node N0(0);
86 Node N1(1);
87 L.insert(L.end(), &N0);
88 L.insert(L.end(), &N1);
89 EXPECT_EQ(0, L.front().Value);
90 EXPECT_EQ(1, L.back().Value);
91
92 L.splice(L.end(), L, L.begin());
93 EXPECT_EQ(1, L.front().Value);
94 EXPECT_EQ(0, L.back().Value);
95
96 L.clearAndLeakNodesUnsafely();
97}
98
Duncan P. N. Exon Smithfbdb2012016-08-30 00:18:43 +000099TEST(IListTest, UnsafeClear) {
Jakob Stoklund Olesen4ccabc12013-01-04 22:35:42 +0000100 ilist<Node> List;
101
102 // Before even allocating a sentinel.
103 List.clearAndLeakNodesUnsafely();
104 EXPECT_EQ(0u, List.size());
105
106 // Empty list with sentinel.
107 ilist<Node>::iterator E = List.end();
108 List.clearAndLeakNodesUnsafely();
109 EXPECT_EQ(0u, List.size());
110 // The sentinel shouldn't change.
111 EXPECT_TRUE(E == List.end());
112
113 // List with contents.
114 List.push_back(1);
115 ASSERT_EQ(1u, List.size());
Duncan P. N. Exon Smithc8925b12015-10-20 18:30:20 +0000116 Node *N = &*List.begin();
Jakob Stoklund Olesen4ccabc12013-01-04 22:35:42 +0000117 EXPECT_EQ(1, N->Value);
118 List.clearAndLeakNodesUnsafely();
119 EXPECT_EQ(0u, List.size());
120 ASSERT_EQ(1, N->Value);
121 delete N;
122
123 // List is still functional.
124 List.push_back(5);
125 List.push_back(6);
126 ASSERT_EQ(2u, List.size());
127 EXPECT_EQ(5, List.front().Value);
128 EXPECT_EQ(6, List.back().Value);
129}
130
Duncan P. N. Exon Smith11cb5382016-08-19 20:17:23 +0000131struct Empty {};
Duncan P. N. Exon Smithfbdb2012016-08-30 00:18:43 +0000132TEST(IListTest, HasObsoleteCustomizationTrait) {
Duncan P. N. Exon Smith11cb5382016-08-19 20:17:23 +0000133 // Negative test for HasObsoleteCustomization.
134 static_assert(!ilist_detail::HasObsoleteCustomization<Empty, Node>::value,
135 "Empty has no customizations");
Daniel Dunbar959ae592010-05-12 21:35:19 +0000136}
Duncan P. N. Exon Smith11cb5382016-08-19 20:17:23 +0000137
138struct GetNext {
139 Node *getNext(Node *);
140};
Duncan P. N. Exon Smithfbdb2012016-08-30 00:18:43 +0000141TEST(IListTest, HasGetNextTrait) {
Duncan P. N. Exon Smith11cb5382016-08-19 20:17:23 +0000142 static_assert(ilist_detail::HasGetNext<GetNext, Node>::value,
143 "GetNext has a getNext(Node*)");
144 static_assert(ilist_detail::HasObsoleteCustomization<GetNext, Node>::value,
145 "Empty should be obsolete because of getNext()");
146
147 // Negative test for HasGetNext.
148 static_assert(!ilist_detail::HasGetNext<Empty, Node>::value,
149 "Empty does not have a getNext(Node*)");
150}
151
Duncan P. N. Exon Smith64093a32016-08-19 20:40:12 +0000152struct CreateSentinel {
153 Node *createSentinel();
154};
Duncan P. N. Exon Smithfbdb2012016-08-30 00:18:43 +0000155TEST(IListTest, HasCreateSentinelTrait) {
Duncan P. N. Exon Smith64093a32016-08-19 20:40:12 +0000156 static_assert(ilist_detail::HasCreateSentinel<CreateSentinel>::value,
157 "CreateSentinel has a getNext(Node*)");
158 static_assert(
159 ilist_detail::HasObsoleteCustomization<CreateSentinel, Node>::value,
160 "Empty should be obsolete because of createSentinel()");
161
162 // Negative test for HasCreateSentinel.
163 static_assert(!ilist_detail::HasCreateSentinel<Empty>::value,
164 "Empty does not have a createSentinel()");
165}
166
167struct NodeWithCallback : ilist_node<NodeWithCallback> {
168 int Value = 0;
169 bool IsInList = false;
Duncan P. N. Exon Smithf947c3a2016-08-30 18:40:47 +0000170 bool WasTransferred = false;
Duncan P. N. Exon Smith64093a32016-08-19 20:40:12 +0000171
172 NodeWithCallback() = default;
173 NodeWithCallback(int Value) : Value(Value) {}
174 NodeWithCallback(const NodeWithCallback &) = delete;
175};
176
177} // end namespace
178
179namespace llvm {
Duncan P. N. Exon Smithf947c3a2016-08-30 18:40:47 +0000180template <> struct ilist_callback_traits<NodeWithCallback> {
Duncan P. N. Exon Smith64093a32016-08-19 20:40:12 +0000181 void addNodeToList(NodeWithCallback *N) { N->IsInList = true; }
182 void removeNodeFromList(NodeWithCallback *N) { N->IsInList = false; }
Duncan P. N. Exon Smithf947c3a2016-08-30 18:40:47 +0000183 template <class Iterator>
184 void transferNodesFromList(ilist_callback_traits &Other, Iterator First,
185 Iterator Last) {
186 for (; First != Last; ++First) {
187 First->WasTransferred = true;
188 Other.removeNodeFromList(&*First);
189 addNodeToList(&*First);
190 }
191 }
Duncan P. N. Exon Smith64093a32016-08-19 20:40:12 +0000192};
193} // end namespace llvm
194
195namespace {
196
Duncan P. N. Exon Smithfbdb2012016-08-30 00:18:43 +0000197TEST(IListTest, addNodeToList) {
Duncan P. N. Exon Smithf947c3a2016-08-30 18:40:47 +0000198 ilist<NodeWithCallback> L1, L2;
Duncan P. N. Exon Smith64093a32016-08-19 20:40:12 +0000199 NodeWithCallback N(7);
200 ASSERT_FALSE(N.IsInList);
Duncan P. N. Exon Smithf947c3a2016-08-30 18:40:47 +0000201 ASSERT_FALSE(N.WasTransferred);
Duncan P. N. Exon Smith64093a32016-08-19 20:40:12 +0000202
Duncan P. N. Exon Smithf947c3a2016-08-30 18:40:47 +0000203 L1.insert(L1.begin(), &N);
204 ASSERT_EQ(1u, L1.size());
205 ASSERT_EQ(&N, &L1.front());
Duncan P. N. Exon Smith64093a32016-08-19 20:40:12 +0000206 ASSERT_TRUE(N.IsInList);
Duncan P. N. Exon Smithf947c3a2016-08-30 18:40:47 +0000207 ASSERT_FALSE(N.WasTransferred);
Duncan P. N. Exon Smith64093a32016-08-19 20:40:12 +0000208
Duncan P. N. Exon Smithf947c3a2016-08-30 18:40:47 +0000209 L2.splice(L2.end(), L1);
210 ASSERT_EQ(&N, &L2.front());
211 ASSERT_TRUE(N.IsInList);
212 ASSERT_TRUE(N.WasTransferred);
213
214 L1.remove(&N);
215 ASSERT_EQ(0u, L1.size());
Duncan P. N. Exon Smith64093a32016-08-19 20:40:12 +0000216 ASSERT_FALSE(N.IsInList);
Duncan P. N. Exon Smithf947c3a2016-08-30 18:40:47 +0000217 ASSERT_TRUE(N.WasTransferred);
Duncan P. N. Exon Smith64093a32016-08-19 20:40:12 +0000218}
219
220struct PrivateNode : private ilist_node<PrivateNode> {
221 friend struct llvm::ilist_node_access;
222
223 int Value = 0;
224
225 PrivateNode() = default;
226 PrivateNode(int Value) : Value(Value) {}
227 PrivateNode(const PrivateNode &) = delete;
228};
229
Duncan P. N. Exon Smithfbdb2012016-08-30 00:18:43 +0000230TEST(IListTest, privateNode) {
Duncan P. N. Exon Smith64093a32016-08-19 20:40:12 +0000231 // Instantiate various APIs to be sure they're callable when ilist_node is
232 // inherited privately.
233 ilist<NodeWithCallback> L;
234 NodeWithCallback N(7);
235 L.insert(L.begin(), &N);
236 ++L.begin();
237 (void)*L.begin();
238 (void)(L.begin() == L.end());
239
240 ilist<NodeWithCallback> L2;
241 L2.splice(L2.end(), L);
242 L2.remove(&N);
243}
244
Duncan P. N. Exon Smith11cb5382016-08-19 20:17:23 +0000245} // end namespace