Apache HTTPD
testskiplist.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "testutil.h"
18#include "apr.h"
19#include "apr_strings.h"
20#include "apr_general.h"
21#include "apr_pools.h"
22#include "apr_skiplist.h"
23#if APR_HAVE_STDIO_H
24#include <stdio.h>
25#endif
26#if APR_HAVE_STDLIB_H
27#include <stdlib.h>
28#endif
29#if APR_HAVE_STRING_H
30#include <string.h>
31#endif
32
35
37{
38 size_t size = 0;
40 for (n = apr_skiplist_getlist(sl); n; apr_skiplist_next(sl, &n)) {
41 ++size;
42 }
44 return size;
45}
46
57
58static void skiplist_find(abts_case *tc, void *data)
59{
60 const char *val;
61
65 ABTS_STR_EQUAL(tc, "baton", val);
66}
67
68static void skiplist_dontfind(abts_case *tc, void *data)
69{
70 const char *val;
71
72 val = apr_skiplist_find(skiplist, "keynotthere", NULL);
73 ABTS_PTR_EQUAL(tc, NULL, (void *)val);
74}
75
76static void skiplist_insert(abts_case *tc, void *data)
77{
78 const char *val;
79 int i, height = 0;
80
81 for (i = 0; i < 10; ++i) {
86 ABTS_STR_EQUAL(tc, "baton", val);
87
88 if (height == 0) {
90 }
91 else {
93 }
94 }
95
100 ABTS_STR_EQUAL(tc, "foo", val);
101
103 ABTS_TRUE(tc, 3 == skiplist_get_size(tc, skiplist));
104 val = apr_skiplist_find(skiplist, "atfirst", NULL);
106 ABTS_STR_EQUAL(tc, "atfirst", val);
107}
108
109#define NUM_ADDS 100
110static void skiplist_add(abts_case *tc, void *data)
111{
112 const char *val;
113 size_t i, n = 0;
114
116 ABTS_TRUE(tc, 0 == skiplist_get_size(tc, skiplist));
117
118 for (i = 0; i < NUM_ADDS; ++i) {
119 n++;
122 val = apr_skiplist_find(skiplist, "daton", NULL);
124 ABTS_STR_EQUAL(tc, "daton", val);
125
126 n++;
129 val = apr_skiplist_find(skiplist, "baton", NULL);
131 ABTS_STR_EQUAL(tc, "baton", val);
132
133 n++;
136 val = apr_skiplist_find(skiplist, "caton", NULL);
138 ABTS_STR_EQUAL(tc, "caton", val);
139
140 n++;
143 val = apr_skiplist_find(skiplist, "aaton", NULL);
145 ABTS_STR_EQUAL(tc, "aaton", val);
146 }
147}
148
149static void skiplist_replace(abts_case *tc, void *data)
150{
151 const char *val;
152 size_t n = skiplist_get_size(tc, skiplist);
153
154 n -= NUM_ADDS - 1;
157 val = apr_skiplist_find(skiplist, "daton", NULL);
159 ABTS_STR_EQUAL(tc, "daton", val);
160
161 n -= NUM_ADDS - 1;
164 val = apr_skiplist_find(skiplist, "baton", NULL);
166 ABTS_STR_EQUAL(tc, "baton", val);
167
168 n -= NUM_ADDS - 1;
171 val = apr_skiplist_find(skiplist, "caton", NULL);
173 ABTS_STR_EQUAL(tc, "caton", val);
174
175 n -= NUM_ADDS - 1;
178 val = apr_skiplist_find(skiplist, "aaton", NULL);
180 ABTS_STR_EQUAL(tc, "aaton", val);
181
182 ABTS_TRUE(tc, n == 4);
183}
184
192
193static void skiplist_size(abts_case *tc, void *data)
194{
195 const char *val;
196
197 ABTS_TRUE(tc, 0 == skiplist_get_size(tc, skiplist));
198
204 ABTS_STR_EQUAL(tc, "abc", val);
207 ABTS_STR_EQUAL(tc, "ghi", val);
210 ABTS_STR_EQUAL(tc, "def", val);
211
212 ABTS_TRUE(tc, 3 == skiplist_get_size(tc, skiplist));
214}
215
216static void skiplist_remove(abts_case *tc, void *data)
217{
218 const char *val;
219
220 ABTS_TRUE(tc, 0 == skiplist_get_size(tc, skiplist));
221
223 ABTS_TRUE(tc, 1 == skiplist_get_size(tc, skiplist));
224 val = apr_skiplist_find(skiplist, "baton", NULL);
226 ABTS_STR_EQUAL(tc, "baton", val);
227
229 ABTS_TRUE(tc, 2 == skiplist_get_size(tc, skiplist));
230 val = apr_skiplist_find(skiplist, "baton", NULL);
232 ABTS_STR_EQUAL(tc, "baton", val);
233
234 ABTS_TRUE(tc, apr_skiplist_remove(skiplist, "baton", NULL) != 0);
235 ABTS_TRUE(tc, 1 == skiplist_get_size(tc, skiplist));
236 val = apr_skiplist_find(skiplist, "baton", NULL);
238 ABTS_STR_EQUAL(tc, "baton", val);
239
241 ABTS_TRUE(tc, 2 == skiplist_get_size(tc, skiplist));
242 val = apr_skiplist_find(skiplist, "baton", NULL);
244 ABTS_STR_EQUAL(tc, "baton", val);
245
246 /* remove all "baton"s */
247 while (apr_skiplist_remove(skiplist, "baton", NULL))
248 ;
249 ABTS_TRUE(tc, 0 == skiplist_get_size(tc, skiplist));
250 val = apr_skiplist_find(skiplist, "baton", NULL);
251 ABTS_PTR_EQUAL(tc, NULL, val);
252}
253
254#define NUM_RAND (100)
255#define NUM_FIND (3 * NUM_RAND)
256static void skiplist_random_loop(abts_case *tc, void *data)
257{
258 char **batons;
259 apr_skiplist *sl;
260 const char *val;
261 int i;
262
268
269 batons = apr_palloc(ptmp, NUM_FIND * sizeof(char*));
270
271 for (i = 0; i < NUM_FIND; ++i) {
272 if (i < NUM_RAND) {
273 batons[i] = apr_psprintf(ptmp, "%.6u", rand() % 1000000);
274 }
275 else {
277 }
281 ABTS_STR_EQUAL(tc, batons[i], val);
282 }
283
285}
286
287typedef struct elem {
288 int b;
289 int a;
291
292
294 int* a = apr_skiplist_alloc(list, sizeof(int));
295 *a = n;
297}
298
304
305static int comp(void *a, void *b){
306 return *((int*) a) - *((int*) b);
307}
308
309static int scomp(void *a, void *b){
310 return ((elem*) a)->a - ((elem*) b)->a;
311}
312
313static int ecomp(void *a, void *b)
314{
315 elem const * const e1 = a;
316 elem const * const e2 = b;
317 if (e1->a < e2->a) {
318 return -1;
319 }
320 else if (e1->a > e2->a) {
321 return +1;
322 }
323 else if (e1->b < e2->b) {
324 return -1;
325 }
326 else if (e1->b > e2->b) {
327 return +1;
328 }
329 else {
330 return 0;
331 }
332}
333
334/* Some tests below add multiple duplicates and then try to remove each one
335 * individually, in arbitrary order.
336 *
337 * Using apr_skiplist_remove_compare(..., scomp, NULL) would not work because
338 * it will likely remove any duplicate (the first one) encountered on the path,
339 * hence possibly not the expected one.
340 *
341 * Using apr_skiplist_remove_compare(..., ecomp, NULL) works provided all the
342 * duplicates (same a) don't also have the same b (which is the case in the
343 * test below), hence uniqueness is cooked in the elem itself.
344 *
345 * Another possibility is to rely on unique pointers, and then cook a remove
346 * function, like the following skiplist_remove_scomp(), which will go straight
347 * to the last duplicate (using scomp) and then iterate on the previous elems
348 * until pointers match.
349 *
350 * Providing uniqueness in the elem itself is the more clean/efficient option,
351 * but if all you have is a unique pointer the pattern in the function may be
352 * worth it ( or it's just a way to test several skiplist functionalities :)
353 */
355{
356 elem *e;
359 while (e && e != n) {
360 ABTS_INT_EQUAL(tc, 0, scomp(n, e));
362 }
365}
366
367static void skiplist_test(abts_case *tc, void *data) {
368 int test_elems = 10;
369 int i = 0, j = 0;
370 int *val = NULL;
371 elem *val2 = NULL;
376 int first_forty_two = 42,
377 second_forty_two = 42;
378 apr_array_header_t *array;
379 elem t1, t2, t3, t4, t5;
380 t1.a = 1; t1.b = 1;
381 t2.a = 42; t2.b = 1;
382 t3.a = 42; t3.b = 2;
383 t4.a = 42; t4.b = 3;
384 t5.a = 142; t5.b = 1;
385
388
389 /* insert 10 objects */
390 for (i = 0; i < test_elems; ++i){
392 }
393
394 /* remove all objects */
395 while ((val = apr_skiplist_pop(list, NULL))){
396 ABTS_INT_EQUAL(tc, *val, j++);
397 }
398
399 /* insert 10 objects again */
400 for (i = test_elems; i < test_elems+test_elems; ++i){
402 }
403
404 j = test_elems;
405 while ((val = apr_skiplist_pop(list, NULL))){
406 ABTS_INT_EQUAL(tc, *val, j++);
407 }
408
409 /* empty */
411 ABTS_PTR_EQUAL(tc, val, NULL);
412
413 add_int_to_skiplist(tc, list, 42);
415 ABTS_INT_EQUAL(tc, *val, 42);
416
417 /* empty */
419 ABTS_PTR_EQUAL(tc, val, NULL);
420
423 add_int_to_skiplist(tc, list, 142);
426 ABTS_INT_EQUAL(tc, *val, 1);
428 ABTS_INT_EQUAL(tc, *val, 1);
431 ABTS_INT_EQUAL(tc, *val, 42);
434 ABTS_INT_EQUAL(tc, *val, 42);
437 ABTS_INT_EQUAL(tc, *val, 42);
439 ABTS_INT_EQUAL(tc, *val, 142);
440
449 ABTS_INT_EQUAL(tc, val2->a, 1);
451 ABTS_INT_EQUAL(tc, val2->a, 42);
452 ABTS_INT_EQUAL(tc, val2->b, 1);
454 ABTS_INT_EQUAL(tc, val2->a, 42);
455 ABTS_INT_EQUAL(tc, val2->b, 2);
457 ABTS_INT_EQUAL(tc, val2->a, 42);
458 ABTS_INT_EQUAL(tc, val2->b, 3);
460 ABTS_INT_EQUAL(tc, val2->a, 142);
461 ABTS_INT_EQUAL(tc, val2->b, 1);
462
465 array = apr_array_make(ptmp, 10, sizeof(elem *));
466 for (i = 0; i < 10; ++i) {
467 elem *e = apr_palloc(ptmp, sizeof *e);
468 e->a = 4224;
469 e->b = i;
470 APR_ARRAY_PUSH(array, elem *) = e;
472 }
473 for (i = 0; i < 5; ++i) {
474 elem *e = APR_ARRAY_IDX(array, i, elem *);
476 ABTS_PTR_EQUAL(tc, e, val2);
478 }
479 for (i = 0; i < 5; ++i) {
480 elem *e = APR_ARRAY_IDX(array, 9 - i, elem *);
482 ABTS_PTR_EQUAL(tc, e, val2);
484 }
485
488 for (i = 0; i < 5; ++i){
490 }
491 for (i = 0; i < 5; ++i){
493 }
495 for (i = 0; i < 5; ++i){
497 }
498 for (i = 0; i < 5; ++i){
500 }
502 for (i = 0; i < 5; ++i){
504 }
505 for (i = 0; i < 5; ++i){
507 }
509 for (i = 0; i < 5; ++i){
511 }
512 for (i = 0; i < 5; ++i){
514 }
518
520}
521
522
546
int n
Definition ap_regex.h:278
void abts_run_test(abts_suite *ts, test_func f, void *value)
Definition abts.c:175
#define ABTS_PTR_EQUAL(a, b, c)
Definition abts.h:126
#define ABTS_TRUE(a, b)
Definition abts.h:127
#define ADD_SUITE(suite)
Definition abts.h:67
#define ABTS_PTR_NOTNULL(a, b)
Definition abts.h:125
#define ABTS_STR_EQUAL(a, b, c)
Definition abts.h:123
#define ABTS_INT_EQUAL(a, b, c)
Definition abts.h:109
APR Miscellaneous library routines.
APR memory allocation.
APR skip list implementation.
APR Strings library.
apr_bucket * e
apr_bucket apr_bucket_brigade * a
apr_size_t size
apr_uint32_t val
Definition apr_atomic.h:66
const apr_array_header_t * list
Definition apr_cstr.h:105
#define APR_SUCCESS
Definition apr_errno.h:225
void * data
apr_pool_t * b
Definition apr_pools.h:529
#define apr_pool_create(newpool, parent)
Definition apr_pools.h:322
void apr_skiplistnode ** iter
void apr_skiplistnode apr_skiplist_compare comp
int(* apr_skiplist_compare)(void *, void *)
#define APR_ARRAY_PUSH(ary, type)
Definition apr_tables.h:150
#define APR_ARRAY_IDX(ary, i, type)
Definition apr_tables.h:141
apr_int64_t apr_time_t
Definition apr_time.h:45
apr_pool_t * p
Definition md_event.c:32
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
apr_array_header_t a
Definition apr_tables.c:339
static int scomp(void *a, void *b)
static void skiplist_insert(abts_case *tc, void *data)
static apr_pool_t * ptmp
static void skiplist_remove_scomp(abts_case *tc, apr_skiplist *list, elem *n)
static void skiplist_test(abts_case *tc, void *data)
static void skiplist_dontfind(abts_case *tc, void *data)
static void skiplist_random_loop(abts_case *tc, void *data)
static int ecomp(void *a, void *b)
static void skiplist_init(abts_case *tc, void *data)
static void skiplist_add(abts_case *tc, void *data)
static void skiplist_size(abts_case *tc, void *data)
#define NUM_RAND
static apr_skiplist * skiplist
static void add_elem_to_skiplist(abts_case *tc, apr_skiplist *list, elem n)
static int skiplist_get_size(abts_case *tc, apr_skiplist *sl)
static void skiplist_destroy(abts_case *tc, void *data)
static void skiplist_find(abts_case *tc, void *data)
static void skiplist_replace(abts_case *tc, void *data)
#define NUM_FIND
static void skiplist_remove(abts_case *tc, void *data)
abts_suite * testskiplist(abts_suite *suite)
static void add_int_to_skiplist(abts_case *tc, apr_skiplist *list, int n)
#define NUM_ADDS
static apr_table_t * t1
Definition testtable.c:34
static apr_time_t now
Definition testtime.c:33