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"
13 constexpr int NB_ELEM = 5000;
15 TEST_CASE("xbt::dynar: generic C vector", "dynar")
17 SECTION("Dynars of integers")
19 /* Vars_decl [doxygen cruft] */
23 INFO("==== Traverse the empty dynar");
24 xbt_dynar_t d = xbt_dynar_new(sizeof(int), nullptr);
25 xbt_dynar_foreach (d, cursor, cpt) {
26 xbt_die("Damnit, there is something in the empty dynar");
28 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
29 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
30 /* in your code is naturally the way to go outside a regression test */
32 INFO("==== Push " << NB_ELEM << " int, set them again 3 times, traverse them, shift them");
33 /* Populate_ints [doxygen cruft] */
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")
267 INFO("==== Traverse the empty dynar");
268 xbt_dynar_t d = xbt_dynar_new(sizeof(char*), &xbt_free_ref);
269 xbt_dynar_foreach (d, iter, s1) {
270 REQUIRE(false); // Damnit, there is something in the empty dynar"
272 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
273 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
274 /* in your code is naturally the way to go outside a regression test */
276 INFO("==== Push " << NB_ELEM << " strings, set them again 3 times, shift them");
277 /* Populate_str [doxygen cruft] */
278 d = xbt_dynar_new(sizeof(char*), &xbt_free_ref);
279 /* 1. Populate the dynar */
280 for (int i = 0; i < NB_ELEM; i++) {
281 snprintf(buf, 1023, "%d", i);
282 s1 = xbt_strdup(buf);
283 xbt_dynar_push(d, &s1);
285 for (int i = 0; i < NB_ELEM; i++) {
286 snprintf(buf, 1023, "%d", i);
287 xbt_dynar_shift(d, &s2);
288 REQUIRE(not strcmp(buf, s2)); // The retrieved value is not the same than the injected one
291 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
292 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
293 /* in your code is naturally the way to go outside a regression test */
295 INFO("==== Unshift, traverse and pop " << NB_ELEM << " strings");
296 d = xbt_dynar_new(sizeof(char**), &xbt_free_ref);
297 for (int i = 0; i < NB_ELEM; i++) {
298 snprintf(buf, 1023, "%d", i);
299 s1 = xbt_strdup(buf);
300 xbt_dynar_unshift(d, &s1);
302 /* 2. Traverse the dynar with the macro */
303 xbt_dynar_foreach (d, iter, s1) {
304 snprintf(buf, 1023, "%u", NB_ELEM - iter - 1);
305 REQUIRE(not strcmp(buf, s1)); // The retrieved value is not the same than the injected one
307 /* 3. Traverse the dynar with the macro */
308 for (int i = 0; i < NB_ELEM; i++) {
309 snprintf(buf, 1023, "%d", i);
310 xbt_dynar_pop(d, &s2);
311 REQUIRE(not strcmp(buf, s2)); // The retrieved value is not the same than the injected one
314 /* 4. Free the resources */
315 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
316 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
317 /* in your code is naturally the way to go outside a regression test */
319 INFO("==== Push " << NB_ELEM << " strings, insert " << (NB_ELEM / 5) << " strings in the middle, shift everything");
320 d = xbt_dynar_new(sizeof(char*), &xbt_free_ref);
321 for (int i = 0; i < NB_ELEM; i++) {
322 snprintf(buf, 1023, "%d", i);
323 s1 = xbt_strdup(buf);
324 xbt_dynar_push(d, &s1);
326 for (int i = 0; i < NB_ELEM / 5; i++) {
327 snprintf(buf, 1023, "%d", i);
328 s1 = xbt_strdup(buf);
329 xbt_dynar_insert_at(d, NB_ELEM / 2, &s1);
332 for (int i = 0; i < NB_ELEM / 2; i++) {
333 snprintf(buf, 1023, "%d", i);
334 xbt_dynar_shift(d, &s2);
335 REQUIRE(not strcmp(buf, s2)); // The retrieved value is not the same than the injected one at the beginning
338 for (int i = (NB_ELEM / 5) - 1; i >= 0; i--) {
339 snprintf(buf, 1023, "%d", i);
340 xbt_dynar_shift(d, &s2);
341 REQUIRE(not strcmp(buf, s2)); // The retrieved value is not the same than the injected one in the middle
344 for (int i = NB_ELEM / 2; i < NB_ELEM; i++) {
345 snprintf(buf, 1023, "%d", i);
346 xbt_dynar_shift(d, &s2);
347 REQUIRE(not strcmp(buf, s2)); // The retrieved value is not the same than the injected one at the end
350 xbt_dynar_free(&d); /* This code is used both as example and as regression test, so we try to */
351 xbt_dynar_free(&d); /* free the struct twice here to check that it's ok, but freeing it only once */
352 /* in your code is naturally the way to go outside a regression test */
354 INFO("==== Push " << NB_ELEM << " strings, remove " << (2 * NB_ELEM / 5) << "-" << (4 * NB_ELEM / 5)
355 << ". free the rest");
356 d = xbt_dynar_new(sizeof(char*), &xbt_free_ref);
357 for (int i = 0; i < NB_ELEM; i++) {
358 snprintf(buf, 1023, "%d", i);
359 s1 = xbt_strdup(buf);
360 xbt_dynar_push(d, &s1);
362 for (int i = 2 * (NB_ELEM / 5); i < 4 * (NB_ELEM / 5); i++) {
363 snprintf(buf, 1023, "%d", i);
364 xbt_dynar_remove_at(d, 2 * (NB_ELEM / 5), &s2);
365 REQUIRE(not strcmp(buf, s2)); // Remove a bad value
368 xbt_dynar_free(&d); /* end_of_doxygen */