quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

unit2601.c (7399B)


      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  * SPDX-License-Identifier: curl
     22  *
     23  ***************************************************************************/
     24 #include "unitcheck.h"
     25 
     26 #include "urldata.h"
     27 #include "bufq.h"
     28 #include "curl_trc.h"
     29 
     30 static const char *tail_err(struct bufq *q)
     31 {
     32   struct buf_chunk *chunk;
     33 
     34   if(!q->tail) {
     35     return q->head ? "tail is NULL, but head is not" : NULL;
     36   }
     37 
     38   chunk = q->head;
     39   while(chunk) {
     40     if(chunk == q->tail) {
     41       if(chunk->next) {
     42         return "tail points to queue, but not at the end";
     43       }
     44       return NULL;
     45     }
     46     chunk = chunk->next;
     47   }
     48   return "tail not part of queue";
     49 }
     50 
     51 static void dump_bufq(struct bufq *q, const char *msg)
     52 {
     53   struct buf_chunk *chunk;
     54   const char *terr;
     55   size_t n;
     56 
     57   curl_mfprintf(stderr, "bufq[chunk_size=%zu, max_chunks=%zu] %s\n",
     58                 q->chunk_size, q->max_chunks, msg);
     59   curl_mfprintf(stderr, "- queue[\n");
     60   chunk = q->head;
     61   while(chunk) {
     62     curl_mfprintf(stderr, "    chunk[len=%zu, roff=%zu, woff=%zu]\n",
     63                   chunk->dlen, chunk->r_offset, chunk->w_offset);
     64     chunk = chunk->next;
     65   }
     66   curl_mfprintf(stderr, "  ]\n");
     67   terr = tail_err(q);
     68   curl_mfprintf(stderr, "- tail: %s\n", terr ? terr : "ok");
     69   n = 0;
     70   chunk = q->spare;
     71   while(chunk) {
     72     ++n;
     73     chunk = chunk->next;
     74   }
     75   curl_mfprintf(stderr, "- chunks: %zu\n", q->chunk_count);
     76   curl_mfprintf(stderr, "- spares: %zu\n", n);
     77 }
     78 
     79 static void check_bufq(size_t pool_spares,
     80                        size_t chunk_size, size_t max_chunks,
     81                        size_t wsize, size_t rsize, int opts)
     82 {
     83   static unsigned char test_data[32*1024];
     84 
     85   struct bufq q;
     86   struct bufc_pool pool;
     87   size_t max_len = chunk_size * max_chunks;
     88   CURLcode result;
     89   ssize_t i;
     90   size_t n2;
     91   size_t nwritten, nread;
     92 
     93   if(pool_spares > 0) {
     94     Curl_bufcp_init(&pool, chunk_size, pool_spares);
     95     Curl_bufq_initp(&q, &pool, max_chunks, opts);
     96   }
     97   else {
     98     Curl_bufq_init2(&q, chunk_size, max_chunks, opts);
     99   }
    100 
    101   fail_unless(q.chunk_size == chunk_size, "chunk_size init wrong");
    102   fail_unless(q.max_chunks == max_chunks, "max_chunks init wrong");
    103   fail_unless(q.head == NULL, "init: head not NULL");
    104   fail_unless(q.tail == NULL, "init: tail not NULL");
    105   fail_unless(q.spare == NULL, "init: spare not NULL");
    106   fail_unless(Curl_bufq_len(&q) == 0, "init: bufq length != 0");
    107 
    108   result = Curl_bufq_write(&q, test_data, wsize, &n2);
    109   fail_unless(n2 <= wsize, "write: wrong size returned");
    110   fail_unless(result == CURLE_OK, "write: wrong result returned");
    111 
    112   /* write empty bufq full */
    113   nwritten = 0;
    114   Curl_bufq_reset(&q);
    115   while(!Curl_bufq_is_full(&q)) {
    116     result = Curl_bufq_write(&q, test_data, wsize, &n2);
    117     if(!result) {
    118       nwritten += n2;
    119     }
    120     else if(result != CURLE_AGAIN) {
    121       fail_unless(result == CURLE_AGAIN, "write-loop: unexpected result");
    122       break;
    123     }
    124   }
    125   if(nwritten != max_len) {
    126     curl_mfprintf(stderr, "%zu bytes written, but max_len=%zu\n",
    127                   nwritten, max_len);
    128     dump_bufq(&q, "after writing full");
    129     fail_if(TRUE, "write: bufq full but nwritten wrong");
    130   }
    131 
    132   /* read full bufq empty */
    133   nread = 0;
    134   while(!Curl_bufq_is_empty(&q)) {
    135     result = Curl_bufq_read(&q, test_data, rsize, &n2);
    136     if(!result) {
    137       nread += n2;
    138     }
    139     else if(result != CURLE_AGAIN) {
    140       fail_unless(result == CURLE_AGAIN, "read-loop: unexpected result");
    141       break;
    142     }
    143   }
    144   if(nread != max_len) {
    145     curl_mfprintf(stderr, "%zu bytes read, but max_len=%zu\n",
    146                   nwritten, max_len);
    147     dump_bufq(&q, "after reading empty");
    148     fail_if(TRUE, "read: bufq empty but nread wrong");
    149   }
    150   if(q.tail) {
    151     dump_bufq(&q, "after reading empty");
    152     fail_if(TRUE, "read empty, but tail is not NULL");
    153   }
    154 
    155   for(i = 0; i < 1000; ++i) {
    156     result = Curl_bufq_write(&q, test_data, wsize, &n2);
    157     if(result && result != CURLE_AGAIN) {
    158       fail_unless(result == CURLE_AGAIN, "rw-loop: unexpected write result");
    159       break;
    160     }
    161     result = Curl_bufq_read(&q, test_data, rsize, &n2);
    162     if(result && result != CURLE_AGAIN) {
    163       fail_unless(result == CURLE_AGAIN, "rw-loop: unexpected read result");
    164       break;
    165     }
    166   }
    167 
    168   /* Test SOFT_LIMIT option */
    169   Curl_bufq_free(&q);
    170   Curl_bufq_init2(&q, chunk_size, max_chunks, (opts|BUFQ_OPT_SOFT_LIMIT));
    171   nwritten = 0;
    172   while(!Curl_bufq_is_full(&q)) {
    173     result = Curl_bufq_write(&q, test_data, wsize, &n2);
    174     if(result || n2 != wsize) {
    175       fail_unless(!result && n2 == wsize, "write should be complete");
    176       break;
    177     }
    178     nwritten += n2;
    179   }
    180   if(nwritten < max_len) {
    181     curl_mfprintf(stderr, "%zu bytes written, but max_len=%zu\n",
    182                   nwritten, max_len);
    183     dump_bufq(&q, "after writing full");
    184     fail_if(TRUE, "write: bufq full but nwritten wrong");
    185   }
    186   /* do one more write on a full bufq, should work */
    187   result = Curl_bufq_write(&q, test_data, wsize, &n2);
    188   fail_unless(!result && n2 == wsize, "write should be complete");
    189   nwritten += n2;
    190   /* see that we get all out again */
    191   nread = 0;
    192   while(!Curl_bufq_is_empty(&q)) {
    193     result = Curl_bufq_read(&q, test_data, rsize, &n2);
    194     if(result) {
    195       fail_unless(result, "read-loop: unexpected fail");
    196       break;
    197     }
    198     nread += n2;
    199   }
    200   fail_unless(nread == nwritten, "did not get the same out as put in");
    201 
    202   dump_bufq(&q, "at end of test");
    203   Curl_bufq_free(&q);
    204   if(pool_spares > 0)
    205     Curl_bufcp_free(&pool);
    206 }
    207 
    208 static CURLcode test_unit2601(char *arg)
    209 {
    210   UNITTEST_BEGIN_SIMPLE
    211 
    212   struct bufq q;
    213   size_t n;
    214   CURLcode result;
    215   unsigned char buf[16*1024];
    216 
    217   Curl_bufq_init(&q, 8*1024, 12);
    218   result = Curl_bufq_read(&q, buf, 128, &n);
    219   fail_unless(result && result == CURLE_AGAIN, "read empty fail");
    220   Curl_bufq_free(&q);
    221 
    222   check_bufq(0, 1024, 4, 128, 128, BUFQ_OPT_NONE);
    223   check_bufq(0, 1024, 4, 129, 127, BUFQ_OPT_NONE);
    224   check_bufq(0, 1024, 4, 2000, 16000, BUFQ_OPT_NONE);
    225   check_bufq(0, 1024, 4, 16000, 3000, BUFQ_OPT_NONE);
    226 
    227   check_bufq(0, 8000, 10, 1234, 1234, BUFQ_OPT_NONE);
    228   check_bufq(0, 8000, 10, 8*1024, 4*1024, BUFQ_OPT_NONE);
    229 
    230   check_bufq(0, 1024, 4, 128, 128, BUFQ_OPT_NO_SPARES);
    231   check_bufq(0, 1024, 4, 129, 127, BUFQ_OPT_NO_SPARES);
    232   check_bufq(0, 1024, 4, 2000, 16000, BUFQ_OPT_NO_SPARES);
    233   check_bufq(0, 1024, 4, 16000, 3000, BUFQ_OPT_NO_SPARES);
    234 
    235   check_bufq(8, 1024, 4, 128, 128, BUFQ_OPT_NONE);
    236   check_bufq(8, 8000, 10, 1234, 1234, BUFQ_OPT_NONE);
    237   check_bufq(8, 1024, 4, 129, 127, BUFQ_OPT_NO_SPARES);
    238 
    239   UNITTEST_END_SIMPLE
    240 }