glsl/list: Fix undefined behaviour of foreach_* macros
[mesa.git] / src / compiler / glsl / tests / list_iterators.cpp
1 /*
2 * Copyright © 2020 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include <gtest/gtest.h>
25
26 #include "list.h"
27
28 class test_node_inherite : public exec_node {
29 public:
30 uint32_t value;
31
32 virtual ~test_node_inherite() = default;
33 };
34
35 class list_iterators_node_inherite : public ::testing::TestWithParam<size_t> {
36 public:
37 virtual void SetUp();
38 virtual void TearDown();
39
40 void *mem_ctx;
41
42 exec_list node_list;
43 };
44
45 void
46 list_iterators_node_inherite::SetUp()
47 {
48 mem_ctx = ralloc_context(NULL);
49
50 exec_list_make_empty(&node_list);
51
52 for (size_t i = 0; i < GetParam(); i++) {
53 test_node_inherite *node = new(mem_ctx) test_node_inherite();
54 node->value = i;
55 exec_list_push_tail(&node_list, node);
56 }
57 }
58
59 void
60 list_iterators_node_inherite::TearDown()
61 {
62 exec_list_make_empty(&node_list);
63
64 ralloc_free(mem_ctx);
65 mem_ctx = NULL;
66 }
67
68 INSTANTIATE_TEST_CASE_P(
69 list_iterators_node_inherite,
70 list_iterators_node_inherite,
71 ::testing::Values(0, 1, 10)
72 );
73
74 TEST_P(list_iterators_node_inherite, foreach_in_list)
75 {
76 size_t i = 0;
77 foreach_in_list(test_node_inherite, n, &node_list) {
78 EXPECT_EQ(n->value, i);
79 i++;
80 }
81 }
82
83 TEST_P(list_iterators_node_inherite, foreach_in_list_reverse)
84 {
85 size_t i = GetParam() - 1;
86 foreach_in_list_reverse(test_node_inherite, n, &node_list) {
87 EXPECT_EQ(n->value, i);
88 i--;
89 }
90 }
91
92 TEST_P(list_iterators_node_inherite, foreach_in_list_safe)
93 {
94 size_t i = 0;
95 foreach_in_list_safe(test_node_inherite, n, &node_list) {
96 EXPECT_EQ(n->value, i);
97
98 if (i % 2 == 0) {
99 n->remove();
100 }
101
102 i++;
103 }
104
105 exec_list_validate(&node_list);
106 }
107
108 TEST_P(list_iterators_node_inherite, foreach_in_list_reverse_safe)
109 {
110 size_t i = GetParam() - 1;
111 foreach_in_list_reverse_safe(test_node_inherite, n, &node_list) {
112 EXPECT_EQ(n->value, i);
113
114 if (i % 2 == 0) {
115 n->remove();
116 }
117
118 i--;
119 }
120
121 exec_list_validate(&node_list);
122 }
123
124 TEST_P(list_iterators_node_inherite, foreach_in_list_use_after)
125 {
126 size_t i = 0;
127 foreach_in_list_use_after(test_node_inherite, n, &node_list) {
128 EXPECT_EQ(n->value, i);
129
130 if (i == GetParam() / 2) {
131 break;
132 }
133
134 i++;
135 }
136
137 if (GetParam() > 0) {
138 EXPECT_EQ(n->value, GetParam() / 2);
139 }
140 }
141
142 class test_node_embed {
143 DECLARE_RZALLOC_CXX_OPERATORS(test_node_embed)
144 public:
145
146 uint32_t value_header;
147 exec_node node;
148 uint32_t value_footer;
149
150 virtual ~test_node_embed() = default;
151 };
152
153 class list_iterators_node_embed : public ::testing::TestWithParam<size_t> {
154 public:
155 virtual void SetUp();
156 virtual void TearDown();
157
158 void *mem_ctx;
159
160 exec_list node_list;
161 };
162
163 void
164 list_iterators_node_embed::SetUp()
165 {
166 mem_ctx = ralloc_context(NULL);
167
168 exec_list_make_empty(&node_list);
169
170 for (size_t i = 0; i < GetParam(); i++) {
171 test_node_embed *node = new(mem_ctx) test_node_embed();
172 node->value_header = i;
173 node->value_footer = i;
174 exec_list_push_tail(&node_list, &node->node);
175 }
176 }
177
178 void
179 list_iterators_node_embed::TearDown()
180 {
181 exec_list_make_empty(&node_list);
182
183 ralloc_free(mem_ctx);
184 mem_ctx = NULL;
185 }
186
187 INSTANTIATE_TEST_CASE_P(
188 list_iterators_node_embed,
189 list_iterators_node_embed,
190 ::testing::Values(0, 1, 10)
191 );
192
193 TEST_P(list_iterators_node_embed, foreach_list_typed)
194 {
195 size_t i = 0;
196 foreach_list_typed(test_node_embed, n, node, &node_list) {
197 EXPECT_EQ(n->value_header, i);
198 EXPECT_EQ(n->value_footer, i);
199 i++;
200 }
201 }
202
203 TEST_P(list_iterators_node_embed, foreach_list_typed_from)
204 {
205 if (GetParam() == 0) {
206 return;
207 }
208
209 exec_node *start_node = node_list.get_head();
210
211 size_t i = 0;
212 for (; i < GetParam() / 2; i++) {
213 start_node = start_node->get_next();
214 }
215
216 foreach_list_typed_from(test_node_embed, n, node, &node_list, start_node) {
217 EXPECT_EQ(n->value_header, i);
218 EXPECT_EQ(n->value_footer, i);
219 i++;
220 }
221 }
222
223 TEST_P(list_iterators_node_embed, foreach_list_typed_reverse)
224 {
225 size_t i = GetParam() - 1;
226 foreach_list_typed_reverse(test_node_embed, n, node, &node_list) {
227 EXPECT_EQ(n->value_header, i);
228 EXPECT_EQ(n->value_footer, i);
229 i--;
230 }
231 }
232
233 TEST_P(list_iterators_node_embed, foreach_list_typed_safe)
234 {
235 size_t i = 0;
236 foreach_list_typed_safe(test_node_embed, n, node, &node_list) {
237 EXPECT_EQ(n->value_header, i);
238 EXPECT_EQ(n->value_footer, i);
239
240 if (i % 2 == 0) {
241 exec_node_remove(&n->node);
242 }
243
244 i++;
245 }
246
247 exec_list_validate(&node_list);
248 }
249
250 TEST_P(list_iterators_node_embed, foreach_list_typed_reverse_safe)
251 {
252 size_t i = GetParam() - 1;
253 foreach_list_typed_reverse_safe(test_node_embed, n, node, &node_list) {
254 EXPECT_EQ(n->value_header, i);
255 EXPECT_EQ(n->value_footer, i);
256
257 if (i % 2 == 0) {
258 exec_node_remove(&n->node);
259 }
260
261 i--;
262 }
263
264 exec_list_validate(&node_list);
265 }