disjoint_interval_tree 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +82 -29
- data/Rakefile +49 -4
- data/ext/disjoint_interval_tree/dit.c +63 -14
- data/ext/disjoint_interval_tree/dit.h +36 -9
- data/ext/disjoint_interval_tree/dit_ruby.c +157 -40
- data/lib/disjoint_interval_tree/version.rb +1 -1
- data/lib/disjoint_interval_tree.rb +11 -6
- data/test/c/test_dit.c +335 -65
- data/test/test_disjoint_interval_tree.rb +225 -36
- metadata +1 -1
data/test/c/test_dit.c
CHANGED
|
@@ -83,6 +83,19 @@ static const char * current_test = NULL;
|
|
|
83
83
|
printf("%s\n", (tests_failed == __before) ? "ok" : "FAILED"); \
|
|
84
84
|
} while (0)
|
|
85
85
|
|
|
86
|
+
///////////////////////
|
|
87
|
+
// OBJECT CONVENTION //
|
|
88
|
+
///////////////////////
|
|
89
|
+
|
|
90
|
+
/* Every interval of the test suite carries an object derived from its lower
|
|
91
|
+
* bound, so that any node whose object went astray - most likely the deletion
|
|
92
|
+
* of a node with two children, which moves an interval from one node to
|
|
93
|
+
* another - is caught the moment it is reported.
|
|
94
|
+
*
|
|
95
|
+
* `+1` keeps the object of [0..b[ distinguishable from a NULL object */
|
|
96
|
+
#define OBJ(A) ((dit_object_t) (uintptr_t) ((A) + 1))
|
|
97
|
+
#define OBJ_MATCHES(O, A) ((O) == OBJ(A))
|
|
98
|
+
|
|
86
99
|
////////////////////////////
|
|
87
100
|
// REFERENCE (NAIVE) MODEL //
|
|
88
101
|
////////////////////////////
|
|
@@ -92,6 +105,7 @@ static const char * current_test = NULL;
|
|
|
92
105
|
typedef struct
|
|
93
106
|
{
|
|
94
107
|
dit_value_t a, b;
|
|
108
|
+
dit_object_t obj;
|
|
95
109
|
} interval_t;
|
|
96
110
|
|
|
97
111
|
#define MODEL_CAPACITY 4096
|
|
@@ -136,8 +150,9 @@ model_insert(model_t * m, dit_value_t a, dit_value_t b)
|
|
|
136
150
|
m->intervals[i] = m->intervals[i - 1];
|
|
137
151
|
--i;
|
|
138
152
|
}
|
|
139
|
-
m->intervals[i].a
|
|
140
|
-
m->intervals[i].b
|
|
153
|
+
m->intervals[i].a = a;
|
|
154
|
+
m->intervals[i].b = b;
|
|
155
|
+
m->intervals[i].obj = OBJ(a);
|
|
141
156
|
++m->n;
|
|
142
157
|
|
|
143
158
|
return 1;
|
|
@@ -175,6 +190,9 @@ typedef struct
|
|
|
175
190
|
|
|
176
191
|
/* stop the traversal after that many intervals, 0 to never stop */
|
|
177
192
|
size_t stop_after;
|
|
193
|
+
|
|
194
|
+
/* number of intervals whose object was not the expected one */
|
|
195
|
+
size_t bad_objects;
|
|
178
196
|
} collect_t;
|
|
179
197
|
|
|
180
198
|
static void
|
|
@@ -182,10 +200,11 @@ collect_init(collect_t * c)
|
|
|
182
200
|
{
|
|
183
201
|
c->n = 0;
|
|
184
202
|
c->stop_after = 0;
|
|
203
|
+
c->bad_objects = 0;
|
|
185
204
|
}
|
|
186
205
|
|
|
187
206
|
static int
|
|
188
|
-
collect_cb(dit_value_t a, dit_value_t b, void * user)
|
|
207
|
+
collect_cb(dit_value_t a, dit_value_t b, dit_object_t obj, void * user)
|
|
189
208
|
{
|
|
190
209
|
collect_t * c = (collect_t *) user;
|
|
191
210
|
|
|
@@ -195,16 +214,84 @@ collect_cb(dit_value_t a, dit_value_t b, void * user)
|
|
|
195
214
|
abort();
|
|
196
215
|
}
|
|
197
216
|
|
|
198
|
-
c->intervals[c->n].a
|
|
199
|
-
c->intervals[c->n].b
|
|
217
|
+
c->intervals[c->n].a = a;
|
|
218
|
+
c->intervals[c->n].b = b;
|
|
219
|
+
c->intervals[c->n].obj = obj;
|
|
200
220
|
++c->n;
|
|
201
221
|
|
|
222
|
+
if (!OBJ_MATCHES(obj, a))
|
|
223
|
+
++c->bad_objects;
|
|
224
|
+
|
|
202
225
|
if (c->stop_after && c->n >= c->stop_after)
|
|
203
226
|
return 42;
|
|
204
227
|
|
|
205
228
|
return 0;
|
|
206
229
|
}
|
|
207
230
|
|
|
231
|
+
/////////////////////////
|
|
232
|
+
// VERIFYING CALLBACK //
|
|
233
|
+
/////////////////////////
|
|
234
|
+
|
|
235
|
+
/* Same checks as the collector, without the storage: for trees holding more
|
|
236
|
+
* than MODEL_CAPACITY intervals */
|
|
237
|
+
|
|
238
|
+
typedef struct
|
|
239
|
+
{
|
|
240
|
+
size_t n;
|
|
241
|
+
size_t bad_objects;
|
|
242
|
+
size_t out_of_order;
|
|
243
|
+
dit_value_t prev_b;
|
|
244
|
+
int has_prev;
|
|
245
|
+
} verify_t;
|
|
246
|
+
|
|
247
|
+
static void
|
|
248
|
+
verify_init(verify_t * v)
|
|
249
|
+
{
|
|
250
|
+
v->n = 0;
|
|
251
|
+
v->bad_objects = 0;
|
|
252
|
+
v->out_of_order = 0;
|
|
253
|
+
v->prev_b = 0;
|
|
254
|
+
v->has_prev = 0;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
static int
|
|
258
|
+
verify_cb(dit_value_t a, dit_value_t b, dit_object_t obj, void * user)
|
|
259
|
+
{
|
|
260
|
+
verify_t * v = (verify_t *) user;
|
|
261
|
+
|
|
262
|
+
if (!OBJ_MATCHES(obj, a))
|
|
263
|
+
++v->bad_objects;
|
|
264
|
+
|
|
265
|
+
if (v->has_prev && v->prev_b > a)
|
|
266
|
+
++v->out_of_order;
|
|
267
|
+
|
|
268
|
+
v->prev_b = b;
|
|
269
|
+
v->has_prev = 1;
|
|
270
|
+
++v->n;
|
|
271
|
+
|
|
272
|
+
return 0;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
#define ASSERT_VERIFIED(V) \
|
|
276
|
+
do { \
|
|
277
|
+
++checks_run; \
|
|
278
|
+
if ((V)->bad_objects) \
|
|
279
|
+
FAIL("%zu of the %zu reported intervals carried a wrong object",\
|
|
280
|
+
(V)->bad_objects, (V)->n); \
|
|
281
|
+
if ((V)->out_of_order) \
|
|
282
|
+
FAIL("%zu of the %zu reported intervals were out of order", \
|
|
283
|
+
(V)->out_of_order, (V)->n); \
|
|
284
|
+
} while (0)
|
|
285
|
+
|
|
286
|
+
/* every reported interval carried the object it was inserted with */
|
|
287
|
+
#define ASSERT_OBJECTS_OK(C) \
|
|
288
|
+
do { \
|
|
289
|
+
++checks_run; \
|
|
290
|
+
if ((C)->bad_objects) \
|
|
291
|
+
FAIL("%zu of the %zu reported intervals carried a wrong object",\
|
|
292
|
+
(C)->bad_objects, (C)->n); \
|
|
293
|
+
} while (0)
|
|
294
|
+
|
|
208
295
|
///////////
|
|
209
296
|
// TESTS //
|
|
210
297
|
///////////
|
|
@@ -222,7 +309,7 @@ test_empty(void)
|
|
|
222
309
|
ASSERT(dit_at(&tree, 0) == NULL);
|
|
223
310
|
ASSERT(dit_intersecting(&tree, 0, 100) == NULL);
|
|
224
311
|
ASSERT_EQ(dit_intersect_p(&tree, 0, 100), 0);
|
|
225
|
-
ASSERT_EQ(dit_remove(&tree, 0, 100), 0);
|
|
312
|
+
ASSERT_EQ(dit_remove(&tree, 0, 100, NULL, NULL), 0);
|
|
226
313
|
|
|
227
314
|
/* an empty tree has no hull, and the out params are left untouched */
|
|
228
315
|
dit_value_t ha = 42;
|
|
@@ -247,11 +334,12 @@ test_insert_single(void)
|
|
|
247
334
|
dit_t tree;
|
|
248
335
|
dit_init(&tree);
|
|
249
336
|
|
|
250
|
-
ASSERT_EQ(dit_insert(&tree, 10, 20), DIT_OK);
|
|
337
|
+
ASSERT_EQ(dit_insert(&tree, 10, 20, OBJ(10)), DIT_OK);
|
|
251
338
|
ASSERT_COHERENT(&tree);
|
|
252
339
|
ASSERT_EQ(dit_size(&tree), 1);
|
|
253
340
|
ASSERT_EQ(dit_empty(&tree), 0);
|
|
254
341
|
ASSERT_EQ(dit_height(&tree), 1);
|
|
342
|
+
ASSERT(tree.root->obj == OBJ(10));
|
|
255
343
|
|
|
256
344
|
/* the hull of a single node is the node interval itself */
|
|
257
345
|
ASSERT_EQ(tree.root->augment.hull.a, 10);
|
|
@@ -274,8 +362,8 @@ test_insert_empty_interval(void)
|
|
|
274
362
|
dit_t tree;
|
|
275
363
|
dit_init(&tree);
|
|
276
364
|
|
|
277
|
-
ASSERT_EQ(dit_insert(&tree, 10, 10), DIT_EMPTY);
|
|
278
|
-
ASSERT_EQ(dit_insert(&tree, 20, 10), DIT_EMPTY);
|
|
365
|
+
ASSERT_EQ(dit_insert(&tree, 10, 10, OBJ(10)), DIT_EMPTY);
|
|
366
|
+
ASSERT_EQ(dit_insert(&tree, 20, 10, OBJ(20)), DIT_EMPTY);
|
|
279
367
|
ASSERT_EQ(dit_size(&tree), 0);
|
|
280
368
|
ASSERT_COHERENT(&tree);
|
|
281
369
|
|
|
@@ -288,25 +376,25 @@ test_insert_overlap_is_rejected(void)
|
|
|
288
376
|
dit_t tree;
|
|
289
377
|
dit_init(&tree);
|
|
290
378
|
|
|
291
|
-
ASSERT_EQ(dit_insert(&tree, 10, 20), DIT_OK);
|
|
292
|
-
ASSERT_EQ(dit_insert(&tree, 30, 40), DIT_OK);
|
|
379
|
+
ASSERT_EQ(dit_insert(&tree, 10, 20, OBJ(10)), DIT_OK);
|
|
380
|
+
ASSERT_EQ(dit_insert(&tree, 30, 40, OBJ(30)), DIT_OK);
|
|
293
381
|
|
|
294
382
|
/* every flavour of overlap */
|
|
295
|
-
ASSERT_EQ(dit_insert(&tree, 10, 20), DIT_OVERLAP); /* identical */
|
|
296
|
-
ASSERT_EQ(dit_insert(&tree, 12, 18), DIT_OVERLAP); /* strictly included */
|
|
297
|
-
ASSERT_EQ(dit_insert(&tree, 5, 25), DIT_OVERLAP); /* strictly includes */
|
|
298
|
-
ASSERT_EQ(dit_insert(&tree, 5, 11), DIT_OVERLAP); /* overlaps the left */
|
|
299
|
-
ASSERT_EQ(dit_insert(&tree, 19, 25), DIT_OVERLAP); /* overlaps the right*/
|
|
300
|
-
ASSERT_EQ(dit_insert(&tree, 0, 35), DIT_OVERLAP); /* spans both */
|
|
383
|
+
ASSERT_EQ(dit_insert(&tree, 10, 20, OBJ(10)), DIT_OVERLAP); /* identical */
|
|
384
|
+
ASSERT_EQ(dit_insert(&tree, 12, 18, OBJ(12)), DIT_OVERLAP); /* strictly included */
|
|
385
|
+
ASSERT_EQ(dit_insert(&tree, 5, 25, OBJ( 5)), DIT_OVERLAP); /* strictly includes */
|
|
386
|
+
ASSERT_EQ(dit_insert(&tree, 5, 11, OBJ( 5)), DIT_OVERLAP); /* overlaps the left */
|
|
387
|
+
ASSERT_EQ(dit_insert(&tree, 19, 25, OBJ(19)), DIT_OVERLAP); /* overlaps the right*/
|
|
388
|
+
ASSERT_EQ(dit_insert(&tree, 0, 35, OBJ( 0)), DIT_OVERLAP); /* spans both */
|
|
301
389
|
|
|
302
390
|
/* and the tree was left untouched */
|
|
303
391
|
ASSERT_EQ(dit_size(&tree), 2);
|
|
304
392
|
ASSERT_COHERENT(&tree);
|
|
305
393
|
|
|
306
394
|
/* adjacent intervals do not overlap */
|
|
307
|
-
ASSERT_EQ(dit_insert(&tree, 0, 10), DIT_OK);
|
|
308
|
-
ASSERT_EQ(dit_insert(&tree, 20, 30), DIT_OK);
|
|
309
|
-
ASSERT_EQ(dit_insert(&tree, 40, 50), DIT_OK);
|
|
395
|
+
ASSERT_EQ(dit_insert(&tree, 0, 10, OBJ( 0)), DIT_OK);
|
|
396
|
+
ASSERT_EQ(dit_insert(&tree, 20, 30, OBJ(20)), DIT_OK);
|
|
397
|
+
ASSERT_EQ(dit_insert(&tree, 40, 50, OBJ(40)), DIT_OK);
|
|
310
398
|
ASSERT_EQ(dit_size(&tree), 5);
|
|
311
399
|
ASSERT_COHERENT(&tree);
|
|
312
400
|
|
|
@@ -322,7 +410,7 @@ test_ordering(void)
|
|
|
322
410
|
/* inserted out of order */
|
|
323
411
|
const dit_value_t starts[] = { 50, 10, 90, 30, 70, 0, 20 };
|
|
324
412
|
for (size_t i = 0 ; i < sizeof(starts) / sizeof(*starts) ; ++i)
|
|
325
|
-
ASSERT_EQ(dit_insert(&tree, starts[i], starts[i] + 5), DIT_OK);
|
|
413
|
+
ASSERT_EQ(dit_insert(&tree, starts[i], starts[i] + 5, OBJ(starts[i])), DIT_OK);
|
|
326
414
|
ASSERT_COHERENT(&tree);
|
|
327
415
|
|
|
328
416
|
collect_t c;
|
|
@@ -349,40 +437,40 @@ test_hull_augment(void)
|
|
|
349
437
|
|
|
350
438
|
dit_value_t a, b;
|
|
351
439
|
|
|
352
|
-
ASSERT_EQ(dit_insert(&tree, 100, 110), DIT_OK);
|
|
440
|
+
ASSERT_EQ(dit_insert(&tree, 100, 110, OBJ(100)), DIT_OK);
|
|
353
441
|
ASSERT_EQ(dit_hull(&tree, &a, &b), 1);
|
|
354
442
|
ASSERT_EQ(a, 100);
|
|
355
443
|
ASSERT_EQ(b, 110);
|
|
356
444
|
|
|
357
445
|
/* growing on the left moves the lower bound only */
|
|
358
|
-
ASSERT_EQ(dit_insert(&tree, 10, 20), DIT_OK);
|
|
446
|
+
ASSERT_EQ(dit_insert(&tree, 10, 20, OBJ(10)), DIT_OK);
|
|
359
447
|
ASSERT_EQ(dit_hull(&tree, &a, &b), 1);
|
|
360
448
|
ASSERT_EQ(a, 10);
|
|
361
449
|
ASSERT_EQ(b, 110);
|
|
362
450
|
|
|
363
451
|
/* growing on the right moves the upper bound only */
|
|
364
|
-
ASSERT_EQ(dit_insert(&tree, 200, 210), DIT_OK);
|
|
452
|
+
ASSERT_EQ(dit_insert(&tree, 200, 210, OBJ(200)), DIT_OK);
|
|
365
453
|
ASSERT_EQ(dit_hull(&tree, &a, &b), 1);
|
|
366
454
|
ASSERT_EQ(a, 10);
|
|
367
455
|
ASSERT_EQ(b, 210);
|
|
368
456
|
|
|
369
457
|
/* inserting in between changes nothing */
|
|
370
|
-
ASSERT_EQ(dit_insert(&tree, 50, 60), DIT_OK);
|
|
458
|
+
ASSERT_EQ(dit_insert(&tree, 50, 60, OBJ(50)), DIT_OK);
|
|
371
459
|
ASSERT_EQ(dit_hull(&tree, &a, &b), 1);
|
|
372
460
|
ASSERT_EQ(a, 10);
|
|
373
461
|
ASSERT_EQ(b, 210);
|
|
374
462
|
|
|
375
463
|
/* enough insertions to trigger rotations at the root */
|
|
376
464
|
for (dit_value_t i = 0 ; i < 64 ; ++i)
|
|
377
|
-
ASSERT_EQ(dit_insert(&tree, 1000 + 10 * i, 1000 + 10 * i + 5), DIT_OK);
|
|
465
|
+
ASSERT_EQ(dit_insert(&tree, 1000 + 10 * i, 1000 + 10 * i + 5, OBJ(1000 + 10 * i)), DIT_OK);
|
|
378
466
|
ASSERT_COHERENT(&tree);
|
|
379
467
|
ASSERT_EQ(dit_hull(&tree, &a, &b), 1);
|
|
380
468
|
ASSERT_EQ(a, 10);
|
|
381
469
|
ASSERT_EQ(b, 1635);
|
|
382
470
|
|
|
383
471
|
/* the hull shrinks back when the extremities are removed */
|
|
384
|
-
ASSERT_EQ(dit_remove(&tree, 10, 20), 1);
|
|
385
|
-
ASSERT_EQ(dit_remove(&tree, 1630, 1635), 1);
|
|
472
|
+
ASSERT_EQ(dit_remove(&tree, 10, 20, NULL, NULL), 1);
|
|
473
|
+
ASSERT_EQ(dit_remove(&tree, 1630, 1635, NULL, NULL), 1);
|
|
386
474
|
ASSERT_COHERENT(&tree);
|
|
387
475
|
ASSERT_EQ(dit_hull(&tree, &a, &b), 1);
|
|
388
476
|
ASSERT_EQ(a, 50);
|
|
@@ -411,7 +499,7 @@ test_intersect(void)
|
|
|
411
499
|
|
|
412
500
|
/* [0..10[ [20..30[ [40..50[ [60..70[ */
|
|
413
501
|
for (dit_value_t i = 0 ; i < 4 ; ++i)
|
|
414
|
-
ASSERT_EQ(dit_insert(&tree, 20 * i, 20 * i + 10), DIT_OK);
|
|
502
|
+
ASSERT_EQ(dit_insert(&tree, 20 * i, 20 * i + 10, OBJ(20 * i)), DIT_OK);
|
|
415
503
|
ASSERT_COHERENT(&tree);
|
|
416
504
|
|
|
417
505
|
collect_t c;
|
|
@@ -468,7 +556,7 @@ test_intersect_early_stop(void)
|
|
|
468
556
|
dit_init(&tree);
|
|
469
557
|
|
|
470
558
|
for (dit_value_t i = 0 ; i < 100 ; ++i)
|
|
471
|
-
ASSERT_EQ(dit_insert(&tree, 10 * i, 10 * i + 5), DIT_OK);
|
|
559
|
+
ASSERT_EQ(dit_insert(&tree, 10 * i, 10 * i + 5, OBJ(10 * i)), DIT_OK);
|
|
472
560
|
|
|
473
561
|
collect_t c;
|
|
474
562
|
collect_init(&c);
|
|
@@ -496,34 +584,34 @@ test_remove(void)
|
|
|
496
584
|
|
|
497
585
|
/* [0..10[ [20..30[ [40..50[ [60..70[ */
|
|
498
586
|
for (dit_value_t i = 0 ; i < 4 ; ++i)
|
|
499
|
-
ASSERT_EQ(dit_insert(&tree, 20 * i, 20 * i + 10), DIT_OK);
|
|
587
|
+
ASSERT_EQ(dit_insert(&tree, 20 * i, 20 * i + 10, OBJ(20 * i)), DIT_OK);
|
|
500
588
|
|
|
501
589
|
/* removing a hole removes nothing */
|
|
502
|
-
ASSERT_EQ(dit_remove(&tree, 10, 20), 0);
|
|
590
|
+
ASSERT_EQ(dit_remove(&tree, 10, 20, NULL, NULL), 0);
|
|
503
591
|
ASSERT_EQ(dit_size(&tree), 4);
|
|
504
592
|
ASSERT_COHERENT(&tree);
|
|
505
593
|
|
|
506
594
|
/* intervals are removed as a whole, never split */
|
|
507
|
-
ASSERT_EQ(dit_remove(&tree, 25, 26), 1);
|
|
595
|
+
ASSERT_EQ(dit_remove(&tree, 25, 26, NULL, NULL), 1);
|
|
508
596
|
ASSERT_EQ(dit_size(&tree), 3);
|
|
509
597
|
ASSERT(dit_at(&tree, 20) == NULL);
|
|
510
598
|
ASSERT(dit_at(&tree, 29) == NULL);
|
|
511
599
|
ASSERT_COHERENT(&tree);
|
|
512
600
|
|
|
513
601
|
/* removing a range spanning several intervals */
|
|
514
|
-
ASSERT_EQ(dit_remove(&tree, 5, 45), 2);
|
|
602
|
+
ASSERT_EQ(dit_remove(&tree, 5, 45, NULL, NULL), 2);
|
|
515
603
|
ASSERT_EQ(dit_size(&tree), 1);
|
|
516
604
|
ASSERT(dit_at(&tree, 65) != NULL);
|
|
517
605
|
ASSERT_COHERENT(&tree);
|
|
518
606
|
|
|
519
607
|
/* removing everything */
|
|
520
|
-
ASSERT_EQ(dit_remove(&tree, 0, 1000), 1);
|
|
608
|
+
ASSERT_EQ(dit_remove(&tree, 0, 1000, NULL, NULL), 1);
|
|
521
609
|
ASSERT_EQ(dit_size(&tree), 0);
|
|
522
610
|
ASSERT(dit_empty(&tree));
|
|
523
611
|
ASSERT_COHERENT(&tree);
|
|
524
612
|
|
|
525
613
|
/* removing from an empty tree */
|
|
526
|
-
ASSERT_EQ(dit_remove(&tree, 0, 1000), 0);
|
|
614
|
+
ASSERT_EQ(dit_remove(&tree, 0, 1000, NULL, NULL), 0);
|
|
527
615
|
ASSERT_COHERENT(&tree);
|
|
528
616
|
|
|
529
617
|
dit_destroy(&tree);
|
|
@@ -536,24 +624,24 @@ test_remove_reinsert(void)
|
|
|
536
624
|
dit_init(&tree);
|
|
537
625
|
|
|
538
626
|
for (dit_value_t i = 0 ; i < 256 ; ++i)
|
|
539
|
-
ASSERT_EQ(dit_insert(&tree, 10 * i, 10 * i + 5), DIT_OK);
|
|
627
|
+
ASSERT_EQ(dit_insert(&tree, 10 * i, 10 * i + 5, OBJ(10 * i)), DIT_OK);
|
|
540
628
|
ASSERT_COHERENT(&tree);
|
|
541
629
|
|
|
542
630
|
/* remove every other interval */
|
|
543
631
|
for (dit_value_t i = 0 ; i < 256 ; i += 2)
|
|
544
|
-
ASSERT_EQ(dit_remove(&tree, 10 * i, 10 * i + 5), 1);
|
|
632
|
+
ASSERT_EQ(dit_remove(&tree, 10 * i, 10 * i + 5, NULL, NULL), 1);
|
|
545
633
|
ASSERT_EQ(dit_size(&tree), 128);
|
|
546
634
|
ASSERT_COHERENT(&tree);
|
|
547
635
|
|
|
548
636
|
/* the removed slots are now free again */
|
|
549
637
|
for (dit_value_t i = 0 ; i < 256 ; i += 2)
|
|
550
|
-
ASSERT_EQ(dit_insert(&tree, 10 * i, 10 * i + 5), DIT_OK);
|
|
638
|
+
ASSERT_EQ(dit_insert(&tree, 10 * i, 10 * i + 5, OBJ(10 * i)), DIT_OK);
|
|
551
639
|
ASSERT_EQ(dit_size(&tree), 256);
|
|
552
640
|
ASSERT_COHERENT(&tree);
|
|
553
641
|
|
|
554
642
|
/* the others are not */
|
|
555
643
|
for (dit_value_t i = 1 ; i < 256 ; i += 2)
|
|
556
|
-
ASSERT_EQ(dit_insert(&tree, 10 * i, 10 * i + 5), DIT_OVERLAP);
|
|
644
|
+
ASSERT_EQ(dit_insert(&tree, 10 * i, 10 * i + 5, OBJ(10 * i)), DIT_OVERLAP);
|
|
557
645
|
ASSERT_COHERENT(&tree);
|
|
558
646
|
|
|
559
647
|
dit_destroy(&tree);
|
|
@@ -566,7 +654,7 @@ test_clear(void)
|
|
|
566
654
|
dit_init(&tree);
|
|
567
655
|
|
|
568
656
|
for (dit_value_t i = 0 ; i < 100 ; ++i)
|
|
569
|
-
ASSERT_EQ(dit_insert(&tree, 10 * i, 10 * i + 5), DIT_OK);
|
|
657
|
+
ASSERT_EQ(dit_insert(&tree, 10 * i, 10 * i + 5, OBJ(10 * i)), DIT_OK);
|
|
570
658
|
|
|
571
659
|
dit_clear(&tree);
|
|
572
660
|
ASSERT(dit_empty(&tree));
|
|
@@ -574,7 +662,7 @@ test_clear(void)
|
|
|
574
662
|
ASSERT_COHERENT(&tree);
|
|
575
663
|
|
|
576
664
|
/* the tree is reusable */
|
|
577
|
-
ASSERT_EQ(dit_insert(&tree, 0, 1000), DIT_OK);
|
|
665
|
+
ASSERT_EQ(dit_insert(&tree, 0, 1000, OBJ(0)), DIT_OK);
|
|
578
666
|
ASSERT_EQ(dit_size(&tree), 1);
|
|
579
667
|
ASSERT_COHERENT(&tree);
|
|
580
668
|
|
|
@@ -591,7 +679,7 @@ test_balance_sorted_insertions(void)
|
|
|
591
679
|
const dit_value_t n = 4095;
|
|
592
680
|
|
|
593
681
|
for (dit_value_t i = 0 ; i < n ; ++i)
|
|
594
|
-
ASSERT_EQ(dit_insert(&tree, 2 * i, 2 * i + 1), DIT_OK);
|
|
682
|
+
ASSERT_EQ(dit_insert(&tree, 2 * i, 2 * i + 1, OBJ(2 * i)), DIT_OK);
|
|
595
683
|
|
|
596
684
|
ASSERT_EQ(dit_size(&tree), n);
|
|
597
685
|
ASSERT_COHERENT(&tree);
|
|
@@ -603,7 +691,7 @@ test_balance_sorted_insertions(void)
|
|
|
603
691
|
/* and reverse sorted insertions too */
|
|
604
692
|
dit_clear(&tree);
|
|
605
693
|
for (dit_value_t i = n ; i > 0 ; --i)
|
|
606
|
-
ASSERT_EQ(dit_insert(&tree, 2 * i, 2 * i + 1), DIT_OK);
|
|
694
|
+
ASSERT_EQ(dit_insert(&tree, 2 * i, 2 * i + 1, OBJ(2 * i)), DIT_OK);
|
|
607
695
|
ASSERT_EQ(dit_size(&tree), n);
|
|
608
696
|
ASSERT(dit_height(&tree) <= 18);
|
|
609
697
|
ASSERT_COHERENT(&tree);
|
|
@@ -611,7 +699,7 @@ test_balance_sorted_insertions(void)
|
|
|
611
699
|
/* sequential deletions from the left */
|
|
612
700
|
for (dit_value_t i = 1 ; i <= n ; ++i)
|
|
613
701
|
{
|
|
614
|
-
ASSERT_EQ(dit_remove(&tree, 2 * i, 2 * i + 1), 1);
|
|
702
|
+
ASSERT_EQ(dit_remove(&tree, 2 * i, 2 * i + 1, NULL, NULL), 1);
|
|
615
703
|
ASSERT_EQ(dit_size(&tree), n - i);
|
|
616
704
|
}
|
|
617
705
|
ASSERT(dit_empty(&tree));
|
|
@@ -627,9 +715,9 @@ test_extreme_values(void)
|
|
|
627
715
|
dit_t tree;
|
|
628
716
|
dit_init(&tree);
|
|
629
717
|
|
|
630
|
-
ASSERT_EQ(dit_insert(&tree, 0, 1), DIT_OK);
|
|
631
|
-
ASSERT_EQ(dit_insert(&tree, DIT_VALUE_MAX - 1, DIT_VALUE_MAX), DIT_OK);
|
|
632
|
-
ASSERT_EQ(dit_insert(&tree, 1, DIT_VALUE_MAX - 1), DIT_OK);
|
|
718
|
+
ASSERT_EQ(dit_insert(&tree, 0, 1, OBJ(0)), DIT_OK);
|
|
719
|
+
ASSERT_EQ(dit_insert(&tree, DIT_VALUE_MAX - 1, DIT_VALUE_MAX, OBJ(DIT_VALUE_MAX - 1)), DIT_OK);
|
|
720
|
+
ASSERT_EQ(dit_insert(&tree, 1, DIT_VALUE_MAX - 1, OBJ(1)), DIT_OK);
|
|
633
721
|
ASSERT_COHERENT(&tree);
|
|
634
722
|
|
|
635
723
|
ASSERT_EQ(tree.root->augment.hull.a, 0);
|
|
@@ -645,7 +733,7 @@ test_extreme_values(void)
|
|
|
645
733
|
dit_intersect(&tree, 0, DIT_VALUE_MAX, collect_cb, &c);
|
|
646
734
|
ASSERT_EQ(c.n, 3);
|
|
647
735
|
|
|
648
|
-
ASSERT_EQ(dit_remove(&tree, 0, DIT_VALUE_MAX), 3);
|
|
736
|
+
ASSERT_EQ(dit_remove(&tree, 0, DIT_VALUE_MAX, NULL, NULL), 3);
|
|
649
737
|
ASSERT(dit_empty(&tree));
|
|
650
738
|
ASSERT_COHERENT(&tree);
|
|
651
739
|
|
|
@@ -662,7 +750,7 @@ test_check_detects_corruption(void)
|
|
|
662
750
|
dit_init(&tree);
|
|
663
751
|
|
|
664
752
|
for (dit_value_t i = 0 ; i < 32 ; ++i)
|
|
665
|
-
ASSERT_EQ(dit_insert(&tree, 10 * i, 10 * i + 5), DIT_OK);
|
|
753
|
+
ASSERT_EQ(dit_insert(&tree, 10 * i, 10 * i + 5, OBJ(10 * i)), DIT_OK);
|
|
666
754
|
ASSERT_EQ(dit_check(&tree, err, sizeof(err)), 0);
|
|
667
755
|
|
|
668
756
|
/* corrupt the cardinality */
|
|
@@ -721,7 +809,7 @@ test_dump_dot(void)
|
|
|
721
809
|
dit_dump_dot(&tree, f);
|
|
722
810
|
|
|
723
811
|
for (dit_value_t i = 0 ; i < 16 ; ++i)
|
|
724
|
-
ASSERT_EQ(dit_insert(&tree, 10 * i, 10 * i + 5), DIT_OK);
|
|
812
|
+
ASSERT_EQ(dit_insert(&tree, 10 * i, 10 * i + 5, OBJ(10 * i)), DIT_OK);
|
|
725
813
|
|
|
726
814
|
dit_dump_dot(&tree, f);
|
|
727
815
|
dit_dump_dot(NULL, f);
|
|
@@ -732,6 +820,137 @@ test_dump_dot(void)
|
|
|
732
820
|
dit_destroy(&tree);
|
|
733
821
|
}
|
|
734
822
|
|
|
823
|
+
/////////////
|
|
824
|
+
// OBJECTS //
|
|
825
|
+
/////////////
|
|
826
|
+
|
|
827
|
+
static void
|
|
828
|
+
test_objects(void)
|
|
829
|
+
{
|
|
830
|
+
dit_t tree;
|
|
831
|
+
dit_init(&tree);
|
|
832
|
+
|
|
833
|
+
int one, two, three;
|
|
834
|
+
|
|
835
|
+
ASSERT_EQ(dit_insert(&tree, 0, 10, &one), DIT_OK);
|
|
836
|
+
ASSERT_EQ(dit_insert(&tree, 20, 30, &two), DIT_OK);
|
|
837
|
+
ASSERT_EQ(dit_insert(&tree, 40, 50, &three), DIT_OK);
|
|
838
|
+
ASSERT_COHERENT(&tree);
|
|
839
|
+
|
|
840
|
+
/* point and range lookups hand the object back */
|
|
841
|
+
ASSERT(dit_at(&tree, 5)->obj == &one);
|
|
842
|
+
ASSERT(dit_at(&tree, 25)->obj == &two);
|
|
843
|
+
ASSERT(dit_at(&tree, 49)->obj == &three);
|
|
844
|
+
ASSERT(dit_intersecting(&tree, 5, 45)->obj != NULL);
|
|
845
|
+
|
|
846
|
+
/* a NULL object is a legitimate object */
|
|
847
|
+
ASSERT_EQ(dit_insert(&tree, 60, 70, NULL), DIT_OK);
|
|
848
|
+
ASSERT(dit_at(&tree, 65) != NULL);
|
|
849
|
+
ASSERT(dit_at(&tree, 65)->obj == NULL);
|
|
850
|
+
|
|
851
|
+
/* two intervals may share the same object */
|
|
852
|
+
ASSERT_EQ(dit_insert(&tree, 80, 90, &one), DIT_OK);
|
|
853
|
+
ASSERT(dit_at(&tree, 85)->obj == &one);
|
|
854
|
+
ASSERT(dit_at(&tree, 5)->obj == &one);
|
|
855
|
+
|
|
856
|
+
/* an object survives the removal of its neighbours */
|
|
857
|
+
ASSERT_EQ(dit_remove(&tree, 20, 30, NULL, NULL), 1);
|
|
858
|
+
ASSERT_EQ(dit_remove(&tree, 40, 50, NULL, NULL), 1);
|
|
859
|
+
ASSERT_COHERENT(&tree);
|
|
860
|
+
ASSERT(dit_at(&tree, 5)->obj == &one);
|
|
861
|
+
ASSERT(dit_at(&tree, 85)->obj == &one);
|
|
862
|
+
ASSERT(dit_at(&tree, 65)->obj == NULL);
|
|
863
|
+
|
|
864
|
+
dit_destroy(&tree);
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
/* The object must travel with its interval when a node with two children is
|
|
868
|
+
* deleted: that deletion moves the in-order successor's interval into the
|
|
869
|
+
* deleted node, and the object has to move with it */
|
|
870
|
+
static void
|
|
871
|
+
test_objects_survive_deletions(void)
|
|
872
|
+
{
|
|
873
|
+
dit_t tree;
|
|
874
|
+
dit_init(&tree);
|
|
875
|
+
|
|
876
|
+
const dit_value_t n = 512;
|
|
877
|
+
|
|
878
|
+
for (dit_value_t i = 0 ; i < n ; ++i)
|
|
879
|
+
ASSERT_EQ(dit_insert(&tree, 10 * i, 10 * i + 5, OBJ(10 * i)), DIT_OK);
|
|
880
|
+
|
|
881
|
+
verify_t v;
|
|
882
|
+
verify_init(&v);
|
|
883
|
+
dit_each(&tree, verify_cb, &v);
|
|
884
|
+
ASSERT_VERIFIED(&v);
|
|
885
|
+
ASSERT_EQ(v.n, n);
|
|
886
|
+
|
|
887
|
+
/* delete in an order that maximizes two-children deletions: always the
|
|
888
|
+
* interval sitting at the root */
|
|
889
|
+
while (!dit_empty(&tree))
|
|
890
|
+
{
|
|
891
|
+
const dit_value_t a = tree.root->a;
|
|
892
|
+
|
|
893
|
+
if (tree.root->obj != OBJ(a))
|
|
894
|
+
FAIL("the root of the tree holds the object of another interval");
|
|
895
|
+
|
|
896
|
+
ASSERT_EQ(dit_remove(&tree, a, a + 1, NULL, NULL), 1);
|
|
897
|
+
|
|
898
|
+
verify_init(&v);
|
|
899
|
+
dit_each(&tree, verify_cb, &v);
|
|
900
|
+
if (v.bad_objects)
|
|
901
|
+
FAIL("%zu intervals carried a wrong object after removing "
|
|
902
|
+
"[%" PRIu64 "..%" PRIu64 "[", v.bad_objects, a, a + 5);
|
|
903
|
+
if (v.n != dit_size(&tree))
|
|
904
|
+
FAIL("the traversal reported %zu of the %zu remaining intervals",
|
|
905
|
+
v.n, dit_size(&tree));
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
ASSERT_COHERENT(&tree);
|
|
909
|
+
dit_destroy(&tree);
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
static void
|
|
913
|
+
test_remove_callback(void)
|
|
914
|
+
{
|
|
915
|
+
dit_t tree;
|
|
916
|
+
dit_init(&tree);
|
|
917
|
+
|
|
918
|
+
/* [0..10[ [20..30[ [40..50[ [60..70[ */
|
|
919
|
+
for (dit_value_t i = 0 ; i < 4 ; ++i)
|
|
920
|
+
ASSERT_EQ(dit_insert(&tree, 20 * i, 20 * i + 10, OBJ(20 * i)), DIT_OK);
|
|
921
|
+
|
|
922
|
+
collect_t c;
|
|
923
|
+
|
|
924
|
+
/* nothing removed, nothing reported */
|
|
925
|
+
collect_init(&c);
|
|
926
|
+
ASSERT_EQ(dit_remove(&tree, 10, 20, collect_cb, &c), 0);
|
|
927
|
+
ASSERT_EQ(c.n, 0);
|
|
928
|
+
|
|
929
|
+
/* every removed interval is reported once, in increasing order, with its
|
|
930
|
+
* object, before the node is freed */
|
|
931
|
+
collect_init(&c);
|
|
932
|
+
ASSERT_EQ(dit_remove(&tree, 5, 45, collect_cb, &c), 3);
|
|
933
|
+
ASSERT_EQ(c.n, 3);
|
|
934
|
+
ASSERT_OBJECTS_OK(&c);
|
|
935
|
+
ASSERT_EQ(c.intervals[0].a, 0);
|
|
936
|
+
ASSERT_EQ(c.intervals[1].a, 20);
|
|
937
|
+
ASSERT_EQ(c.intervals[2].a, 40);
|
|
938
|
+
ASSERT(c.intervals[0].obj == OBJ(0));
|
|
939
|
+
ASSERT(c.intervals[1].obj == OBJ(20));
|
|
940
|
+
ASSERT(c.intervals[2].obj == OBJ(40));
|
|
941
|
+
ASSERT_COHERENT(&tree);
|
|
942
|
+
ASSERT_EQ(dit_size(&tree), 1);
|
|
943
|
+
|
|
944
|
+
/* a removal cannot be interrupted: the callback return value is ignored */
|
|
945
|
+
collect_init(&c);
|
|
946
|
+
c.stop_after = 1;
|
|
947
|
+
ASSERT_EQ(dit_remove(&tree, 0, 1000, collect_cb, &c), 1);
|
|
948
|
+
ASSERT(dit_empty(&tree));
|
|
949
|
+
ASSERT_COHERENT(&tree);
|
|
950
|
+
|
|
951
|
+
dit_destroy(&tree);
|
|
952
|
+
}
|
|
953
|
+
|
|
735
954
|
///////////////////////
|
|
736
955
|
// RANDOMIZED TESTS //
|
|
737
956
|
///////////////////////
|
|
@@ -783,9 +1002,13 @@ same_as_model(dit_t * tree, const model_t * m, collect_t * c)
|
|
|
783
1002
|
if (c->n != m->n)
|
|
784
1003
|
return 0;
|
|
785
1004
|
|
|
1005
|
+
if (c->bad_objects)
|
|
1006
|
+
return 0;
|
|
1007
|
+
|
|
786
1008
|
for (size_t i = 0 ; i < m->n ; ++i)
|
|
787
|
-
if (c->intervals[i].a
|
|
788
|
-
c->intervals[i].b
|
|
1009
|
+
if (c->intervals[i].a != m->intervals[i].a ||
|
|
1010
|
+
c->intervals[i].b != m->intervals[i].b ||
|
|
1011
|
+
c->intervals[i].obj != m->intervals[i].obj)
|
|
789
1012
|
return 0;
|
|
790
1013
|
|
|
791
1014
|
return 1;
|
|
@@ -817,7 +1040,7 @@ test_random_against_model(void)
|
|
|
817
1040
|
case 0:
|
|
818
1041
|
{
|
|
819
1042
|
const int insertable = !model_intersect(&model, a, b);
|
|
820
|
-
const dit_status_t status = dit_insert(&tree, a, b);
|
|
1043
|
+
const dit_status_t status = dit_insert(&tree, a, b, OBJ(a));
|
|
821
1044
|
|
|
822
1045
|
if (insertable)
|
|
823
1046
|
{
|
|
@@ -835,14 +1058,35 @@ test_random_against_model(void)
|
|
|
835
1058
|
break ;
|
|
836
1059
|
}
|
|
837
1060
|
|
|
838
|
-
/* remove */
|
|
1061
|
+
/* remove, checking what the removal callback reports */
|
|
839
1062
|
case 1:
|
|
840
1063
|
{
|
|
841
|
-
|
|
842
|
-
|
|
1064
|
+
collect_init(&c);
|
|
1065
|
+
|
|
1066
|
+
size_t expected = 0;
|
|
1067
|
+
for (size_t i = 0 ; i < model.n ; ++i)
|
|
1068
|
+
if (a < model.intervals[i].b && model.intervals[i].a < b)
|
|
1069
|
+
++expected;
|
|
1070
|
+
|
|
1071
|
+
const size_t got = dit_remove(&tree, a, b, collect_cb, &c);
|
|
1072
|
+
model_remove(&model, a, b);
|
|
1073
|
+
|
|
843
1074
|
if (got != expected)
|
|
844
1075
|
FAIL("remove([%" PRIu64 "..%" PRIu64 "[) removed %zu "
|
|
845
1076
|
"intervals, expected %zu", a, b, got, expected);
|
|
1077
|
+
|
|
1078
|
+
/* the callback saw every removed interval, in increasing
|
|
1079
|
+
* order, each with the object it was inserted with */
|
|
1080
|
+
if (c.n != got)
|
|
1081
|
+
FAIL("remove([%" PRIu64 "..%" PRIu64 "[) reported %zu of "
|
|
1082
|
+
"the %zu intervals it removed", a, b, c.n, got);
|
|
1083
|
+
if (c.bad_objects)
|
|
1084
|
+
FAIL("remove([%" PRIu64 "..%" PRIu64 "[) reported %zu "
|
|
1085
|
+
"wrong objects", a, b, c.bad_objects);
|
|
1086
|
+
for (size_t i = 1 ; i < c.n ; ++i)
|
|
1087
|
+
if (c.intervals[i - 1].a >= c.intervals[i].a)
|
|
1088
|
+
FAIL("remove([%" PRIu64 "..%" PRIu64 "[) reported "
|
|
1089
|
+
"intervals out of order at %zu", a, b, i);
|
|
846
1090
|
break ;
|
|
847
1091
|
}
|
|
848
1092
|
|
|
@@ -857,8 +1101,9 @@ test_random_against_model(void)
|
|
|
857
1101
|
if (a < model.intervals[i].b && model.intervals[i].a < b)
|
|
858
1102
|
{
|
|
859
1103
|
if (expected >= c.n ||
|
|
860
|
-
c.intervals[expected].a
|
|
861
|
-
c.intervals[expected].b
|
|
1104
|
+
c.intervals[expected].a != model.intervals[i].a ||
|
|
1105
|
+
c.intervals[expected].b != model.intervals[i].b ||
|
|
1106
|
+
c.intervals[expected].obj != model.intervals[i].obj)
|
|
862
1107
|
FAIL("intersect([%" PRIu64 "..%" PRIu64 "[) "
|
|
863
1108
|
"mismatch at %zu", a, b, expected);
|
|
864
1109
|
++expected;
|
|
@@ -867,6 +1112,9 @@ test_random_against_model(void)
|
|
|
867
1112
|
if (c.n != expected)
|
|
868
1113
|
FAIL("intersect([%" PRIu64 "..%" PRIu64 "[) reported %zu "
|
|
869
1114
|
"intervals, expected %zu", a, b, c.n, expected);
|
|
1115
|
+
if (c.bad_objects)
|
|
1116
|
+
FAIL("intersect([%" PRIu64 "..%" PRIu64 "[) reported %zu "
|
|
1117
|
+
"wrong objects", a, b, c.bad_objects);
|
|
870
1118
|
break ;
|
|
871
1119
|
}
|
|
872
1120
|
}
|
|
@@ -903,6 +1151,8 @@ test_random_large(void)
|
|
|
903
1151
|
dit_t tree;
|
|
904
1152
|
dit_init(&tree);
|
|
905
1153
|
|
|
1154
|
+
verify_t v;
|
|
1155
|
+
|
|
906
1156
|
size_t inserted = 0;
|
|
907
1157
|
size_t removed = 0;
|
|
908
1158
|
|
|
@@ -912,8 +1162,8 @@ test_random_large(void)
|
|
|
912
1162
|
const dit_value_t b = a + 1 + rng_below(64);
|
|
913
1163
|
|
|
914
1164
|
if (rng_below(4) == 0)
|
|
915
|
-
removed += dit_remove(&tree, a, b);
|
|
916
|
-
else if (dit_insert(&tree, a, b) == DIT_OK)
|
|
1165
|
+
removed += dit_remove(&tree, a, b, NULL, NULL);
|
|
1166
|
+
else if (dit_insert(&tree, a, b, OBJ(a)) == DIT_OK)
|
|
917
1167
|
++inserted;
|
|
918
1168
|
|
|
919
1169
|
if ((it % 5000) == 0)
|
|
@@ -921,6 +1171,14 @@ test_random_large(void)
|
|
|
921
1171
|
char err[512];
|
|
922
1172
|
if (dit_check(&tree, err, sizeof(err)))
|
|
923
1173
|
FAIL("iteration %d: incoherent tree: %s", it, err);
|
|
1174
|
+
|
|
1175
|
+
/* `dit_check()` cannot know anything about opaque objects, so
|
|
1176
|
+
* walk the tree and check them against the convention */
|
|
1177
|
+
verify_init(&v);
|
|
1178
|
+
dit_each(&tree, verify_cb, &v);
|
|
1179
|
+
if (v.bad_objects)
|
|
1180
|
+
FAIL("iteration %d: %zu of the %zu intervals carried a wrong "
|
|
1181
|
+
"object", it, v.bad_objects, v.n);
|
|
924
1182
|
}
|
|
925
1183
|
}
|
|
926
1184
|
|
|
@@ -929,8 +1187,17 @@ test_random_large(void)
|
|
|
929
1187
|
ASSERT(inserted > 1000);
|
|
930
1188
|
ASSERT(removed > 1000);
|
|
931
1189
|
|
|
932
|
-
|
|
933
|
-
|
|
1190
|
+
verify_init(&v);
|
|
1191
|
+
dit_each(&tree, verify_cb, &v);
|
|
1192
|
+
ASSERT_VERIFIED(&v);
|
|
1193
|
+
ASSERT_EQ(v.n, dit_size(&tree));
|
|
1194
|
+
|
|
1195
|
+
/* removing everything must empty the tree, and hand every object back,
|
|
1196
|
+
* in increasing order */
|
|
1197
|
+
verify_init(&v);
|
|
1198
|
+
const size_t all = dit_remove(&tree, 0, DIT_VALUE_MAX, verify_cb, &v);
|
|
1199
|
+
ASSERT_VERIFIED(&v);
|
|
1200
|
+
ASSERT_EQ(v.n, all);
|
|
934
1201
|
ASSERT(dit_empty(&tree));
|
|
935
1202
|
ASSERT_COHERENT(&tree);
|
|
936
1203
|
|
|
@@ -965,7 +1232,7 @@ test_random_insert_then_remove(void)
|
|
|
965
1232
|
|
|
966
1233
|
for (size_t i = 0 ; i < n ; ++i)
|
|
967
1234
|
{
|
|
968
|
-
if (dit_insert(&tree, 10 * order[i], 10 * order[i] + 7) != DIT_OK)
|
|
1235
|
+
if (dit_insert(&tree, 10 * order[i], 10 * order[i] + 7, OBJ(10 * order[i])) != DIT_OK)
|
|
969
1236
|
{
|
|
970
1237
|
free(order);
|
|
971
1238
|
FAIL("insertion %zu failed", i);
|
|
@@ -998,7 +1265,7 @@ test_random_insert_then_remove(void)
|
|
|
998
1265
|
|
|
999
1266
|
for (size_t i = 0 ; i < n ; ++i)
|
|
1000
1267
|
{
|
|
1001
|
-
if (dit_remove(&tree, 10 * order[i], 10 * order[i] + 7) != 1)
|
|
1268
|
+
if (dit_remove(&tree, 10 * order[i], 10 * order[i] + 7, NULL, NULL) != 1)
|
|
1002
1269
|
{
|
|
1003
1270
|
free(order);
|
|
1004
1271
|
FAIL("removal %zu failed", i);
|
|
@@ -1061,6 +1328,9 @@ main(int argc, char ** argv)
|
|
|
1061
1328
|
RUN(test_extreme_values);
|
|
1062
1329
|
RUN(test_check_detects_corruption);
|
|
1063
1330
|
RUN(test_dump_dot);
|
|
1331
|
+
RUN(test_objects);
|
|
1332
|
+
RUN(test_objects_survive_deletions);
|
|
1333
|
+
RUN(test_remove_callback);
|
|
1064
1334
|
RUN(test_random_against_model);
|
|
1065
1335
|
RUN(test_random_large);
|
|
1066
1336
|
RUN(test_random_insert_then_remove);
|