Commit r331416 breaks the big-endian PPC bot. On the big endian build, we
[llvm-core.git] / unittests / ADT / IListTest.cpp
blob0dee4c10f68f65d714dffab9def6a6cb57ce4e0f
1 //===- unittests/ADT/IListTest.cpp - ilist unit tests ---------------------===//
2 //
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 //===----------------------------------------------------------------------===//
10 #include "llvm/ADT/ilist.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/ilist_node.h"
13 #include "gtest/gtest.h"
14 #include <ostream>
16 using namespace llvm;
18 namespace {
20 struct Node : ilist_node<Node> {
21 int Value;
23 Node() {}
24 Node(int Value) : Value(Value) {}
25 Node(const Node&) = default;
26 ~Node() { Value = -1; }
29 TEST(IListTest, Basic) {
30 ilist<Node> List;
31 List.push_back(new Node(1));
32 EXPECT_EQ(1, List.back().Value);
33 EXPECT_EQ(nullptr, List.getPrevNode(List.back()));
34 EXPECT_EQ(nullptr, List.getNextNode(List.back()));
36 List.push_back(new Node(2));
37 EXPECT_EQ(2, List.back().Value);
38 EXPECT_EQ(2, List.getNextNode(List.front())->Value);
39 EXPECT_EQ(1, List.getPrevNode(List.back())->Value);
41 const ilist<Node> &ConstList = List;
42 EXPECT_EQ(2, ConstList.back().Value);
43 EXPECT_EQ(2, ConstList.getNextNode(ConstList.front())->Value);
44 EXPECT_EQ(1, ConstList.getPrevNode(ConstList.back())->Value);
47 TEST(IListTest, cloneFrom) {
48 Node L1Nodes[] = {Node(0), Node(1)};
49 Node L2Nodes[] = {Node(0), Node(1)};
50 ilist<Node> L1, L2, L3;
52 // Build L1 from L1Nodes.
53 L1.push_back(&L1Nodes[0]);
54 L1.push_back(&L1Nodes[1]);
56 // Build L2 from L2Nodes, based on L1 nodes.
57 L2.cloneFrom(L1, [&](const Node &N) { return &L2Nodes[N.Value]; });
59 // Add a node to L3 to be deleted, and then rebuild L3 by copying L1.
60 L3.push_back(new Node(7));
61 L3.cloneFrom(L1, [](const Node &N) { return new Node(N); });
63 EXPECT_EQ(2u, L1.size());
64 EXPECT_EQ(&L1Nodes[0], &L1.front());
65 EXPECT_EQ(&L1Nodes[1], &L1.back());
66 EXPECT_EQ(2u, L2.size());
67 EXPECT_EQ(&L2Nodes[0], &L2.front());
68 EXPECT_EQ(&L2Nodes[1], &L2.back());
69 EXPECT_EQ(2u, L3.size());
70 EXPECT_EQ(0, L3.front().Value);
71 EXPECT_EQ(1, L3.back().Value);
73 // Don't free nodes on the stack.
74 L1.clearAndLeakNodesUnsafely();
75 L2.clearAndLeakNodesUnsafely();
78 TEST(IListTest, SpliceOne) {
79 ilist<Node> List;
80 List.push_back(new Node(1));
82 // The single-element splice operation supports noops.
83 List.splice(List.begin(), List, List.begin());
84 EXPECT_EQ(1u, List.size());
85 EXPECT_EQ(1, List.front().Value);
86 EXPECT_TRUE(std::next(List.begin()) == List.end());
88 // Altenative noop. Move the first element behind itself.
89 List.push_back(new Node(2));
90 List.push_back(new Node(3));
91 List.splice(std::next(List.begin()), List, List.begin());
92 EXPECT_EQ(3u, List.size());
93 EXPECT_EQ(1, List.front().Value);
94 EXPECT_EQ(2, std::next(List.begin())->Value);
95 EXPECT_EQ(3, List.back().Value);
98 TEST(IListTest, SpliceSwap) {
99 ilist<Node> L;
100 Node N0(0);
101 Node N1(1);
102 L.insert(L.end(), &N0);
103 L.insert(L.end(), &N1);
104 EXPECT_EQ(0, L.front().Value);
105 EXPECT_EQ(1, L.back().Value);
107 L.splice(L.begin(), L, ++L.begin());
108 EXPECT_EQ(1, L.front().Value);
109 EXPECT_EQ(0, L.back().Value);
111 L.clearAndLeakNodesUnsafely();
114 TEST(IListTest, SpliceSwapOtherWay) {
115 ilist<Node> L;
116 Node N0(0);
117 Node N1(1);
118 L.insert(L.end(), &N0);
119 L.insert(L.end(), &N1);
120 EXPECT_EQ(0, L.front().Value);
121 EXPECT_EQ(1, L.back().Value);
123 L.splice(L.end(), L, L.begin());
124 EXPECT_EQ(1, L.front().Value);
125 EXPECT_EQ(0, L.back().Value);
127 L.clearAndLeakNodesUnsafely();
130 TEST(IListTest, UnsafeClear) {
131 ilist<Node> List;
133 // Before even allocating a sentinel.
134 List.clearAndLeakNodesUnsafely();
135 EXPECT_EQ(0u, List.size());
137 // Empty list with sentinel.
138 ilist<Node>::iterator E = List.end();
139 List.clearAndLeakNodesUnsafely();
140 EXPECT_EQ(0u, List.size());
141 // The sentinel shouldn't change.
142 EXPECT_TRUE(E == List.end());
144 // List with contents.
145 List.push_back(new Node(1));
146 ASSERT_EQ(1u, List.size());
147 Node *N = &*List.begin();
148 EXPECT_EQ(1, N->Value);
149 List.clearAndLeakNodesUnsafely();
150 EXPECT_EQ(0u, List.size());
151 ASSERT_EQ(1, N->Value);
152 delete N;
154 // List is still functional.
155 List.push_back(new Node(5));
156 List.push_back(new Node(6));
157 ASSERT_EQ(2u, List.size());
158 EXPECT_EQ(5, List.front().Value);
159 EXPECT_EQ(6, List.back().Value);
162 struct Empty {};
163 TEST(IListTest, HasObsoleteCustomizationTrait) {
164 // Negative test for HasObsoleteCustomization.
165 static_assert(!ilist_detail::HasObsoleteCustomization<Empty, Node>::value,
166 "Empty has no customizations");
169 struct GetNext {
170 Node *getNext(Node *);
172 TEST(IListTest, HasGetNextTrait) {
173 static_assert(ilist_detail::HasGetNext<GetNext, Node>::value,
174 "GetNext has a getNext(Node*)");
175 static_assert(ilist_detail::HasObsoleteCustomization<GetNext, Node>::value,
176 "Empty should be obsolete because of getNext()");
178 // Negative test for HasGetNext.
179 static_assert(!ilist_detail::HasGetNext<Empty, Node>::value,
180 "Empty does not have a getNext(Node*)");
183 struct CreateSentinel {
184 Node *createSentinel();
186 TEST(IListTest, HasCreateSentinelTrait) {
187 static_assert(ilist_detail::HasCreateSentinel<CreateSentinel>::value,
188 "CreateSentinel has a getNext(Node*)");
189 static_assert(
190 ilist_detail::HasObsoleteCustomization<CreateSentinel, Node>::value,
191 "Empty should be obsolete because of createSentinel()");
193 // Negative test for HasCreateSentinel.
194 static_assert(!ilist_detail::HasCreateSentinel<Empty>::value,
195 "Empty does not have a createSentinel()");
198 struct NodeWithCallback : ilist_node<NodeWithCallback> {
199 int Value = 0;
200 bool IsInList = false;
201 bool WasTransferred = false;
203 NodeWithCallback() = default;
204 NodeWithCallback(int Value) : Value(Value) {}
205 NodeWithCallback(const NodeWithCallback &) = delete;
208 } // end namespace
210 namespace llvm {
211 template <> struct ilist_callback_traits<NodeWithCallback> {
212 void addNodeToList(NodeWithCallback *N) { N->IsInList = true; }
213 void removeNodeFromList(NodeWithCallback *N) { N->IsInList = false; }
214 template <class Iterator>
215 void transferNodesFromList(ilist_callback_traits &Other, Iterator First,
216 Iterator Last) {
217 for (; First != Last; ++First) {
218 First->WasTransferred = true;
219 Other.removeNodeFromList(&*First);
220 addNodeToList(&*First);
224 } // end namespace llvm
226 namespace {
228 TEST(IListTest, addNodeToList) {
229 ilist<NodeWithCallback> L1, L2;
230 NodeWithCallback N(7);
231 ASSERT_FALSE(N.IsInList);
232 ASSERT_FALSE(N.WasTransferred);
234 L1.insert(L1.begin(), &N);
235 ASSERT_EQ(1u, L1.size());
236 ASSERT_EQ(&N, &L1.front());
237 ASSERT_TRUE(N.IsInList);
238 ASSERT_FALSE(N.WasTransferred);
240 L2.splice(L2.end(), L1);
241 ASSERT_EQ(&N, &L2.front());
242 ASSERT_TRUE(N.IsInList);
243 ASSERT_TRUE(N.WasTransferred);
245 L1.remove(&N);
246 ASSERT_EQ(0u, L1.size());
247 ASSERT_FALSE(N.IsInList);
248 ASSERT_TRUE(N.WasTransferred);
251 struct PrivateNode : private ilist_node<PrivateNode> {
252 friend struct llvm::ilist_detail::NodeAccess;
254 int Value = 0;
256 PrivateNode() = default;
257 PrivateNode(int Value) : Value(Value) {}
258 PrivateNode(const PrivateNode &) = delete;
261 TEST(IListTest, privateNode) {
262 // Instantiate various APIs to be sure they're callable when ilist_node is
263 // inherited privately.
264 ilist<PrivateNode> L;
265 PrivateNode N(7);
266 L.insert(L.begin(), &N);
267 ++L.begin();
268 (void)*L.begin();
269 (void)(L.begin() == L.end());
271 ilist<PrivateNode> L2;
272 L2.splice(L2.end(), L);
273 L2.remove(&N);
276 } // end namespace