1 /* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
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.
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
;
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
,
81 apr_bucket_brigade
*bb
= apr_brigade_create(p
, ba
);
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
);
93 /* tests that 'bb' flattens to string 'expect'. */
94 static void flatten_match(abts_case
*tc
, const char *ctx
,
95 apr_bucket_brigade
*bb
,
98 apr_size_t elen
= strlen(expect
);
99 char *buf
= malloc(elen
);
100 apr_size_t len
= elen
;
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
);
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
)
131 for (e
= APR_BRIGADE_FIRST(bb
);
132 e
!= APR_BRIGADE_SENTINEL(bb
);
133 e
= APR_BUCKET_NEXT(e
)) {
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
;
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
);
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
);
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
,
221 apr_assert_success(tc
, "read from bucket",
222 apr_bucket_read(e
, &adata
, &alen
,
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
;
234 char *str
= "alphabeta";
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
,
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
++) {
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
++) {
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;
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
)) {
323 apr_file_remove(TIF_FNAME
, p
);
324 ABTS_NOT_IMPL(tc
, "Skipped: could not create large file");
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. */
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);
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);
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
)
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
);
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
);
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");
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
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");
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
));
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
);
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
),
458 test_bucket_content(tc
, APR_BRIGADE_LAST(bb
),
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
);