Author: rhuijben
Date: Sat Nov 14 14:03:36 2015
New Revision: 1714328
URL: http://svn.apache.org/viewvc?rev=1714328&view=rev
Log:
Replicate some of the http2 data splitting in a test for the split buckets.
(Test some event/accounting bucket behavior while we're at it)
* buckets/split_buckets.c
(serf_split_peek): When peeking gets more data than we are allowed to read
determine the final bucketsize to avoid underdelivering.
* test/test_buckets.c
(update_total): New function.
(test_split_buckets): Extend test.
Modified:
serf/trunk/buckets/split_buckets.c
serf/trunk/test/test_buckets.c
Modified: serf/trunk/buckets/split_buckets.c
URL:
http://svn.apache.org/viewvc/serf/trunk/buckets/split_buckets.c?rev=1714328&r1=1714327&r2=1714328&view=diff
==============================================================================
--- serf/trunk/buckets/split_buckets.c (original)
+++ serf/trunk/buckets/split_buckets.c Sat Nov 14 14:03:36 2015
@@ -231,18 +231,27 @@ static apr_status_t serf_split_peek(serf
status = serf_bucket_peek(ctx->stream, data, len);
- if (!SERF_BUCKET_READ_ERROR(status)
- && (*len > (sctx->max_size - sctx->read_size)))
- {
- /* We can read to the max size. If we provide this
- much data now, we must promise to return as much
- later
- */
- sctx->min_size = sctx->fixed_size = sctx->max_size;
- *len = (sctx->max_size - sctx->read_size);
+ if (!SERF_BUCKET_READ_ERROR(status)) {
+
+ if (*len >= (sctx->min_size - sctx->read_size)) {
+ /* We peeked more data than we need to continue
+ to the next bucket. We have to be careful that
+ we don't promise data and not deliver later.
+ */
+
+ if (! sctx->fixed_size) {
+ /* Determine the maximum size to what we can deliver now */
+ sctx->fixed_size = MIN(sctx->max_size, sctx->read_size + *len);
+ sctx->min_size = sctx->max_size = sctx->fixed_size;
+ }
+
+ *len = sctx->fixed_size - sctx->read_size;
+ status = APR_EOF;
+ }
+
sctx->cant_read = (*len > 0);
}
- else
+ else if (SERF_BUCKET_READ_ERROR(status))
sctx->cant_read = false;
return status;
@@ -426,8 +435,8 @@ void serf_bucket_split_create(serf_bucke
tail_ctx->ctx = ctx;
head_ctx->fixed_size = 0; /* Not fixed yet. This might change an existing
tail bucket that we received as stream! */
- head_ctx->min_size = min_chunk_size;
- head_ctx->max_size = max_chunk_size;
+ head_ctx->min_size = MAX(1, min_chunk_size);
+ head_ctx->max_size = MAX(head_ctx->min_size, max_chunk_size);
/* tail_ctx->fixed_size = 0; // Unknown */
tail_ctx->min_size = SERF_READ_ALL_AVAIL;
Modified: serf/trunk/test/test_buckets.c
URL:
http://svn.apache.org/viewvc/serf/trunk/test/test_buckets.c?rev=1714328&r1=1714327&r2=1714328&view=diff
==============================================================================
--- serf/trunk/test/test_buckets.c (original)
+++ serf/trunk/test/test_buckets.c Sat Nov 14 14:03:36 2015
@@ -2222,11 +2222,21 @@ static void test_limit_buckets(CuTest *t
}
}
+/* Implements serf_bucket_event_callback_t */
+static apr_status_t update_total(void *baton,
+ apr_uint64_t bytes_read)
+{
+ apr_uint64_t *sum = baton;
+
+ (*sum) += bytes_read;
+ return APR_SUCCESS;
+}
+
static void test_split_buckets(CuTest *tc)
{
test_baton_t *tb = tc->testBaton;
serf_bucket_alloc_t *alloc = tb->bkt_alloc;
- char buffer[26];
+ char buffer[128];
apr_size_t len;
serf_bucket_t *raw;
serf_bucket_t *head, *tail;
@@ -2251,6 +2261,7 @@ static void test_split_buckets(CuTest *t
status = read_all(head, buffer, sizeof(buffer), &len);
CuAssertIntEquals(tc, APR_EOF, status);
+ CuAssertIntEquals(tc, len, 5);
serf_bucket_destroy(head);
serf_bucket_destroy(tail);
@@ -2301,6 +2312,56 @@ static void test_split_buckets(CuTest *t
serf_bucket_destroy(head);
serf_bucket_destroy(tail);
}
+
+ {
+ const char *data;
+ int i;
+ apr_int64_t total1, total2;
+ agg = serf_bucket_aggregate_create(alloc);
+ apr_size_t min_r, max_r;
+
+ /* Create a huge body of 173 times 59 chars (both primes) */
+ for (i = 0; i < 173; i++)
+ {
+ serf_bucket_aggregate_append(agg,
+ serf_bucket_simple_create(
+ "12345678901234567890123456789012345678901234567890123", 53,
+ NULL, NULL, alloc));
+ }
+
+ CuAssertIntEquals(tc, (173 * 53), (int)serf_bucket_get_remaining(agg));
+
+ total1 = total2 = 0;
+ min_r = APR_SIZE_MAX;
+ max_r = 0;
+ tail = agg;
+ while ((APR_EOF != serf_bucket_peek(tail, &data, &len)) || len)
+ {
+ serf_bucket_split_create(&head, &tail, tail, 5, 17);
+
+ head = serf__bucket_event_create(head, &total1, NULL, update_total,
+ NULL, alloc);
+
+ status = read_all(head, buffer, sizeof(buffer), &len);
+ CuAssertIntEquals(tc, APR_EOF, status);
+ total2 += len;
+
+ serf_bucket_destroy(head);
+
+ if (total1 < (173 * 53)) {
+ CuAssertTrue(tc, (len >= 5) && (len <= 17));
+
+ min_r = MIN(min_r, len);
+ max_r = MAX(max_r, len);
+ }
+ }
+ serf_bucket_destroy(tail);
+
+ CuAssertTrue(tc, min_r < 10); /* There should be much smaller buckets */
+ CuAssertIntEquals(tc, 17, max_r); /* First call should hit 17 */
+ CuAssertIntEquals(tc, (173 * 53), (int)total1);
+ CuAssertIntEquals(tc, (173 * 53), (int)total2);
+ }
}
static void test_deflate_compress_buckets(CuTest *tc)