xref: /aosp_15_r20/external/scudo/standalone/tests/list_test.cpp (revision 76559068c068bd27e82aff38fac3bfc865233bca)
1 //===-- list_test.cpp -------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "tests/scudo_unit_test.h"
10 
11 #include "list.h"
12 
13 #include <array>
14 
15 struct ListItemLinkedWithPtr {
16   ListItemLinkedWithPtr *Next;
17   ListItemLinkedWithPtr *Prev;
18 };
19 
20 struct ListItemLinkedWithIndex {
21   scudo::uptr Next;
22   scudo::uptr Prev;
23   static constexpr scudo::uptr EndOfListVal = 1ULL << 30;
24 };
25 
26 template <typename ListT, typename ListItemTy>
setList(ListT * L,ListItemTy * I1=nullptr,ListItemTy * I2=nullptr,ListItemTy * I3=nullptr)27 static void setList(ListT *L, ListItemTy *I1 = nullptr,
28                     ListItemTy *I2 = nullptr, ListItemTy *I3 = nullptr) {
29   L->clear();
30   if (I1)
31     L->push_back(I1);
32   if (I2)
33     L->push_back(I2);
34   if (I3)
35     L->push_back(I3);
36 }
37 
38 template <typename ListT, typename ListItemTy>
checkList(ListT * L,ListItemTy * I1,ListItemTy * I2=nullptr,ListItemTy * I3=nullptr,ListItemTy * I4=nullptr,ListItemTy * I5=nullptr,ListItemTy * I6=nullptr)39 static void checkList(ListT *L, ListItemTy *I1, ListItemTy *I2 = nullptr,
40                       ListItemTy *I3 = nullptr, ListItemTy *I4 = nullptr,
41                       ListItemTy *I5 = nullptr, ListItemTy *I6 = nullptr) {
42   if (I1) {
43     EXPECT_EQ(L->front(), I1);
44     L->pop_front();
45   }
46   if (I2) {
47     EXPECT_EQ(L->front(), I2);
48     L->pop_front();
49   }
50   if (I3) {
51     EXPECT_EQ(L->front(), I3);
52     L->pop_front();
53   }
54   if (I4) {
55     EXPECT_EQ(L->front(), I4);
56     L->pop_front();
57   }
58   if (I5) {
59     EXPECT_EQ(L->front(), I5);
60     L->pop_front();
61   }
62   if (I6) {
63     EXPECT_EQ(L->front(), I6);
64     L->pop_front();
65   }
66   EXPECT_TRUE(L->empty());
67 }
68 
69 template <template <typename> class ListTy, typename ListItemTy>
testListCommon(void)70 static void testListCommon(void) {
71   ListItemTy Items[3];
72   ListItemTy *X = &Items[0];
73   ListItemTy *Y = &Items[1];
74   ListItemTy *Z = &Items[2];
75 
76   ListTy<ListItemTy> L;
77   L.clear();
78   L.init(Items, sizeof(Items));
79 
80   EXPECT_EQ(L.size(), 0U);
81   L.push_back(X);
82   EXPECT_EQ(L.size(), 1U);
83   EXPECT_EQ(L.back(), X);
84   EXPECT_EQ(L.front(), X);
85   L.pop_front();
86   EXPECT_TRUE(L.empty());
87   L.checkConsistency();
88 
89   L.push_front(X);
90   EXPECT_EQ(L.size(), 1U);
91   EXPECT_EQ(L.back(), X);
92   EXPECT_EQ(L.front(), X);
93   L.pop_front();
94   EXPECT_TRUE(L.empty());
95   L.checkConsistency();
96 
97   L.push_front(X);
98   L.push_front(Y);
99   L.push_front(Z);
100   EXPECT_EQ(L.size(), 3U);
101   EXPECT_EQ(L.front(), Z);
102   EXPECT_EQ(L.back(), X);
103   L.checkConsistency();
104 
105   L.pop_front();
106   EXPECT_EQ(L.size(), 2U);
107   EXPECT_EQ(L.front(), Y);
108   EXPECT_EQ(L.back(), X);
109   L.pop_front();
110   L.pop_front();
111   EXPECT_TRUE(L.empty());
112   L.checkConsistency();
113 
114   L.push_back(X);
115   L.push_back(Y);
116   L.push_back(Z);
117   EXPECT_EQ(L.size(), 3U);
118   EXPECT_EQ(L.front(), X);
119   EXPECT_EQ(L.back(), Z);
120   L.checkConsistency();
121 
122   L.pop_front();
123   EXPECT_EQ(L.size(), 2U);
124   EXPECT_EQ(L.front(), Y);
125   EXPECT_EQ(L.back(), Z);
126   L.pop_front();
127   L.pop_front();
128   EXPECT_TRUE(L.empty());
129   L.checkConsistency();
130 
131   L.push_back(X);
132   L.push_back(Y);
133   L.push_back(Z);
134 
135   // Verify the iterator
136   std::array<ListItemTy *, 3> visitOrder{X, Y, Z};
137   auto Iter = visitOrder.begin();
138   for (const auto &Item : L) {
139     EXPECT_EQ(&Item, *Iter);
140     ++Iter;
141   }
142 }
143 
TEST(ScudoListTest,LinkedListCommon)144 TEST(ScudoListTest, LinkedListCommon) {
145   testListCommon<scudo::SinglyLinkedList, ListItemLinkedWithPtr>();
146   testListCommon<scudo::SinglyLinkedList, ListItemLinkedWithIndex>();
147   testListCommon<scudo::DoublyLinkedList, ListItemLinkedWithPtr>();
148   testListCommon<scudo::DoublyLinkedList, ListItemLinkedWithIndex>();
149 }
150 
151 template <template <typename> class ListTy, typename ListItemTy>
testSinglyLinkedList()152 static void testSinglyLinkedList() {
153   ListItemTy Items[6];
154   ListItemTy *X = &Items[0];
155   ListItemTy *Y = &Items[1];
156   ListItemTy *Z = &Items[2];
157   ListItemTy *A = &Items[3];
158   ListItemTy *B = &Items[4];
159   ListItemTy *C = &Items[5];
160 
161   ListTy<ListItemTy> L;
162   L.clear();
163   L.init(Items, sizeof(Items));
164 
165   L.push_back(X);
166   L.push_back(Y);
167   L.push_back(Z);
168   L.extract(X, Y);
169   EXPECT_EQ(L.size(), 2U);
170   EXPECT_EQ(L.front(), X);
171   EXPECT_EQ(L.back(), Z);
172   L.checkConsistency();
173   L.extract(X, Z);
174   EXPECT_EQ(L.size(), 1U);
175   EXPECT_EQ(L.front(), X);
176   EXPECT_EQ(L.back(), X);
177   L.checkConsistency();
178   L.pop_front();
179   EXPECT_TRUE(L.empty());
180 
181   ListTy<ListItemTy> L1, L2;
182   L1.clear();
183   L2.clear();
184   L1.init(Items, sizeof(Items));
185   L2.init(Items, sizeof(Items));
186 
187   L1.append_back(&L2);
188   EXPECT_TRUE(L1.empty());
189   EXPECT_TRUE(L2.empty());
190 
191   setList(&L1, X);
192   checkList(&L1, X);
193 
194   setList(&L1, X, Y);
195   L1.insert(X, Z);
196   checkList(&L1, X, Z, Y);
197 
198   setList(&L1, X, Y, Z);
199   setList(&L2, A, B, C);
200   L1.append_back(&L2);
201   checkList(&L1, X, Y, Z, A, B, C);
202   EXPECT_TRUE(L2.empty());
203 
204   L1.clear();
205   L2.clear();
206   L1.push_back(X);
207   L1.append_back(&L2);
208   EXPECT_EQ(L1.back(), X);
209   EXPECT_EQ(L1.front(), X);
210   EXPECT_EQ(L1.size(), 1U);
211 }
212 
TEST(ScudoListTest,SinglyLinkedList)213 TEST(ScudoListTest, SinglyLinkedList) {
214   testSinglyLinkedList<scudo::SinglyLinkedList, ListItemLinkedWithPtr>();
215   testSinglyLinkedList<scudo::SinglyLinkedList, ListItemLinkedWithIndex>();
216 }
217 
218 template <template <typename> class ListTy, typename ListItemTy>
testDoublyLinkedList()219 static void testDoublyLinkedList() {
220   ListItemTy Items[3];
221   ListItemTy *X = &Items[0];
222   ListItemTy *Y = &Items[1];
223   ListItemTy *Z = &Items[2];
224 
225   ListTy<ListItemTy> L;
226   L.clear();
227   L.init(Items, sizeof(Items));
228 
229   L.push_back(X);
230   L.push_back(Y);
231   L.push_back(Z);
232   L.remove(Y);
233   EXPECT_EQ(L.size(), 2U);
234   EXPECT_EQ(L.front(), X);
235   EXPECT_EQ(L.back(), Z);
236   L.checkConsistency();
237   L.remove(Z);
238   EXPECT_EQ(L.size(), 1U);
239   EXPECT_EQ(L.front(), X);
240   EXPECT_EQ(L.back(), X);
241   L.checkConsistency();
242   L.pop_front();
243   EXPECT_TRUE(L.empty());
244 
245   L.push_back(X);
246   L.insert(Y, X);
247   EXPECT_EQ(L.size(), 2U);
248   EXPECT_EQ(L.front(), Y);
249   EXPECT_EQ(L.back(), X);
250   L.checkConsistency();
251   L.remove(Y);
252   EXPECT_EQ(L.size(), 1U);
253   EXPECT_EQ(L.front(), X);
254   EXPECT_EQ(L.back(), X);
255   L.checkConsistency();
256   L.pop_front();
257   EXPECT_TRUE(L.empty());
258 }
259 
TEST(ScudoListTest,DoublyLinkedList)260 TEST(ScudoListTest, DoublyLinkedList) {
261   testDoublyLinkedList<scudo::DoublyLinkedList, ListItemLinkedWithPtr>();
262   testDoublyLinkedList<scudo::DoublyLinkedList, ListItemLinkedWithIndex>();
263 }
264