1251876Speter/* Licensed to the Apache Software Foundation (ASF) under one or more
2251876Speter * contributor license agreements.  See the NOTICE file distributed with
3251876Speter * this work for additional information regarding copyright ownership.
4251876Speter * The ASF licenses this file to You under the Apache License, Version 2.0
5251876Speter * (the "License"); you may not use this file except in compliance with
6251876Speter * the License.  You may obtain a copy of the License at
7251876Speter *
8251876Speter *     http://www.apache.org/licenses/LICENSE-2.0
9251876Speter *
10251876Speter * Unless required by applicable law or agreed to in writing, software
11251876Speter * distributed under the License is distributed on an "AS IS" BASIS,
12251876Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13251876Speter * See the License for the specific language governing permissions and
14251876Speter * limitations under the License.
15251876Speter */
16251876Speter
17251876Speter#include "abts.h"
18251876Speter#include "testutil.h"
19251876Speter#include "apr_buckets.h"
20251876Speter#include "apr_strings.h"
21251876Speter
22251876Speterstatic void test_create(abts_case *tc, void *data)
23251876Speter{
24251876Speter    apr_bucket_alloc_t *ba;
25251876Speter    apr_bucket_brigade *bb;
26251876Speter
27251876Speter    ba = apr_bucket_alloc_create(p);
28251876Speter    bb = apr_brigade_create(p, ba);
29251876Speter
30251876Speter    ABTS_ASSERT(tc, "new brigade not NULL", bb != NULL);
31251876Speter    ABTS_ASSERT(tc, "new brigade is empty", APR_BRIGADE_EMPTY(bb));
32251876Speter
33251876Speter    apr_brigade_destroy(bb);
34251876Speter    apr_bucket_alloc_destroy(ba);
35251876Speter}
36251876Speter
37251876Speterstatic void test_simple(abts_case *tc, void *data)
38251876Speter{
39251876Speter    apr_bucket_alloc_t *ba;
40251876Speter    apr_bucket_brigade *bb;
41251876Speter    apr_bucket *fb, *tb;
42251876Speter
43251876Speter    ba = apr_bucket_alloc_create(p);
44251876Speter    bb = apr_brigade_create(p, ba);
45251876Speter
46251876Speter    fb = APR_BRIGADE_FIRST(bb);
47251876Speter    ABTS_ASSERT(tc, "first bucket of empty brigade is sentinel",
48251876Speter                fb == APR_BRIGADE_SENTINEL(bb));
49251876Speter
50251876Speter    fb = apr_bucket_flush_create(ba);
51251876Speter    APR_BRIGADE_INSERT_HEAD(bb, fb);
52251876Speter
53251876Speter    ABTS_ASSERT(tc, "first bucket of brigade is flush",
54251876Speter                APR_BRIGADE_FIRST(bb) == fb);
55251876Speter
56251876Speter    ABTS_ASSERT(tc, "bucket after flush is sentinel",
57251876Speter                APR_BUCKET_NEXT(fb) == APR_BRIGADE_SENTINEL(bb));
58251876Speter
59251876Speter    tb = apr_bucket_transient_create("aaa", 3, ba);
60251876Speter    APR_BUCKET_INSERT_BEFORE(fb, tb);
61251876Speter
62251876Speter    ABTS_ASSERT(tc, "bucket before flush now transient",
63251876Speter                APR_BUCKET_PREV(fb) == tb);
64251876Speter    ABTS_ASSERT(tc, "bucket after transient is flush",
65251876Speter                APR_BUCKET_NEXT(tb) == fb);
66251876Speter    ABTS_ASSERT(tc, "bucket before transient is sentinel",
67251876Speter                APR_BUCKET_PREV(tb) == APR_BRIGADE_SENTINEL(bb));
68251876Speter
69251876Speter    apr_brigade_cleanup(bb);
70251876Speter
71251876Speter    ABTS_ASSERT(tc, "cleaned up brigade was empty", APR_BRIGADE_EMPTY(bb));
72251876Speter
73251876Speter    apr_brigade_destroy(bb);
74251876Speter    apr_bucket_alloc_destroy(ba);
75251876Speter}
76251876Speter
77251876Speterstatic apr_bucket_brigade *make_simple_brigade(apr_bucket_alloc_t *ba,
78251876Speter                                               const char *first,
79251876Speter                                               const char *second)
80251876Speter{
81251876Speter    apr_bucket_brigade *bb = apr_brigade_create(p, ba);
82251876Speter    apr_bucket *e;
83251876Speter
84251876Speter    e = apr_bucket_transient_create(first, strlen(first), ba);
85251876Speter    APR_BRIGADE_INSERT_TAIL(bb, e);
86251876Speter
87251876Speter    e = apr_bucket_transient_create(second, strlen(second), ba);
88251876Speter    APR_BRIGADE_INSERT_TAIL(bb, e);
89251876Speter
90251876Speter    return bb;
91251876Speter}
92251876Speter
93251876Speter/* tests that 'bb' flattens to string 'expect'. */
94251876Speterstatic void flatten_match(abts_case *tc, const char *ctx,
95251876Speter                          apr_bucket_brigade *bb,
96251876Speter                          const char *expect)
97251876Speter{
98251876Speter    apr_size_t elen = strlen(expect);
99251876Speter    char *buf = malloc(elen);
100251876Speter    apr_size_t len = elen;
101251876Speter    char msg[200];
102251876Speter
103251876Speter    sprintf(msg, "%s: flatten brigade", ctx);
104251876Speter    apr_assert_success(tc, msg, apr_brigade_flatten(bb, buf, &len));
105251876Speter    sprintf(msg, "%s: length match (%ld not %ld)", ctx,
106251876Speter            (long)len, (long)elen);
107251876Speter    ABTS_ASSERT(tc, msg, len == elen);
108251876Speter    sprintf(msg, "%s: result match", msg);
109251876Speter    ABTS_STR_NEQUAL(tc, expect, buf, len);
110251876Speter    free(buf);
111251876Speter}
112251876Speter
113251876Speterstatic void test_flatten(abts_case *tc, void *data)
114251876Speter{
115251876Speter    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
116251876Speter    apr_bucket_brigade *bb;
117251876Speter
118251876Speter    bb = make_simple_brigade(ba, "hello, ", "world");
119251876Speter
120251876Speter    flatten_match(tc, "flatten brigade", bb, "hello, world");
121251876Speter
122251876Speter    apr_brigade_destroy(bb);
123251876Speter    apr_bucket_alloc_destroy(ba);
124251876Speter}
125251876Speter
126251876Speterstatic int count_buckets(apr_bucket_brigade *bb)
127251876Speter{
128251876Speter    apr_bucket *e;
129251876Speter    int count = 0;
130251876Speter
131251876Speter    for (e = APR_BRIGADE_FIRST(bb);
132251876Speter         e != APR_BRIGADE_SENTINEL(bb);
133251876Speter         e = APR_BUCKET_NEXT(e)) {
134251876Speter        count++;
135251876Speter    }
136251876Speter
137251876Speter    return count;
138251876Speter}
139251876Speter
140251876Speterstatic void test_split(abts_case *tc, void *data)
141251876Speter{
142251876Speter    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
143251876Speter    apr_bucket_brigade *bb, *bb2;
144251876Speter    apr_bucket *e;
145251876Speter
146251876Speter    bb = make_simple_brigade(ba, "hello, ", "world");
147251876Speter
148251876Speter    /* split at the "world" bucket */
149251876Speter    e = APR_BRIGADE_LAST(bb);
150251876Speter    bb2 = apr_brigade_split(bb, e);
151251876Speter
152251876Speter    ABTS_ASSERT(tc, "split brigade contains one bucket",
153251876Speter                count_buckets(bb2) == 1);
154251876Speter    ABTS_ASSERT(tc, "original brigade contains one bucket",
155251876Speter                count_buckets(bb) == 1);
156251876Speter
157251876Speter    flatten_match(tc, "match original brigade", bb, "hello, ");
158251876Speter    flatten_match(tc, "match split brigade", bb2, "world");
159251876Speter
160251876Speter    apr_brigade_destroy(bb2);
161251876Speter    apr_brigade_destroy(bb);
162251876Speter    apr_bucket_alloc_destroy(ba);
163251876Speter}
164251876Speter
165251876Speter#define COUNT 3000
166251876Speter#define THESTR "hello"
167251876Speter
168251876Speterstatic void test_bwrite(abts_case *tc, void *data)
169251876Speter{
170251876Speter    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
171251876Speter    apr_bucket_brigade *bb = apr_brigade_create(p, ba);
172251876Speter    apr_off_t length;
173251876Speter    int n;
174251876Speter
175251876Speter    for (n = 0; n < COUNT; n++) {
176251876Speter        apr_assert_success(tc, "brigade_write",
177251876Speter                           apr_brigade_write(bb, NULL, NULL,
178251876Speter                                             THESTR, sizeof THESTR));
179251876Speter    }
180251876Speter
181251876Speter    apr_assert_success(tc, "determine brigade length",
182251876Speter                       apr_brigade_length(bb, 1, &length));
183251876Speter
184251876Speter    ABTS_ASSERT(tc, "brigade has correct length",
185251876Speter                length == (COUNT * sizeof THESTR));
186251876Speter
187251876Speter    apr_brigade_destroy(bb);
188251876Speter    apr_bucket_alloc_destroy(ba);
189251876Speter}
190251876Speter
191251876Speterstatic void test_splitline(abts_case *tc, void *data)
192251876Speter{
193251876Speter    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
194251876Speter    apr_bucket_brigade *bin, *bout;
195251876Speter
196251876Speter    bin = make_simple_brigade(ba, "blah blah blah-",
197251876Speter                              "end of line.\nfoo foo foo");
198251876Speter    bout = apr_brigade_create(p, ba);
199251876Speter
200251876Speter    apr_assert_success(tc, "split line",
201251876Speter                       apr_brigade_split_line(bout, bin,
202251876Speter                                              APR_BLOCK_READ, 100));
203251876Speter
204251876Speter    flatten_match(tc, "split line", bout, "blah blah blah-end of line.\n");
205251876Speter    flatten_match(tc, "remainder", bin, "foo foo foo");
206251876Speter
207251876Speter    apr_brigade_destroy(bout);
208251876Speter    apr_brigade_destroy(bin);
209251876Speter    apr_bucket_alloc_destroy(ba);
210251876Speter}
211251876Speter
212251876Speter/* Test that bucket E has content EDATA of length ELEN. */
213251876Speterstatic void test_bucket_content(abts_case *tc,
214251876Speter                                apr_bucket *e,
215251876Speter                                const char *edata,
216251876Speter                                apr_size_t elen)
217251876Speter{
218251876Speter    const char *adata;
219251876Speter    apr_size_t alen;
220251876Speter
221251876Speter    apr_assert_success(tc, "read from bucket",
222251876Speter                       apr_bucket_read(e, &adata, &alen,
223251876Speter                                       APR_BLOCK_READ));
224251876Speter
225251876Speter    ABTS_ASSERT(tc, "read expected length", alen == elen);
226251876Speter    ABTS_STR_NEQUAL(tc, edata, adata, elen);
227251876Speter}
228251876Speter
229251876Speterstatic void test_splits(abts_case *tc, void *ctx)
230251876Speter{
231251876Speter    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
232251876Speter    apr_bucket_brigade *bb;
233251876Speter    apr_bucket *e;
234251876Speter    char *str = "alphabeta";
235251876Speter    int n;
236251876Speter
237251876Speter    bb = apr_brigade_create(p, ba);
238251876Speter
239251876Speter    APR_BRIGADE_INSERT_TAIL(bb,
240251876Speter                            apr_bucket_immortal_create(str, 9, ba));
241251876Speter    APR_BRIGADE_INSERT_TAIL(bb,
242251876Speter                            apr_bucket_transient_create(str, 9, ba));
243251876Speter    APR_BRIGADE_INSERT_TAIL(bb,
244251876Speter                            apr_bucket_heap_create(strdup(str), 9, free, ba));
245251876Speter    APR_BRIGADE_INSERT_TAIL(bb,
246251876Speter                            apr_bucket_pool_create(apr_pstrdup(p, str), 9, p,
247251876Speter                                                   ba));
248251876Speter
249251876Speter    ABTS_ASSERT(tc, "four buckets inserted", count_buckets(bb) == 4);
250251876Speter
251251876Speter    /* now split each of the buckets after byte 5 */
252251876Speter    for (n = 0, e = APR_BRIGADE_FIRST(bb); n < 4; n++) {
253251876Speter        ABTS_ASSERT(tc, "reached end of brigade",
254251876Speter                    e != APR_BRIGADE_SENTINEL(bb));
255251876Speter        ABTS_ASSERT(tc, "split bucket OK",
256251876Speter                    apr_bucket_split(e, 5) == APR_SUCCESS);
257251876Speter        e = APR_BUCKET_NEXT(e);
258251876Speter        ABTS_ASSERT(tc, "split OK", e != APR_BRIGADE_SENTINEL(bb));
259251876Speter        e = APR_BUCKET_NEXT(e);
260251876Speter    }
261251876Speter
262251876Speter    ABTS_ASSERT(tc, "four buckets split into eight",
263251876Speter                count_buckets(bb) == 8);
264251876Speter
265251876Speter    for (n = 0, e = APR_BRIGADE_FIRST(bb); n < 4; n++) {
266251876Speter        const char *data;
267251876Speter        apr_size_t len;
268251876Speter
269251876Speter        apr_assert_success(tc, "read alpha from bucket",
270251876Speter                           apr_bucket_read(e, &data, &len, APR_BLOCK_READ));
271251876Speter        ABTS_ASSERT(tc, "read 5 bytes", len == 5);
272251876Speter        ABTS_STR_NEQUAL(tc, "alpha", data, 5);
273251876Speter
274251876Speter        e = APR_BUCKET_NEXT(e);
275251876Speter
276251876Speter        apr_assert_success(tc, "read beta from bucket",
277251876Speter                           apr_bucket_read(e, &data, &len, APR_BLOCK_READ));
278251876Speter        ABTS_ASSERT(tc, "read 4 bytes", len == 4);
279251876Speter        ABTS_STR_NEQUAL(tc, "beta", data, 5);
280251876Speter
281251876Speter        e = APR_BUCKET_NEXT(e);
282251876Speter    }
283251876Speter
284251876Speter    /* now delete the "alpha" buckets */
285251876Speter    for (n = 0, e = APR_BRIGADE_FIRST(bb); n < 4; n++) {
286251876Speter        apr_bucket *f;
287251876Speter
288251876Speter        ABTS_ASSERT(tc, "reached end of brigade",
289251876Speter                    e != APR_BRIGADE_SENTINEL(bb));
290251876Speter        f = APR_BUCKET_NEXT(e);
291251876Speter        apr_bucket_delete(e);
292251876Speter        e = APR_BUCKET_NEXT(f);
293251876Speter    }
294251876Speter
295251876Speter    ABTS_ASSERT(tc, "eight buckets reduced to four",
296251876Speter                count_buckets(bb) == 4);
297251876Speter
298251876Speter    flatten_match(tc, "flatten beta brigade", bb,
299251876Speter                  "beta" "beta" "beta" "beta");
300251876Speter
301251876Speter    apr_brigade_destroy(bb);
302251876Speter    apr_bucket_alloc_destroy(ba);
303251876Speter}
304251876Speter
305251876Speter#define TIF_FNAME "testfile.txt"
306251876Speter
307251876Speterstatic void test_insertfile(abts_case *tc, void *ctx)
308251876Speter{
309251876Speter    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
310251876Speter    apr_bucket_brigade *bb;
311251876Speter    const apr_off_t bignum = (APR_INT64_C(2) << 32) + 424242;
312251876Speter    apr_off_t count;
313251876Speter    apr_file_t *f;
314251876Speter    apr_bucket *e;
315251876Speter
316251876Speter    ABTS_ASSERT(tc, "open test file",
317251876Speter                apr_file_open(&f, TIF_FNAME,
318251876Speter                              APR_FOPEN_WRITE | APR_FOPEN_TRUNCATE
319251876Speter                            | APR_FOPEN_CREATE | APR_FOPEN_SPARSE,
320251876Speter                              APR_OS_DEFAULT, p) == APR_SUCCESS);
321251876Speter
322251876Speter    if (apr_file_trunc(f, bignum)) {
323251876Speter        apr_file_close(f);
324251876Speter        apr_file_remove(TIF_FNAME, p);
325251876Speter        ABTS_NOT_IMPL(tc, "Skipped: could not create large file");
326251876Speter        return;
327251876Speter    }
328251876Speter
329251876Speter    bb = apr_brigade_create(p, ba);
330251876Speter
331251876Speter    e = apr_brigade_insert_file(bb, f, 0, bignum, p);
332251876Speter
333251876Speter    ABTS_ASSERT(tc, "inserted file was not at end of brigade",
334251876Speter                e == APR_BRIGADE_LAST(bb));
335251876Speter
336251876Speter    /* check that the total size of inserted buckets is equal to the
337251876Speter     * total size of the file. */
338251876Speter    count = 0;
339251876Speter
340251876Speter    for (e = APR_BRIGADE_FIRST(bb);
341251876Speter         e != APR_BRIGADE_SENTINEL(bb);
342251876Speter         e = APR_BUCKET_NEXT(e)) {
343251876Speter        ABTS_ASSERT(tc, "bucket size sane", e->length != (apr_size_t)-1);
344251876Speter        count += e->length;
345251876Speter    }
346251876Speter
347251876Speter    ABTS_ASSERT(tc, "total size of buckets incorrect", count == bignum);
348251876Speter
349251876Speter    apr_brigade_destroy(bb);
350251876Speter
351251876Speter    /* Truncate the file to zero size before close() so that we don't
352251876Speter     * actually write out the large file if we are on a non-sparse file
353251876Speter     * system - like Mac OS X's HFS.  Otherwise, pity the poor user who
354251876Speter     * has to wait for the 8GB file to be written to disk.
355251876Speter     */
356251876Speter    apr_file_trunc(f, 0);
357251876Speter
358251876Speter    apr_file_close(f);
359251876Speter    apr_bucket_alloc_destroy(ba);
360251876Speter    apr_file_remove(TIF_FNAME, p);
361251876Speter}
362251876Speter
363251876Speter/* Make a test file named FNAME, and write CONTENTS to it. */
364251876Speterstatic apr_file_t *make_test_file(abts_case *tc, const char *fname,
365251876Speter                                  const char *contents)
366251876Speter{
367251876Speter    apr_file_t *f;
368251876Speter
369251876Speter    ABTS_ASSERT(tc, "create test file",
370251876Speter                apr_file_open(&f, fname,
371251876Speter                              APR_FOPEN_READ|APR_FOPEN_WRITE|APR_FOPEN_TRUNCATE|APR_FOPEN_CREATE,
372251876Speter                              APR_OS_DEFAULT, p) == APR_SUCCESS);
373251876Speter
374251876Speter    ABTS_ASSERT(tc, "write test file contents",
375251876Speter                apr_file_puts(contents, f) == APR_SUCCESS);
376251876Speter
377251876Speter    return f;
378251876Speter}
379251876Speter
380251876Speterstatic void test_manyfile(abts_case *tc, void *data)
381251876Speter{
382251876Speter    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
383251876Speter    apr_bucket_brigade *bb = apr_brigade_create(p, ba);
384251876Speter    apr_file_t *f;
385251876Speter
386251876Speter    f = make_test_file(tc, "manyfile.bin",
387251876Speter                       "world" "hello" "brave" " ,\n");
388251876Speter
389251876Speter    apr_brigade_insert_file(bb, f, 5, 5, p);
390251876Speter    apr_brigade_insert_file(bb, f, 16, 1, p);
391251876Speter    apr_brigade_insert_file(bb, f, 15, 1, p);
392251876Speter    apr_brigade_insert_file(bb, f, 10, 5, p);
393251876Speter    apr_brigade_insert_file(bb, f, 15, 1, p);
394251876Speter    apr_brigade_insert_file(bb, f, 0, 5, p);
395251876Speter    apr_brigade_insert_file(bb, f, 17, 1, p);
396251876Speter
397251876Speter    /* can you tell what it is yet? */
398251876Speter    flatten_match(tc, "file seek test", bb,
399251876Speter                  "hello, brave world\n");
400251876Speter
401251876Speter    apr_file_close(f);
402251876Speter    apr_brigade_destroy(bb);
403251876Speter    apr_bucket_alloc_destroy(ba);
404251876Speter}
405251876Speter
406251876Speter/* Regression test for PR 34708, where a file bucket will keep
407251876Speter * duplicating itself on being read() when EOF is reached
408251876Speter * prematurely. */
409251876Speterstatic void test_truncfile(abts_case *tc, void *data)
410251876Speter{
411251876Speter    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
412251876Speter    apr_bucket_brigade *bb = apr_brigade_create(p, ba);
413251876Speter    apr_file_t *f = make_test_file(tc, "testfile.txt", "hello");
414251876Speter    apr_bucket *e;
415251876Speter    const char *buf;
416251876Speter    apr_size_t len;
417251876Speter
418251876Speter    apr_brigade_insert_file(bb, f, 0, 5, p);
419251876Speter
420251876Speter    apr_file_trunc(f, 0);
421251876Speter
422251876Speter    e = APR_BRIGADE_FIRST(bb);
423251876Speter
424251876Speter    ABTS_ASSERT(tc, "single bucket in brigade",
425251876Speter                APR_BUCKET_NEXT(e) == APR_BRIGADE_SENTINEL(bb));
426251876Speter
427251876Speter    apr_bucket_file_enable_mmap(e, 0);
428251876Speter
429251876Speter    ABTS_ASSERT(tc, "read gave APR_EOF",
430251876Speter                apr_bucket_read(e, &buf, &len, APR_BLOCK_READ) == APR_EOF);
431251876Speter
432251876Speter    ABTS_ASSERT(tc, "read length 0", len == 0);
433251876Speter
434251876Speter    ABTS_ASSERT(tc, "still a single bucket in brigade",
435251876Speter                APR_BUCKET_NEXT(e) == APR_BRIGADE_SENTINEL(bb));
436251876Speter
437251876Speter    apr_file_close(f);
438251876Speter    apr_brigade_destroy(bb);
439251876Speter    apr_bucket_alloc_destroy(ba);
440251876Speter}
441251876Speter
442251876Speterstatic const char hello[] = "hello, world";
443251876Speter
444251876Speterstatic void test_partition(abts_case *tc, void *data)
445251876Speter{
446251876Speter    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
447251876Speter    apr_bucket_brigade *bb = apr_brigade_create(p, ba);
448251876Speter    apr_bucket *e;
449251876Speter
450251876Speter    e = apr_bucket_immortal_create(hello, strlen(hello), ba);
451251876Speter    APR_BRIGADE_INSERT_HEAD(bb, e);
452251876Speter
453251876Speter    apr_assert_success(tc, "partition brigade",
454251876Speter                       apr_brigade_partition(bb, 5, &e));
455251876Speter
456251876Speter    test_bucket_content(tc, APR_BRIGADE_FIRST(bb),
457251876Speter                        "hello", 5);
458251876Speter
459251876Speter    test_bucket_content(tc, APR_BRIGADE_LAST(bb),
460251876Speter                        ", world", 7);
461251876Speter
462251876Speter    ABTS_ASSERT(tc, "partition returns APR_INCOMPLETE",
463251876Speter                apr_brigade_partition(bb, 8192, &e));
464251876Speter
465251876Speter    ABTS_ASSERT(tc, "APR_INCOMPLETE partition returned sentinel",
466251876Speter                e == APR_BRIGADE_SENTINEL(bb));
467251876Speter
468251876Speter    apr_brigade_destroy(bb);
469251876Speter    apr_bucket_alloc_destroy(ba);
470251876Speter}
471251876Speter
472253734Speterstatic void test_write_split(abts_case *tc, void *data)
473253734Speter{
474253734Speter    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
475253734Speter    apr_bucket_brigade *bb1 = apr_brigade_create(p, ba);
476253734Speter    apr_bucket_brigade *bb2;
477253734Speter    apr_bucket *e;
478253734Speter
479253734Speter    e = apr_bucket_heap_create(hello, strlen(hello), NULL, ba);
480253734Speter    APR_BRIGADE_INSERT_HEAD(bb1, e);
481253734Speter    apr_bucket_split(e, strlen("hello, "));
482253734Speter    bb2 = apr_brigade_split(bb1, APR_BRIGADE_LAST(bb1));
483253734Speter    apr_brigade_write(bb1, NULL, NULL, "foo", strlen("foo"));
484253734Speter    test_bucket_content(tc, APR_BRIGADE_FIRST(bb2), "world", 5);
485253734Speter
486253734Speter    apr_brigade_destroy(bb1);
487253734Speter    apr_brigade_destroy(bb2);
488253734Speter    apr_bucket_alloc_destroy(ba);
489253734Speter}
490253734Speter
491253734Speterstatic void test_write_putstrs(abts_case *tc, void *data)
492253734Speter{
493253734Speter    apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
494253734Speter    apr_bucket_brigade *bb = apr_brigade_create(p, ba);
495253734Speter    apr_bucket *e;
496253734Speter    char buf[30];
497253734Speter    apr_size_t len = sizeof(buf);
498253734Speter    const char *expect = "123456789abcdefghij";
499253734Speter
500253734Speter    e = apr_bucket_heap_create("1", 1, NULL, ba);
501253734Speter    APR_BRIGADE_INSERT_HEAD(bb, e);
502253734Speter
503253734Speter    apr_brigade_putstrs(bb, NULL, NULL, "2", "34", "567", "8", "9a", "bcd",
504253734Speter                        "e", "f", "gh", "i", NULL);
505253734Speter    apr_brigade_putstrs(bb, NULL, NULL, "j", NULL);
506253734Speter    apr_assert_success(tc, "apr_brigade_flatten",
507253734Speter                       apr_brigade_flatten(bb, buf, &len));
508253734Speter    ABTS_STR_NEQUAL(tc, expect, buf, strlen(expect));
509253734Speter
510253734Speter    apr_brigade_destroy(bb);
511253734Speter    apr_bucket_alloc_destroy(ba);
512253734Speter}
513253734Speter
514251876Speterabts_suite *testbuckets(abts_suite *suite)
515251876Speter{
516251876Speter    suite = ADD_SUITE(suite);
517251876Speter
518251876Speter    abts_run_test(suite, test_create, NULL);
519251876Speter    abts_run_test(suite, test_simple, NULL);
520251876Speter    abts_run_test(suite, test_flatten, NULL);
521251876Speter    abts_run_test(suite, test_split, NULL);
522251876Speter    abts_run_test(suite, test_bwrite, NULL);
523251876Speter    abts_run_test(suite, test_splitline, NULL);
524251876Speter    abts_run_test(suite, test_splits, NULL);
525251876Speter    abts_run_test(suite, test_insertfile, NULL);
526251876Speter    abts_run_test(suite, test_manyfile, NULL);
527251876Speter    abts_run_test(suite, test_truncfile, NULL);
528251876Speter    abts_run_test(suite, test_partition, NULL);
529253734Speter    abts_run_test(suite, test_write_split, NULL);
530253734Speter    abts_run_test(suite, test_write_putstrs, NULL);
531251876Speter
532251876Speter    return suite;
533251876Speter}
534251876Speter
535251876Speter
536