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)


Reply via email to