| 1 /* |
|
| 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
|
| 3 * |
|
| 4 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. |
|
| 5 * |
|
| 6 * Redistribution and use in source and binary forms, with or without |
|
| 7 * modification, are permitted provided that the following conditions are met: |
|
| 8 * |
|
| 9 * 1. Redistributions of source code must retain the above copyright |
|
| 10 * notice, this list of conditions and the following disclaimer. |
|
| 11 * |
|
| 12 * 2. Redistributions in binary form must reproduce the above copyright |
|
| 13 * notice, this list of conditions and the following disclaimer in the |
|
| 14 * documentation and/or other materials provided with the distribution. |
|
| 15 * |
|
| 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
| 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
| 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
| 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
|
| 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
| 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
| 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
| 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
| 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
| 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
| 26 * POSSIBILITY OF SUCH DAMAGE. |
|
| 27 */ |
|
| 28 |
|
| 29 #include "cx/linked_list.h" |
|
| 30 #include "cx/utils.h" |
|
| 31 #include "test_config.h" |
|
| 32 #include "util_allocator.h" |
|
| 33 |
|
| 34 static int cmp_int_impl( |
|
| 35 int const *l, |
|
| 36 int const *r |
|
| 37 ) { |
|
| 38 int left = *l, right = *r; |
|
| 39 return left == right ? 0 : (left < right ? -1 : 1); |
|
| 40 } |
|
| 41 |
|
| 42 #define cmp_int ((CxListComparator) cmp_int_impl) |
|
| 43 |
|
| 44 struct node { |
|
| 45 struct node *next; |
|
| 46 struct node *prev; |
|
| 47 int data; |
|
| 48 }; |
|
| 49 |
|
| 50 #define nd(name) name = {0} |
|
| 51 |
|
| 52 const ptrdiff_t loc_prev = offsetof(struct node, prev); |
|
| 53 const ptrdiff_t loc_next = offsetof(struct node, next); |
|
| 54 const ptrdiff_t loc_data = offsetof(struct node, data); |
|
| 55 |
|
| 56 static struct node *create_nodes_test_data( |
|
| 57 size_t n, |
|
| 58 int const data[] |
|
| 59 ) { |
|
| 60 CU_ASSERT_NOT_EQUAL_FATAL(n, 0) |
|
| 61 struct node *begin = calloc(1, sizeof(struct node)); |
|
| 62 struct node *prev = begin; |
|
| 63 if (data) begin->data = data[0]; |
|
| 64 for (size_t i = 1; i < n; i++) { |
|
| 65 struct node *node = calloc(1, sizeof(struct node)); |
|
| 66 if (data) node->data = data[i]; |
|
| 67 cx_linked_list_link(prev, node, loc_prev, loc_next); |
|
| 68 prev = node; |
|
| 69 } |
|
| 70 return begin; |
|
| 71 } |
|
| 72 |
|
| 73 static void destroy_nodes_test_data(struct node *begin) { |
|
| 74 struct node *node = begin; |
|
| 75 while (node) { |
|
| 76 struct node *next = node->next; |
|
| 77 free(node); |
|
| 78 node = next; |
|
| 79 } |
|
| 80 } |
|
| 81 |
|
| 82 static int *create_ints_test_data(size_t len) { |
|
| 83 int *data = malloc(sizeof(int) * len); |
|
| 84 cx_for_n (i, len) data[i] = rand(); // NOLINT(cert-msc50-cpp) |
|
| 85 return data; |
|
| 86 } |
|
| 87 |
|
| 88 void test_linked_list_link_unlink(void) { |
|
| 89 |
|
| 90 struct node nd(a), nd(b), nd(c); |
|
| 91 |
|
| 92 cx_linked_list_link(&a, &b, loc_prev, loc_next); |
|
| 93 CU_ASSERT_PTR_NULL(a.prev) |
|
| 94 CU_ASSERT_PTR_EQUAL(a.next, &b) |
|
| 95 CU_ASSERT_PTR_EQUAL(b.prev, &a) |
|
| 96 CU_ASSERT_PTR_NULL(b.next) |
|
| 97 |
|
| 98 cx_linked_list_unlink(&a, &b, loc_prev, loc_next); |
|
| 99 CU_ASSERT_PTR_NULL(a.prev) |
|
| 100 CU_ASSERT_PTR_NULL(a.next) |
|
| 101 CU_ASSERT_PTR_NULL(b.prev) |
|
| 102 CU_ASSERT_PTR_NULL(b.next) |
|
| 103 |
|
| 104 cx_linked_list_link(&b, &c, loc_prev, loc_next); |
|
| 105 cx_linked_list_link(&a, &b, loc_prev, loc_next); |
|
| 106 cx_linked_list_unlink(&b, &c, loc_prev, loc_next); |
|
| 107 CU_ASSERT_PTR_NULL(a.prev) |
|
| 108 CU_ASSERT_PTR_EQUAL(a.next, &b) |
|
| 109 CU_ASSERT_PTR_EQUAL(b.prev, &a) |
|
| 110 CU_ASSERT_PTR_NULL(b.next) |
|
| 111 CU_ASSERT_PTR_NULL(c.prev) |
|
| 112 CU_ASSERT_PTR_NULL(c.next) |
|
| 113 } |
|
| 114 |
|
| 115 void test_linked_list_at(void) { |
|
| 116 struct node nd(a), nd(b), nd(c), nd(d); |
|
| 117 cx_linked_list_link(&a, &b, loc_prev, loc_next); |
|
| 118 cx_linked_list_link(&b, &c, loc_prev, loc_next); |
|
| 119 cx_linked_list_link(&c, &d, loc_prev, loc_next); |
|
| 120 |
|
| 121 CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&a, 0, loc_next, 0), &a) |
|
| 122 CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&a, 0, loc_next, 1), &b) |
|
| 123 CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&a, 0, loc_next, 2), &c) |
|
| 124 CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&a, 0, loc_next, 3), &d) |
|
| 125 CU_ASSERT_PTR_NULL(cx_linked_list_at(&a, 0, loc_next, 4)) |
|
| 126 |
|
| 127 CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&b, 1, loc_prev, 0), &a) |
|
| 128 CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&b, 1, loc_next, 1), &b) |
|
| 129 CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&b, 1, loc_next, 2), &c) |
|
| 130 CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&b, 1, loc_next, 3), &d) |
|
| 131 CU_ASSERT_PTR_NULL(cx_linked_list_at(&b, 1, loc_next, 4)) |
|
| 132 |
|
| 133 CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&d, 3, loc_prev, 0), &a) |
|
| 134 CU_ASSERT_PTR_EQUAL(cx_linked_list_at(&d, 3, loc_prev, 1), &b) |
|
| 135 } |
|
| 136 |
|
| 137 void test_linked_list_find(void) { |
|
| 138 int data[] = {2, 4, 6, 8}; |
|
| 139 void *list = create_nodes_test_data(4, data); |
|
| 140 int s; |
|
| 141 |
|
| 142 s = 2; |
|
| 143 CU_ASSERT_EQUAL(cx_linked_list_find(list, loc_next, loc_data, |
|
| 144 false, cmp_int, &s), 0) |
|
| 145 s = 4; |
|
| 146 CU_ASSERT_EQUAL(cx_linked_list_find(list, loc_next, loc_data, |
|
| 147 false, cmp_int, &s), 1) |
|
| 148 s = 6; |
|
| 149 CU_ASSERT_EQUAL(cx_linked_list_find(list, loc_next, loc_data, |
|
| 150 false, cmp_int, &s), 2) |
|
| 151 s = 8; |
|
| 152 CU_ASSERT_EQUAL(cx_linked_list_find(list, loc_next, loc_data, |
|
| 153 false, cmp_int, &s), 3) |
|
| 154 s = 10; |
|
| 155 CU_ASSERT_EQUAL(cx_linked_list_find(list, loc_next, loc_data, |
|
| 156 false, cmp_int, &s), 4) |
|
| 157 s = -2; |
|
| 158 CU_ASSERT_EQUAL(cx_linked_list_find(list, loc_next, loc_data, |
|
| 159 false, cmp_int, &s), 4) |
|
| 160 } |
|
| 161 |
|
| 162 void test_linked_list_compare(void) { |
|
| 163 int a[] = {2, 4, 6, 8}; |
|
| 164 int b[] = {2, 4, 6}; |
|
| 165 int c[] = {2, 4, 6, 9}; |
|
| 166 |
|
| 167 void *la = create_nodes_test_data(4, a); |
|
| 168 void *lb = create_nodes_test_data(3, b); |
|
| 169 void *lc = create_nodes_test_data(4, c); |
|
| 170 |
|
| 171 CU_ASSERT_TRUE(0 < cx_linked_list_compare(la, lb, loc_next, loc_data, |
|
| 172 false, cmp_int) |
|
| 173 ) |
|
| 174 CU_ASSERT_TRUE(0 > cx_linked_list_compare(lb, la, loc_next, loc_data, |
|
| 175 false, cmp_int) |
|
| 176 ) |
|
| 177 CU_ASSERT_TRUE(0 < cx_linked_list_compare(lc, la, loc_next, loc_data, |
|
| 178 false, cmp_int) |
|
| 179 ) |
|
| 180 CU_ASSERT_TRUE(0 > cx_linked_list_compare(la, lc, loc_next, loc_data, |
|
| 181 false, cmp_int) |
|
| 182 ) |
|
| 183 CU_ASSERT_TRUE(0 == cx_linked_list_compare(la, la, loc_next, loc_data, |
|
| 184 false, cmp_int) |
|
| 185 ) |
|
| 186 |
|
| 187 destroy_nodes_test_data(la); |
|
| 188 destroy_nodes_test_data(lb); |
|
| 189 destroy_nodes_test_data(lc); |
|
| 190 } |
|
| 191 |
|
| 192 void test_linked_list_add(void) { |
|
| 193 struct node nodes[4]; |
|
| 194 void *begin, *end; |
|
| 195 |
|
| 196 // test with begin, end / prev, next |
|
| 197 memset(nodes, 0, 4 * sizeof(struct node)); |
|
| 198 begin = end = NULL; |
|
| 199 |
|
| 200 cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[0]); |
|
| 201 CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) |
|
| 202 CU_ASSERT_PTR_EQUAL(end, &nodes[0]) |
|
| 203 CU_ASSERT_PTR_NULL(nodes[0].prev) |
|
| 204 CU_ASSERT_PTR_NULL(nodes[0].next) |
|
| 205 |
|
| 206 cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[1]); |
|
| 207 CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) |
|
| 208 CU_ASSERT_PTR_EQUAL(end, &nodes[1]) |
|
| 209 CU_ASSERT_PTR_EQUAL(nodes[0].next, &nodes[1]) |
|
| 210 CU_ASSERT_PTR_EQUAL(nodes[1].prev, &nodes[0]) |
|
| 211 |
|
| 212 // test with begin only / prev, next |
|
| 213 memset(nodes, 0, 4 * sizeof(struct node)); |
|
| 214 begin = end = NULL; |
|
| 215 |
|
| 216 cx_linked_list_add(&begin, NULL, loc_prev, loc_next, &nodes[0]); |
|
| 217 CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) |
|
| 218 cx_linked_list_add(&begin, NULL, loc_prev, loc_next, &nodes[1]); |
|
| 219 CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) |
|
| 220 CU_ASSERT_PTR_EQUAL(nodes[0].next, &nodes[1]) |
|
| 221 CU_ASSERT_PTR_EQUAL(nodes[1].prev, &nodes[0]) |
|
| 222 |
|
| 223 cx_linked_list_add(&begin, NULL, loc_prev, loc_next, &nodes[2]); |
|
| 224 CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[2]) |
|
| 225 CU_ASSERT_PTR_EQUAL(nodes[2].prev, &nodes[1]) |
|
| 226 |
|
| 227 // test with end only / prev, next |
|
| 228 memset(nodes, 0, 4 * sizeof(struct node)); |
|
| 229 begin = end = NULL; |
|
| 230 |
|
| 231 cx_linked_list_add(NULL, &end, loc_prev, loc_next, &nodes[0]); |
|
| 232 CU_ASSERT_PTR_EQUAL(end, &nodes[0]) |
|
| 233 cx_linked_list_add(NULL, &end, loc_prev, loc_next, &nodes[1]); |
|
| 234 CU_ASSERT_PTR_EQUAL(end, &nodes[1]) |
|
| 235 CU_ASSERT_PTR_EQUAL(nodes[0].next, &nodes[1]) |
|
| 236 CU_ASSERT_PTR_EQUAL(nodes[1].prev, &nodes[0]) |
|
| 237 |
|
| 238 cx_linked_list_add(NULL, &end, loc_prev, loc_next, &nodes[2]); |
|
| 239 CU_ASSERT_PTR_EQUAL(end, &nodes[2]) |
|
| 240 CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[2]) |
|
| 241 CU_ASSERT_PTR_EQUAL(nodes[2].prev, &nodes[1]) |
|
| 242 |
|
| 243 // test with begin, end / next |
|
| 244 memset(nodes, 0, 4 * sizeof(struct node)); |
|
| 245 begin = end = NULL; |
|
| 246 |
|
| 247 cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[0]); |
|
| 248 CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) |
|
| 249 CU_ASSERT_PTR_EQUAL(end, &nodes[0]) |
|
| 250 cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[1]); |
|
| 251 CU_ASSERT_PTR_EQUAL(end, &nodes[1]) |
|
| 252 CU_ASSERT_PTR_EQUAL(nodes[0].next, &nodes[1]) |
|
| 253 CU_ASSERT_PTR_NULL(nodes[1].prev) |
|
| 254 } |
|
| 255 |
|
| 256 void test_linked_list_prepend(void) { |
|
| 257 struct node nodes[4]; |
|
| 258 void *begin, *end; |
|
| 259 |
|
| 260 // test with begin, end / prev, next |
|
| 261 memset(nodes, 0, 4 * sizeof(struct node)); |
|
| 262 begin = end = NULL; |
|
| 263 |
|
| 264 cx_linked_list_prepend(&begin, &end, loc_prev, loc_next, &nodes[0]); |
|
| 265 CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) |
|
| 266 CU_ASSERT_PTR_EQUAL(end, &nodes[0]) |
|
| 267 CU_ASSERT_PTR_NULL(nodes[0].prev) |
|
| 268 CU_ASSERT_PTR_NULL(nodes[0].next) |
|
| 269 |
|
| 270 cx_linked_list_prepend(&begin, &end, loc_prev, loc_next, &nodes[1]); |
|
| 271 CU_ASSERT_PTR_EQUAL(begin, &nodes[1]) |
|
| 272 CU_ASSERT_PTR_EQUAL(end, &nodes[0]) |
|
| 273 CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[0]) |
|
| 274 CU_ASSERT_PTR_EQUAL(nodes[0].prev, &nodes[1]) |
|
| 275 |
|
| 276 // test with begin only / prev, next |
|
| 277 memset(nodes, 0, 4 * sizeof(struct node)); |
|
| 278 begin = end = NULL; |
|
| 279 |
|
| 280 cx_linked_list_prepend(&begin, NULL, loc_prev, loc_next, &nodes[0]); |
|
| 281 CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) |
|
| 282 cx_linked_list_prepend(&begin, NULL, loc_prev, loc_next, &nodes[1]); |
|
| 283 CU_ASSERT_PTR_EQUAL(begin, &nodes[1]) |
|
| 284 CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[0]) |
|
| 285 CU_ASSERT_PTR_EQUAL(nodes[0].prev, &nodes[1]) |
|
| 286 |
|
| 287 cx_linked_list_prepend(&begin, NULL, loc_prev, loc_next, &nodes[2]); |
|
| 288 CU_ASSERT_PTR_EQUAL(begin, &nodes[2]) |
|
| 289 CU_ASSERT_PTR_EQUAL(nodes[2].next, &nodes[1]) |
|
| 290 CU_ASSERT_PTR_EQUAL(nodes[1].prev, &nodes[2]) |
|
| 291 |
|
| 292 // test with end only / prev, next |
|
| 293 memset(nodes, 0, 4 * sizeof(struct node)); |
|
| 294 begin = end = NULL; |
|
| 295 |
|
| 296 cx_linked_list_prepend(NULL, &end, loc_prev, loc_next, &nodes[0]); |
|
| 297 CU_ASSERT_PTR_EQUAL(end, &nodes[0]) |
|
| 298 cx_linked_list_prepend(NULL, &end, loc_prev, loc_next, &nodes[1]); |
|
| 299 CU_ASSERT_PTR_EQUAL(end, &nodes[0]) |
|
| 300 CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[0]) |
|
| 301 CU_ASSERT_PTR_EQUAL(nodes[0].prev, &nodes[1]) |
|
| 302 |
|
| 303 cx_linked_list_prepend(NULL, &end, loc_prev, loc_next, &nodes[2]); |
|
| 304 CU_ASSERT_PTR_EQUAL(end, &nodes[0]) |
|
| 305 CU_ASSERT_PTR_EQUAL(nodes[2].next, &nodes[1]) |
|
| 306 CU_ASSERT_PTR_EQUAL(nodes[1].prev, &nodes[2]) |
|
| 307 |
|
| 308 // test with begin, end / next |
|
| 309 memset(nodes, 0, 4 * sizeof(struct node)); |
|
| 310 begin = end = NULL; |
|
| 311 |
|
| 312 cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[0]); |
|
| 313 CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) |
|
| 314 CU_ASSERT_PTR_EQUAL(end, &nodes[0]) |
|
| 315 cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[1]); |
|
| 316 cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[2]); |
|
| 317 CU_ASSERT_PTR_EQUAL(begin, &nodes[2]) |
|
| 318 CU_ASSERT_PTR_EQUAL(end, &nodes[0]) |
|
| 319 CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[0]) |
|
| 320 CU_ASSERT_PTR_EQUAL(nodes[2].next, &nodes[1]) |
|
| 321 CU_ASSERT_PTR_NULL(nodes[1].prev) |
|
| 322 CU_ASSERT_PTR_NULL(nodes[0].prev) |
|
| 323 } |
|
| 324 |
|
| 325 void test_linked_list_insert(void) { |
|
| 326 struct node nodes[4]; |
|
| 327 void *begin, *end; |
|
| 328 |
|
| 329 // insert mid list |
|
| 330 memset(nodes, 0, 4 * sizeof(struct node)); |
|
| 331 begin = &nodes[0]; |
|
| 332 end = &nodes[2]; |
|
| 333 |
|
| 334 cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); |
|
| 335 cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); |
|
| 336 |
|
| 337 cx_linked_list_insert(&begin, &end, loc_prev, loc_next, &nodes[1], &nodes[3]); |
|
| 338 CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) |
|
| 339 CU_ASSERT_PTR_EQUAL(end, &nodes[2]) |
|
| 340 CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[3]) |
|
| 341 CU_ASSERT_PTR_EQUAL(nodes[2].prev, &nodes[3]) |
|
| 342 CU_ASSERT_PTR_EQUAL(nodes[3].prev, &nodes[1]) |
|
| 343 CU_ASSERT_PTR_EQUAL(nodes[3].next, &nodes[2]) |
|
| 344 |
|
| 345 // insert end |
|
| 346 memset(nodes, 0, 4 * sizeof(struct node)); |
|
| 347 begin = &nodes[0]; |
|
| 348 end = &nodes[2]; |
|
| 349 |
|
| 350 cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); |
|
| 351 cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); |
|
| 352 |
|
| 353 cx_linked_list_insert(&begin, &end, loc_prev, loc_next, &nodes[2], &nodes[3]); |
|
| 354 CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) |
|
| 355 CU_ASSERT_PTR_EQUAL(end, &nodes[3]) |
|
| 356 CU_ASSERT_PTR_EQUAL(nodes[2].next, &nodes[3]) |
|
| 357 CU_ASSERT_PTR_EQUAL(nodes[3].prev, &nodes[2]) |
|
| 358 CU_ASSERT_PTR_NULL(nodes[3].next) |
|
| 359 |
|
| 360 // insert begin |
|
| 361 memset(nodes, 0, 4 * sizeof(struct node)); |
|
| 362 begin = &nodes[0]; |
|
| 363 end = &nodes[2]; |
|
| 364 |
|
| 365 cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); |
|
| 366 cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); |
|
| 367 |
|
| 368 cx_linked_list_insert(&begin, &end, loc_prev, loc_next, NULL, &nodes[3]); |
|
| 369 CU_ASSERT_PTR_EQUAL(begin, &nodes[3]) |
|
| 370 CU_ASSERT_PTR_EQUAL(end, &nodes[2]) |
|
| 371 CU_ASSERT_PTR_EQUAL(nodes[0].prev, &nodes[3]) |
|
| 372 CU_ASSERT_PTR_NULL(nodes[3].prev) |
|
| 373 CU_ASSERT_PTR_EQUAL(nodes[3].next, &nodes[0]) |
|
| 374 } |
|
| 375 |
|
| 376 void test_linked_list_insert_chain(void) { |
|
| 377 struct node nodes[5]; |
|
| 378 void *begin, *end; |
|
| 379 |
|
| 380 // insert mid list |
|
| 381 memset(nodes, 0, 5 * sizeof(struct node)); |
|
| 382 begin = &nodes[0]; |
|
| 383 end = &nodes[2]; |
|
| 384 |
|
| 385 cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); |
|
| 386 cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); |
|
| 387 cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); |
|
| 388 |
|
| 389 cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, &nodes[1], &nodes[3], NULL); |
|
| 390 CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) |
|
| 391 CU_ASSERT_PTR_EQUAL(end, &nodes[2]) |
|
| 392 CU_ASSERT_PTR_EQUAL(nodes[1].next, &nodes[3]) |
|
| 393 CU_ASSERT_PTR_EQUAL(nodes[2].prev, &nodes[4]) |
|
| 394 CU_ASSERT_PTR_EQUAL(nodes[3].prev, &nodes[1]) |
|
| 395 CU_ASSERT_PTR_EQUAL(nodes[4].next, &nodes[2]) |
|
| 396 |
|
| 397 // insert end |
|
| 398 memset(nodes, 0, 5 * sizeof(struct node)); |
|
| 399 begin = &nodes[0]; |
|
| 400 end = &nodes[2]; |
|
| 401 |
|
| 402 cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); |
|
| 403 cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); |
|
| 404 cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); |
|
| 405 |
|
| 406 cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, &nodes[2], &nodes[3], NULL); |
|
| 407 CU_ASSERT_PTR_EQUAL(begin, &nodes[0]) |
|
| 408 CU_ASSERT_PTR_EQUAL(end, &nodes[4]) |
|
| 409 CU_ASSERT_PTR_EQUAL(nodes[2].next, &nodes[3]) |
|
| 410 CU_ASSERT_PTR_EQUAL(nodes[3].prev, &nodes[2]) |
|
| 411 CU_ASSERT_PTR_NULL(nodes[4].next) |
|
| 412 |
|
| 413 // insert begin |
|
| 414 memset(nodes, 0, 5 * sizeof(struct node)); |
|
| 415 begin = &nodes[0]; |
|
| 416 end = &nodes[2]; |
|
| 417 |
|
| 418 cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); |
|
| 419 cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); |
|
| 420 cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); |
|
| 421 |
|
| 422 cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, NULL, &nodes[3], NULL); |
|
| 423 CU_ASSERT_PTR_EQUAL(begin, &nodes[3]) |
|
| 424 CU_ASSERT_PTR_EQUAL(end, &nodes[2]) |
|
| 425 CU_ASSERT_PTR_EQUAL(nodes[0].prev, &nodes[4]) |
|
| 426 CU_ASSERT_PTR_NULL(nodes[3].prev) |
|
| 427 CU_ASSERT_PTR_EQUAL(nodes[4].next, &nodes[0]) |
|
| 428 } |
|
| 429 |
|
| 430 void test_linked_list_first(void) { |
|
| 431 struct node *begin = create_nodes_test_data(3, NULL); |
|
| 432 CU_ASSERT_PTR_EQUAL(cx_linked_list_first(begin, loc_prev), begin) |
|
| 433 CU_ASSERT_PTR_EQUAL(cx_linked_list_first(begin->next, loc_prev), begin) |
|
| 434 CU_ASSERT_PTR_EQUAL(cx_linked_list_first(begin->next->next, loc_prev), begin) |
|
| 435 destroy_nodes_test_data(begin); |
|
| 436 } |
|
| 437 |
|
| 438 void test_linked_list_last(void) { |
|
| 439 struct node *begin = create_nodes_test_data(3, NULL); |
|
| 440 struct node *end = begin->next->next; |
|
| 441 CU_ASSERT_PTR_EQUAL(cx_linked_list_last(begin, loc_next), end) |
|
| 442 CU_ASSERT_PTR_EQUAL(cx_linked_list_last(begin->next, loc_next), end) |
|
| 443 CU_ASSERT_PTR_EQUAL(cx_linked_list_last(begin->next->next, loc_next), end) |
|
| 444 destroy_nodes_test_data(begin); |
|
| 445 } |
|
| 446 |
|
| 447 void test_linked_list_prev(void) { |
|
| 448 struct node *begin = create_nodes_test_data(3, NULL); |
|
| 449 CU_ASSERT_PTR_NULL(cx_linked_list_prev(begin, loc_next, begin)) |
|
| 450 CU_ASSERT_PTR_EQUAL(cx_linked_list_prev(begin, loc_next, begin->next), begin) |
|
| 451 CU_ASSERT_PTR_EQUAL(cx_linked_list_prev(begin, loc_next, begin->next->next), begin->next) |
|
| 452 destroy_nodes_test_data(begin); |
|
| 453 } |
|
| 454 |
|
| 455 void test_linked_list_remove(void) { |
|
| 456 void *begin, *end; |
|
| 457 |
|
| 458 int data[] = {2, 4, 6}; |
|
| 459 begin = create_nodes_test_data(3, data); |
|
| 460 struct node *first = begin; |
|
| 461 struct node *second = first->next; |
|
| 462 struct node *third = second->next; |
|
| 463 end = third; |
|
| 464 |
|
| 465 cx_linked_list_remove(&begin, &end, loc_prev, loc_next, second); |
|
| 466 CU_ASSERT_PTR_EQUAL(begin, first) |
|
| 467 CU_ASSERT_PTR_EQUAL(end, third) |
|
| 468 CU_ASSERT_PTR_NULL(first->prev) |
|
| 469 CU_ASSERT_PTR_EQUAL(first->next, third) |
|
| 470 CU_ASSERT_PTR_EQUAL(third->prev, first) |
|
| 471 CU_ASSERT_PTR_NULL(third->next) |
|
| 472 |
|
| 473 cx_linked_list_remove(&begin, &end, loc_prev, loc_next, third); |
|
| 474 CU_ASSERT_PTR_EQUAL(begin, first) |
|
| 475 CU_ASSERT_PTR_EQUAL(end, first) |
|
| 476 CU_ASSERT_PTR_NULL(first->prev) |
|
| 477 CU_ASSERT_PTR_NULL(first->next) |
|
| 478 |
|
| 479 cx_linked_list_remove(&begin, &end, loc_prev, loc_next, first); |
|
| 480 CU_ASSERT_PTR_NULL(begin) |
|
| 481 CU_ASSERT_PTR_NULL(end) |
|
| 482 |
|
| 483 free(first); |
|
| 484 free(second); |
|
| 485 free(third); |
|
| 486 } |
|
| 487 |
|
| 488 void test_linked_list_size(void) { |
|
| 489 struct node *list; |
|
| 490 |
|
| 491 CU_ASSERT_PTR_EQUAL(cx_linked_list_size(NULL, loc_next), 0) |
|
| 492 |
|
| 493 list = create_nodes_test_data(5, NULL); |
|
| 494 CU_ASSERT_EQUAL(cx_linked_list_size(list, loc_next), 5) |
|
| 495 destroy_nodes_test_data(list); |
|
| 496 |
|
| 497 list = create_nodes_test_data(13, NULL); |
|
| 498 CU_ASSERT_EQUAL(cx_linked_list_size(list, loc_next), 13) |
|
| 499 destroy_nodes_test_data(list); |
|
| 500 } |
|
| 501 |
|
| 502 void test_linked_list_sort(void) { |
|
| 503 int expected[] = { |
|
| 504 14, 30, 151, 163, 227, 300, 315, 317, 363, 398, 417, 424, 438, 446, 508, 555, 605, 713, 716, 759, 761, 880, |
|
| 505 894, 1034, 1077, 1191, 1231, 1264, 1297, 1409, 1423, 1511, 1544, 1659, 1686, 1707, 1734, 1771, 1874, 1894, |
|
| 506 1976, 2079, 2124, 2130, 2135, 2266, 2338, 2358, 2430, 2500, 2540, 2542, 2546, 2711, 2733, 2754, 2764, 2797, |
|
| 507 2888, 2900, 3020, 3053, 3109, 3244, 3275, 3302, 3362, 3363, 3364, 3441, 3515, 3539, 3579, 3655, 3675, 3677, |
|
| 508 3718, 3724, 3757, 3866, 3896, 3906, 3941, 3984, 3994, 4016, 4085, 4121, 4254, 4319, 4366, 4459, 4514, 4681, |
|
| 509 4785, 4791, 4801, 4859, 4903, 4973 |
|
| 510 }; |
|
| 511 int scrambled[] = { |
|
| 512 759, 716, 880, 761, 2358, 2542, 2500, 2540, 2546, 2711, 2430, 1707, 1874, 1771, 1894, 1734, 1976, 2079, |
|
| 513 2124, 2130, 2135, 2266, 2338, 2733, 2754, 2764, 2797, 3362, 3363, 3364, 3441, 3515, 3539, 3579, 3655, 2888, |
|
| 514 2900, 3020, 3053, 3109, 3244, 3275, 3302, 438, 446, 508, 555, 605, 713, 14, 30, 151, 163, 227, 300, |
|
| 515 894, 1034, 1077, 1191, 1231, 1264, 1297, 1409, 1423, 1511, 1544, 1659, 1686, 315, 317, 363, 398, 417, 424, |
|
| 516 3675, 3677, 3718, 3724, 3757, 3866, 3896, 3906, 3941, 3984, 3994, 4785, 4791, 4801, 4859, 4903, 4973, |
|
| 517 4016, 4085, 4121, 4254, 4319, 4366, 4459, 4514, 4681 |
|
| 518 }; |
|
| 519 |
|
| 520 void *begin = create_nodes_test_data(100, scrambled); |
|
| 521 void *end = cx_linked_list_last(begin, loc_next); |
|
| 522 |
|
| 523 cx_linked_list_sort(&begin, &end, loc_prev, loc_next, loc_data, |
|
| 524 false, cmp_int); |
|
| 525 |
|
| 526 struct node *check = begin; |
|
| 527 struct node *check_last = NULL; |
|
| 528 CU_ASSERT_PTR_NULL(check->prev) |
|
| 529 CU_ASSERT_EQUAL(check->data, expected[0]) |
|
| 530 cx_for_n (i, 100) { |
|
| 531 CU_ASSERT_EQUAL(check->data, expected[i]) |
|
| 532 CU_ASSERT_PTR_EQUAL(check->prev, check_last) |
|
| 533 if (i < 99) { |
|
| 534 CU_ASSERT_PTR_NOT_NULL(check->next) |
|
| 535 } |
|
| 536 check_last = check; |
|
| 537 check = check->next; |
|
| 538 } |
|
| 539 CU_ASSERT_PTR_NULL(check) |
|
| 540 CU_ASSERT_PTR_EQUAL(end, check_last) |
|
| 541 |
|
| 542 destroy_nodes_test_data(begin); |
|
| 543 } |
|
| 544 |
|
| 545 void test_linked_list_reverse(void) { |
|
| 546 void *begin, *end; |
|
| 547 |
|
| 548 int data[] = {2, 4, 6, 8}; |
|
| 549 int reversed[] = {8, 6, 4, 2}; |
|
| 550 |
|
| 551 void *list = create_nodes_test_data(4, data); |
|
| 552 void *expected = create_nodes_test_data(4, reversed); |
|
| 553 |
|
| 554 begin = list; |
|
| 555 end = cx_linked_list_last(list, loc_next); |
|
| 556 |
|
| 557 cx_linked_list_reverse(&begin, &end, loc_prev, loc_next); |
|
| 558 CU_ASSERT_PTR_EQUAL(end, list) |
|
| 559 CU_ASSERT_PTR_EQUAL(begin, cx_linked_list_first(end, loc_prev)) |
|
| 560 CU_ASSERT_TRUE(0 == cx_linked_list_compare(begin, expected, loc_next, loc_data, |
|
| 561 0, cmp_int)) |
|
| 562 |
|
| 563 destroy_nodes_test_data(begin); |
|
| 564 destroy_nodes_test_data(expected); |
|
| 565 } |
|
| 566 |
|
| 567 static void verify_linked_list_create(CxList *list) { |
|
| 568 CU_ASSERT_EQUAL(list->size, 0) |
|
| 569 CU_ASSERT_EQUAL(list->capacity, (size_t) -1) |
|
| 570 CU_ASSERT_PTR_EQUAL(list->allocator, cxTestingAllocator) |
|
| 571 CU_ASSERT_PTR_EQUAL(list->cmpfunc, cmp_int) |
|
| 572 |
|
| 573 cxListDestroy(list); |
|
| 574 } |
|
| 575 |
|
| 576 void test_hl_linked_list_create(void) { |
|
| 577 CxList *list = cxLinkedListCreate(cxTestingAllocator, cmp_int, sizeof(int)); |
|
| 578 CU_ASSERT_EQUAL(list->itemsize, sizeof(int)) |
|
| 579 verify_linked_list_create(list); |
|
| 580 } |
|
| 581 |
|
| 582 void test_hl_ptr_linked_list_create(void) { |
|
| 583 CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); |
|
| 584 CU_ASSERT_EQUAL(list->itemsize, sizeof(void *)) |
|
| 585 verify_linked_list_create(list); |
|
| 586 } |
|
| 587 |
|
| 588 void test_hl_linked_list_from_array(void) { |
|
| 589 int data[] = {2, 4, 5, 7, 10, 15}; |
|
| 590 |
|
| 591 CxList *expected = cxLinkedListCreate(cxTestingAllocator, cmp_int, sizeof(int)); |
|
| 592 cx_for_n (i, 5) cxListAdd(expected, &data[i]); |
|
| 593 |
|
| 594 CxList *list = cxLinkedListFromArray(cxTestingAllocator, cmp_int, sizeof(int), 5, data); |
|
| 595 |
|
| 596 CU_ASSERT_TRUE(0 == cxListCompare(list, expected)) |
|
| 597 |
|
| 598 cxListDestroy(list); |
|
| 599 cxListDestroy(expected); |
|
| 600 } |
|
| 601 |
|
| 602 static void verify_hl_linked_list_add( |
|
| 603 CxList *list, |
|
| 604 int data[], |
|
| 605 size_t len, |
|
| 606 bool write_through |
|
| 607 ) { |
|
| 608 cx_for_n (i, len) CU_ASSERT_EQUAL(cxListAdd(list, &data[i]), 0) |
|
| 609 CU_ASSERT_EQUAL(list->size, len) |
|
| 610 CU_ASSERT_TRUE(list->capacity >= list->size) |
|
| 611 cx_for_n (i, len) CU_ASSERT_EQUAL(*(int *) cxListAt(list, i), data[i]) |
|
| 612 cx_for_n (i, len) ++data[i]; |
|
| 613 if (write_through) { |
|
| 614 cx_for_n (i, len) CU_ASSERT_EQUAL(*(int *) cxListAt(list, i), data[i]) |
|
| 615 } else { |
|
| 616 cx_for_n (i, len) CU_ASSERT_EQUAL(*(int *) cxListAt(list, i), data[i] - 1) |
|
| 617 } |
|
| 618 cxListDestroy(list); |
|
| 619 } |
|
| 620 |
|
| 621 void test_hl_linked_list_add(void) { |
|
| 622 CxList *list = cxLinkedListCreate(cxTestingAllocator, cmp_int, sizeof(int)); |
|
| 623 int data[] = {5, 47, 13, 9, 18, 1, 42}; |
|
| 624 verify_hl_linked_list_add(list, data, sizeof(data) / sizeof(int), false); |
|
| 625 } |
|
| 626 |
|
| 627 void test_hl_ptr_linked_list_add(void) { |
|
| 628 CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); |
|
| 629 int data[] = {5, 47, 84, 13, 9, 18, 90, 1, 42}; |
|
| 630 verify_hl_linked_list_add(list, data, sizeof(data) / sizeof(int), true); |
|
| 631 } |
|
| 632 |
|
| 633 static void verify_hl_linked_list_insert(CxList *list) { |
|
| 634 int a = 5, b = 47, c = 13, d = 42; |
|
| 635 |
|
| 636 CU_ASSERT_NOT_EQUAL(cxListInsert(list, 1, &a), 0) |
|
| 637 CU_ASSERT_EQUAL(list->size, 0) |
|
| 638 CU_ASSERT_EQUAL(cxListInsert(list, 0, &a), 0) |
|
| 639 CU_ASSERT_EQUAL(list->size, 1) |
|
| 640 CU_ASSERT_EQUAL(cxListInsert(list, 0, &b), 0) |
|
| 641 CU_ASSERT_EQUAL(list->size, 2) |
|
| 642 CU_ASSERT_EQUAL(cxListInsert(list, 1, &c), 0) |
|
| 643 CU_ASSERT_EQUAL(list->size, 3) |
|
| 644 CU_ASSERT_EQUAL(cxListInsert(list, 3, &d), 0) |
|
| 645 |
|
| 646 CU_ASSERT_EQUAL(list->size, 4) |
|
| 647 CU_ASSERT_TRUE(list->capacity >= list->size) |
|
| 648 |
|
| 649 CU_ASSERT_EQUAL(*(int *) cxListAt(list, 0), 47) |
|
| 650 CU_ASSERT_EQUAL(*(int *) cxListAt(list, 1), 13) |
|
| 651 CU_ASSERT_EQUAL(*(int *) cxListAt(list, 2), 5) |
|
| 652 CU_ASSERT_EQUAL(*(int *) cxListAt(list, 3), 42) |
|
| 653 |
|
| 654 cxListDestroy(list); |
|
| 655 } |
|
| 656 |
|
| 657 void test_hl_linked_list_insert(void) { |
|
| 658 verify_hl_linked_list_insert(cxLinkedListCreate(cxTestingAllocator, cmp_int, sizeof(int))); |
|
| 659 } |
|
| 660 |
|
| 661 void test_hl_ptr_linked_list_insert(void) { |
|
| 662 verify_hl_linked_list_insert(cxPointerLinkedListCreate(cxTestingAllocator, cmp_int)); |
|
| 663 } |
|
| 664 |
|
| 665 static void verify_hl_linked_list_remove(CxList *list) { |
|
| 666 CU_ASSERT_EQUAL(list->size, 4) |
|
| 667 CU_ASSERT_TRUE(list->capacity >= list->size) |
|
| 668 |
|
| 669 CU_ASSERT_NOT_EQUAL(cxListRemove(list, 4), 0) |
|
| 670 |
|
| 671 CU_ASSERT_EQUAL(cxListRemove(list, 2), 0) |
|
| 672 CU_ASSERT_EQUAL(list->size, 3) |
|
| 673 CU_ASSERT_TRUE(list->capacity >= list->size) |
|
| 674 CU_ASSERT_EQUAL(*(int *) cxListAt(list, 0), 5) |
|
| 675 CU_ASSERT_EQUAL(*(int *) cxListAt(list, 1), 47) |
|
| 676 CU_ASSERT_EQUAL(*(int *) cxListAt(list, 2), 13) |
|
| 677 |
|
| 678 CU_ASSERT_EQUAL(cxListRemove(list, 0), 0) |
|
| 679 CU_ASSERT_EQUAL(list->size, 2) |
|
| 680 CU_ASSERT_TRUE(list->capacity >= list->size) |
|
| 681 CU_ASSERT_EQUAL(*(int *) cxListAt(list, 0), 47) |
|
| 682 CU_ASSERT_EQUAL(*(int *) cxListAt(list, 1), 13) |
|
| 683 |
|
| 684 CU_ASSERT_EQUAL(cxListRemove(list, 1), 0) |
|
| 685 CU_ASSERT_EQUAL(list->size, 1) |
|
| 686 CU_ASSERT_TRUE(list->capacity >= list->size) |
|
| 687 CU_ASSERT_EQUAL(*(int *) cxListAt(list, 0), 47) |
|
| 688 |
|
| 689 CU_ASSERT_EQUAL(cxListRemove(list, 0), 0) |
|
| 690 CU_ASSERT_EQUAL(list->size, 0) |
|
| 691 CU_ASSERT_TRUE(list->capacity >= list->size) |
|
| 692 |
|
| 693 CU_ASSERT_NOT_EQUAL(cxListRemove(list, 0), 0) |
|
| 694 |
|
| 695 cxListDestroy(list); |
|
| 696 } |
|
| 697 |
|
| 698 void test_hl_linked_list_remove(void) { |
|
| 699 int data[] = {5, 47, 42, 13}; |
|
| 700 CxList *list = cxLinkedListFromArray(cxTestingAllocator, cmp_int, |
|
| 701 sizeof(int), 4, data); |
|
| 702 verify_hl_linked_list_remove(list); |
|
| 703 } |
|
| 704 |
|
| 705 void test_hl_ptr_linked_list_remove(void) { |
|
| 706 int a = 5, b = 47, c = 42, d = 13; |
|
| 707 CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); |
|
| 708 cxListAdd(list, &a); |
|
| 709 cxListAdd(list, &b); |
|
| 710 cxListAdd(list, &c); |
|
| 711 cxListAdd(list, &d); |
|
| 712 verify_hl_linked_list_remove(list); |
|
| 713 } |
|
| 714 |
|
| 715 static void verify_hl_linked_list_at( |
|
| 716 CxList *list, |
|
| 717 size_t len, |
|
| 718 int *data |
|
| 719 ) { |
|
| 720 CU_ASSERT_EQUAL(list->size, len) |
|
| 721 cx_for_n (i, len) CU_ASSERT_EQUAL(*(int *) cxListAt(list, i), data[i]) |
|
| 722 CU_ASSERT_PTR_NULL(cxListAt(list, len)) |
|
| 723 free(data); |
|
| 724 cxListDestroy(list); |
|
| 725 } |
|
| 726 |
|
| 727 void test_hl_linked_list_at(void) { |
|
| 728 size_t len = 100; |
|
| 729 int *data = create_ints_test_data(len); |
|
| 730 CxList *list = cxLinkedListFromArray(cxTestingAllocator, cmp_int, |
|
| 731 sizeof(int), len, data); |
|
| 732 verify_hl_linked_list_at(list, len, data); |
|
| 733 } |
|
| 734 |
|
| 735 void test_hl_ptr_linked_list_at(void) { |
|
| 736 size_t len = 250; |
|
| 737 int *data = create_ints_test_data(len); |
|
| 738 CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); |
|
| 739 cx_for_n (i, len) cxListAdd(list, &data[i]); |
|
| 740 verify_hl_linked_list_at(list, len, data); |
|
| 741 } |
|
| 742 |
|
| 743 static void verify_hl_linked_list_find( |
|
| 744 CxList *list, |
|
| 745 size_t len, |
|
| 746 int *data |
|
| 747 ) { |
|
| 748 cx_for_n (attempt, 100) { |
|
| 749 size_t exp = rand() % len; // NOLINT(cert-msc50-cpp) |
|
| 750 int val = data[exp]; |
|
| 751 cx_for_n (i, exp) { |
|
| 752 if (data[i] == val) { |
|
| 753 exp = i; |
|
| 754 break; |
|
| 755 } |
|
| 756 } |
|
| 757 CU_ASSERT_EQUAL(cxListFind(list, &val), exp) |
|
| 758 } |
|
| 759 free(data); |
|
| 760 cxListDestroy(list); |
|
| 761 } |
|
| 762 |
|
| 763 void test_hl_linked_list_find(void) { |
|
| 764 size_t len = 100; |
|
| 765 int *data = create_ints_test_data(len); |
|
| 766 CxList *list = cxLinkedListFromArray(cxTestingAllocator, cmp_int, sizeof(int), len, data); |
|
| 767 verify_hl_linked_list_find(list, len, data); |
|
| 768 } |
|
| 769 |
|
| 770 void test_hl_ptr_linked_list_find(void) { |
|
| 771 size_t len = 250; |
|
| 772 int *data = create_ints_test_data(len); |
|
| 773 CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); |
|
| 774 cx_for_n (i, len) cxListAdd(list, &data[i]); |
|
| 775 verify_hl_linked_list_find(list, len, data); |
|
| 776 } |
|
| 777 |
|
| 778 struct sort_test_data { |
|
| 779 size_t len; |
|
| 780 int *data; |
|
| 781 int *sorted; |
|
| 782 }; |
|
| 783 |
|
| 784 static struct sort_test_data create_sort_test_data(void) { |
|
| 785 size_t len = 1000; |
|
| 786 int *data = create_ints_test_data(len); |
|
| 787 int *sorted = malloc(sizeof(int) * len); |
|
| 788 memcpy(sorted, data, sizeof(int) * len); |
|
| 789 qsort(sorted, len, sizeof(int), cmp_int); |
|
| 790 struct sort_test_data s = {len, data, sorted}; |
|
| 791 return s; |
|
| 792 } |
|
| 793 |
|
| 794 static void free_sort_test_data(struct sort_test_data s) { |
|
| 795 free(s.data); |
|
| 796 free(s.sorted); |
|
| 797 } |
|
| 798 |
|
| 799 static void verify_hl_linked_list_sort( |
|
| 800 CxList *list, |
|
| 801 struct sort_test_data td |
|
| 802 ) { |
|
| 803 cxListSort(list); |
|
| 804 cx_for_n (i, td.len) CU_ASSERT_EQUAL_FATAL(*(int *) cxListAt(list, i), td.sorted[i]) |
|
| 805 free_sort_test_data(td); |
|
| 806 cxListDestroy(list); |
|
| 807 } |
|
| 808 |
|
| 809 void test_hl_linked_list_sort(void) { |
|
| 810 struct sort_test_data td = create_sort_test_data(); |
|
| 811 CxList *list = cxLinkedListFromArray(cxTestingAllocator, cmp_int, sizeof(int), td.len, td.data); |
|
| 812 verify_hl_linked_list_sort(list, td); |
|
| 813 } |
|
| 814 |
|
| 815 void test_hl_ptr_linked_list_sort(void) { |
|
| 816 struct sort_test_data td = create_sort_test_data(); |
|
| 817 CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); |
|
| 818 cx_for_n (i, td.len) cxListAdd(list, &td.data[i]); |
|
| 819 verify_hl_linked_list_sort(list, td); |
|
| 820 } |
|
| 821 |
|
| 822 void verify_hl_linked_list_iterator(CxList *list) { |
|
| 823 int i = 0; |
|
| 824 CxIterator iter = cxListBegin(list); |
|
| 825 cx_foreach(int*, x, iter) { |
|
| 826 CU_ASSERT_EQUAL(iter.index, (size_t) (i + 1) / 2) |
|
| 827 CU_ASSERT_EQUAL(*x, i) |
|
| 828 if (*x % 2 == 1) iter.remove = true; |
|
| 829 i++; |
|
| 830 } |
|
| 831 CU_ASSERT_EQUAL(i, 10) |
|
| 832 CU_ASSERT_EQUAL_FATAL(list->size, 5) |
|
| 833 cx_for_n(j, 5) CU_ASSERT_EQUAL(*(int *) cxListAt(list, j), (int) j * 2) |
|
| 834 cxListDestroy(list); |
|
| 835 } |
|
| 836 |
|
| 837 void test_hl_linked_list_iterator(void) { |
|
| 838 CxList *list = cxLinkedListCreate(cxTestingAllocator, cmp_int, sizeof(int)); |
|
| 839 cx_for_n (i, 10) cxListAdd(list, &i); |
|
| 840 verify_hl_linked_list_iterator(list); |
|
| 841 } |
|
| 842 |
|
| 843 void test_hl_ptr_linked_list_iterator(void) { |
|
| 844 CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); |
|
| 845 int data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; |
|
| 846 cx_for_n (i, 10) cxListAdd(list, &data[i]); |
|
| 847 verify_hl_linked_list_iterator(list); |
|
| 848 } |
|
| 849 |
|
| 850 static void verify_hl_linked_list_insert_via_iterator( |
|
| 851 CxList *list, |
|
| 852 int *testdata |
|
| 853 ) { |
|
| 854 CxIterator iter = cxListIterator(list, 2); |
|
| 855 CU_ASSERT_EQUAL(iter.index, 2) |
|
| 856 CU_ASSERT_EQUAL(*(int *) cxIteratorCurrent(&iter), 2) |
|
| 857 size_t i = 4; |
|
| 858 |
|
| 859 ++i; |
|
| 860 cxListInsertAfter(&iter, &testdata[i]); |
|
| 861 CU_ASSERT_EQUAL(iter.index, 2) |
|
| 862 CU_ASSERT_EQUAL(*(int *) cxIteratorCurrent(&iter), 2) |
|
| 863 ++i; |
|
| 864 cxListInsertBefore(&iter, &testdata[i]); |
|
| 865 CU_ASSERT_EQUAL(iter.index, 3) |
|
| 866 CU_ASSERT_EQUAL(*(int *) cxIteratorCurrent(&iter), 2) |
|
| 867 |
|
| 868 iter = cxListBegin(list); |
|
| 869 ++i; |
|
| 870 cxListInsertBefore(&iter, &testdata[i]); |
|
| 871 CU_ASSERT_EQUAL(iter.index, 1) |
|
| 872 CU_ASSERT_EQUAL(*(int *) cxIteratorCurrent(&iter), 0) |
|
| 873 iter = cxListIterator(list, list->size); |
|
| 874 ++i; |
|
| 875 cxListInsertBefore(&iter, &testdata[i]); |
|
| 876 CU_ASSERT_EQUAL(iter.index, 9) |
|
| 877 CU_ASSERT_FALSE(cxIteratorValid(&iter)) |
|
| 878 iter = cxListIterator(list, list->size); |
|
| 879 ++i; |
|
| 880 cxListInsertAfter(&iter, &testdata[i]); |
|
| 881 CU_ASSERT_EQUAL(iter.index, 10) |
|
| 882 CU_ASSERT_FALSE(cxIteratorValid(&iter)) |
|
| 883 |
|
| 884 int expdata[] = {30, 0, 1, 20, 2, 10, 3, 4, 40, 50}; |
|
| 885 cx_for_n (j, 10) CU_ASSERT_EQUAL(*(int *) cxListAt(list, j), expdata[j]) |
|
| 886 cxListDestroy(list); |
|
| 887 } |
|
| 888 |
|
| 889 void test_hl_linked_list_insert_via_iterator(void) { |
|
| 890 int testdata[] = {0, 1, 2, 3, 4, 10, 20, 30, 40, 50}; |
|
| 891 // only add the first five elements, the remaining five will be inserted |
|
| 892 CxList *list = cxLinkedListFromArray(cxTestingAllocator, cmp_int, sizeof(int), 5, testdata); |
|
| 893 verify_hl_linked_list_insert_via_iterator(list, testdata); |
|
| 894 } |
|
| 895 |
|
| 896 void test_hl_ptr_linked_list_insert_via_iterator(void) { |
|
| 897 int testdata[] = {0, 1, 2, 3, 4, 10, 20, 30, 40, 50}; |
|
| 898 CxList *list = cxPointerLinkedListCreate(cxTestingAllocator, cmp_int); |
|
| 899 // only add the first five elements, the remaining five will be inserted |
|
| 900 cx_for_n (i, 5) cxListAdd(list, &testdata[i]); |
|
| 901 verify_hl_linked_list_insert_via_iterator(list, testdata); |
|
| 902 } |
|
| 903 |
|
| 904 static void test_setup_allocator(void) { |
|
| 905 cxTestingAllocatorReset(); |
|
| 906 } |
|
| 907 |
|
| 908 static void test_verify_allocator(void) { |
|
| 909 CU_ASSERT_TRUE(cxTestingAllocatorVerify()) |
|
| 910 } |
|
| 911 |
|
| 912 int main() { |
|
| 913 CU_pSuite suite = NULL; |
|
| 914 |
|
| 915 if (CUE_SUCCESS != CU_initialize_registry()) { |
|
| 916 return CU_get_error(); |
|
| 917 } |
|
| 918 |
|
| 919 suite = CU_add_suite("low level linked list", NULL, NULL); |
|
| 920 |
|
| 921 cu_add_test(suite, test_linked_list_link_unlink); |
|
| 922 cu_add_test(suite, test_linked_list_at); |
|
| 923 cu_add_test(suite, test_linked_list_find); |
|
| 924 cu_add_test(suite, test_linked_list_compare); |
|
| 925 cu_add_test(suite, test_linked_list_prepend); |
|
| 926 cu_add_test(suite, test_linked_list_add); |
|
| 927 cu_add_test(suite, test_linked_list_insert); |
|
| 928 cu_add_test(suite, test_linked_list_insert_chain); |
|
| 929 cu_add_test(suite, test_linked_list_first); |
|
| 930 cu_add_test(suite, test_linked_list_last); |
|
| 931 cu_add_test(suite, test_linked_list_prev); |
|
| 932 cu_add_test(suite, test_linked_list_remove); |
|
| 933 cu_add_test(suite, test_linked_list_size); |
|
| 934 cu_add_test(suite, test_linked_list_sort); |
|
| 935 cu_add_test(suite, test_linked_list_reverse); |
|
| 936 |
|
| 937 suite = CU_add_suite_with_setup_and_teardown( |
|
| 938 "high level linked list", NULL, NULL, |
|
| 939 test_setup_allocator, test_verify_allocator); |
|
| 940 |
|
| 941 cu_add_test(suite, test_hl_linked_list_create); |
|
| 942 cu_add_test(suite, test_hl_linked_list_from_array); |
|
| 943 cu_add_test(suite, test_hl_linked_list_add); |
|
| 944 cu_add_test(suite, test_hl_linked_list_insert); |
|
| 945 cu_add_test(suite, test_hl_linked_list_remove); |
|
| 946 cu_add_test(suite, test_hl_linked_list_at); |
|
| 947 cu_add_test(suite, test_hl_linked_list_find); |
|
| 948 cu_add_test(suite, test_hl_linked_list_sort); |
|
| 949 cu_add_test(suite, test_hl_linked_list_iterator); |
|
| 950 cu_add_test(suite, test_hl_linked_list_insert_via_iterator); |
|
| 951 |
|
| 952 suite = CU_add_suite_with_setup_and_teardown( |
|
| 953 "high level pointer linked list", NULL, NULL, |
|
| 954 test_setup_allocator, test_verify_allocator); |
|
| 955 |
|
| 956 cu_add_test(suite, test_hl_ptr_linked_list_create); |
|
| 957 cu_add_test(suite, test_hl_ptr_linked_list_add); |
|
| 958 cu_add_test(suite, test_hl_ptr_linked_list_insert); |
|
| 959 cu_add_test(suite, test_hl_ptr_linked_list_remove); |
|
| 960 cu_add_test(suite, test_hl_ptr_linked_list_at); |
|
| 961 cu_add_test(suite, test_hl_ptr_linked_list_find); |
|
| 962 cu_add_test(suite, test_hl_ptr_linked_list_sort); |
|
| 963 cu_add_test(suite, test_hl_ptr_linked_list_iterator); |
|
| 964 cu_add_test(suite, test_hl_ptr_linked_list_insert_via_iterator); |
|
| 965 |
|
| 966 CU_basic_set_mode(UCX_CU_BRM); |
|
| 967 |
|
| 968 int exitcode; |
|
| 969 if (CU_basic_run_tests()) { |
|
| 970 exitcode = CU_get_error(); |
|
| 971 } else { |
|
| 972 exitcode = CU_get_number_of_failures() == 0 ? 0 : 1; |
|
| 973 } |
|
| 974 CU_cleanup_registry(); |
|
| 975 return exitcode; |
|
| 976 } |
|