tests/test_buffer.cpp

Mon, 01 Jan 2024 16:42:37 +0100

author
Mike Becker <universe@uap-core.de>
date
Mon, 01 Jan 2024 16:42:37 +0100
changeset 789
9b2f5661bebd
parent 761
61d5197d612b
child 792
3ca984931e1d
permissions
-rw-r--r--

begin migration of buffer tests - relates to #342

     1 /*
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
     5  *
     6  * Redistribution and use in source and binary forms, with or without
     7  * modification, are permitted provided that the following conditions are met:
     8  *
     9  *   1. Redistributions of source code must retain the above copyright
    10  *      notice, this list of conditions and the following disclaimer.
    11  *
    12  *   2. Redistributions in binary form must reproduce the above copyright
    13  *      notice, this list of conditions and the following disclaimer in the
    14  *      documentation and/or other materials provided with the distribution.
    15  *
    16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    19  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    26  * POSSIBILITY OF SUCH DAMAGE.
    27  */
    29 #include "cx/buffer.h"
    31 #include <gtest/gtest.h>
    32 #include "util_allocator.h"
    34 class BufferFixture : public ::testing::Test {
    35 protected:
    36     void SetUp() override {
    37         cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
    38         buf.size = 6;
    39         buf.pos = 3;
    40     }
    42     void TearDown() override {
    43         cxBufferDestroy(&buf);
    44     }
    46     CxBuffer buf{};
    47 };
    49 class BufferShiftFixture : public ::testing::Test {
    50 protected:
    51     void SetUp() override {
    52         CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
    53         cxBufferInit(&buf, NULL, 16, &alloc, CX_BUFFER_DEFAULT);
    54         memcpy(buf.space, "test____________", 16);
    55         buf.capacity = 8; // purposely pretend that the buffer has less capacity s.t. we can test beyond the range
    56         buf.pos = 4;
    57         buf.size = 4;
    58     }
    60     void TearDown() override {
    61         cxBufferDestroy(&buf);
    62         CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
    63     }
    65     CxTestingAllocator alloc;
    66     CxBuffer buf{};
    67 };
    69 class BufferShiftLeft : public BufferShiftFixture {
    70 };
    72 TEST_F(BufferShiftLeft, Zero) {
    73     CX_TEST_ASSERT(buf.pos == 4);
    74     CX_TEST_ASSERT(buf.size == 4);
    75     int ret = cxBufferShiftLeft(&buf, 0);
    76     CX_TEST_ASSERT(ret == 0);
    77     CX_TEST_ASSERT(buf.pos == 4);
    78     CX_TEST_ASSERT(buf.size == 4);
    79     CX_TEST_ASSERT(memcmp(buf.space, "test________", 8) == 0);
    80 }
    82 TEST_F(BufferShiftLeft, ZeroOffsetInterface) {
    83     CX_TEST_ASSERT(buf.pos == 4);
    84     CX_TEST_ASSERT(buf.size == 4);
    85     int ret = cxBufferShift(&buf, -0);
    86     CX_TEST_ASSERT(ret == 0);
    87     CX_TEST_ASSERT(buf.pos == 4);
    88     CX_TEST_ASSERT(buf.size == 4);
    89     CX_TEST_ASSERT(memcmp(buf.space, "test________", 8) == 0);
    90 }
    92 TEST_F(BufferShiftLeft, Standard) {
    93     CX_TEST_ASSERT(buf.pos == 4);
    94     CX_TEST_ASSERT(buf.size == 4);
    95     int ret = cxBufferShiftLeft(&buf, 2);
    96     CX_TEST_ASSERT(ret == 0);
    97     CX_TEST_ASSERT(buf.pos == 2);
    98     CX_TEST_ASSERT(buf.size == 2);
    99     CX_TEST_ASSERT(memcmp(buf.space, "stst________", 8) == 0);
   100 }
   102 TEST_F(BufferShiftLeft, Overshift) {
   103     ASSERT_LT(buf.pos, 6);
   104     ASSERT_LT(buf.size, 6);
   105     int ret = cxBufferShiftLeft(&buf, 6);
   106     CX_TEST_ASSERT(ret == 0);
   107     CX_TEST_ASSERT(buf.pos == 0);
   108     CX_TEST_ASSERT(buf.size == 0);
   109     CX_TEST_ASSERT(memcmp(buf.space, "test________", 8) == 0);
   110 }
   112 TEST_F(BufferShiftLeft, OvershiftPosOnly) {
   113     buf.pos = 2;
   114     CX_TEST_ASSERT(buf.size == 4);
   115     int ret = cxBufferShiftLeft(&buf, 3);
   116     CX_TEST_ASSERT(ret == 0);
   117     CX_TEST_ASSERT(buf.pos == 0);
   118     CX_TEST_ASSERT(buf.size == 1);
   119     CX_TEST_ASSERT(memcmp(buf.space, "test________", 8) == 0);
   120 }
   122 TEST_F(BufferShiftLeft, OffsetInterface) {
   123     buf.pos = 3;
   124     CX_TEST_ASSERT(buf.size == 4);
   125     int ret = cxBufferShift(&buf, -2);
   126     CX_TEST_ASSERT(ret == 0);
   127     CX_TEST_ASSERT(buf.pos == 1);
   128     CX_TEST_ASSERT(buf.size == 2);
   129     CX_TEST_ASSERT(memcmp(buf.space, "stst________", 8) == 0);
   130 }
   132 TEST_F(BufferShiftRight, Zero) {
   133     CX_TEST_ASSERT(buf.pos == 4);
   134     CX_TEST_ASSERT(buf.size == 4);
   135     int ret = cxBufferShiftRight(&buf, 0);
   136     CX_TEST_ASSERT(ret == 0);
   137     CX_TEST_ASSERT(buf.pos == 4);
   138     CX_TEST_ASSERT(buf.size == 4);
   139     CX_TEST_ASSERT(memcmp(buf.space, "test________", 8) == 0);
   140 }
   142 TEST_F(BufferShiftRight, ZeroOffsetInterface) {
   143     CX_TEST_ASSERT(buf.pos == 4);
   144     CX_TEST_ASSERT(buf.size == 4);
   145     int ret = cxBufferShift(&buf, +0);
   146     CX_TEST_ASSERT(ret == 0);
   147     CX_TEST_ASSERT(buf.pos == 4);
   148     CX_TEST_ASSERT(buf.size == 4);
   149     CX_TEST_ASSERT(memcmp(buf.space, "test________", 8) == 0);
   150 }
   152 TEST_F(BufferShiftRight, Standard) {
   153     CX_TEST_ASSERT(buf.pos == 4);
   154     CX_TEST_ASSERT(buf.size == 4);
   155     int ret = cxBufferShiftRight(&buf, 3);
   156     CX_TEST_ASSERT(ret == 0);
   157     CX_TEST_ASSERT(buf.pos == 7);
   158     CX_TEST_ASSERT(buf.size == 7);
   159     CX_TEST_ASSERT(memcmp(buf.space, "testest_____", 8) == 0);
   160 }
   162 TEST_F(BufferShiftRight, OvershiftDiscard) {
   163     CX_TEST_ASSERT(buf.pos == 4);
   164     CX_TEST_ASSERT(buf.size == 4);
   165     CX_TEST_ASSERT(buf.capacity == 8);
   166     int ret = cxBufferShiftRight(&buf, 6);
   167     CX_TEST_ASSERT(ret == 0);
   168     CX_TEST_ASSERT(buf.pos == 8);
   169     CX_TEST_ASSERT(buf.size == 8);
   170     CX_TEST_ASSERT(buf.capacity == 8);
   171     CX_TEST_ASSERT(memcmp(buf.space, "test__te____", 8) == 0);
   172 }
   174 TEST_F(BufferShiftRight, OvershiftExtend) {
   175     CX_TEST_ASSERT(buf.pos == 4);
   176     CX_TEST_ASSERT(buf.size == 4);
   177     CX_TEST_ASSERT(buf.capacity == 8);
   178     buf.flags |= CX_BUFFER_AUTO_EXTEND;
   179     int ret = cxBufferShiftRight(&buf, 6);
   180     CX_TEST_ASSERT(ret == 0);
   181     CX_TEST_ASSERT(buf.pos == 10);
   182     CX_TEST_ASSERT(buf.size == 10);
   183     EXPECT_GE(buf.capacity, 10);
   184     CX_TEST_ASSERT(memcmp(buf.space, "test__test__", 8) == 0);
   185 }
   187 TEST_F(BufferShiftRight, OffsetInterface) {
   188     buf.pos = 3;
   189     CX_TEST_ASSERT(buf.size == 4);
   190     int ret = cxBufferShift(&buf, 2);
   191     CX_TEST_ASSERT(ret == 0);
   192     CX_TEST_ASSERT(buf.pos == 5);
   193     CX_TEST_ASSERT(buf.size == 6);
   194     CX_TEST_ASSERT(memcmp(buf.space, "tetest______", 8) == 0);
   195 }
   197 class BufferWrite : public ::testing::Test {
   198 protected:
   199     CxBuffer buf{}, target{};
   201     void SetUp() override {
   202         cxBufferInit(&target, NULL, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
   203         cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
   204         buf.capacity = 8; // artificially reduce capacity to check OOB writes
   205         memset(buf.space, 0, 16);
   206         memcpy(buf.space, "prep", 4);
   207         buf.size = buf.pos = 4;
   208     }
   210     void TearDown() override {
   211         cxBufferDestroy(&buf);
   212         cxBufferDestroy(&target);
   213     }
   215     void enableFlushing() {
   216         buf.flush_target = &target;
   217         buf.flush_func = reinterpret_cast<cx_write_func>(cxBufferWrite);
   218         buf.flush_blkmax = 1;
   219     }
   220 };
   222 static size_t mock_write_limited_rate(
   223         void const *ptr,
   224         size_t size,
   225         __attribute__((unused)) size_t nitems,
   226         CxBuffer *buffer
   227 ) {
   228     // simulate limited target drain capacity
   229     static bool full = false;
   230     if (full) {
   231         full = false;
   232         return 0;
   233     } else {
   234         full = true;
   235         return cxBufferWrite(ptr, size, nitems > 2 ? 2 : nitems, buffer);
   236     }
   237 }
   239 TEST_F(BufferWrite, SizeOneFit) {
   240     const char *data = "test";
   241     CX_TEST_ASSERT(buf.capacity == 8);
   242     CX_TEST_ASSERT(buf.pos == 4);
   243     CX_TEST_ASSERT(buf.size == 4);
   244     size_t written = cxBufferWrite(data, 1, 4, &buf);
   245     CX_TEST_ASSERT(written == 4);
   246     CX_TEST_ASSERT(buf.size == 8);
   247     CX_TEST_ASSERT(buf.pos == 8);
   248     CX_TEST_ASSERT(buf.capacity == 8);
   249     EXPECT_EQ(memcmp(buf.space, "preptest", 8), 0);
   250 }
   252 TEST_F(BufferWrite, SizeOneDiscard) {
   253     const char *data = "testing";
   254     CX_TEST_ASSERT(buf.capacity == 8);
   255     CX_TEST_ASSERT(buf.pos == 4);
   256     CX_TEST_ASSERT(buf.size == 4);
   257     size_t written = cxBufferWrite(data, 1, 7, &buf);
   258     CX_TEST_ASSERT(written == 4);
   259     CX_TEST_ASSERT(buf.size == 8);
   260     CX_TEST_ASSERT(buf.pos == 8);
   261     CX_TEST_ASSERT(buf.capacity == 8);
   262     EXPECT_EQ(memcmp(buf.space, "preptest\0", 9), 0);
   263 }
   265 TEST_F(BufferWrite, SizeOneExtend) {
   266     buf.flags |= CX_BUFFER_AUTO_EXTEND;
   267     const char *data = "testing";
   268     CX_TEST_ASSERT(buf.capacity == 8);
   269     CX_TEST_ASSERT(buf.pos == 4);
   270     CX_TEST_ASSERT(buf.size == 4);
   271     size_t written = cxBufferWrite(data, 1, 7, &buf);
   272     CX_TEST_ASSERT(written == 7);
   273     CX_TEST_ASSERT(buf.size == 11);
   274     CX_TEST_ASSERT(buf.pos == 11);
   275     EXPECT_GE(buf.capacity, 11);
   276     EXPECT_EQ(memcmp(buf.space, "preptesting", 11), 0);
   277 }
   279 TEST_F(BufferWrite, MultibyteFit) {
   280     const char *data = "test";
   281     CX_TEST_ASSERT(buf.capacity == 8);
   282     CX_TEST_ASSERT(buf.pos == 4);
   283     CX_TEST_ASSERT(buf.size == 4);
   284     size_t written = cxBufferWrite(data, 2, 2, &buf);
   285     CX_TEST_ASSERT(written == 2);
   286     CX_TEST_ASSERT(buf.size == 8);
   287     CX_TEST_ASSERT(buf.pos == 8);
   288     CX_TEST_ASSERT(buf.capacity == 8);
   289     EXPECT_EQ(memcmp(buf.space, "preptest", 8), 0);
   290 }
   292 TEST_F(BufferWrite, MultibyteDiscard) {
   293     const char *data = "testing";
   294     CX_TEST_ASSERT(buf.capacity == 8);
   295     CX_TEST_ASSERT(buf.size == 4);
   296     buf.pos = 3;
   297     size_t written = cxBufferWrite(data, 2, 4, &buf);
   298     // remember: whole elements are discarded if they do not fit
   299     CX_TEST_ASSERT(written == 2);
   300     CX_TEST_ASSERT(buf.size == 7);
   301     CX_TEST_ASSERT(buf.pos == 7);
   302     CX_TEST_ASSERT(buf.capacity == 8);
   303     EXPECT_EQ(memcmp(buf.space, "pretest\0", 8), 0);
   304 }
   306 TEST_F(BufferWrite, MultibyteExtend) {
   307     buf.flags |= CX_BUFFER_AUTO_EXTEND;
   308     const char *data = "tester";
   309     CX_TEST_ASSERT(buf.capacity == 8);
   310     CX_TEST_ASSERT(buf.size == 4);
   311     buf.pos = 3;
   312     size_t written = cxBufferWrite(data, 2, 3, &buf);
   313     // remember: whole elements are discarded if they do not fit
   314     CX_TEST_ASSERT(written == 3);
   315     CX_TEST_ASSERT(buf.size == 9);
   316     CX_TEST_ASSERT(buf.pos == 9);
   317     EXPECT_GE(buf.capacity, 9);
   318     EXPECT_EQ(memcmp(buf.space, "pretester", 9), 0);
   319 }
   321 TEST_F(BufferWrite, PutcWrapperFit) {
   322     CX_TEST_ASSERT(buf.capacity == 8);
   323     CX_TEST_ASSERT(buf.pos == 4);
   324     CX_TEST_ASSERT(buf.size == 4);
   325     int c = cxBufferPut(&buf, 0x200 | 'a');
   326     CX_TEST_ASSERT(c == 'a');
   327     CX_TEST_ASSERT(buf.size == 5);
   328     CX_TEST_ASSERT(buf.pos == 5);
   329     CX_TEST_ASSERT(buf.capacity == 8);
   330     EXPECT_EQ(memcmp(buf.space, "prepa\0", 6), 0);
   331 }
   333 TEST_F(BufferWrite, PutcWrapperDiscard) {
   334     CX_TEST_ASSERT(buf.capacity == 8);
   335     CX_TEST_ASSERT(buf.size == 4);
   336     buf.pos = 8;
   337     int c = cxBufferPut(&buf, 0x200 | 'a');
   338     CX_TEST_ASSERT(c == EOF);
   339     CX_TEST_ASSERT(buf.size == 4);
   340     CX_TEST_ASSERT(buf.pos == 8);
   341     CX_TEST_ASSERT(buf.capacity == 8);
   342     EXPECT_EQ(memcmp(buf.space, "prep\0\0\0\0\0", 9), 0);
   343 }
   345 TEST_F(BufferWrite, PutcWrapperExtend) {
   346     buf.flags |= CX_BUFFER_AUTO_EXTEND;
   347     CX_TEST_ASSERT(buf.capacity == 8);
   348     CX_TEST_ASSERT(buf.size == 4);
   349     buf.pos = 8;
   350     int c = cxBufferPut(&buf, 0x200 | 'a');
   351     CX_TEST_ASSERT(c == 'a');
   352     CX_TEST_ASSERT(buf.size == 9);
   353     CX_TEST_ASSERT(buf.pos == 9);
   354     EXPECT_GE(buf.capacity, 9);
   355     EXPECT_EQ(memcmp(buf.space, "prep\0\0\0\0a", 9), 0);
   356 }
   358 TEST_F(BufferWrite, PutStringWrapperFit) {
   359     const char *data = "test";
   360     CX_TEST_ASSERT(buf.capacity == 8);
   361     CX_TEST_ASSERT(buf.pos == 4);
   362     CX_TEST_ASSERT(buf.size == 4);
   363     size_t written = cxBufferPutString(&buf, data);
   364     CX_TEST_ASSERT(written == 4);
   365     CX_TEST_ASSERT(buf.size == 8);
   366     CX_TEST_ASSERT(buf.pos == 8);
   367     CX_TEST_ASSERT(buf.capacity == 8);
   368     EXPECT_EQ(memcmp(buf.space, "preptest", 8), 0);
   369 }
   371 TEST_F(BufferWrite, PutStringWrapperDiscard) {
   372     const char *data = "testing";
   373     CX_TEST_ASSERT(buf.capacity == 8);
   374     CX_TEST_ASSERT(buf.pos == 4);
   375     CX_TEST_ASSERT(buf.size == 4);
   376     size_t written = cxBufferPutString(&buf, data);
   377     CX_TEST_ASSERT(written == 4);
   378     CX_TEST_ASSERT(buf.size == 8);
   379     CX_TEST_ASSERT(buf.pos == 8);
   380     CX_TEST_ASSERT(buf.capacity == 8);
   381     EXPECT_EQ(memcmp(buf.space, "preptest\0", 9), 0);
   382 }
   384 TEST_F(BufferWrite, PutStringWrapperExtend) {
   385     buf.flags |= CX_BUFFER_AUTO_EXTEND;
   386     const char *data = "testing";
   387     CX_TEST_ASSERT(buf.capacity == 8);
   388     CX_TEST_ASSERT(buf.pos == 4);
   389     CX_TEST_ASSERT(buf.size == 4);
   390     size_t written = cxBufferPutString(&buf, data);
   391     CX_TEST_ASSERT(written == 7);
   392     CX_TEST_ASSERT(buf.size == 11);
   393     CX_TEST_ASSERT(buf.pos == 11);
   394     EXPECT_GE(buf.capacity, 11);
   395     EXPECT_EQ(memcmp(buf.space, "preptesting", 11), 0);
   396 }
   398 TEST_F(BufferWrite, MultOverflow) {
   399     const char *data = "testing";
   400     CX_TEST_ASSERT(buf.capacity == 8);
   401     CX_TEST_ASSERT(buf.pos == 4);
   402     CX_TEST_ASSERT(buf.size == 4);
   403     size_t written = cxBufferWrite(data, 8, SIZE_MAX / 4, &buf);
   404     CX_TEST_ASSERT(written == 0);
   405     CX_TEST_ASSERT(buf.capacity == 8);
   406     CX_TEST_ASSERT(buf.pos == 4);
   407     CX_TEST_ASSERT(buf.size == 4);
   408     EXPECT_EQ(memcmp(buf.space, "prep\0", 5), 0);
   409 }
   411 TEST_F(BufferWrite, MaxCapaOverflow) {
   412     buf.flags |= CX_BUFFER_AUTO_EXTEND;
   413     const char *data = "testing";
   414     CX_TEST_ASSERT(buf.capacity == 8);
   415     CX_TEST_ASSERT(buf.pos == 4);
   416     CX_TEST_ASSERT(buf.size == 4);
   417     size_t written = cxBufferWrite(data, 1, SIZE_MAX - 2, &buf);
   418     CX_TEST_ASSERT(written == 0);
   419     CX_TEST_ASSERT(buf.capacity == 8);
   420     CX_TEST_ASSERT(buf.pos == 4);
   421     CX_TEST_ASSERT(buf.size == 4);
   422     EXPECT_EQ(memcmp(buf.space, "prep\0", 5), 0);
   423 }
   425 TEST_F(BufferWrite, OnlyOverwrite) {
   426     buf.flags |= CX_BUFFER_AUTO_EXTEND;
   427     CX_TEST_ASSERT(buf.capacity == 8);
   428     memcpy(buf.space, "preptest", 8);
   429     buf.pos = 3;
   430     buf.size = 8;
   431     size_t written = cxBufferWrite("XXX", 2, 2, &buf);
   432     CX_TEST_ASSERT(written == 2);
   433     CX_TEST_ASSERT(buf.capacity == 8);
   434     CX_TEST_ASSERT(buf.size == 8);
   435     CX_TEST_ASSERT(buf.pos == 7);
   436     EXPECT_EQ(memcmp(buf.space, "preXXX\0t", 8), 0);
   437 }
   439 TEST_F(BufferWrite, FlushAtCapacity) {
   440     enableFlushing();
   441     CX_TEST_ASSERT(buf.capacity == 8);
   442     CX_TEST_ASSERT(buf.pos == 4);
   443     size_t written = cxBufferWrite("foo", 1, 3, &buf);
   444     CX_TEST_ASSERT(written == 3);
   445     CX_TEST_ASSERT(buf.pos == 7);
   446     CX_TEST_ASSERT(buf.size == 7);
   447     CX_TEST_ASSERT(target.pos == 0);
   448     CX_TEST_ASSERT(target.size == 0);
   449     written = cxBufferWrite("hello", 1, 5, &buf);
   450     CX_TEST_ASSERT(written == 5);
   451     CX_TEST_ASSERT(buf.pos == 0);
   452     CX_TEST_ASSERT(buf.size == 0);
   453     CX_TEST_ASSERT(buf.capacity == 8);
   454     CX_TEST_ASSERT(target.pos == 12);
   455     CX_TEST_ASSERT(target.size == 12);
   456     EXPECT_EQ(memcmp(target.space, "prepfoohello", 12), 0);
   457 }
   459 TEST_F(BufferWrite, FlushAtThreshold) {
   460     enableFlushing();
   461     buf.flush_threshold = 12;
   462     buf.flags |= CX_BUFFER_AUTO_EXTEND;
   463     CX_TEST_ASSERT(buf.capacity == 8);
   464     CX_TEST_ASSERT(buf.pos == 4);
   465     size_t written = cxBufferWrite("foobar", 1, 6, &buf);
   466     CX_TEST_ASSERT(written == 6);
   467     CX_TEST_ASSERT(buf.pos == 10);
   468     CX_TEST_ASSERT(buf.size == 10);
   469     ASSERT_GE(buf.capacity, 10);
   470     ASSERT_LE(buf.capacity, 12);
   471     CX_TEST_ASSERT(target.pos == 0);
   472     CX_TEST_ASSERT(target.size == 0);
   473     written = cxBufferWrite("hello", 1, 5, &buf);
   474     CX_TEST_ASSERT(written == 5);
   475     CX_TEST_ASSERT(buf.pos == 0);
   476     CX_TEST_ASSERT(buf.size == 0);
   477     EXPECT_LE(buf.capacity, 12);
   478     CX_TEST_ASSERT(target.pos == 15);
   479     CX_TEST_ASSERT(target.size == 15);
   480     EXPECT_EQ(memcmp(target.space, "prepfoobarhello", 15), 0);
   481 }
   483 TEST_F(BufferWrite, FlushRateLimited) {
   484     enableFlushing();
   485     // limit the rate of the flush function and the capacity of the target
   486     target.capacity = 16;
   487     target.flags &= ~CX_BUFFER_AUTO_EXTEND;
   488     buf.flush_func = (cx_write_func) mock_write_limited_rate;
   489     CX_TEST_ASSERT(buf.capacity == 8);
   490     CX_TEST_ASSERT(buf.pos == 4);
   491     size_t written = cxBufferWrite("foo", 1, 3, &buf);
   492     CX_TEST_ASSERT(written == 3);
   493     CX_TEST_ASSERT(buf.pos == 7);
   494     CX_TEST_ASSERT(buf.size == 7);
   495     CX_TEST_ASSERT(target.pos == 0);
   496     CX_TEST_ASSERT(target.size == 0);
   497     written = cxBufferWrite("hello, world!", 1, 13, &buf);
   498     // " world!" fits into this buffer, the remaining stuff is flushed out
   499     CX_TEST_ASSERT(written == 13);
   500     CX_TEST_ASSERT(buf.pos == 7);
   501     CX_TEST_ASSERT(buf.size == 7);
   502     CX_TEST_ASSERT(buf.capacity == 8);
   503     EXPECT_EQ(memcmp(buf.space, " world!", 7), 0);
   504     CX_TEST_ASSERT(target.pos == 13);
   505     CX_TEST_ASSERT(target.size == 13);
   506     CX_TEST_ASSERT(target.capacity == 16);
   507     EXPECT_EQ(memcmp(target.space, "prepfoohello,", 13), 0);
   508 }
   511 TEST_F(BufferEof, Reached) {
   512     buf.pos = buf.size;
   513     CX_TEST_ASSERT(cxBufferEof(&buf));
   514     buf.pos = buf.size - 1;
   515     CX_TEST_ASSERT(!cxBufferEof(&buf));
   516     cxBufferPut(&buf, 'a');
   517     CX_TEST_ASSERT(cxBufferEof(&buf));
   518 }
   520 TEST_F(BufferEof, NotReached) {
   521     buf.pos = buf.size - 1;
   522     CX_TEST_ASSERT(!cxBufferEof(&buf));
   523     buf.pos = 0;
   524     cxBufferWrite("test", 1, 5, &buf);
   525     CX_TEST_ASSERT(!cxBufferEof(&buf));
   526 }
   528 class BufferRead : public ::testing::Test {
   529 protected:
   530     CxBuffer buf{};
   532     void SetUp() override {
   533         cxBufferInit(&buf, NULL, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
   534         buf.capacity = 8; // artificially reduce capacity to check OOB writes
   535         memset(buf.space, 0, 16);
   536         memcpy(buf.space, "some data", 9);
   537         buf.size = 9;
   538     }
   540     void TearDown() override {
   541         cxBufferDestroy(&buf);
   542     }
   543 };
   545 TEST_F(BufferRead, GetByte) {
   546     buf.pos = 2;
   547     EXPECT_EQ(cxBufferGet(&buf), 'm');
   548     EXPECT_EQ(cxBufferGet(&buf), 'e');
   549     EXPECT_EQ(cxBufferGet(&buf), ' ');
   550     EXPECT_EQ(cxBufferGet(&buf), 'd');
   551     CX_TEST_ASSERT(buf.pos == 6);
   552 }
   554 TEST_F(BufferRead, GetEof) {
   555     buf.pos = buf.size;
   556     EXPECT_EQ(cxBufferGet(&buf), EOF);
   557 }
   559 TEST_F(BufferRead, ReadWithinBounds) {
   560     buf.pos = 2;
   561     char target[4];
   562     auto read = cxBufferRead(&target, 1, 4, &buf);
   563     CX_TEST_ASSERT(read == 4);
   564     EXPECT_EQ(memcmp(&target, "me d", 4), 0);
   565     CX_TEST_ASSERT(buf.pos == 6);
   566 }
   568 TEST_F(BufferRead, ReadOutOfBounds) {
   569     buf.pos = 6;
   570     char target[4];
   571     auto read = cxBufferRead(&target, 1, 4, &buf);
   572     CX_TEST_ASSERT(read == 3);
   573     EXPECT_EQ(memcmp(&target, "ata", 3), 0);
   574     CX_TEST_ASSERT(buf.pos == 9);
   575 }
   577 TEST_F(BufferRead, ReadOutOfBoundsMultibyte) {
   578     buf.pos = 6;
   579     char target[4];
   580     target[2] = '\0';
   581     auto read = cxBufferRead(&target, 2, 2, &buf);
   582     CX_TEST_ASSERT(read == 1);
   583     EXPECT_EQ(memcmp(&target, "at\0", 3), 0);
   584     CX_TEST_ASSERT(buf.pos == 8);
   585 }
   587 TEST_F(BufferRead, ReadEof) {
   588     buf.pos = 9;
   589     char target[4];
   590     auto read = cxBufferRead(&target, 1, 1, &buf);
   591     CX_TEST_ASSERT(read == 0);
   592     CX_TEST_ASSERT(buf.pos == 9);
   593 }

mercurial