1 | //===-- Unittests for queue -----------------------------------------------===// |
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 | // SPDSList-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "src/__support/CPP/string.h" |
10 | #include "src/__support/char_vector.h" |
11 | #include "test/UnitTest/Test.h" |
12 | |
13 | #include "include/llvm-libc-macros/sys-queue-macros.h" |
14 | |
15 | using LIBC_NAMESPACE::CharVector; |
16 | using LIBC_NAMESPACE::cpp::string; |
17 | |
18 | namespace LIBC_NAMESPACE { |
19 | |
20 | TEST(LlvmLibcQueueTest, SList) { |
21 | struct Entry { |
22 | char c; |
23 | SLIST_ENTRY(Entry) entries; |
24 | }; |
25 | |
26 | SLIST_HEAD(Head, Entry); |
27 | |
28 | Head head = SLIST_HEAD_INITIALIZER(head); |
29 | |
30 | struct Contains : public testing::Matcher<Head> { |
31 | string s; |
32 | Contains(string s) : s(s) {} |
33 | bool match(Head head) { |
34 | Entry *e; |
35 | CharVector v; |
36 | SLIST_FOREACH(e, &head, entries) { v.append(new_char: e->c); } |
37 | return s == v.c_str(); |
38 | } |
39 | }; |
40 | |
41 | Entry e1 = {.c: 'a', .entries: {NULL}}; |
42 | SLIST_INSERT_HEAD(&head, &e1, entries); |
43 | |
44 | ASSERT_THAT(head, Contains("a" )); |
45 | |
46 | Entry e2 = {.c: 'b', .entries: {NULL}}; |
47 | SLIST_INSERT_AFTER(&e1, &e2, entries); |
48 | |
49 | ASSERT_THAT(head, Contains("ab" )); |
50 | |
51 | Head head2 = SLIST_HEAD_INITIALIZER(head); |
52 | |
53 | Entry e3 = {.c: 'c', .entries: {NULL}}; |
54 | SLIST_INSERT_HEAD(&head2, &e3, entries); |
55 | |
56 | ASSERT_THAT(head2, Contains("c" )); |
57 | |
58 | SLIST_SWAP(&head, &head2, Entry); |
59 | |
60 | ASSERT_THAT(head2, Contains("ab" )); |
61 | |
62 | SLIST_CONCAT(&head2, &head, Entry, entries); |
63 | |
64 | ASSERT_THAT(head2, Contains("abc" )); |
65 | |
66 | SLIST_CONCAT(&head, &head2, Entry, entries); |
67 | |
68 | ASSERT_THAT(head, Contains("abc" )); |
69 | |
70 | Entry *e = NULL, *tmp = NULL; |
71 | SLIST_FOREACH_SAFE(e, &head, entries, tmp) { |
72 | if (e == &e2) { |
73 | SLIST_REMOVE(&head, e, Entry, entries); |
74 | } |
75 | } |
76 | |
77 | ASSERT_THAT(head, Contains("ac" )); |
78 | |
79 | while (!SLIST_EMPTY(&head)) { |
80 | e = SLIST_FIRST(&head); |
81 | SLIST_REMOVE_HEAD(&head, entries); |
82 | } |
83 | |
84 | ASSERT_TRUE(SLIST_EMPTY(&head)); |
85 | } |
86 | |
87 | TEST(LlvmLibcQueueTest, STailQ) { |
88 | struct Entry { |
89 | char c; |
90 | STAILQ_ENTRY(Entry) entries; |
91 | }; |
92 | |
93 | STAILQ_HEAD(Head, Entry); |
94 | |
95 | Head head = STAILQ_HEAD_INITIALIZER(head); |
96 | |
97 | struct Contains : public testing::Matcher<Head> { |
98 | string s; |
99 | Contains(string s) : s(s) {} |
100 | bool match(Head head) { |
101 | Entry *e; |
102 | CharVector v; |
103 | STAILQ_FOREACH(e, &head, entries) { v.append(new_char: e->c); } |
104 | return s == v.c_str(); |
105 | } |
106 | }; |
107 | |
108 | STAILQ_INIT(&head); |
109 | ASSERT_TRUE(STAILQ_EMPTY(&head)); |
110 | |
111 | Entry e1 = {.c: 'a', .entries: {NULL}}; |
112 | STAILQ_INSERT_HEAD(&head, &e1, entries); |
113 | |
114 | ASSERT_THAT(head, Contains("a" )); |
115 | |
116 | Entry e2 = {.c: 'b', .entries: {NULL}}; |
117 | STAILQ_INSERT_TAIL(&head, &e2, entries); |
118 | |
119 | ASSERT_THAT(head, Contains("ab" )); |
120 | |
121 | Entry e3 = {.c: 'c', .entries: {NULL}}; |
122 | STAILQ_INSERT_AFTER(&head, &e2, &e3, entries); |
123 | |
124 | ASSERT_THAT(head, Contains("abc" )); |
125 | |
126 | Head head2 = STAILQ_HEAD_INITIALIZER(head); |
127 | |
128 | Entry e4 = {.c: 'd', .entries: {NULL}}; |
129 | STAILQ_INSERT_HEAD(&head2, &e4, entries); |
130 | |
131 | ASSERT_THAT(head2, Contains("d" )); |
132 | |
133 | STAILQ_SWAP(&head, &head2, Entry); |
134 | |
135 | ASSERT_THAT(head2, Contains("abc" )); |
136 | |
137 | STAILQ_CONCAT(&head2, &head, Entry, entries); |
138 | |
139 | ASSERT_EQ(STAILQ_FIRST(&head2), &e1); |
140 | ASSERT_EQ(STAILQ_LAST(&head2, Entry, entries), &e4); |
141 | |
142 | ASSERT_THAT(head2, Contains("abcd" )); |
143 | |
144 | STAILQ_CONCAT(&head, &head2, Entry, entries); |
145 | |
146 | ASSERT_EQ(STAILQ_FIRST(&head), &e1); |
147 | ASSERT_EQ(STAILQ_LAST(&head, Entry, entries), &e4); |
148 | |
149 | ASSERT_THAT(head, Contains("abcd" )); |
150 | |
151 | Entry *e = NULL, *tmp = NULL; |
152 | STAILQ_FOREACH_SAFE(e, &head, entries, tmp) { |
153 | if (e == &e2) { |
154 | STAILQ_REMOVE(&head, e, Entry, entries); |
155 | } |
156 | } |
157 | |
158 | ASSERT_THAT(head, Contains("acd" )); |
159 | |
160 | while (!STAILQ_EMPTY(&head)) { |
161 | e = STAILQ_FIRST(&head); |
162 | STAILQ_REMOVE_HEAD(&head, entries); |
163 | } |
164 | |
165 | ASSERT_TRUE(STAILQ_EMPTY(&head)); |
166 | } |
167 | |
168 | } // namespace LIBC_NAMESPACE |
169 | |