Revert because of veto.
[apr-util.git] / test / testbuckets.c
blob52b4840039c0d8ad6b46a5f9d6c5ccca8a638681
1 /* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
2 * applicable.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "abts.h"
18 #include "testutil.h"
19 #include "apr_buckets.h"
20 #include "apr_strings.h"
22 static void test_create(abts_case *tc, void *data)
24 apr_bucket_alloc_t *ba;
25 apr_bucket_brigade *bb;
27 ba = apr_bucket_alloc_create(p);
28 bb = apr_brigade_create(p, ba);
30 ABTS_ASSERT(tc, "new brigade not NULL", bb != NULL);
31 ABTS_ASSERT(tc, "new brigade is empty", APR_BRIGADE_EMPTY(bb));
33 apr_brigade_destroy(bb);
34 apr_bucket_alloc_destroy(ba);
37 static void test_simple(abts_case *tc, void *data)
39 apr_bucket_alloc_t *ba;
40 apr_bucket_brigade *bb;
41 apr_bucket *fb, *tb;
43 ba = apr_bucket_alloc_create(p);
44 bb = apr_brigade_create(p, ba);
46 fb = APR_BRIGADE_FIRST(bb);
47 ABTS_ASSERT(tc, "first bucket of empty brigade is sentinel",
48 fb == APR_BRIGADE_SENTINEL(bb));
50 fb = apr_bucket_flush_create(ba);
51 APR_BRIGADE_INSERT_HEAD(bb, fb);
53 ABTS_ASSERT(tc, "first bucket of brigade is flush",
54 APR_BRIGADE_FIRST(bb) == fb);
56 ABTS_ASSERT(tc, "bucket after flush is sentinel",
57 APR_BUCKET_NEXT(fb) == APR_BRIGADE_SENTINEL(bb));
59 tb = apr_bucket_transient_create("aaa", 3, ba);
60 APR_BUCKET_INSERT_BEFORE(fb, tb);
62 ABTS_ASSERT(tc, "bucket before flush now transient",
63 APR_BUCKET_PREV(fb) == tb);
64 ABTS_ASSERT(tc, "bucket after transient is flush",
65 APR_BUCKET_NEXT(tb) == fb);
66 ABTS_ASSERT(tc, "bucket before transient is sentinel",
67 APR_BUCKET_PREV(tb) == APR_BRIGADE_SENTINEL(bb));
69 apr_brigade_cleanup(bb);
71 ABTS_ASSERT(tc, "cleaned up brigade was empty", APR_BRIGADE_EMPTY(bb));
73 apr_brigade_destroy(bb);
74 apr_bucket_alloc_destroy(ba);
77 static apr_bucket_brigade *make_simple_brigade(apr_bucket_alloc_t *ba,
78 const char *first,
79 const char *second)
81 apr_bucket_brigade *bb = apr_brigade_create(p, ba);
82 apr_bucket *e;
84 e = apr_bucket_transient_create(first, strlen(first), ba);
85 APR_BRIGADE_INSERT_TAIL(bb, e);
87 e = apr_bucket_transient_create(second, strlen(second), ba);
88 APR_BRIGADE_INSERT_TAIL(bb, e);
90 return bb;
93 /* tests that 'bb' flattens to string 'expect'. */
94 static void flatten_match(abts_case *tc, const char *ctx,
95 apr_bucket_brigade *bb,
96 const char *expect)
98 apr_size_t elen = strlen(expect);
99 char *buf = malloc(elen);
100 apr_size_t len = elen;
101 char msg[200];
103 sprintf(msg, "%s: flatten brigade", ctx);
104 apr_assert_success(tc, msg, apr_brigade_flatten(bb, buf, &len));
105 sprintf(msg, "%s: length match (%ld not %ld)", ctx,
106 (long)len, (long)elen);
107 ABTS_ASSERT(tc, msg, len == elen);
108 sprintf(msg, "%s: result match", msg);
109 ABTS_STR_NEQUAL(tc, expect, buf, len);
110 free(buf);
113 static void test_flatten(abts_case *tc, void *data)
115 apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
116 apr_bucket_brigade *bb;
118 bb = make_simple_brigade(ba, "hello, ", "world");
120 flatten_match(tc, "flatten brigade", bb, "hello, world");
122 apr_brigade_destroy(bb);
123 apr_bucket_alloc_destroy(ba);
126 static int count_buckets(apr_bucket_brigade *bb)
128 apr_bucket *e;
129 int count = 0;
131 for (e = APR_BRIGADE_FIRST(bb);
132 e != APR_BRIGADE_SENTINEL(bb);
133 e = APR_BUCKET_NEXT(e)) {
134 count++;
137 return count;
140 static void test_split(abts_case *tc, void *data)
142 apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
143 apr_bucket_brigade *bb, *bb2;
144 apr_bucket *e;
146 bb = make_simple_brigade(ba, "hello, ", "world");
148 /* split at the "world" bucket */
149 e = APR_BRIGADE_LAST(bb);
150 bb2 = apr_brigade_split(bb, e);
152 ABTS_ASSERT(tc, "split brigade contains one bucket",
153 count_buckets(bb2) == 1);
154 ABTS_ASSERT(tc, "original brigade contains one bucket",
155 count_buckets(bb) == 1);
157 flatten_match(tc, "match original brigade", bb, "hello, ");
158 flatten_match(tc, "match split brigade", bb2, "world");
160 apr_brigade_destroy(bb2);
161 apr_brigade_destroy(bb);
162 apr_bucket_alloc_destroy(ba);
165 #define COUNT 3000
166 #define THESTR "hello"
168 static void test_bwrite(abts_case *tc, void *data)
170 apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
171 apr_bucket_brigade *bb = apr_brigade_create(p, ba);
172 apr_off_t length;
173 int n;
175 for (n = 0; n < COUNT; n++) {
176 apr_assert_success(tc, "brigade_write",
177 apr_brigade_write(bb, NULL, NULL,
178 THESTR, sizeof THESTR));
181 apr_assert_success(tc, "determine brigade length",
182 apr_brigade_length(bb, 1, &length));
184 ABTS_ASSERT(tc, "brigade has correct length",
185 length == (COUNT * sizeof THESTR));
187 apr_brigade_destroy(bb);
188 apr_bucket_alloc_destroy(ba);
191 static void test_splitline(abts_case *tc, void *data)
193 apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
194 apr_bucket_brigade *bin, *bout;
196 bin = make_simple_brigade(ba, "blah blah blah-",
197 "end of line.\nfoo foo foo");
198 bout = apr_brigade_create(p, ba);
200 apr_assert_success(tc, "split line",
201 apr_brigade_split_line(bout, bin,
202 APR_BLOCK_READ, 100));
204 flatten_match(tc, "split line", bout, "blah blah blah-end of line.\n");
205 flatten_match(tc, "remainder", bin, "foo foo foo");
207 apr_brigade_destroy(bout);
208 apr_brigade_destroy(bin);
209 apr_bucket_alloc_destroy(ba);
212 /* Test that bucket E has content EDATA of length ELEN. */
213 static void test_bucket_content(abts_case *tc,
214 apr_bucket *e,
215 const char *edata,
216 apr_size_t elen)
218 const char *adata;
219 apr_size_t alen;
221 apr_assert_success(tc, "read from bucket",
222 apr_bucket_read(e, &adata, &alen,
223 APR_BLOCK_READ));
225 ABTS_ASSERT(tc, "read expected length", alen == elen);
226 ABTS_STR_NEQUAL(tc, edata, adata, elen);
229 static void test_splits(abts_case *tc, void *ctx)
231 apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
232 apr_bucket_brigade *bb;
233 apr_bucket *e;
234 char *str = "alphabeta";
235 int n;
237 bb = apr_brigade_create(p, ba);
239 APR_BRIGADE_INSERT_TAIL(bb,
240 apr_bucket_immortal_create(str, 9, ba));
241 APR_BRIGADE_INSERT_TAIL(bb,
242 apr_bucket_transient_create(str, 9, ba));
243 APR_BRIGADE_INSERT_TAIL(bb,
244 apr_bucket_heap_create(strdup(str), 9, free, ba));
245 APR_BRIGADE_INSERT_TAIL(bb,
246 apr_bucket_pool_create(apr_pstrdup(p, str), 9, p,
247 ba));
249 ABTS_ASSERT(tc, "four buckets inserted", count_buckets(bb) == 4);
251 /* now split each of the buckets after byte 5 */
252 for (n = 0, e = APR_BRIGADE_FIRST(bb); n < 4; n++) {
253 ABTS_ASSERT(tc, "reached end of brigade",
254 e != APR_BRIGADE_SENTINEL(bb));
255 ABTS_ASSERT(tc, "split bucket OK",
256 apr_bucket_split(e, 5) == APR_SUCCESS);
257 e = APR_BUCKET_NEXT(e);
258 ABTS_ASSERT(tc, "split OK", e != APR_BRIGADE_SENTINEL(bb));
259 e = APR_BUCKET_NEXT(e);
262 ABTS_ASSERT(tc, "four buckets split into eight",
263 count_buckets(bb) == 8);
265 for (n = 0, e = APR_BRIGADE_FIRST(bb); n < 4; n++) {
266 const char *data;
267 apr_size_t len;
269 apr_assert_success(tc, "read alpha from bucket",
270 apr_bucket_read(e, &data, &len, APR_BLOCK_READ));
271 ABTS_ASSERT(tc, "read 5 bytes", len == 5);
272 ABTS_STR_NEQUAL(tc, "alpha", data, 5);
274 e = APR_BUCKET_NEXT(e);
276 apr_assert_success(tc, "read beta from bucket",
277 apr_bucket_read(e, &data, &len, APR_BLOCK_READ));
278 ABTS_ASSERT(tc, "read 4 bytes", len == 4);
279 ABTS_STR_NEQUAL(tc, "beta", data, 5);
281 e = APR_BUCKET_NEXT(e);
284 /* now delete the "alpha" buckets */
285 for (n = 0, e = APR_BRIGADE_FIRST(bb); n < 4; n++) {
286 apr_bucket *f;
288 ABTS_ASSERT(tc, "reached end of brigade",
289 e != APR_BRIGADE_SENTINEL(bb));
290 f = APR_BUCKET_NEXT(e);
291 apr_bucket_delete(e);
292 e = APR_BUCKET_NEXT(f);
295 ABTS_ASSERT(tc, "eight buckets reduced to four",
296 count_buckets(bb) == 4);
298 flatten_match(tc, "flatten beta brigade", bb,
299 "beta" "beta" "beta" "beta");
301 apr_brigade_destroy(bb);
302 apr_bucket_alloc_destroy(ba);
305 #define TIF_FNAME "testfile.txt"
307 static void test_insertfile(abts_case *tc, void *ctx)
309 apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
310 apr_bucket_brigade *bb;
311 const apr_off_t bignum = (APR_INT64_C(2) << 32) + 424242;
312 apr_off_t count;
313 apr_file_t *f;
314 apr_bucket *e;
316 ABTS_ASSERT(tc, "open test file",
317 apr_file_open(&f, TIF_FNAME,
318 APR_WRITE|APR_TRUNCATE|APR_CREATE,
319 APR_OS_DEFAULT, p) == APR_SUCCESS);
321 if (apr_file_trunc(f, bignum)) {
322 apr_file_close(f);
323 apr_file_remove(TIF_FNAME, p);
324 ABTS_NOT_IMPL(tc, "Skipped: could not create large file");
325 return;
328 bb = apr_brigade_create(p, ba);
330 e = apr_brigade_insert_file(bb, f, 0, bignum, p);
332 ABTS_ASSERT(tc, "inserted file was not at end of brigade",
333 e == APR_BRIGADE_LAST(bb));
335 /* check that the total size of inserted buckets is equal to the
336 * total size of the file. */
337 count = 0;
339 for (e = APR_BRIGADE_FIRST(bb);
340 e != APR_BRIGADE_SENTINEL(bb);
341 e = APR_BUCKET_NEXT(e)) {
342 ABTS_ASSERT(tc, "bucket size sane", e->length != (apr_size_t)-1);
343 count += e->length;
346 ABTS_ASSERT(tc, "total size of buckets incorrect", count == bignum);
348 apr_brigade_destroy(bb);
350 /* Truncate the file to zero size before close() so that we don't
351 * actually write out the large file if we are on a non-sparse file
352 * system - like Mac OS X's HFS. Otherwise, pity the poor user who
353 * has to wait for the 8GB file to be written to disk.
355 apr_file_trunc(f, 0);
357 apr_file_close(f);
358 apr_bucket_alloc_destroy(ba);
359 apr_file_remove(TIF_FNAME, p);
362 /* Make a test file named FNAME, and write CONTENTS to it. */
363 static apr_file_t *make_test_file(abts_case *tc, const char *fname,
364 const char *contents)
366 apr_file_t *f;
368 ABTS_ASSERT(tc, "create test file",
369 apr_file_open(&f, fname,
370 APR_READ|APR_WRITE|APR_TRUNCATE|APR_CREATE,
371 APR_OS_DEFAULT, p) == APR_SUCCESS);
373 ABTS_ASSERT(tc, "write test file contents",
374 apr_file_puts(contents, f) == APR_SUCCESS);
376 return f;
379 static void test_manyfile(abts_case *tc, void *data)
381 apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
382 apr_bucket_brigade *bb = apr_brigade_create(p, ba);
383 apr_file_t *f;
385 f = make_test_file(tc, "manyfile.bin",
386 "world" "hello" "brave" " ,\n");
388 apr_brigade_insert_file(bb, f, 5, 5, p);
389 apr_brigade_insert_file(bb, f, 16, 1, p);
390 apr_brigade_insert_file(bb, f, 15, 1, p);
391 apr_brigade_insert_file(bb, f, 10, 5, p);
392 apr_brigade_insert_file(bb, f, 15, 1, p);
393 apr_brigade_insert_file(bb, f, 0, 5, p);
394 apr_brigade_insert_file(bb, f, 17, 1, p);
396 /* can you tell what it is yet? */
397 flatten_match(tc, "file seek test", bb,
398 "hello, brave world\n");
400 apr_file_close(f);
401 apr_brigade_destroy(bb);
402 apr_bucket_alloc_destroy(ba);
405 /* Regression test for PR 34708, where a file bucket will keep
406 * duplicating itself on being read() when EOF is reached
407 * prematurely. */
408 static void test_truncfile(abts_case *tc, void *data)
410 apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
411 apr_bucket_brigade *bb = apr_brigade_create(p, ba);
412 apr_file_t *f = make_test_file(tc, "testfile.txt", "hello");
413 apr_bucket *e;
414 const char *buf;
415 apr_size_t len;
417 apr_brigade_insert_file(bb, f, 0, 5, p);
419 apr_file_trunc(f, 0);
421 e = APR_BRIGADE_FIRST(bb);
423 ABTS_ASSERT(tc, "single bucket in brigade",
424 APR_BUCKET_NEXT(e) == APR_BRIGADE_SENTINEL(bb));
426 apr_bucket_file_enable_mmap(e, 0);
428 ABTS_ASSERT(tc, "read gave APR_EOF",
429 apr_bucket_read(e, &buf, &len, APR_BLOCK_READ) == APR_EOF);
431 ABTS_ASSERT(tc, "read length 0", len == 0);
433 ABTS_ASSERT(tc, "still a single bucket in brigade",
434 APR_BUCKET_NEXT(e) == APR_BRIGADE_SENTINEL(bb));
436 apr_file_close(f);
437 apr_brigade_destroy(bb);
438 apr_bucket_alloc_destroy(ba);
441 static const char hello[] = "hello, world";
443 static void test_partition(abts_case *tc, void *data)
445 apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
446 apr_bucket_brigade *bb = apr_brigade_create(p, ba);
447 apr_bucket *e;
449 e = apr_bucket_immortal_create(hello, strlen(hello), ba);
450 APR_BRIGADE_INSERT_HEAD(bb, e);
452 apr_assert_success(tc, "partition brigade",
453 apr_brigade_partition(bb, 5, &e));
455 test_bucket_content(tc, APR_BRIGADE_FIRST(bb),
456 "hello", 5);
458 test_bucket_content(tc, APR_BRIGADE_LAST(bb),
459 ", world", 7);
461 ABTS_ASSERT(tc, "partition returns APR_INCOMPLETE",
462 apr_brigade_partition(bb, 8192, &e));
464 ABTS_ASSERT(tc, "APR_INCOMPLETE partition returned sentinel",
465 e == APR_BRIGADE_SENTINEL(bb));
467 apr_brigade_destroy(bb);
468 apr_bucket_alloc_destroy(ba);
471 abts_suite *testbuckets(abts_suite *suite)
473 suite = ADD_SUITE(suite);
475 abts_run_test(suite, test_create, NULL);
476 abts_run_test(suite, test_simple, NULL);
477 abts_run_test(suite, test_flatten, NULL);
478 abts_run_test(suite, test_split, NULL);
479 abts_run_test(suite, test_bwrite, NULL);
480 abts_run_test(suite, test_splitline, NULL);
481 abts_run_test(suite, test_splits, NULL);
482 abts_run_test(suite, test_insertfile, NULL);
483 abts_run_test(suite, test_manyfile, NULL);
484 abts_run_test(suite, test_truncfile, NULL);
485 abts_run_test(suite, test_partition, NULL);
487 return suite;