1 /* a generic DYNamic ARray implementation. */
3 /* Copyright (c) 2004-2021. The SimGrid Team. All rights reserved. */
5 /* This program is free software; you can redistribute it and/or modify it
6 * under the terms of the license (GNU LGPL) which comes with this package. */
9 #include "xbt/sysdep.h"
15 constexpr int NB_ELEM = 5000;
17 TEST_CASE("xbt::dynar: generic C vector", "dynar")
19 SECTION("Dynars of integers")
24 INFO("==== Traverse the empty dynar");
25 xbt_dynar_t d = xbt_dynar_new(sizeof(int), nullptr);
26 xbt_dynar_foreach (d, cursor, cpt) {
27 xbt_die("Damnit, there is something in the empty dynar");
29 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
30 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
31 /* in your code is naturally the way to go outside a regression test */
33 INFO("==== Push " << NB_ELEM << " int, set them again 3 times, traverse them, shift them");
34 /* 1. Populate the dynar */
35 d = xbt_dynar_new(sizeof(int), nullptr);
36 for (int i = 0; i < NB_ELEM; i++) {
37 xbt_dynar_push_as(d, int, i); /* This is faster (and possible only with scalars) */
38 /* xbt_dynar_push(d, &i); This would also work */
41 /* 2. Traverse manually the dynar */
42 for (int i = 0; i < NB_ELEM; i++) {
43 const int* iptr = (int*)xbt_dynar_get_ptr(d, i);
44 REQUIRE(i == *iptr); // The retrieved value is not the same than the injected one
47 /* 3. Traverse the dynar using the neat macro to that extend */
48 xbt_dynar_foreach (d, cursor, cpt) {
49 REQUIRE(cursor == (unsigned int)cpt); // The retrieved value is not the same than the injected one
51 /* end_of_traversal */
53 for (int i = 0; i < NB_ELEM; i++)
54 *(int*)xbt_dynar_get_ptr(d, i) = i;
56 for (int i = 0; i < NB_ELEM; i++)
57 *(int*)xbt_dynar_get_ptr(d, i) = i;
59 for (int i = 0; i < NB_ELEM; i++)
60 *(int*)xbt_dynar_get_ptr(d, i) = i;
63 xbt_dynar_foreach (d, cursor, cpt) {
64 REQUIRE(cpt == count); // The retrieved value is not the same than the injected one
67 REQUIRE(count == NB_ELEM); // Cannot retrieve all my values. cpt is the last one I got
69 /* shifting [doxygen cruft] */
70 /* 4. Shift all the values */
71 for (int i = 0; i < NB_ELEM; i++) {
73 xbt_dynar_shift(d, &val);
74 REQUIRE(val == i); // The retrieved value is not the same than the injected one
76 REQUIRE(xbt_dynar_is_empty(d));
78 /* 5. Free the resources */
79 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
80 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
81 /* in your code is naturally the way to go outside a regression test */
83 INFO("==== Unshift/pop " << NB_ELEM << " int");
84 d = xbt_dynar_new(sizeof(int), nullptr);
85 for (int i = 0; i < NB_ELEM; i++) {
86 xbt_dynar_unshift(d, &i);
88 for (int i = 0; i < NB_ELEM; i++) {
89 int val = xbt_dynar_pop_as(d, int);
90 REQUIRE(val == i); // The retrieved value is not the same than the injected one
92 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
93 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
94 /* in your code is naturally the way to go outside a regression test */
96 INFO("==== Push " << NB_ELEM << "%d int, insert 1000 int in the middle, shift everything");
97 d = xbt_dynar_new(sizeof(int), nullptr);
98 for (int i = 0; i < NB_ELEM; i++) {
99 xbt_dynar_push_as(d, int, i);
102 for (int i = 0; i < NB_ELEM; i++) {
104 xbt_dynar_shift(d, &val);
105 REQUIRE(val == i); // The retrieved value is not the same than the injected one at the beginning
107 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
108 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
109 /* in your code is naturally the way to go outside a regression test */
111 INFO("==== Push " << NB_ELEM << " int, remove 2000-4000. free the rest");
112 d = xbt_dynar_new(sizeof(int), nullptr);
113 for (int i = 0; i < NB_ELEM; i++)
114 xbt_dynar_push_as(d, int, i);
116 for (int i = 2000; i < 4000; i++) {
118 xbt_dynar_remove_at(d, 2000, &val);
119 REQUIRE(val == i); // Remove a bad value
121 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
122 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
123 /* in your code is naturally the way to go outside a regression test */
126 /*******************************************************************************/
127 SECTION("Using the xbt_dynar_insert and xbt_dynar_remove functions")
129 xbt_dynar_t d = xbt_dynar_new(sizeof(unsigned int), nullptr);
132 INFO("==== Insert " << NB_ELEM << " int, traverse them, remove them");
133 /* Populate_ints [doxygen cruft] */
134 /* 1. Populate the dynar */
135 for (int i = 0; i < NB_ELEM; i++) {
136 xbt_dynar_insert_at(d, i, &i);
139 /* 3. Traverse the dynar */
141 xbt_dynar_foreach (d, cursor, cpt) {
142 REQUIRE(cursor == (unsigned int)cpt); // The retrieved value is not the same than the injected one
144 /* end_of_traversal */
146 /* Re-fill with the same values using set_as (and re-verify) */
147 for (int i = 0; i < NB_ELEM; i++)
148 xbt_dynar_set_as(d, i, int, i);
149 xbt_dynar_foreach (d, cursor, cpt)
150 REQUIRE(cursor == (unsigned int)cpt); // The retrieved value is not the same than the injected one
152 for (int i = 0; i < NB_ELEM; i++) {
154 xbt_dynar_remove_at(d, 0, &val);
155 REQUIRE(i == val); // The retrieved value is not the same than the injected one
157 REQUIRE(xbt_dynar_is_empty(d));
161 /*******************************************************************************/
162 SECTION("Dynars of doubles")
170 INFO("==== Traverse the empty dynar");
171 d = xbt_dynar_new(sizeof(int), nullptr);
172 xbt_dynar_foreach (d, cursor, cpt) {
173 REQUIRE(false); // Damnit, there is something in the empty dynar
175 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
176 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
177 /* in your code is naturally the way to go outside a regression test */
179 INFO("==== Push/shift 5000 doubles");
180 d = xbt_dynar_new(sizeof(double), nullptr);
181 for (int i = 0; i < 5000; i++) {
183 xbt_dynar_push(d, &d1);
185 xbt_dynar_foreach (d, cursor, d2) {
187 REQUIRE(d1 == d2); // The retrieved value is not the same than the injected one
189 for (int i = 0; i < 5000; i++) {
191 xbt_dynar_shift(d, &d2);
192 REQUIRE(d1 == d2); // The retrieved value is not the same than the injected one
194 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
195 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
196 /* in your code is naturally the way to go outside a regression test */
198 INFO("==== Unshift/pop 5000 doubles");
199 d = xbt_dynar_new(sizeof(double), nullptr);
200 for (int i = 0; i < 5000; i++) {
202 xbt_dynar_unshift(d, &d1);
204 for (int i = 0; i < 5000; i++) {
206 xbt_dynar_pop(d, &d2);
207 REQUIRE(d1 == d2); // The retrieved value is not the same than the injected one
209 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
210 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
211 /* in your code is naturally the way to go outside a regression test */
213 INFO("==== Push 5000 doubles, insert 1000 doubles in the middle, shift everything");
214 d = xbt_dynar_new(sizeof(double), nullptr);
215 for (int i = 0; i < 5000; i++) {
217 xbt_dynar_push(d, &d1);
219 for (int i = 0; i < 1000; i++) {
221 xbt_dynar_insert_at(d, 2500, &d1);
224 for (int i = 0; i < 2500; i++) {
226 xbt_dynar_shift(d, &d2);
227 REQUIRE(d1 == d2); // The retrieved value is not the same than the injected one at the beginning
229 for (int i = 999; i >= 0; i--) {
231 xbt_dynar_shift(d, &d2);
232 REQUIRE(d1 == d2); // The retrieved value is not the same than the injected one in the middle
234 for (int i = 2500; i < 5000; i++) {
236 xbt_dynar_shift(d, &d2);
237 REQUIRE(d1 == d2); // The retrieved value is not the same than the injected one at the end
239 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
240 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
241 /* in your code is naturally the way to go outside a regression test */
243 INFO("==== Push 5000 double, remove 2000-4000. free the rest");
244 d = xbt_dynar_new(sizeof(double), nullptr);
245 for (int i = 0; i < 5000; i++) {
247 xbt_dynar_push(d, &d1);
249 for (int i = 2000; i < 4000; i++) {
251 xbt_dynar_remove_at(d, 2000, &d2);
252 REQUIRE(d1 == d2); // Remove a bad value
254 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
255 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
256 /* in your code is naturally the way to go outside a regression test */
259 /*******************************************************************************/
260 SECTION("Dynars of strings")
266 INFO("==== Traverse the empty dynar");
267 xbt_dynar_t d = xbt_dynar_new(sizeof(char*), &xbt_free_ref);
268 xbt_dynar_foreach (d, iter, s1) {
269 REQUIRE(false); // Damnit, there is something in the empty dynar"
271 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
272 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
273 /* in your code is naturally the way to go outside a regression test */
275 INFO("==== Push " << NB_ELEM << " strings, set them again 3 times, shift them");
276 /* Populate_str [doxygen cruft] */
277 d = xbt_dynar_new(sizeof(char*), &xbt_free_ref);
278 /* 1. Populate the dynar */
279 for (int i = 0; i < NB_ELEM; i++) {
280 std::string val = std::to_string(i);
281 s1 = xbt_strdup(val.c_str());
282 xbt_dynar_push(d, &s1);
284 for (int i = 0; i < NB_ELEM; i++) {
285 std::string val = std::to_string(i);
286 xbt_dynar_shift(d, &s2);
287 REQUIRE(s2 == val); // The retrieved value is not the same than the injected one
290 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
291 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
292 /* in your code is naturally the way to go outside a regression test */
294 INFO("==== Unshift, traverse and pop " << NB_ELEM << " strings");
295 d = xbt_dynar_new(sizeof(char**), &xbt_free_ref);
296 for (int i = 0; i < NB_ELEM; i++) {
297 std::string val = std::to_string(i);
298 s1 = xbt_strdup(val.c_str());
299 xbt_dynar_unshift(d, &s1);
301 /* 2. Traverse the dynar with the macro */
302 xbt_dynar_foreach (d, iter, s1) {
303 std::string val = std::to_string(NB_ELEM - iter - 1);
304 REQUIRE(s1 == val); // The retrieved value is not the same than the injected one
306 /* 3. Traverse the dynar with the macro */
307 for (int i = 0; i < NB_ELEM; i++) {
308 std::string val = std::to_string(i);
309 xbt_dynar_pop(d, &s2);
310 REQUIRE(s2 == val); // The retrieved value is not the same than the injected one
313 /* 4. Free the resources */
314 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
315 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
316 /* in your code is naturally the way to go outside a regression test */
318 INFO("==== Push " << NB_ELEM << " strings, insert " << (NB_ELEM / 5) << " strings in the middle, shift everything");
319 d = xbt_dynar_new(sizeof(char*), &xbt_free_ref);
320 for (int i = 0; i < NB_ELEM; i++) {
321 std::string val = std::to_string(i);
322 s1 = xbt_strdup(val.c_str());
323 xbt_dynar_push(d, &s1);
325 for (int i = 0; i < NB_ELEM / 5; i++) {
326 std::string val = std::to_string(i);
327 s1 = xbt_strdup(val.c_str());
328 xbt_dynar_insert_at(d, NB_ELEM / 2, &s1);
331 for (int i = 0; i < NB_ELEM / 2; i++) {
332 std::string val = std::to_string(i);
333 xbt_dynar_shift(d, &s2);
334 REQUIRE(s2 == val); // The retrieved value is not the same than the injected one at the beginning
337 for (int i = (NB_ELEM / 5) - 1; i >= 0; i--) {
338 std::string val = std::to_string(i);
339 xbt_dynar_shift(d, &s2);
340 REQUIRE(s2 == val); // The retrieved value is not the same than the injected one in the middle
343 for (int i = NB_ELEM / 2; i < NB_ELEM; i++) {
344 std::string val = std::to_string(i);
345 xbt_dynar_shift(d, &s2);
346 REQUIRE(s2 == val); // The retrieved value is not the same than the injected one at the end
349 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
350 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
351 /* in your code is naturally the way to go outside a regression test */
353 INFO("==== Push " << NB_ELEM << " strings, remove " << (2 * NB_ELEM / 5) << "-" << (4 * NB_ELEM / 5)
354 << ". free the rest");
355 d = xbt_dynar_new(sizeof(char*), &xbt_free_ref);
356 for (int i = 0; i < NB_ELEM; i++) {
357 std::string val = std::to_string(i);
358 s1 = xbt_strdup(val.c_str());
359 xbt_dynar_push(d, &s1);
361 for (int i = 2 * (NB_ELEM / 5); i < 4 * (NB_ELEM / 5); i++) {
362 std::string val = std::to_string(i);
363 xbt_dynar_remove_at(d, 2 * (NB_ELEM / 5), &s2);
364 REQUIRE(s2 == val); // Remove a bad value
367 xbt_dynar_free(&d); /* end_of_doxygen */