1 /* a generic DYNamic ARray implementation. */
3 /* Copyright (c) 2004-2020. 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")
21 /* Vars_decl [doxygen cruft] */
25 INFO("==== Traverse the empty dynar");
26 xbt_dynar_t d = xbt_dynar_new(sizeof(int), nullptr);
27 xbt_dynar_foreach (d, cursor, cpt) {
28 xbt_die("Damnit, there is something in the empty dynar");
30 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
31 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
32 /* in your code is naturally the way to go outside a regression test */
34 INFO("==== Push " << NB_ELEM << " int, set them again 3 times, traverse them, shift them");
35 /* Populate_ints [doxygen cruft] */
36 /* 1. Populate the dynar */
37 d = xbt_dynar_new(sizeof(int), nullptr);
38 for (int i = 0; i < NB_ELEM; i++) {
39 xbt_dynar_push_as(d, int, i); /* This is faster (and possible only with scalars) */
40 /* xbt_dynar_push(d, &i); This would also work */
43 /* 2. Traverse manually the dynar */
44 for (int i = 0; i < NB_ELEM; i++) {
45 const int* iptr = (int*)xbt_dynar_get_ptr(d, i);
46 REQUIRE(i == *iptr); // The retrieved value is not the same than the injected one
49 /* 3. Traverse the dynar using the neat macro to that extend */
50 xbt_dynar_foreach (d, cursor, cpt) {
51 REQUIRE(cursor == (unsigned int)cpt); // The retrieved value is not the same than the injected one
53 /* end_of_traversal */
55 for (int i = 0; i < NB_ELEM; i++)
56 *(int*)xbt_dynar_get_ptr(d, i) = i;
58 for (int i = 0; i < NB_ELEM; i++)
59 *(int*)xbt_dynar_get_ptr(d, i) = i;
61 for (int i = 0; i < NB_ELEM; i++)
62 *(int*)xbt_dynar_get_ptr(d, i) = i;
65 xbt_dynar_foreach (d, cursor, cpt) {
66 REQUIRE(cpt == count); // The retrieved value is not the same than the injected one
69 REQUIRE(count == NB_ELEM); // Cannot retrieve all my values. cpt is the last one I got
71 /* shifting [doxygen cruft] */
72 /* 4. Shift all the values */
73 for (int i = 0; i < NB_ELEM; i++) {
75 xbt_dynar_shift(d, &val);
76 REQUIRE(val == i); // The retrieved value is not the same than the injected one
78 REQUIRE(xbt_dynar_is_empty(d));
80 /* 5. Free the resources */
81 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
82 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
83 /* in your code is naturally the way to go outside a regression test */
85 INFO("==== Unshift/pop " << NB_ELEM << " int");
86 d = xbt_dynar_new(sizeof(int), nullptr);
87 for (int i = 0; i < NB_ELEM; i++) {
88 xbt_dynar_unshift(d, &i);
90 for (int i = 0; i < NB_ELEM; i++) {
91 int val = xbt_dynar_pop_as(d, int);
92 REQUIRE(val == i); // The retrieved value is not the same than the injected one
94 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
95 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
96 /* in your code is naturally the way to go outside a regression test */
98 INFO("==== Push " << NB_ELEM << "%d int, insert 1000 int in the middle, shift everything");
99 d = xbt_dynar_new(sizeof(int), nullptr);
100 for (int i = 0; i < NB_ELEM; i++) {
101 xbt_dynar_push_as(d, int, i);
104 for (int i = 0; i < NB_ELEM; i++) {
106 xbt_dynar_shift(d, &val);
107 REQUIRE(val == i); // The retrieved value is not the same than the injected one at the beginning
109 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
110 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
111 /* in your code is naturally the way to go outside a regression test */
113 INFO("==== Push " << NB_ELEM << " int, remove 2000-4000. free the rest");
114 d = xbt_dynar_new(sizeof(int), nullptr);
115 for (int i = 0; i < NB_ELEM; i++)
116 xbt_dynar_push_as(d, int, i);
118 for (int i = 2000; i < 4000; i++) {
120 xbt_dynar_remove_at(d, 2000, &val);
121 REQUIRE(val == i); // Remove a bad value
123 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
124 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
125 /* in your code is naturally the way to go outside a regression test */
128 /*******************************************************************************/
129 SECTION("Using the xbt_dynar_insert and xbt_dynar_remove functions")
131 xbt_dynar_t d = xbt_dynar_new(sizeof(unsigned int), nullptr);
134 INFO("==== Insert " << NB_ELEM << " int, traverse them, remove them");
135 /* Populate_ints [doxygen cruft] */
136 /* 1. Populate the dynar */
137 for (int i = 0; i < NB_ELEM; i++) {
138 xbt_dynar_insert_at(d, i, &i);
141 /* 3. Traverse the dynar */
143 xbt_dynar_foreach (d, cursor, cpt) {
144 REQUIRE(cursor == (unsigned int)cpt); // The retrieved value is not the same than the injected one
146 /* end_of_traversal */
148 /* Re-fill with the same values using set_as (and re-verify) */
149 for (int i = 0; i < NB_ELEM; i++)
150 xbt_dynar_set_as(d, i, int, i);
151 xbt_dynar_foreach (d, cursor, cpt)
152 REQUIRE(cursor == (unsigned int)cpt); // The retrieved value is not the same than the injected one
154 for (int i = 0; i < NB_ELEM; i++) {
156 xbt_dynar_remove_at(d, 0, &val);
157 REQUIRE(i == val); // The retrieved value is not the same than the injected one
159 REQUIRE(xbt_dynar_is_empty(d));
163 /*******************************************************************************/
164 SECTION("Dynars of doubles")
172 INFO("==== Traverse the empty dynar");
173 d = xbt_dynar_new(sizeof(int), nullptr);
174 xbt_dynar_foreach (d, cursor, cpt) {
175 REQUIRE(false); // Damnit, there is something in the empty dynar
177 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
178 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
179 /* in your code is naturally the way to go outside a regression test */
181 INFO("==== Push/shift 5000 doubles");
182 d = xbt_dynar_new(sizeof(double), nullptr);
183 for (int i = 0; i < 5000; i++) {
185 xbt_dynar_push(d, &d1);
187 xbt_dynar_foreach (d, cursor, d2) {
189 REQUIRE(d1 == d2); // The retrieved value is not the same than the injected one
191 for (int i = 0; i < 5000; i++) {
193 xbt_dynar_shift(d, &d2);
194 REQUIRE(d1 == d2); // The retrieved value is not the same than the injected one
196 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
197 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
198 /* in your code is naturally the way to go outside a regression test */
200 INFO("==== Unshift/pop 5000 doubles");
201 d = xbt_dynar_new(sizeof(double), nullptr);
202 for (int i = 0; i < 5000; i++) {
204 xbt_dynar_unshift(d, &d1);
206 for (int i = 0; i < 5000; i++) {
208 xbt_dynar_pop(d, &d2);
209 REQUIRE(d1 == d2); // The retrieved value is not the same than the injected one
211 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
212 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
213 /* in your code is naturally the way to go outside a regression test */
215 INFO("==== Push 5000 doubles, insert 1000 doubles in the middle, shift everything");
216 d = xbt_dynar_new(sizeof(double), nullptr);
217 for (int i = 0; i < 5000; i++) {
219 xbt_dynar_push(d, &d1);
221 for (int i = 0; i < 1000; i++) {
223 xbt_dynar_insert_at(d, 2500, &d1);
226 for (int i = 0; i < 2500; i++) {
228 xbt_dynar_shift(d, &d2);
229 REQUIRE(d1 == d2); // The retrieved value is not the same than the injected one at the beginning
231 for (int i = 999; i >= 0; i--) {
233 xbt_dynar_shift(d, &d2);
234 REQUIRE(d1 == d2); // The retrieved value is not the same than the injected one in the middle
236 for (int i = 2500; i < 5000; i++) {
238 xbt_dynar_shift(d, &d2);
239 REQUIRE(d1 == d2); // The retrieved value is not the same than the injected one at the end
241 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
242 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
243 /* in your code is naturally the way to go outside a regression test */
245 INFO("==== Push 5000 double, remove 2000-4000. free the rest");
246 d = xbt_dynar_new(sizeof(double), nullptr);
247 for (int i = 0; i < 5000; i++) {
249 xbt_dynar_push(d, &d1);
251 for (int i = 2000; i < 4000; i++) {
253 xbt_dynar_remove_at(d, 2000, &d2);
254 REQUIRE(d1 == d2); // Remove a bad value
256 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
257 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
258 /* in your code is naturally the way to go outside a regression test */
261 /*******************************************************************************/
262 SECTION("Dynars of strings")
268 INFO("==== Traverse the empty dynar");
269 xbt_dynar_t d = xbt_dynar_new(sizeof(char*), &xbt_free_ref);
270 xbt_dynar_foreach (d, iter, s1) {
271 REQUIRE(false); // Damnit, there is something in the empty dynar"
273 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
274 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
275 /* in your code is naturally the way to go outside a regression test */
277 INFO("==== Push " << NB_ELEM << " strings, set them again 3 times, shift them");
278 /* Populate_str [doxygen cruft] */
279 d = xbt_dynar_new(sizeof(char*), &xbt_free_ref);
280 /* 1. Populate the dynar */
281 for (int i = 0; i < NB_ELEM; i++) {
282 std::string val = std::to_string(i);
283 s1 = xbt_strdup(val.c_str());
284 xbt_dynar_push(d, &s1);
286 for (int i = 0; i < NB_ELEM; i++) {
287 std::string val = std::to_string(i);
288 xbt_dynar_shift(d, &s2);
289 REQUIRE(s2 == val); // The retrieved value is not the same than the injected one
292 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
293 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
294 /* in your code is naturally the way to go outside a regression test */
296 INFO("==== Unshift, traverse and pop " << NB_ELEM << " strings");
297 d = xbt_dynar_new(sizeof(char**), &xbt_free_ref);
298 for (int i = 0; i < NB_ELEM; i++) {
299 std::string val = std::to_string(i);
300 s1 = xbt_strdup(val.c_str());
301 xbt_dynar_unshift(d, &s1);
303 /* 2. Traverse the dynar with the macro */
304 xbt_dynar_foreach (d, iter, s1) {
305 std::string val = std::to_string(NB_ELEM - iter - 1);
306 REQUIRE(s1 == val); // The retrieved value is not the same than the injected one
308 /* 3. Traverse the dynar with the macro */
309 for (int i = 0; i < NB_ELEM; i++) {
310 std::string val = std::to_string(i);
311 xbt_dynar_pop(d, &s2);
312 REQUIRE(s2 == val); // The retrieved value is not the same than the injected one
315 /* 4. Free the resources */
316 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
317 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
318 /* in your code is naturally the way to go outside a regression test */
320 INFO("==== Push " << NB_ELEM << " strings, insert " << (NB_ELEM / 5) << " strings in the middle, shift everything");
321 d = xbt_dynar_new(sizeof(char*), &xbt_free_ref);
322 for (int i = 0; i < NB_ELEM; i++) {
323 std::string val = std::to_string(i);
324 s1 = xbt_strdup(val.c_str());
325 xbt_dynar_push(d, &s1);
327 for (int i = 0; i < NB_ELEM / 5; i++) {
328 std::string val = std::to_string(i);
329 s1 = xbt_strdup(val.c_str());
330 xbt_dynar_insert_at(d, NB_ELEM / 2, &s1);
333 for (int i = 0; i < NB_ELEM / 2; i++) {
334 std::string val = std::to_string(i);
335 xbt_dynar_shift(d, &s2);
336 REQUIRE(s2 == val); // The retrieved value is not the same than the injected one at the beginning
339 for (int i = (NB_ELEM / 5) - 1; i >= 0; i--) {
340 std::string val = std::to_string(i);
341 xbt_dynar_shift(d, &s2);
342 REQUIRE(s2 == val); // The retrieved value is not the same than the injected one in the middle
345 for (int i = NB_ELEM / 2; i < NB_ELEM; i++) {
346 std::string val = std::to_string(i);
347 xbt_dynar_shift(d, &s2);
348 REQUIRE(s2 == val); // The retrieved value is not the same than the injected one at the end
351 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
352 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
353 /* in your code is naturally the way to go outside a regression test */
355 INFO("==== Push " << NB_ELEM << " strings, remove " << (2 * NB_ELEM / 5) << "-" << (4 * NB_ELEM / 5)
356 << ". free the rest");
357 d = xbt_dynar_new(sizeof(char*), &xbt_free_ref);
358 for (int i = 0; i < NB_ELEM; i++) {
359 std::string val = std::to_string(i);
360 s1 = xbt_strdup(val.c_str());
361 xbt_dynar_push(d, &s1);
363 for (int i = 2 * (NB_ELEM / 5); i < 4 * (NB_ELEM / 5); i++) {
364 std::string val = std::to_string(i);
365 xbt_dynar_remove_at(d, 2 * (NB_ELEM / 5), &s2);
366 REQUIRE(s2 == val); // Remove a bad value
369 xbt_dynar_free(&d); /* end_of_doxygen */