Apache HTTPD
testbuckets.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 "abts.h"
18#include "testutil.h"
19#include "apr_buckets.h"
20#include "apr_strings.h"
21
22static void test_create(abts_case *tc, void *data)
23{
26
28 bb = apr_brigade_create(p, ba);
29
30 ABTS_ASSERT(tc, "new brigade not NULL", bb != NULL);
31 ABTS_ASSERT(tc, "new brigade is empty", APR_BRIGADE_EMPTY(bb));
32
35}
36
37static void test_simple(abts_case *tc, void *data)
38{
41 apr_bucket *fb, *tb;
42
44 bb = apr_brigade_create(p, ba);
45
47 ABTS_ASSERT(tc, "first bucket of empty brigade is sentinel",
49
52
53 ABTS_ASSERT(tc, "first bucket of brigade is flush",
54 APR_BRIGADE_FIRST(bb) == fb);
55
56 ABTS_ASSERT(tc, "bucket after flush is sentinel",
58
59 tb = apr_bucket_transient_create("aaa", 3, ba);
61
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",
68
70
71 ABTS_ASSERT(tc, "cleaned up brigade was empty", APR_BRIGADE_EMPTY(bb));
72
75}
76
78 const char *first,
79 const char *second)
80{
83
86
89
90 return bb;
91}
92
93/* tests that 'bb' flattens to string 'expect'. */
94static void flatten_match(abts_case *tc, const char *ctx,
96 const char *expect)
97{
98 apr_size_t elen = strlen(expect);
99 char *buf = malloc(elen);
101 char msg[200];
102
103 sprintf(msg, "%s: flatten brigade", ctx);
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);
110 free(buf);
111}
112
113static void test_flatten(abts_case *tc, void *data)
114{
117
118 bb = make_simple_brigade(ba, "hello, ", "world");
119
120 flatten_match(tc, "flatten brigade", bb, "hello, world");
121
124}
125
127{
128 apr_bucket *e;
129 int count = 0;
130
131 for (e = APR_BRIGADE_FIRST(bb);
132 e != APR_BRIGADE_SENTINEL(bb);
133 e = APR_BUCKET_NEXT(e)) {
134 count++;
135 }
136
137 return count;
138}
139
140static void test_split(abts_case *tc, void *data)
141{
144 apr_bucket *e;
145
146 bb = make_simple_brigade(ba, "hello, ", "world");
147
148 /* split at the "world" bucket */
149 e = APR_BRIGADE_LAST(bb);
150 bb2 = apr_brigade_split(bb, e);
151
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);
156
157 flatten_match(tc, "match original brigade", bb, "hello, ");
158 flatten_match(tc, "match split brigade", bb2, "world");
159
163}
164
165#define COUNT 3000
166#define THESTR "hello"
167
168static void test_bwrite(abts_case *tc, void *data)
169{
173 int n;
174
175 for (n = 0; n < COUNT; n++) {
176 apr_assert_success(tc, "brigade_write",
178 THESTR, sizeof THESTR));
179 }
180
181 apr_assert_success(tc, "determine brigade length",
182 apr_brigade_length(bb, 1, &length));
183
184 ABTS_ASSERT(tc, "brigade has correct length",
185 length == (COUNT * sizeof THESTR));
186
189}
190
191static void test_splitline(abts_case *tc, void *data)
192{
195
196 bin = make_simple_brigade(ba, "blah blah blah-",
197 "end of line.\nfoo foo foo");
199
200 apr_assert_success(tc, "split line",
202 APR_BLOCK_READ, 100));
203
204 flatten_match(tc, "split line", bout, "blah blah blah-end of line.\n");
205 flatten_match(tc, "remainder", bin, "foo foo foo");
206
210}
211
212/* Test that bucket E has content EDATA of length ELEN. */
214 apr_bucket *e,
215 const char *edata,
217{
218 const char *adata;
220
221 apr_assert_success(tc, "read from bucket",
224
225 ABTS_ASSERT(tc, "read expected length", alen == elen);
227}
228
229static void test_splits(abts_case *tc, void *ctx)
230{
233 apr_bucket *e;
234 char *str = "alphabeta";
235 int n;
236
237 bb = apr_brigade_create(p, ba);
238
244 apr_bucket_heap_create(strdup(str), 9, free, ba));
247 ba));
248
249 ABTS_ASSERT(tc, "four buckets inserted", count_buckets(bb) == 4);
250
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",
258 ABTS_ASSERT(tc, "split OK", e != APR_BRIGADE_SENTINEL(bb));
260 }
261
262 ABTS_ASSERT(tc, "four buckets split into eight",
263 count_buckets(bb) == 8);
264
265 for (n = 0, e = APR_BRIGADE_FIRST(bb); n < 4; n++) {
266 const char *data;
268
269 apr_assert_success(tc, "read alpha from bucket",
271 ABTS_ASSERT(tc, "read 5 bytes", len == 5);
272 ABTS_STR_NEQUAL(tc, "alpha", data, 5);
273
275
276 apr_assert_success(tc, "read beta from bucket",
278 ABTS_ASSERT(tc, "read 4 bytes", len == 4);
279 ABTS_STR_NEQUAL(tc, "beta", data, 5);
280
282 }
283
284 /* now delete the "alpha" buckets */
285 for (n = 0, e = APR_BRIGADE_FIRST(bb); n < 4; n++) {
286 apr_bucket *f;
287
288 ABTS_ASSERT(tc, "reached end of brigade",
289 e != APR_BRIGADE_SENTINEL(bb));
293 }
294
295 ABTS_ASSERT(tc, "eight buckets reduced to four",
296 count_buckets(bb) == 4);
297
298 flatten_match(tc, "flatten beta brigade", bb,
299 "beta" "beta" "beta" "beta");
300
303}
304
305#define TIF_FNAME "testfile.txt"
306
307static void test_insertfile(abts_case *tc, void *ctx)
308{
311 const apr_off_t bignum = (APR_INT64_C(2) << 32) + 424242;
313 apr_file_t *f;
314 apr_bucket *e;
315
316 ABTS_ASSERT(tc, "open test file",
321
322 if (apr_file_trunc(f, bignum)) {
325 ABTS_NOT_IMPL(tc, "Skipped: could not create large file");
326 return;
327 }
328
329 bb = apr_brigade_create(p, ba);
330
331 e = apr_brigade_insert_file(bb, f, 0, bignum, p);
332
333 ABTS_ASSERT(tc, "inserted file was not at end of brigade",
334 e == APR_BRIGADE_LAST(bb));
335
336 /* check that the total size of inserted buckets is equal to the
337 * total size of the file. */
338 count = 0;
339
340 for (e = APR_BRIGADE_FIRST(bb);
341 e != APR_BRIGADE_SENTINEL(bb);
342 e = APR_BUCKET_NEXT(e)) {
343 ABTS_ASSERT(tc, "bucket size sane", e->length != (apr_size_t)-1);
344 count += e->length;
345 }
346
347 ABTS_ASSERT(tc, "total size of buckets incorrect", count == bignum);
348
350
351 /* Truncate the file to zero size before close() so that we don't
352 * actually write out the large file if we are on a non-sparse file
353 * system - like Mac OS X's HFS. Otherwise, pity the poor user who
354 * has to wait for the 8GB file to be written to disk.
355 */
356 apr_file_trunc(f, 0);
357
361}
362
363/* Make a test file named FNAME, and write CONTENTS to it. */
364static apr_file_t *make_test_file(abts_case *tc, const char *fname,
365 const char *contents)
366{
367 apr_file_t *f;
368
369 ABTS_ASSERT(tc, "create test file",
373
374 ABTS_ASSERT(tc, "write test file contents",
375 apr_file_puts(contents, f) == APR_SUCCESS);
376
377 return f;
378}
379
380static void test_manyfile(abts_case *tc, void *data)
381{
384 apr_file_t *f;
385
386 f = make_test_file(tc, "manyfile.bin",
387 "world" "hello" "brave" " ,\n");
388
389 apr_brigade_insert_file(bb, f, 5, 5, p);
390 apr_brigade_insert_file(bb, f, 16, 1, p);
391 apr_brigade_insert_file(bb, f, 15, 1, p);
392 apr_brigade_insert_file(bb, f, 10, 5, p);
393 apr_brigade_insert_file(bb, f, 15, 1, p);
394 apr_brigade_insert_file(bb, f, 0, 5, p);
395 apr_brigade_insert_file(bb, f, 17, 1, p);
396
397 /* can you tell what it is yet? */
398 flatten_match(tc, "file seek test", bb,
399 "hello, brave world\n");
400
404}
405
406/* Regression test for PR 34708, where a file bucket will keep
407 * duplicating itself on being read() when EOF is reached
408 * prematurely. */
409static void test_truncfile(abts_case *tc, void *data)
410{
413 apr_file_t *f = make_test_file(tc, "testfile.txt", "hello");
414 apr_bucket *e;
415 const char *buf;
417
418 apr_brigade_insert_file(bb, f, 0, 5, p);
419
420 apr_file_trunc(f, 0);
421
422 e = APR_BRIGADE_FIRST(bb);
423
424 ABTS_ASSERT(tc, "single bucket in brigade",
426
428
429 ABTS_ASSERT(tc, "read gave APR_EOF",
431
432 ABTS_ASSERT(tc, "read length 0", len == 0);
433
434 ABTS_ASSERT(tc, "still a single bucket in brigade",
436
440}
441
442static const char hello[] = "hello, world";
443
444static void test_partition(abts_case *tc, void *data)
445{
448 apr_bucket *e;
449
452
453 apr_assert_success(tc, "partition brigade",
454 apr_brigade_partition(bb, 5, &e));
455
457 "hello", 5);
458
460 ", world", 7);
461
462 ABTS_ASSERT(tc, "partition returns APR_INCOMPLETE",
463 apr_brigade_partition(bb, 8192, &e));
464
465 ABTS_ASSERT(tc, "APR_INCOMPLETE partition returned sentinel",
466 e == APR_BRIGADE_SENTINEL(bb));
467
470}
471
490
491static void test_write_putstrs(abts_case *tc, void *data)
492{
495 apr_bucket *e;
496 char buf[30];
497 apr_size_t len = sizeof(buf);
498 const char *expect = "123456789abcdefghij";
499
500 e = apr_bucket_heap_create("1", 1, NULL, ba);
502
503 apr_brigade_putstrs(bb, NULL, NULL, "2", "34", "567", "8", "9a", "bcd",
504 "e", "f", "gh", "i", NULL);
505 apr_brigade_putstrs(bb, NULL, NULL, "j", NULL);
506 apr_assert_success(tc, "apr_brigade_flatten",
508 ABTS_STR_NEQUAL(tc, expect, buf, strlen(expect));
509
512}
513
515{
516 suite = ADD_SUITE(suite);
517
531
532 return suite;
533}
534
535
int n
Definition ap_regex.h:278
const char apr_size_t len
Definition ap_regex.h:187
void abts_run_test(abts_suite *ts, test_func f, void *value)
Definition abts.c:175
#define ADD_SUITE(suite)
Definition abts.h:67
#define ABTS_NOT_IMPL(a, b)
Definition abts.h:129
#define ABTS_STR_NEQUAL(a, b, c, d)
Definition abts.h:124
#define ABTS_ASSERT(a, b, c)
Definition abts.h:130
void apr_assert_success(abts_case *tc, const char *context, apr_status_t rv, int lineno)
Definition testutil.c:29
APR-UTIL Buckets/Bucket Brigades.
char * strdup(const char *str)
APR Strings library.
const unsigned char * buf
Definition util_md5.h:50
#define APR_EOF
Definition apr_errno.h:461
unsigned int count
Definition apr_md5.h:152
apr_file_t * f
#define APR_BRIGADE_LAST(b)
#define APR_BRIGADE_INSERT_TAIL(b, e)
#define apr_bucket_split(e, point)
#define APR_BRIGADE_INSERT_HEAD(b, e)
#define APR_BUCKET_NEXT(e)
apr_bucket * e
#define APR_BRIGADE_EMPTY(b)
#define APR_BRIGADE_SENTINEL(b)
#define apr_bucket_delete(e)
apr_brigade_flush void * ctx
#define APR_BRIGADE_FIRST(b)
#define APR_BUCKET_INSERT_BEFORE(a, b)
#define apr_bucket_read(e, str, len, block)
int apr_off_t * length
#define APR_BUCKET_PREV(e)
@ APR_BLOCK_READ
Definition apr_buckets.h:58
apr_size_t size
#define APR_SUCCESS
Definition apr_errno.h:225
void * data
#define APR_FOPEN_TRUNCATE
Definition apr_file_io.h:58
#define APR_FOPEN_SPARSE
Definition apr_file_io.h:85
#define APR_FOPEN_WRITE
Definition apr_file_io.h:55
#define APR_FOPEN_READ
Definition apr_file_io.h:54
#define APR_FOPEN_CREATE
Definition apr_file_io.h:56
#define APR_OS_DEFAULT
const char * fname
const apr_array_header_t * first
Definition apr_tables.h:207
const apr_array_header_t const apr_array_header_t * second
Definition apr_tables.h:208
apr_pool_t * p
Definition md_event.c:32
return NULL
Definition mod_so.c:359
apr_size_t length
static void test_write_putstrs(abts_case *tc, void *data)
static apr_bucket_brigade * make_simple_brigade(apr_bucket_alloc_t *ba, const char *first, const char *second)
Definition testbuckets.c:77
static void test_create(abts_case *tc, void *data)
Definition testbuckets.c:22
#define THESTR
static void test_bucket_content(abts_case *tc, apr_bucket *e, const char *edata, apr_size_t elen)
static void test_manyfile(abts_case *tc, void *data)
static const char hello[]
static void test_flatten(abts_case *tc, void *data)
static void test_splits(abts_case *tc, void *ctx)
static void test_truncfile(abts_case *tc, void *data)
#define TIF_FNAME
#define COUNT
static void test_write_split(abts_case *tc, void *data)
static void test_insertfile(abts_case *tc, void *ctx)
abts_suite * testbuckets(abts_suite *suite)
static void test_bwrite(abts_case *tc, void *data)
static void test_splitline(abts_case *tc, void *data)
static int count_buckets(apr_bucket_brigade *bb)
static void test_simple(abts_case *tc, void *data)
Definition testbuckets.c:37
static void test_partition(abts_case *tc, void *data)
static void test_split(abts_case *tc, void *data)
static apr_file_t * make_test_file(abts_case *tc, const char *fname, const char *contents)
static void flatten_match(abts_case *tc, const char *ctx, apr_bucket_brigade *bb, const char *expect)
Definition testbuckets.c:94
apr_status_t apr_file_trunc(apr_file_t *fp, apr_off_t offset)
Definition seek.c:99
#define str