tests/test_buffer.cpp

Sun, 21 May 2023 16:22:09 +0200

author
Mike Becker <universe@uap-core.de>
date
Sun, 21 May 2023 16:22:09 +0200
changeset 710
2dd409ed056f
parent 683
aa0d09f2d81c
child 761
61d5197d612b
permissions
-rw-r--r--

fix const-ness of non-mutating iterator creation for maps

universe@530 1 /*
universe@530 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
universe@530 3 *
universe@530 4 * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved.
universe@530 5 *
universe@530 6 * Redistribution and use in source and binary forms, with or without
universe@530 7 * modification, are permitted provided that the following conditions are met:
universe@530 8 *
universe@530 9 * 1. Redistributions of source code must retain the above copyright
universe@530 10 * notice, this list of conditions and the following disclaimer.
universe@530 11 *
universe@530 12 * 2. Redistributions in binary form must reproduce the above copyright
universe@530 13 * notice, this list of conditions and the following disclaimer in the
universe@530 14 * documentation and/or other materials provided with the distribution.
universe@530 15 *
universe@530 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
universe@530 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
universe@530 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
universe@530 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
universe@530 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
universe@530 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
universe@530 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
universe@530 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
universe@530 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
universe@530 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
universe@530 26 * POSSIBILITY OF SUCH DAMAGE.
universe@530 27 */
universe@530 28
universe@530 29 #include "cx/buffer.h"
universe@530 30
universe@530 31 #include <gtest/gtest.h>
universe@530 32 #include "util_allocator.h"
universe@530 33
universe@548 34 class BufferFixture : public ::testing::Test {
universe@548 35 protected:
universe@548 36 void SetUp() override {
universe@548 37 cxBufferInit(&buf, nullptr, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
universe@548 38 buf.size = 6;
universe@548 39 buf.pos = 3;
universe@548 40 }
universe@548 41
universe@548 42 void TearDown() override {
universe@548 43 cxBufferDestroy(&buf);
universe@548 44 }
universe@548 45
universe@548 46 CxBuffer buf{};
universe@548 47 };
universe@548 48
universe@539 49 static void expect_default_flush_config(CxBuffer *buf) {
universe@539 50 EXPECT_EQ(buf->flush_blkmax, 0);
universe@539 51 EXPECT_EQ(buf->flush_blksize, 4096);
universe@539 52 EXPECT_EQ(buf->flush_threshold, SIZE_MAX);
universe@539 53 EXPECT_EQ(buf->flush_func, nullptr);
universe@541 54 EXPECT_EQ(buf->flush_target, nullptr);
universe@539 55 }
universe@539 56
universe@535 57 TEST(BufferInit, WrapSpace) {
universe@535 58 CxTestingAllocator alloc;
universe@530 59 CxBuffer buf;
universe@535 60 void *space = cxMalloc(&alloc, 16);
universe@535 61 cxBufferInit(&buf, space, 16, &alloc, CX_BUFFER_DEFAULT);
universe@539 62 expect_default_flush_config(&buf);
universe@530 63 EXPECT_EQ(buf.space, space);
universe@530 64 EXPECT_EQ(buf.flags & CX_BUFFER_AUTO_EXTEND, 0);
universe@530 65 EXPECT_EQ(buf.flags & CX_BUFFER_FREE_CONTENTS, 0);
universe@530 66 EXPECT_EQ(buf.pos, 0);
universe@530 67 EXPECT_EQ(buf.size, 0);
universe@530 68 EXPECT_EQ(buf.capacity, 16);
universe@535 69 EXPECT_EQ(buf.allocator, &alloc);
universe@530 70 cxBufferDestroy(&buf);
universe@535 71 EXPECT_FALSE(alloc.verify());
universe@535 72 cxFree(&alloc, space);
universe@535 73 EXPECT_TRUE(alloc.verify());
universe@530 74 }
universe@530 75
universe@539 76 TEST(BufferInit, WrapSpaceAutoExtend) {
universe@539 77 CxTestingAllocator alloc;
universe@539 78 CxBuffer buf;
universe@539 79 void *space = cxMalloc(&alloc, 16);
universe@539 80 cxBufferInit(&buf, space, 16, &alloc, CX_BUFFER_AUTO_EXTEND);
universe@539 81 expect_default_flush_config(&buf);
universe@539 82 EXPECT_EQ(buf.space, space);
universe@539 83 EXPECT_EQ(buf.flags & CX_BUFFER_AUTO_EXTEND, CX_BUFFER_AUTO_EXTEND);
universe@539 84 EXPECT_EQ(buf.flags & CX_BUFFER_FREE_CONTENTS, 0);
universe@539 85 EXPECT_EQ(buf.pos, 0);
universe@539 86 EXPECT_EQ(buf.size, 0);
universe@539 87 EXPECT_EQ(buf.capacity, 16);
universe@539 88 EXPECT_EQ(buf.allocator, &alloc);
universe@539 89 cxBufferDestroy(&buf);
universe@539 90 EXPECT_FALSE(alloc.verify());
universe@539 91 cxFree(&alloc, space);
universe@539 92 EXPECT_TRUE(alloc.verify());
universe@539 93 }
universe@539 94
universe@535 95 TEST(BufferInit, WrapSpaceAutoFree) {
universe@535 96 CxTestingAllocator alloc;
universe@530 97 CxBuffer buf;
universe@535 98 void *space = cxMalloc(&alloc, 16);
universe@535 99 cxBufferInit(&buf, space, 16, &alloc, CX_BUFFER_FREE_CONTENTS);
universe@539 100 expect_default_flush_config(&buf);
universe@530 101 EXPECT_EQ(buf.space, space);
universe@530 102 EXPECT_EQ(buf.flags & CX_BUFFER_AUTO_EXTEND, 0);
universe@530 103 EXPECT_EQ(buf.flags & CX_BUFFER_FREE_CONTENTS, CX_BUFFER_FREE_CONTENTS);
universe@530 104 EXPECT_EQ(buf.pos, 0);
universe@530 105 EXPECT_EQ(buf.size, 0);
universe@530 106 EXPECT_EQ(buf.capacity, 16);
universe@535 107 EXPECT_EQ(buf.allocator, &alloc);
universe@535 108 EXPECT_FALSE(alloc.verify());
universe@530 109 cxBufferDestroy(&buf);
universe@535 110 EXPECT_TRUE(alloc.verify());
universe@530 111 }
universe@535 112
universe@535 113 TEST(BufferInit, FreshSpace) {
universe@535 114 CxTestingAllocator alloc;
universe@535 115 CxBuffer buf;
universe@535 116 cxBufferInit(&buf, nullptr, 8, &alloc, CX_BUFFER_DEFAULT);
universe@539 117 expect_default_flush_config(&buf);
universe@535 118 EXPECT_NE(buf.space, nullptr);
universe@535 119 EXPECT_EQ(buf.flags & CX_BUFFER_AUTO_EXTEND, 0);
universe@535 120 EXPECT_EQ(buf.flags & CX_BUFFER_FREE_CONTENTS, CX_BUFFER_FREE_CONTENTS);
universe@535 121 EXPECT_EQ(buf.pos, 0);
universe@535 122 EXPECT_EQ(buf.size, 0);
universe@535 123 EXPECT_EQ(buf.capacity, 8);
universe@535 124 EXPECT_EQ(buf.allocator, &alloc);
universe@535 125 EXPECT_FALSE(alloc.verify()); // space is still allocated
universe@535 126 cxBufferDestroy(&buf);
universe@535 127 EXPECT_TRUE(alloc.verify());
universe@535 128 }
universe@535 129
universe@683 130 TEST(BufferInit, OnHeap) {
universe@683 131 CxTestingAllocator alloc;
universe@683 132 CxBuffer *buf;
universe@683 133 void *space = cxMalloc(&alloc, 16);
universe@683 134 buf = cxBufferCreate(space, 16, &alloc, CX_BUFFER_FREE_CONTENTS);
universe@683 135 EXPECT_NE(buf, nullptr);
universe@683 136 expect_default_flush_config(buf);
universe@683 137 EXPECT_EQ(buf->space, space);
universe@683 138 EXPECT_EQ(buf->flags & CX_BUFFER_AUTO_EXTEND, 0);
universe@683 139 EXPECT_EQ(buf->flags & CX_BUFFER_FREE_CONTENTS, CX_BUFFER_FREE_CONTENTS);
universe@683 140 EXPECT_EQ(buf->pos, 0);
universe@683 141 EXPECT_EQ(buf->size, 0);
universe@683 142 EXPECT_EQ(buf->capacity, 16);
universe@683 143 EXPECT_EQ(buf->allocator, &alloc);
universe@683 144 cxBufferFree(buf);
universe@683 145 EXPECT_TRUE(alloc.verify());
universe@683 146 }
universe@683 147
universe@535 148 class BufferShiftFixture : public ::testing::Test {
universe@535 149 protected:
universe@535 150 void SetUp() override {
universe@535 151 ASSERT_TRUE(alloc.verify());
universe@535 152 cxBufferInit(&buf, nullptr, 16, &alloc, CX_BUFFER_DEFAULT);
universe@535 153 memcpy(buf.space, "test____________", 16);
universe@535 154 buf.capacity = 8; // purposely pretend that the buffer has less capacity s.t. we can test beyond the range
universe@535 155 buf.pos = 4;
universe@535 156 buf.size = 4;
universe@535 157 }
universe@535 158
universe@535 159 void TearDown() override {
universe@535 160 cxBufferDestroy(&buf);
universe@535 161 EXPECT_TRUE(alloc.verify());
universe@535 162 }
universe@535 163
universe@535 164 CxTestingAllocator alloc;
universe@535 165 CxBuffer buf{};
universe@535 166 };
universe@535 167
universe@535 168 class BufferShiftLeft : public BufferShiftFixture {
universe@535 169 };
universe@535 170
universe@535 171 TEST_F(BufferShiftLeft, Zero) {
universe@535 172 ASSERT_EQ(buf.pos, 4);
universe@535 173 ASSERT_EQ(buf.size, 4);
universe@535 174 int ret = cxBufferShiftLeft(&buf, 0);
universe@535 175 EXPECT_EQ(ret, 0);
universe@535 176 EXPECT_EQ(buf.pos, 4);
universe@535 177 EXPECT_EQ(buf.size, 4);
universe@535 178 EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0);
universe@535 179 }
universe@535 180
universe@547 181 TEST_F(BufferShiftLeft, ZeroOffsetInterface) {
universe@547 182 ASSERT_EQ(buf.pos, 4);
universe@547 183 ASSERT_EQ(buf.size, 4);
universe@547 184 int ret = cxBufferShift(&buf, -0);
universe@547 185 EXPECT_EQ(ret, 0);
universe@547 186 EXPECT_EQ(buf.pos, 4);
universe@547 187 EXPECT_EQ(buf.size, 4);
universe@547 188 EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0);
universe@547 189 }
universe@547 190
universe@535 191 TEST_F(BufferShiftLeft, Standard) {
universe@535 192 ASSERT_EQ(buf.pos, 4);
universe@535 193 ASSERT_EQ(buf.size, 4);
universe@535 194 int ret = cxBufferShiftLeft(&buf, 2);
universe@535 195 EXPECT_EQ(ret, 0);
universe@535 196 EXPECT_EQ(buf.pos, 2);
universe@535 197 EXPECT_EQ(buf.size, 2);
universe@535 198 EXPECT_TRUE(memcmp(buf.space, "stst________", 8) == 0);
universe@535 199 }
universe@535 200
universe@535 201 TEST_F(BufferShiftLeft, Overshift) {
universe@535 202 ASSERT_LT(buf.pos, 6);
universe@535 203 ASSERT_LT(buf.size, 6);
universe@535 204 int ret = cxBufferShiftLeft(&buf, 6);
universe@535 205 EXPECT_EQ(ret, 0);
universe@535 206 EXPECT_EQ(buf.pos, 0);
universe@535 207 EXPECT_EQ(buf.size, 0);
universe@535 208 EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0);
universe@535 209 }
universe@535 210
universe@535 211 TEST_F(BufferShiftLeft, OvershiftPosOnly) {
universe@535 212 buf.pos = 2;
universe@535 213 ASSERT_EQ(buf.size, 4);
universe@535 214 int ret = cxBufferShiftLeft(&buf, 3);
universe@535 215 EXPECT_EQ(ret, 0);
universe@535 216 EXPECT_EQ(buf.pos, 0);
universe@535 217 EXPECT_EQ(buf.size, 1);
universe@535 218 EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0);
universe@535 219 }
universe@535 220
universe@535 221 TEST_F(BufferShiftLeft, OffsetInterface) {
universe@535 222 buf.pos = 3;
universe@535 223 ASSERT_EQ(buf.size, 4);
universe@535 224 int ret = cxBufferShift(&buf, -2);
universe@535 225 EXPECT_EQ(ret, 0);
universe@535 226 EXPECT_EQ(buf.pos, 1);
universe@535 227 EXPECT_EQ(buf.size, 2);
universe@535 228 EXPECT_TRUE(memcmp(buf.space, "stst________", 8) == 0);
universe@535 229 }
universe@535 230
universe@535 231 class BufferShiftRight : public BufferShiftFixture {
universe@535 232 };
universe@535 233
universe@535 234 TEST_F(BufferShiftRight, Zero) {
universe@535 235 ASSERT_EQ(buf.pos, 4);
universe@535 236 ASSERT_EQ(buf.size, 4);
universe@535 237 int ret = cxBufferShiftRight(&buf, 0);
universe@535 238 EXPECT_EQ(ret, 0);
universe@535 239 EXPECT_EQ(buf.pos, 4);
universe@535 240 EXPECT_EQ(buf.size, 4);
universe@535 241 EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0);
universe@535 242 }
universe@535 243
universe@547 244 TEST_F(BufferShiftRight, ZeroOffsetInterface) {
universe@547 245 ASSERT_EQ(buf.pos, 4);
universe@547 246 ASSERT_EQ(buf.size, 4);
universe@547 247 int ret = cxBufferShift(&buf, +0);
universe@547 248 EXPECT_EQ(ret, 0);
universe@547 249 EXPECT_EQ(buf.pos, 4);
universe@547 250 EXPECT_EQ(buf.size, 4);
universe@547 251 EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0);
universe@547 252 }
universe@547 253
universe@535 254 TEST_F(BufferShiftRight, Standard) {
universe@535 255 ASSERT_EQ(buf.pos, 4);
universe@535 256 ASSERT_EQ(buf.size, 4);
universe@535 257 int ret = cxBufferShiftRight(&buf, 3);
universe@535 258 EXPECT_EQ(ret, 0);
universe@535 259 EXPECT_EQ(buf.pos, 7);
universe@535 260 EXPECT_EQ(buf.size, 7);
universe@535 261 EXPECT_TRUE(memcmp(buf.space, "testest_____", 8) == 0);
universe@535 262 }
universe@535 263
universe@535 264 TEST_F(BufferShiftRight, OvershiftDiscard) {
universe@535 265 ASSERT_EQ(buf.pos, 4);
universe@535 266 ASSERT_EQ(buf.size, 4);
universe@535 267 ASSERT_EQ(buf.capacity, 8);
universe@535 268 int ret = cxBufferShiftRight(&buf, 6);
universe@535 269 EXPECT_EQ(ret, 0);
universe@535 270 EXPECT_EQ(buf.pos, 8);
universe@535 271 EXPECT_EQ(buf.size, 8);
universe@535 272 EXPECT_EQ(buf.capacity, 8);
universe@535 273 EXPECT_TRUE(memcmp(buf.space, "test__te____", 8) == 0);
universe@535 274 }
universe@535 275
universe@535 276 TEST_F(BufferShiftRight, OvershiftExtend) {
universe@535 277 ASSERT_EQ(buf.pos, 4);
universe@535 278 ASSERT_EQ(buf.size, 4);
universe@535 279 ASSERT_EQ(buf.capacity, 8);
universe@535 280 buf.flags |= CX_BUFFER_AUTO_EXTEND;
universe@535 281 int ret = cxBufferShiftRight(&buf, 6);
universe@535 282 EXPECT_EQ(ret, 0);
universe@535 283 EXPECT_EQ(buf.pos, 10);
universe@535 284 EXPECT_EQ(buf.size, 10);
universe@535 285 EXPECT_GE(buf.capacity, 10);
universe@535 286 EXPECT_TRUE(memcmp(buf.space, "test__test__", 8) == 0);
universe@535 287 }
universe@535 288
universe@535 289 TEST_F(BufferShiftRight, OffsetInterface) {
universe@535 290 buf.pos = 3;
universe@535 291 ASSERT_EQ(buf.size, 4);
universe@535 292 int ret = cxBufferShift(&buf, 2);
universe@535 293 EXPECT_EQ(ret, 0);
universe@535 294 EXPECT_EQ(buf.pos, 5);
universe@535 295 EXPECT_EQ(buf.size, 6);
universe@535 296 EXPECT_TRUE(memcmp(buf.space, "tetest______", 8) == 0);
universe@535 297 }
universe@535 298
universe@535 299 TEST(BufferMinimumCapacity, Sufficient) {
universe@535 300 CxTestingAllocator alloc;
universe@535 301 auto space = cxMalloc(&alloc, 8);
universe@535 302 CxBuffer buf;
universe@535 303 cxBufferInit(&buf, space, 8, &alloc, CX_BUFFER_FREE_CONTENTS);
universe@535 304 memcpy(space, "Testing", 8);
universe@535 305 buf.size = 8;
universe@535 306 cxBufferMinimumCapacity(&buf, 6);
universe@535 307 EXPECT_EQ(buf.capacity, 8);
universe@535 308 EXPECT_EQ(buf.size, 8);
universe@535 309 EXPECT_TRUE(memcmp(buf.space, "Testing", 8) == 0);
universe@535 310 cxBufferDestroy(&buf);
universe@535 311 EXPECT_TRUE(alloc.verify());
universe@535 312 }
universe@535 313
universe@535 314 TEST(BufferMinimumCapacity, Extend) {
universe@535 315 CxTestingAllocator alloc;
universe@535 316 auto space = cxMalloc(&alloc, 8);
universe@535 317 CxBuffer buf;
universe@535 318 cxBufferInit(&buf, space, 8, &alloc, CX_BUFFER_FREE_CONTENTS); // NO auto extend!
universe@535 319 memcpy(space, "Testing", 8);
universe@535 320 buf.size = 8;
universe@535 321 cxBufferMinimumCapacity(&buf, 16);
universe@535 322 EXPECT_EQ(buf.capacity, 16);
universe@535 323 EXPECT_EQ(buf.size, 8);
universe@535 324 EXPECT_TRUE(memcmp(buf.space, "Testing", 8) == 0);
universe@535 325 cxBufferDestroy(&buf);
universe@535 326 EXPECT_TRUE(alloc.verify());
universe@535 327 }
universe@536 328
universe@536 329 TEST(BufferClear, Test) {
universe@536 330 char space[16];
universe@536 331 strcpy(space, "clear test");
universe@536 332 CxBuffer buf;
universe@536 333 cxBufferInit(&buf, space, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
universe@536 334 ASSERT_EQ(buf.size, 0);
universe@536 335 // only clear the used part of the buffer
universe@536 336 cxBufferClear(&buf);
universe@536 337 EXPECT_EQ(memcmp(space, "clear test", 10), 0);
universe@536 338 buf.size = 5;
universe@536 339 buf.pos = 3;
universe@536 340 cxBufferClear(&buf);
universe@536 341 EXPECT_EQ(memcmp(space, "\0\0\0\0\0 test", 10), 0);
universe@536 342 EXPECT_EQ(buf.size, 0);
universe@536 343 EXPECT_EQ(buf.pos, 0);
universe@538 344 cxBufferDestroy(&buf);
universe@536 345 }
universe@538 346
universe@538 347 class BufferWrite : public ::testing::Test {
universe@538 348 protected:
universe@545 349 CxBuffer buf{}, target{};
universe@538 350
universe@538 351 void SetUp() override {
universe@545 352 cxBufferInit(&target, nullptr, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND);
universe@538 353 cxBufferInit(&buf, nullptr, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
universe@538 354 buf.capacity = 8; // artificially reduce capacity to check OOB writes
universe@538 355 memset(buf.space, 0, 16);
universe@538 356 memcpy(buf.space, "prep", 4);
universe@538 357 buf.size = buf.pos = 4;
universe@538 358 }
universe@538 359
universe@538 360 void TearDown() override {
universe@538 361 cxBufferDestroy(&buf);
universe@545 362 cxBufferDestroy(&target);
universe@545 363 }
universe@545 364
universe@545 365 void enableFlushing() {
universe@545 366 buf.flush_target = &target;
universe@545 367 buf.flush_func = reinterpret_cast<cx_write_func>(cxBufferWrite);
universe@545 368 buf.flush_blkmax = 1;
universe@538 369 }
universe@538 370 };
universe@538 371
universe@567 372 static size_t mock_write_limited_rate(
universe@567 373 void const *ptr,
universe@567 374 size_t size,
universe@567 375 __attribute__((unused)) size_t nitems,
universe@567 376 CxBuffer *buffer
universe@567 377 ) {
universe@567 378 // simulate limited target drain capacity
universe@567 379 static bool full = false;
universe@567 380 if (full) {
universe@567 381 full = false;
universe@567 382 return 0;
universe@567 383 } else {
universe@567 384 full = true;
universe@567 385 return cxBufferWrite(ptr, size, nitems > 2 ? 2 : nitems, buffer);
universe@567 386 }
universe@567 387 }
universe@567 388
universe@538 389 TEST_F(BufferWrite, SizeOneFit) {
universe@538 390 const char *data = "test";
universe@538 391 ASSERT_EQ(buf.capacity, 8);
universe@538 392 ASSERT_EQ(buf.pos, 4);
universe@541 393 ASSERT_EQ(buf.size, 4);
universe@538 394 size_t written = cxBufferWrite(data, 1, 4, &buf);
universe@538 395 EXPECT_EQ(written, 4);
universe@538 396 EXPECT_EQ(buf.size, 8);
universe@538 397 EXPECT_EQ(buf.pos, 8);
universe@538 398 EXPECT_EQ(buf.capacity, 8);
universe@538 399 EXPECT_EQ(memcmp(buf.space, "preptest", 8), 0);
universe@538 400 }
universe@538 401
universe@538 402 TEST_F(BufferWrite, SizeOneDiscard) {
universe@538 403 const char *data = "testing";
universe@538 404 ASSERT_EQ(buf.capacity, 8);
universe@538 405 ASSERT_EQ(buf.pos, 4);
universe@541 406 ASSERT_EQ(buf.size, 4);
universe@538 407 size_t written = cxBufferWrite(data, 1, 7, &buf);
universe@538 408 EXPECT_EQ(written, 4);
universe@538 409 EXPECT_EQ(buf.size, 8);
universe@538 410 EXPECT_EQ(buf.pos, 8);
universe@538 411 EXPECT_EQ(buf.capacity, 8);
universe@538 412 EXPECT_EQ(memcmp(buf.space, "preptest\0", 9), 0);
universe@538 413 }
universe@538 414
universe@538 415 TEST_F(BufferWrite, SizeOneExtend) {
universe@538 416 buf.flags |= CX_BUFFER_AUTO_EXTEND;
universe@538 417 const char *data = "testing";
universe@538 418 ASSERT_EQ(buf.capacity, 8);
universe@538 419 ASSERT_EQ(buf.pos, 4);
universe@541 420 ASSERT_EQ(buf.size, 4);
universe@538 421 size_t written = cxBufferWrite(data, 1, 7, &buf);
universe@538 422 EXPECT_EQ(written, 7);
universe@538 423 EXPECT_EQ(buf.size, 11);
universe@538 424 EXPECT_EQ(buf.pos, 11);
universe@538 425 EXPECT_GE(buf.capacity, 11);
universe@538 426 EXPECT_EQ(memcmp(buf.space, "preptesting", 11), 0);
universe@538 427 }
universe@538 428
universe@538 429 TEST_F(BufferWrite, MultibyteFit) {
universe@541 430 const char *data = "test";
universe@541 431 ASSERT_EQ(buf.capacity, 8);
universe@541 432 ASSERT_EQ(buf.pos, 4);
universe@541 433 ASSERT_EQ(buf.size, 4);
universe@541 434 size_t written = cxBufferWrite(data, 2, 2, &buf);
universe@541 435 EXPECT_EQ(written, 2);
universe@541 436 EXPECT_EQ(buf.size, 8);
universe@541 437 EXPECT_EQ(buf.pos, 8);
universe@541 438 EXPECT_EQ(buf.capacity, 8);
universe@541 439 EXPECT_EQ(memcmp(buf.space, "preptest", 8), 0);
universe@538 440 }
universe@538 441
universe@538 442 TEST_F(BufferWrite, MultibyteDiscard) {
universe@542 443 const char *data = "testing";
universe@541 444 ASSERT_EQ(buf.capacity, 8);
universe@541 445 ASSERT_EQ(buf.size, 4);
universe@541 446 buf.pos = 3;
universe@542 447 size_t written = cxBufferWrite(data, 2, 4, &buf);
universe@538 448 // remember: whole elements are discarded if they do not fit
universe@541 449 EXPECT_EQ(written, 2);
universe@541 450 EXPECT_EQ(buf.size, 7);
universe@541 451 EXPECT_EQ(buf.pos, 7);
universe@541 452 EXPECT_EQ(buf.capacity, 8);
universe@541 453 EXPECT_EQ(memcmp(buf.space, "pretest\0", 8), 0);
universe@538 454 }
universe@538 455
universe@538 456 TEST_F(BufferWrite, MultibyteExtend) {
universe@541 457 buf.flags |= CX_BUFFER_AUTO_EXTEND;
universe@541 458 const char *data = "tester";
universe@541 459 ASSERT_EQ(buf.capacity, 8);
universe@541 460 ASSERT_EQ(buf.size, 4);
universe@541 461 buf.pos = 3;
universe@541 462 size_t written = cxBufferWrite(data, 2, 3, &buf);
universe@541 463 // remember: whole elements are discarded if they do not fit
universe@541 464 EXPECT_EQ(written, 3);
universe@541 465 EXPECT_EQ(buf.size, 9);
universe@541 466 EXPECT_EQ(buf.pos, 9);
universe@541 467 EXPECT_GE(buf.capacity, 9);
universe@566 468 EXPECT_EQ(memcmp(buf.space, "pretester", 9), 0);
universe@538 469 }
universe@538 470
universe@538 471 TEST_F(BufferWrite, PutcWrapperFit) {
universe@541 472 ASSERT_EQ(buf.capacity, 8);
universe@541 473 ASSERT_EQ(buf.pos, 4);
universe@541 474 ASSERT_EQ(buf.size, 4);
universe@565 475 int c = cxBufferPut(&buf, 0x200 | 'a');
universe@541 476 EXPECT_EQ(c, 'a');
universe@541 477 EXPECT_EQ(buf.size, 5);
universe@541 478 EXPECT_EQ(buf.pos, 5);
universe@541 479 EXPECT_EQ(buf.capacity, 8);
universe@541 480 EXPECT_EQ(memcmp(buf.space, "prepa\0", 6), 0);
universe@538 481 }
universe@538 482
universe@538 483 TEST_F(BufferWrite, PutcWrapperDiscard) {
universe@541 484 ASSERT_EQ(buf.capacity, 8);
universe@541 485 ASSERT_EQ(buf.size, 4);
universe@541 486 buf.pos = 8;
universe@565 487 int c = cxBufferPut(&buf, 0x200 | 'a');
universe@541 488 EXPECT_EQ(c, EOF);
universe@541 489 EXPECT_EQ(buf.size, 4);
universe@541 490 EXPECT_EQ(buf.pos, 8);
universe@541 491 EXPECT_EQ(buf.capacity, 8);
universe@541 492 EXPECT_EQ(memcmp(buf.space, "prep\0\0\0\0\0", 9), 0);
universe@538 493 }
universe@538 494
universe@538 495 TEST_F(BufferWrite, PutcWrapperExtend) {
universe@541 496 buf.flags |= CX_BUFFER_AUTO_EXTEND;
universe@541 497 ASSERT_EQ(buf.capacity, 8);
universe@541 498 ASSERT_EQ(buf.size, 4);
universe@541 499 buf.pos = 8;
universe@565 500 int c = cxBufferPut(&buf, 0x200 | 'a');
universe@541 501 EXPECT_EQ(c, 'a');
universe@541 502 EXPECT_EQ(buf.size, 9);
universe@541 503 EXPECT_EQ(buf.pos, 9);
universe@541 504 EXPECT_GE(buf.capacity, 9);
universe@566 505 EXPECT_EQ(memcmp(buf.space, "prep\0\0\0\0a", 9), 0);
universe@538 506 }
universe@538 507
universe@538 508 TEST_F(BufferWrite, PutStringWrapperFit) {
universe@541 509 const char *data = "test";
universe@541 510 ASSERT_EQ(buf.capacity, 8);
universe@541 511 ASSERT_EQ(buf.pos, 4);
universe@541 512 ASSERT_EQ(buf.size, 4);
universe@541 513 size_t written = cxBufferPutString(&buf, data);
universe@541 514 EXPECT_EQ(written, 4);
universe@541 515 EXPECT_EQ(buf.size, 8);
universe@541 516 EXPECT_EQ(buf.pos, 8);
universe@541 517 EXPECT_EQ(buf.capacity, 8);
universe@541 518 EXPECT_EQ(memcmp(buf.space, "preptest", 8), 0);
universe@538 519 }
universe@538 520
universe@538 521 TEST_F(BufferWrite, PutStringWrapperDiscard) {
universe@541 522 const char *data = "testing";
universe@541 523 ASSERT_EQ(buf.capacity, 8);
universe@541 524 ASSERT_EQ(buf.pos, 4);
universe@541 525 ASSERT_EQ(buf.size, 4);
universe@541 526 size_t written = cxBufferPutString(&buf, data);
universe@541 527 EXPECT_EQ(written, 4);
universe@541 528 EXPECT_EQ(buf.size, 8);
universe@541 529 EXPECT_EQ(buf.pos, 8);
universe@541 530 EXPECT_EQ(buf.capacity, 8);
universe@541 531 EXPECT_EQ(memcmp(buf.space, "preptest\0", 9), 0);
universe@538 532 }
universe@538 533
universe@538 534 TEST_F(BufferWrite, PutStringWrapperExtend) {
universe@541 535 buf.flags |= CX_BUFFER_AUTO_EXTEND;
universe@541 536 const char *data = "testing";
universe@541 537 ASSERT_EQ(buf.capacity, 8);
universe@541 538 ASSERT_EQ(buf.pos, 4);
universe@541 539 ASSERT_EQ(buf.size, 4);
universe@541 540 size_t written = cxBufferPutString(&buf, data);
universe@541 541 EXPECT_EQ(written, 7);
universe@541 542 EXPECT_EQ(buf.size, 11);
universe@541 543 EXPECT_EQ(buf.pos, 11);
universe@541 544 EXPECT_GE(buf.capacity, 11);
universe@541 545 EXPECT_EQ(memcmp(buf.space, "preptesting", 11), 0);
universe@541 546 }
universe@538 547
universe@541 548 TEST_F(BufferWrite, MultOverflow) {
universe@541 549 const char *data = "testing";
universe@541 550 ASSERT_EQ(buf.capacity, 8);
universe@541 551 ASSERT_EQ(buf.pos, 4);
universe@541 552 ASSERT_EQ(buf.size, 4);
universe@541 553 size_t written = cxBufferWrite(data, 8, SIZE_MAX / 4, &buf);
universe@541 554 EXPECT_EQ(written, 0);
universe@541 555 EXPECT_EQ(buf.capacity, 8);
universe@541 556 EXPECT_EQ(buf.pos, 4);
universe@541 557 EXPECT_EQ(buf.size, 4);
universe@541 558 EXPECT_EQ(memcmp(buf.space, "prep\0", 5), 0);
universe@538 559 }
universe@541 560
universe@541 561 TEST_F(BufferWrite, MaxCapaOverflow) {
universe@541 562 buf.flags |= CX_BUFFER_AUTO_EXTEND;
universe@541 563 const char *data = "testing";
universe@541 564 ASSERT_EQ(buf.capacity, 8);
universe@541 565 ASSERT_EQ(buf.pos, 4);
universe@541 566 ASSERT_EQ(buf.size, 4);
universe@541 567 size_t written = cxBufferWrite(data, 1, SIZE_MAX - 2, &buf);
universe@541 568 EXPECT_EQ(written, 0);
universe@541 569 EXPECT_EQ(buf.capacity, 8);
universe@541 570 EXPECT_EQ(buf.pos, 4);
universe@541 571 EXPECT_EQ(buf.size, 4);
universe@541 572 EXPECT_EQ(memcmp(buf.space, "prep\0", 5), 0);
universe@541 573 }
universe@541 574
universe@541 575 TEST_F(BufferWrite, OnlyOverwrite) {
universe@541 576 buf.flags |= CX_BUFFER_AUTO_EXTEND;
universe@541 577 ASSERT_EQ(buf.capacity, 8);
universe@541 578 memcpy(buf.space, "preptest", 8);
universe@541 579 buf.pos = 3;
universe@541 580 buf.size = 8;
universe@541 581 size_t written = cxBufferWrite("XXX", 2, 2, &buf);
universe@541 582 EXPECT_EQ(written, 2);
universe@541 583 EXPECT_EQ(buf.capacity, 8);
universe@541 584 EXPECT_EQ(buf.size, 8);
universe@541 585 EXPECT_EQ(buf.pos, 7);
universe@541 586 EXPECT_EQ(memcmp(buf.space, "preXXX\0t", 8), 0);
universe@541 587 }
universe@545 588
universe@545 589 TEST_F(BufferWrite, FlushAtCapacity) {
universe@545 590 enableFlushing();
universe@545 591 ASSERT_EQ(buf.capacity, 8);
universe@545 592 ASSERT_EQ(buf.pos, 4);
universe@545 593 size_t written = cxBufferWrite("foo", 1, 3, &buf);
universe@545 594 EXPECT_EQ(written, 3);
universe@545 595 ASSERT_EQ(buf.pos, 7);
universe@545 596 ASSERT_EQ(buf.size, 7);
universe@545 597 ASSERT_EQ(target.pos, 0);
universe@545 598 ASSERT_EQ(target.size, 0);
universe@545 599 written = cxBufferWrite("hello", 1, 5, &buf);
universe@545 600 EXPECT_EQ(written, 5);
universe@545 601 EXPECT_EQ(buf.pos, 0);
universe@545 602 EXPECT_EQ(buf.size, 0);
universe@545 603 EXPECT_EQ(buf.capacity, 8);
universe@545 604 EXPECT_EQ(target.pos, 12);
universe@545 605 ASSERT_EQ(target.size, 12);
universe@545 606 EXPECT_EQ(memcmp(target.space, "prepfoohello", 12), 0);
universe@545 607 }
universe@546 608
universe@546 609 TEST_F(BufferWrite, FlushAtThreshold) {
universe@546 610 enableFlushing();
universe@546 611 buf.flush_threshold = 12;
universe@546 612 buf.flags |= CX_BUFFER_AUTO_EXTEND;
universe@546 613 ASSERT_EQ(buf.capacity, 8);
universe@546 614 ASSERT_EQ(buf.pos, 4);
universe@546 615 size_t written = cxBufferWrite("foobar", 1, 6, &buf);
universe@546 616 EXPECT_EQ(written, 6);
universe@546 617 ASSERT_EQ(buf.pos, 10);
universe@546 618 ASSERT_EQ(buf.size, 10);
universe@546 619 ASSERT_GE(buf.capacity, 10);
universe@546 620 ASSERT_LE(buf.capacity, 12);
universe@546 621 ASSERT_EQ(target.pos, 0);
universe@546 622 ASSERT_EQ(target.size, 0);
universe@546 623 written = cxBufferWrite("hello", 1, 5, &buf);
universe@546 624 EXPECT_EQ(written, 5);
universe@546 625 EXPECT_EQ(buf.pos, 0);
universe@546 626 EXPECT_EQ(buf.size, 0);
universe@546 627 EXPECT_LE(buf.capacity, 12);
universe@546 628 EXPECT_EQ(target.pos, 15);
universe@546 629 ASSERT_EQ(target.size, 15);
universe@546 630 EXPECT_EQ(memcmp(target.space, "prepfoobarhello", 15), 0);
universe@546 631 }
universe@547 632
universe@567 633 TEST_F(BufferWrite, FlushRateLimited) {
universe@567 634 enableFlushing();
universe@567 635 // limit the rate of the flush function and the capacity of the target
universe@567 636 target.capacity = 16;
universe@567 637 target.flags &= ~CX_BUFFER_AUTO_EXTEND;
universe@567 638 buf.flush_func = (cx_write_func) mock_write_limited_rate;
universe@567 639 ASSERT_EQ(buf.capacity, 8);
universe@567 640 ASSERT_EQ(buf.pos, 4);
universe@567 641 size_t written = cxBufferWrite("foo", 1, 3, &buf);
universe@567 642 EXPECT_EQ(written, 3);
universe@567 643 ASSERT_EQ(buf.pos, 7);
universe@567 644 ASSERT_EQ(buf.size, 7);
universe@567 645 ASSERT_EQ(target.pos, 0);
universe@567 646 ASSERT_EQ(target.size, 0);
universe@567 647 written = cxBufferWrite("hello, world!", 1, 13, &buf);
universe@567 648 // " world!" fits into this buffer, the remaining stuff is flushed out
universe@567 649 EXPECT_EQ(written, 13);
universe@567 650 EXPECT_EQ(buf.pos, 7);
universe@567 651 EXPECT_EQ(buf.size, 7);
universe@567 652 EXPECT_EQ(buf.capacity, 8);
universe@567 653 EXPECT_EQ(memcmp(buf.space, " world!", 7), 0);
universe@567 654 EXPECT_EQ(target.pos, 13);
universe@567 655 ASSERT_EQ(target.size, 13);
universe@567 656 EXPECT_EQ(target.capacity, 16);
universe@567 657 EXPECT_EQ(memcmp(target.space, "prepfoohello,", 13), 0);
universe@567 658 }
universe@567 659
universe@548 660 class BufferSeek : public BufferFixture {
universe@547 661 };
universe@547 662
universe@547 663 TEST_F(BufferSeek, SetZero) {
universe@547 664 int result = cxBufferSeek(&buf, 0, SEEK_SET);
universe@547 665 EXPECT_EQ(result, 0);
universe@547 666 EXPECT_EQ(buf.pos, 0);
universe@547 667 }
universe@547 668
universe@547 669 TEST_F(BufferSeek, SetValid) {
universe@547 670 int result = cxBufferSeek(&buf, 5, SEEK_SET);
universe@547 671 EXPECT_EQ(result, 0);
universe@547 672 EXPECT_EQ(buf.pos, 5);
universe@547 673 }
universe@547 674
universe@547 675 TEST_F(BufferSeek, SetInvalid) {
universe@547 676 ASSERT_EQ(buf.pos, 3);
universe@547 677 int result = cxBufferSeek(&buf, 6, SEEK_SET);
universe@547 678 EXPECT_NE(result, 0);
universe@547 679 EXPECT_EQ(buf.pos, 3);
universe@547 680 }
universe@547 681
universe@547 682 TEST_F(BufferSeek, CurZero) {
universe@547 683 ASSERT_EQ(buf.pos, 3);
universe@547 684 int result = cxBufferSeek(&buf, 0, SEEK_CUR);
universe@547 685 EXPECT_EQ(result, 0);
universe@547 686 EXPECT_EQ(buf.pos, 3);
universe@547 687 }
universe@547 688
universe@547 689 TEST_F(BufferSeek, CurValidPositive) {
universe@547 690 ASSERT_EQ(buf.pos, 3);
universe@547 691 int result = cxBufferSeek(&buf, 2, SEEK_CUR);
universe@547 692 EXPECT_EQ(result, 0);
universe@547 693 EXPECT_EQ(buf.pos, 5);
universe@547 694 }
universe@547 695
universe@547 696 TEST_F(BufferSeek, CurValidNegative) {
universe@547 697 ASSERT_EQ(buf.pos, 3);
universe@547 698 int result = cxBufferSeek(&buf, -3, SEEK_CUR);
universe@547 699 EXPECT_EQ(result, 0);
universe@547 700 EXPECT_EQ(buf.pos, 0);
universe@547 701 }
universe@547 702
universe@547 703 TEST_F(BufferSeek, CurInvalidPositive) {
universe@547 704 ASSERT_EQ(buf.pos, 3);
universe@547 705 int result = cxBufferSeek(&buf, 3, SEEK_CUR);
universe@547 706 EXPECT_NE(result, 0);
universe@547 707 EXPECT_EQ(buf.pos, 3);
universe@547 708 }
universe@547 709
universe@547 710 TEST_F(BufferSeek, CurInvalidNegative) {
universe@547 711 ASSERT_EQ(buf.pos, 3);
universe@547 712 int result = cxBufferSeek(&buf, -4, SEEK_CUR);
universe@547 713 EXPECT_NE(result, 0);
universe@547 714 EXPECT_EQ(buf.pos, 3);
universe@547 715 }
universe@547 716
universe@547 717 TEST_F(BufferSeek, EndZero) {
universe@547 718 ASSERT_EQ(buf.size, 6);
universe@547 719 int result = cxBufferSeek(&buf, 0, SEEK_END);
universe@547 720 // the (past-the-)end position is always invalid
universe@547 721 EXPECT_NE(result, 0);
universe@547 722 EXPECT_EQ(buf.pos, 3);
universe@547 723 }
universe@547 724
universe@547 725 TEST_F(BufferSeek, EndValid) {
universe@547 726 ASSERT_EQ(buf.size, 6);
universe@547 727 int result = cxBufferSeek(&buf, -6, SEEK_END);
universe@547 728 EXPECT_EQ(result, 0);
universe@547 729 EXPECT_EQ(buf.pos, 0);
universe@547 730 }
universe@547 731
universe@547 732 TEST_F(BufferSeek, EndInvalid) {
universe@547 733 ASSERT_EQ(buf.size, 6);
universe@547 734 int result = cxBufferSeek(&buf, 1, SEEK_END);
universe@547 735 EXPECT_NE(result, 0);
universe@547 736 EXPECT_EQ(buf.pos, 3);
universe@547 737 }
universe@547 738
universe@547 739 TEST_F(BufferSeek, WhenceInvalid) {
universe@547 740 ASSERT_EQ(buf.size, 6);
universe@547 741 ASSERT_EQ(buf.pos, 3);
universe@547 742 int result = cxBufferSeek(&buf, 2, 9000);
universe@547 743 EXPECT_NE(result, 0);
universe@547 744 EXPECT_EQ(buf.size, 6);
universe@547 745 EXPECT_EQ(buf.pos, 3);
universe@548 746 }
universe@548 747
universe@548 748 class BufferEof : public BufferFixture {
universe@548 749 };
universe@548 750
universe@548 751 TEST_F(BufferEof, Reached) {
universe@548 752 buf.pos = buf.size;
universe@548 753 EXPECT_TRUE(cxBufferEof(&buf));
universe@548 754 buf.pos = buf.size - 1;
universe@548 755 ASSERT_FALSE(cxBufferEof(&buf));
universe@548 756 cxBufferPut(&buf, 'a');
universe@548 757 EXPECT_TRUE(cxBufferEof(&buf));
universe@548 758 }
universe@548 759
universe@548 760 TEST_F(BufferEof, NotReached) {
universe@548 761 buf.pos = buf.size - 1;
universe@548 762 EXPECT_FALSE(cxBufferEof(&buf));
universe@548 763 buf.pos = 0;
universe@548 764 cxBufferWrite("test", 1, 5, &buf);
universe@548 765 EXPECT_FALSE(cxBufferEof(&buf));
universe@548 766 }
universe@568 767
universe@568 768 class BufferRead : public ::testing::Test {
universe@568 769 protected:
universe@568 770 CxBuffer buf{};
universe@568 771
universe@568 772 void SetUp() override {
universe@568 773 cxBufferInit(&buf, nullptr, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT);
universe@568 774 buf.capacity = 8; // artificially reduce capacity to check OOB writes
universe@568 775 memset(buf.space, 0, 16);
universe@568 776 memcpy(buf.space, "some data", 9);
universe@568 777 buf.size = 9;
universe@568 778 }
universe@568 779
universe@568 780 void TearDown() override {
universe@568 781 cxBufferDestroy(&buf);
universe@568 782 }
universe@568 783 };
universe@568 784
universe@568 785 TEST_F(BufferRead, GetByte) {
universe@568 786 buf.pos = 2;
universe@568 787 EXPECT_EQ(cxBufferGet(&buf), 'm');
universe@568 788 EXPECT_EQ(cxBufferGet(&buf), 'e');
universe@568 789 EXPECT_EQ(cxBufferGet(&buf), ' ');
universe@568 790 EXPECT_EQ(cxBufferGet(&buf), 'd');
universe@568 791 EXPECT_EQ(buf.pos, 6);
universe@568 792 }
universe@568 793
universe@568 794 TEST_F(BufferRead, GetEof) {
universe@568 795 buf.pos = buf.size;
universe@568 796 EXPECT_EQ(cxBufferGet(&buf), EOF);
universe@568 797 }
universe@569 798
universe@569 799 TEST_F(BufferRead, ReadWithinBounds) {
universe@569 800 buf.pos = 2;
universe@569 801 char target[4];
universe@569 802 auto read = cxBufferRead(&target, 1, 4, &buf);
universe@569 803 ASSERT_EQ(read, 4);
universe@569 804 EXPECT_EQ(memcmp(&target, "me d", 4), 0);
universe@569 805 EXPECT_EQ(buf.pos, 6);
universe@569 806 }
universe@569 807
universe@569 808 TEST_F(BufferRead, ReadOutOfBounds) {
universe@569 809 buf.pos = 6;
universe@569 810 char target[4];
universe@569 811 auto read = cxBufferRead(&target, 1, 4, &buf);
universe@569 812 ASSERT_EQ(read, 3);
universe@569 813 EXPECT_EQ(memcmp(&target, "ata", 3), 0);
universe@569 814 EXPECT_EQ(buf.pos, 9);
universe@569 815 }
universe@569 816
universe@569 817 TEST_F(BufferRead, ReadOutOfBoundsMultibyte) {
universe@569 818 buf.pos = 6;
universe@569 819 char target[4];
universe@569 820 target[2] = '\0';
universe@569 821 auto read = cxBufferRead(&target, 2, 2, &buf);
universe@569 822 ASSERT_EQ(read, 1);
universe@569 823 EXPECT_EQ(memcmp(&target, "at\0", 3), 0);
universe@569 824 EXPECT_EQ(buf.pos, 8);
universe@569 825 }
universe@569 826
universe@569 827 TEST_F(BufferRead, ReadEof) {
universe@569 828 buf.pos = 9;
universe@569 829 char target[4];
universe@569 830 auto read = cxBufferRead(&target, 1, 1, &buf);
universe@569 831 ASSERT_EQ(read, 0);
universe@569 832 EXPECT_EQ(buf.pos, 9);
universe@569 833 }

mercurial