blob: 64096eef84f9e77070eefae208ad00f3ab8839bb [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;
170
171 NodeWithCallback() = default;
172 NodeWithCallback(int Value) : Value(Value) {}
173 NodeWithCallback(const NodeWithCallback &) = delete;
174};
175
176} // end namespace
177
178namespace llvm {
179template <>
180struct ilist_traits<NodeWithCallback>
181 : public ilist_node_traits<NodeWithCallback> {
182 void addNodeToList(NodeWithCallback *N) { N->IsInList = true; }
183 void removeNodeFromList(NodeWithCallback *N) { N->IsInList = false; }
184};
185} // end namespace llvm
186
187namespace {
188
Duncan P. N. Exon Smithfbdb2012016-08-30 00:18:43 +0000189TEST(IListTest, addNodeToList) {
Duncan P. N. Exon Smith64093a32016-08-19 20:40:12 +0000190 ilist<NodeWithCallback> L;
191 NodeWithCallback N(7);
192 ASSERT_FALSE(N.IsInList);
193
194 L.insert(L.begin(), &N);
195 ASSERT_EQ(1u, L.size());
196 ASSERT_EQ(&N, &*L.begin());
197 ASSERT_TRUE(N.IsInList);
198
199 L.remove(&N);
200 ASSERT_EQ(0u, L.size());
201 ASSERT_FALSE(N.IsInList);
202}
203
204struct PrivateNode : private ilist_node<PrivateNode> {
205 friend struct llvm::ilist_node_access;
206
207 int Value = 0;
208
209 PrivateNode() = default;
210 PrivateNode(int Value) : Value(Value) {}
211 PrivateNode(const PrivateNode &) = delete;
212};
213
Duncan P. N. Exon Smithfbdb2012016-08-30 00:18:43 +0000214TEST(IListTest, privateNode) {
Duncan P. N. Exon Smith64093a32016-08-19 20:40:12 +0000215 // Instantiate various APIs to be sure they're callable when ilist_node is
216 // inherited privately.
217 ilist<NodeWithCallback> L;
218 NodeWithCallback N(7);
219 L.insert(L.begin(), &N);
220 ++L.begin();
221 (void)*L.begin();
222 (void)(L.begin() == L.end());
223
224 ilist<NodeWithCallback> L2;
225 L2.splice(L2.end(), L);
226 L2.remove(&N);
227}
228
Duncan P. N. Exon Smith11cb5382016-08-19 20:17:23 +0000229} // end namespace