Tue, 07 Feb 2023 21:55:37 +0100
rename test directory to avoid name clash with Makefile target
1.1 --- a/CMakeLists.txt Tue Feb 07 21:53:06 2023 +0100 1.2 +++ b/CMakeLists.txt Tue Feb 07 21:55:37 2023 +0100 1.3 @@ -15,7 +15,7 @@ 1.4 1.5 # Tests 1.6 enable_testing() 1.7 -add_subdirectory(test) 1.8 +add_subdirectory(tests) 1.9 1.10 # Web Documentation 1.11 add_subdirectory(docs/src)
2.1 --- a/test/.clang-tidy Tue Feb 07 21:53:06 2023 +0100 2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 2.3 @@ -1,2 +0,0 @@ 2.4 -# Disable static initialization warning for test code 2.5 -Checks: '-cert-err58-cpp'
3.1 --- a/test/CMakeLists.txt Tue Feb 07 21:53:06 2023 +0100 3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 3.3 @@ -1,32 +0,0 @@ 3.4 -# Load Google Test Framework 3.5 -set(CMAKE_CXX_STANDARD 17) 3.6 - 3.7 -include(FetchContent) 3.8 -FetchContent_Declare( 3.9 - googletest 3.10 - GIT_REPOSITORY https://github.com/google/googletest.git 3.11 - GIT_TAG e2239ee6043f73722e7aa812a459f54a28552929 # release 1.11.0 3.12 -) 3.13 -# For Windows: Prevent overriding the parent project's compiler/linker settings 3.14 -set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 3.15 -FetchContent_MakeAvailable(googletest) 3.16 -include(GoogleTest) 3.17 -message(STATUS "Google Test made available") 3.18 - 3.19 -add_executable(ucxtest 3.20 - test_utils.cpp 3.21 - test_allocator.cpp 3.22 - test_compare.cpp 3.23 - test_string.cpp 3.24 - test_buffer.cpp 3.25 - test_list.cpp 3.26 - test_tree.cpp 3.27 - test_hash_key.cpp 3.28 - test_map.cpp 3.29 - test_basic_mempool.cpp 3.30 - test_printf.cpp 3.31 - selftest.cpp 3.32 - util_allocator.cpp 3.33 - ) 3.34 -target_link_libraries(ucxtest PRIVATE ucx_static gtest_main) 3.35 -gtest_discover_tests(ucxtest)
4.1 --- a/test/selftest.cpp Tue Feb 07 21:53:06 2023 +0100 4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 4.3 @@ -1,39 +0,0 @@ 4.4 -/* 4.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 4.6 - * 4.7 - * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 4.8 - * 4.9 - * Redistribution and use in source and binary forms, with or without 4.10 - * modification, are permitted provided that the following conditions are met: 4.11 - * 4.12 - * 1. Redistributions of source code must retain the above copyright 4.13 - * notice, this list of conditions and the following disclaimer. 4.14 - * 4.15 - * 2. Redistributions in binary form must reproduce the above copyright 4.16 - * notice, this list of conditions and the following disclaimer in the 4.17 - * documentation and/or other materials provided with the distribution. 4.18 - * 4.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 4.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 4.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 4.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 4.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 4.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 4.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 4.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4.29 - * POSSIBILITY OF SUCH DAMAGE. 4.30 - */ 4.31 - 4.32 -#include <gtest/gtest.h> 4.33 -#include <cx/common.h> 4.34 - 4.35 -TEST(SelfTest, BasicAssertion) { 4.36 - EXPECT_EQ(7 * 6, 42); 4.37 -} 4.38 - 4.39 -TEST(SelfTest, UcxVersion) { 4.40 - EXPECT_GE(UCX_VERSION_MAJOR, 3); 4.41 - EXPECT_GE(UCX_VERSION, 3 << 16); 4.42 -}
5.1 --- a/test/test_allocator.cpp Tue Feb 07 21:53:06 2023 +0100 5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 5.3 @@ -1,96 +0,0 @@ 5.4 -/* 5.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 5.6 - * 5.7 - * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 5.8 - * 5.9 - * Redistribution and use in source and binary forms, with or without 5.10 - * modification, are permitted provided that the following conditions are met: 5.11 - * 5.12 - * 1. Redistributions of source code must retain the above copyright 5.13 - * notice, this list of conditions and the following disclaimer. 5.14 - * 5.15 - * 2. Redistributions in binary form must reproduce the above copyright 5.16 - * notice, this list of conditions and the following disclaimer in the 5.17 - * documentation and/or other materials provided with the distribution. 5.18 - * 5.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 5.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 5.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 5.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 5.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 5.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 5.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 5.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 5.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 5.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 5.29 - * POSSIBILITY OF SUCH DAMAGE. 5.30 - */ 5.31 - 5.32 -#include "cx/allocator.h" 5.33 -#include <gtest/gtest.h> 5.34 - 5.35 -TEST(Allocator, DefaultAllocator) { 5.36 - cx_allocator_class *clazz = cxDefaultAllocator->cl; 5.37 - ASSERT_NE(clazz, nullptr); 5.38 -} 5.39 - 5.40 -TEST(Allocator, DefaultMalloc) { 5.41 - void *test = cxMalloc(cxDefaultAllocator, 16); 5.42 - ASSERT_NE(test, nullptr); 5.43 - free(test); 5.44 -} 5.45 - 5.46 -TEST(Allocator, DefaultRealloc) { 5.47 - void *test = calloc(8, 1); 5.48 - memcpy(test, "Test", 5); 5.49 - test = cxRealloc(cxDefaultAllocator, test, 16); 5.50 - ASSERT_NE(test, nullptr); 5.51 - EXPECT_STREQ(reinterpret_cast<char *>(test), "Test"); 5.52 - free(test); 5.53 -} 5.54 - 5.55 -TEST(Allocator, Reallocate) { 5.56 - void *test = calloc(8, 1); 5.57 - memcpy(test, "Test", 5); 5.58 - int ret = cxReallocate(cxDefaultAllocator, &test, 16); 5.59 - EXPECT_EQ(ret, 0); 5.60 - ASSERT_NE(test, nullptr); 5.61 - EXPECT_STREQ(reinterpret_cast<char *>(test), "Test"); 5.62 - free(test); 5.63 -} 5.64 - 5.65 -TEST(Allocator, DefaultCalloc) { 5.66 - char *test = reinterpret_cast<char *>(cxCalloc(cxDefaultAllocator, 8, 2)); 5.67 - ASSERT_NE(test, nullptr); 5.68 - for (int i = 0; i < 16; i++) ASSERT_EQ(test[i], 0); 5.69 - free(test); 5.70 -} 5.71 - 5.72 -TEST(Allocator, DefaultFree) { 5.73 - void *test = malloc(16); 5.74 - EXPECT_NO_FATAL_FAILURE( 5.75 - cxFree(cxDefaultAllocator, test); 5.76 - ); 5.77 -} 5.78 - 5.79 -TEST(Allocator, FailingReallocate) { 5.80 - // Mock an allocator that always returns nullptr on realloc 5.81 - cx_allocator_class mock_cl; 5.82 - mock_cl.realloc = []( 5.83 - [[maybe_unused]]void *p, 5.84 - [[maybe_unused]]void *d, 5.85 - [[maybe_unused]]size_t n 5.86 - ) -> void * { return nullptr; }; 5.87 - cx_allocator_s mock{&mock_cl, nullptr}; 5.88 - 5.89 - void *test = calloc(8, 1); 5.90 - memcpy(test, "Test", 5); 5.91 - void *original = test; 5.92 - int ret = cxReallocate(&mock, &test, 16); 5.93 - // non-zero return code because of the failure 5.94 - EXPECT_NE(ret, 0); 5.95 - // the test pointer was not changed and still points to the same memory 5.96 - EXPECT_EQ(test, original); 5.97 - EXPECT_STREQ(reinterpret_cast<char *>(test), "Test"); 5.98 - free(test); 5.99 -}
6.1 --- a/test/test_basic_mempool.cpp Tue Feb 07 21:53:06 2023 +0100 6.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 6.3 @@ -1,154 +0,0 @@ 6.4 -/* 6.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 6.6 - * 6.7 - * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 6.8 - * 6.9 - * Redistribution and use in source and binary forms, with or without 6.10 - * modification, are permitted provided that the following conditions are met: 6.11 - * 6.12 - * 1. Redistributions of source code must retain the above copyright 6.13 - * notice, this list of conditions and the following disclaimer. 6.14 - * 6.15 - * 2. Redistributions in binary form must reproduce the above copyright 6.16 - * notice, this list of conditions and the following disclaimer in the 6.17 - * documentation and/or other materials provided with the distribution. 6.18 - * 6.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 6.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 6.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 6.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 6.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 6.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 6.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 6.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 6.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 6.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 6.29 - * POSSIBILITY OF SUCH DAMAGE. 6.30 - */ 6.31 - 6.32 -#include "cx/basic_mempool.h" 6.33 -#include "util_allocator.h" 6.34 -#include <gtest/gtest.h> 6.35 - 6.36 -class CxBasicMempool : public ::testing::Test { 6.37 -protected: 6.38 - CxMempool *pool = nullptr; 6.39 - 6.40 - void TearDown() override { 6.41 - if (pool != nullptr) { 6.42 - cxMempoolDestroy(pool); 6.43 - } 6.44 - } 6.45 -}; 6.46 - 6.47 -TEST_F(CxBasicMempool, Create) { 6.48 - pool = cxBasicMempoolCreate(16); 6.49 - ASSERT_NE(pool->allocator, nullptr); 6.50 - ASSERT_NE(pool->cl, nullptr); 6.51 - EXPECT_NE(pool->cl->destroy, nullptr); 6.52 - ASSERT_NE(pool->allocator->cl, nullptr); 6.53 - EXPECT_EQ(pool->allocator->data, pool); 6.54 - EXPECT_NE(pool->allocator->cl->malloc, nullptr); 6.55 - EXPECT_NE(pool->allocator->cl->calloc, nullptr); 6.56 - EXPECT_NE(pool->allocator->cl->realloc, nullptr); 6.57 - EXPECT_NE(pool->allocator->cl->free, nullptr); 6.58 - 6.59 - auto basic_pool = reinterpret_cast<cx_basic_mempool_s *>(pool); 6.60 - EXPECT_EQ(basic_pool->size, 16); 6.61 - EXPECT_EQ(basic_pool->ndata, 0); 6.62 - EXPECT_NE(basic_pool->data, nullptr); 6.63 -} 6.64 - 6.65 -TEST_F(CxBasicMempool, malloc) { 6.66 - pool = cxBasicMempoolCreate(4); 6.67 - auto basic_pool = reinterpret_cast<cx_basic_mempool_s *>(pool); 6.68 - EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 6.69 - EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 6.70 - EXPECT_EQ(basic_pool->ndata, 2); 6.71 - EXPECT_EQ(basic_pool->size, 4); 6.72 - EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 6.73 - EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 6.74 - EXPECT_EQ(basic_pool->ndata, 4); 6.75 - EXPECT_EQ(basic_pool->size, 4); 6.76 - EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 6.77 - EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 6.78 - EXPECT_EQ(basic_pool->ndata, 6); 6.79 - EXPECT_GE(basic_pool->size, 6); 6.80 -} 6.81 - 6.82 -TEST_F(CxBasicMempool, calloc) { 6.83 - pool = cxBasicMempoolCreate(4); 6.84 - 6.85 - auto test = (int *) cxCalloc(pool->allocator, 2, sizeof(int)); 6.86 - ASSERT_NE(test, nullptr); 6.87 - EXPECT_EQ(test[0], 0); 6.88 - EXPECT_EQ(test[1], 0); 6.89 -} 6.90 - 6.91 -static unsigned test_destructor_called = 0; 6.92 - 6.93 -static void test_destructor([[maybe_unused]] void *mem) { 6.94 - test_destructor_called++; 6.95 -} 6.96 - 6.97 -TEST_F(CxBasicMempool, destructor) { 6.98 - pool = cxBasicMempoolCreate(4); 6.99 - auto data = cxMalloc(pool->allocator, sizeof(int)); 6.100 - *((int *) data) = 13; 6.101 - cxMempoolSetDestructor(pool, data, test_destructor); 6.102 - EXPECT_EQ(*((int *) data), 13); 6.103 - test_destructor_called = 0; 6.104 - cxFree(pool->allocator, data); 6.105 - EXPECT_EQ(test_destructor_called, 1); 6.106 - data = cxMalloc(pool->allocator, sizeof(int)); 6.107 - cxMempoolSetDestructor(pool, data, test_destructor); 6.108 - cxMempoolDestroy(pool); 6.109 - pool = nullptr; 6.110 - EXPECT_EQ(test_destructor_called, 2); 6.111 -} 6.112 - 6.113 -TEST_F(CxBasicMempool, realloc) { 6.114 - pool = cxBasicMempoolCreate(4); 6.115 - auto data = cxMalloc(pool->allocator, sizeof(int)); 6.116 - *((int *) data) = 13; 6.117 - cxMempoolSetDestructor(pool, data, test_destructor); 6.118 - 6.119 - void *rdata = data; 6.120 - unsigned n = 1; 6.121 - while (rdata == data) { 6.122 - n <<= 1; 6.123 - ASSERT_LT(n, 65536); // eventually the memory should be moved elsewhere 6.124 - rdata = cxRealloc(pool->allocator, data, n * sizeof(intptr_t)); 6.125 - } 6.126 - 6.127 - EXPECT_EQ(*((int *) rdata), 13); 6.128 - // test if destructor is still intact 6.129 - test_destructor_called = 0; 6.130 - cxFree(pool->allocator, rdata); 6.131 - EXPECT_EQ(test_destructor_called, 1); 6.132 -} 6.133 - 6.134 - 6.135 -TEST_F(CxBasicMempool, free) { 6.136 - pool = cxBasicMempoolCreate(4); 6.137 - auto basic_pool = reinterpret_cast<cx_basic_mempool_s *>(pool); 6.138 - 6.139 - void *mem1; 6.140 - void *mem2; 6.141 - 6.142 - mem1 = cxMalloc(pool->allocator, 16); 6.143 - cxFree(pool->allocator, mem1); 6.144 - EXPECT_EQ(basic_pool->ndata, 0); 6.145 - 6.146 - cxMalloc(pool->allocator, 16); 6.147 - cxMalloc(pool->allocator, 16); 6.148 - mem1 = cxMalloc(pool->allocator, 16); 6.149 - cxMalloc(pool->allocator, 16); 6.150 - mem2 = cxMalloc(pool->allocator, 16); 6.151 - 6.152 - EXPECT_EQ(basic_pool->ndata, 5); 6.153 - cxFree(pool->allocator, mem1); 6.154 - EXPECT_EQ(basic_pool->ndata, 4); 6.155 - cxFree(pool->allocator, mem2); 6.156 - EXPECT_EQ(basic_pool->ndata, 3); 6.157 -} 6.158 \ No newline at end of file
7.1 --- a/test/test_buffer.cpp Tue Feb 07 21:53:06 2023 +0100 7.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 7.3 @@ -1,815 +0,0 @@ 7.4 -/* 7.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 7.6 - * 7.7 - * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 7.8 - * 7.9 - * Redistribution and use in source and binary forms, with or without 7.10 - * modification, are permitted provided that the following conditions are met: 7.11 - * 7.12 - * 1. Redistributions of source code must retain the above copyright 7.13 - * notice, this list of conditions and the following disclaimer. 7.14 - * 7.15 - * 2. Redistributions in binary form must reproduce the above copyright 7.16 - * notice, this list of conditions and the following disclaimer in the 7.17 - * documentation and/or other materials provided with the distribution. 7.18 - * 7.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 7.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 7.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 7.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 7.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 7.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 7.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 7.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 7.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 7.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 7.29 - * POSSIBILITY OF SUCH DAMAGE. 7.30 - */ 7.31 - 7.32 -#include "cx/buffer.h" 7.33 - 7.34 -#include <gtest/gtest.h> 7.35 -#include "util_allocator.h" 7.36 - 7.37 -class BufferFixture : public ::testing::Test { 7.38 -protected: 7.39 - void SetUp() override { 7.40 - cxBufferInit(&buf, nullptr, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT); 7.41 - buf.size = 6; 7.42 - buf.pos = 3; 7.43 - } 7.44 - 7.45 - void TearDown() override { 7.46 - cxBufferDestroy(&buf); 7.47 - } 7.48 - 7.49 - CxBuffer buf{}; 7.50 -}; 7.51 - 7.52 -static void expect_default_flush_config(CxBuffer *buf) { 7.53 - EXPECT_EQ(buf->flush_blkmax, 0); 7.54 - EXPECT_EQ(buf->flush_blksize, 4096); 7.55 - EXPECT_EQ(buf->flush_threshold, SIZE_MAX); 7.56 - EXPECT_EQ(buf->flush_func, nullptr); 7.57 - EXPECT_EQ(buf->flush_target, nullptr); 7.58 -} 7.59 - 7.60 -TEST(BufferInit, WrapSpace) { 7.61 - CxTestingAllocator alloc; 7.62 - CxBuffer buf; 7.63 - void *space = cxMalloc(&alloc, 16); 7.64 - cxBufferInit(&buf, space, 16, &alloc, CX_BUFFER_DEFAULT); 7.65 - expect_default_flush_config(&buf); 7.66 - EXPECT_EQ(buf.space, space); 7.67 - EXPECT_EQ(buf.flags & CX_BUFFER_AUTO_EXTEND, 0); 7.68 - EXPECT_EQ(buf.flags & CX_BUFFER_FREE_CONTENTS, 0); 7.69 - EXPECT_EQ(buf.pos, 0); 7.70 - EXPECT_EQ(buf.size, 0); 7.71 - EXPECT_EQ(buf.capacity, 16); 7.72 - EXPECT_EQ(buf.allocator, &alloc); 7.73 - cxBufferDestroy(&buf); 7.74 - EXPECT_FALSE(alloc.verify()); 7.75 - cxFree(&alloc, space); 7.76 - EXPECT_TRUE(alloc.verify()); 7.77 -} 7.78 - 7.79 -TEST(BufferInit, WrapSpaceAutoExtend) { 7.80 - CxTestingAllocator alloc; 7.81 - CxBuffer buf; 7.82 - void *space = cxMalloc(&alloc, 16); 7.83 - cxBufferInit(&buf, space, 16, &alloc, CX_BUFFER_AUTO_EXTEND); 7.84 - expect_default_flush_config(&buf); 7.85 - EXPECT_EQ(buf.space, space); 7.86 - EXPECT_EQ(buf.flags & CX_BUFFER_AUTO_EXTEND, CX_BUFFER_AUTO_EXTEND); 7.87 - EXPECT_EQ(buf.flags & CX_BUFFER_FREE_CONTENTS, 0); 7.88 - EXPECT_EQ(buf.pos, 0); 7.89 - EXPECT_EQ(buf.size, 0); 7.90 - EXPECT_EQ(buf.capacity, 16); 7.91 - EXPECT_EQ(buf.allocator, &alloc); 7.92 - cxBufferDestroy(&buf); 7.93 - EXPECT_FALSE(alloc.verify()); 7.94 - cxFree(&alloc, space); 7.95 - EXPECT_TRUE(alloc.verify()); 7.96 -} 7.97 - 7.98 -TEST(BufferInit, WrapSpaceAutoFree) { 7.99 - CxTestingAllocator alloc; 7.100 - CxBuffer buf; 7.101 - void *space = cxMalloc(&alloc, 16); 7.102 - cxBufferInit(&buf, space, 16, &alloc, CX_BUFFER_FREE_CONTENTS); 7.103 - expect_default_flush_config(&buf); 7.104 - EXPECT_EQ(buf.space, space); 7.105 - EXPECT_EQ(buf.flags & CX_BUFFER_AUTO_EXTEND, 0); 7.106 - EXPECT_EQ(buf.flags & CX_BUFFER_FREE_CONTENTS, CX_BUFFER_FREE_CONTENTS); 7.107 - EXPECT_EQ(buf.pos, 0); 7.108 - EXPECT_EQ(buf.size, 0); 7.109 - EXPECT_EQ(buf.capacity, 16); 7.110 - EXPECT_EQ(buf.allocator, &alloc); 7.111 - EXPECT_FALSE(alloc.verify()); 7.112 - cxBufferDestroy(&buf); 7.113 - EXPECT_TRUE(alloc.verify()); 7.114 -} 7.115 - 7.116 -TEST(BufferInit, FreshSpace) { 7.117 - CxTestingAllocator alloc; 7.118 - CxBuffer buf; 7.119 - cxBufferInit(&buf, nullptr, 8, &alloc, CX_BUFFER_DEFAULT); 7.120 - expect_default_flush_config(&buf); 7.121 - EXPECT_NE(buf.space, nullptr); 7.122 - EXPECT_EQ(buf.flags & CX_BUFFER_AUTO_EXTEND, 0); 7.123 - EXPECT_EQ(buf.flags & CX_BUFFER_FREE_CONTENTS, CX_BUFFER_FREE_CONTENTS); 7.124 - EXPECT_EQ(buf.pos, 0); 7.125 - EXPECT_EQ(buf.size, 0); 7.126 - EXPECT_EQ(buf.capacity, 8); 7.127 - EXPECT_EQ(buf.allocator, &alloc); 7.128 - EXPECT_FALSE(alloc.verify()); // space is still allocated 7.129 - cxBufferDestroy(&buf); 7.130 - EXPECT_TRUE(alloc.verify()); 7.131 -} 7.132 - 7.133 -class BufferShiftFixture : public ::testing::Test { 7.134 -protected: 7.135 - void SetUp() override { 7.136 - ASSERT_TRUE(alloc.verify()); 7.137 - cxBufferInit(&buf, nullptr, 16, &alloc, CX_BUFFER_DEFAULT); 7.138 - memcpy(buf.space, "test____________", 16); 7.139 - buf.capacity = 8; // purposely pretend that the buffer has less capacity s.t. we can test beyond the range 7.140 - buf.pos = 4; 7.141 - buf.size = 4; 7.142 - } 7.143 - 7.144 - void TearDown() override { 7.145 - cxBufferDestroy(&buf); 7.146 - EXPECT_TRUE(alloc.verify()); 7.147 - } 7.148 - 7.149 - CxTestingAllocator alloc; 7.150 - CxBuffer buf{}; 7.151 -}; 7.152 - 7.153 -class BufferShiftLeft : public BufferShiftFixture { 7.154 -}; 7.155 - 7.156 -TEST_F(BufferShiftLeft, Zero) { 7.157 - ASSERT_EQ(buf.pos, 4); 7.158 - ASSERT_EQ(buf.size, 4); 7.159 - int ret = cxBufferShiftLeft(&buf, 0); 7.160 - EXPECT_EQ(ret, 0); 7.161 - EXPECT_EQ(buf.pos, 4); 7.162 - EXPECT_EQ(buf.size, 4); 7.163 - EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 7.164 -} 7.165 - 7.166 -TEST_F(BufferShiftLeft, ZeroOffsetInterface) { 7.167 - ASSERT_EQ(buf.pos, 4); 7.168 - ASSERT_EQ(buf.size, 4); 7.169 - int ret = cxBufferShift(&buf, -0); 7.170 - EXPECT_EQ(ret, 0); 7.171 - EXPECT_EQ(buf.pos, 4); 7.172 - EXPECT_EQ(buf.size, 4); 7.173 - EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 7.174 -} 7.175 - 7.176 -TEST_F(BufferShiftLeft, Standard) { 7.177 - ASSERT_EQ(buf.pos, 4); 7.178 - ASSERT_EQ(buf.size, 4); 7.179 - int ret = cxBufferShiftLeft(&buf, 2); 7.180 - EXPECT_EQ(ret, 0); 7.181 - EXPECT_EQ(buf.pos, 2); 7.182 - EXPECT_EQ(buf.size, 2); 7.183 - EXPECT_TRUE(memcmp(buf.space, "stst________", 8) == 0); 7.184 -} 7.185 - 7.186 -TEST_F(BufferShiftLeft, Overshift) { 7.187 - ASSERT_LT(buf.pos, 6); 7.188 - ASSERT_LT(buf.size, 6); 7.189 - int ret = cxBufferShiftLeft(&buf, 6); 7.190 - EXPECT_EQ(ret, 0); 7.191 - EXPECT_EQ(buf.pos, 0); 7.192 - EXPECT_EQ(buf.size, 0); 7.193 - EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 7.194 -} 7.195 - 7.196 -TEST_F(BufferShiftLeft, OvershiftPosOnly) { 7.197 - buf.pos = 2; 7.198 - ASSERT_EQ(buf.size, 4); 7.199 - int ret = cxBufferShiftLeft(&buf, 3); 7.200 - EXPECT_EQ(ret, 0); 7.201 - EXPECT_EQ(buf.pos, 0); 7.202 - EXPECT_EQ(buf.size, 1); 7.203 - EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 7.204 -} 7.205 - 7.206 -TEST_F(BufferShiftLeft, OffsetInterface) { 7.207 - buf.pos = 3; 7.208 - ASSERT_EQ(buf.size, 4); 7.209 - int ret = cxBufferShift(&buf, -2); 7.210 - EXPECT_EQ(ret, 0); 7.211 - EXPECT_EQ(buf.pos, 1); 7.212 - EXPECT_EQ(buf.size, 2); 7.213 - EXPECT_TRUE(memcmp(buf.space, "stst________", 8) == 0); 7.214 -} 7.215 - 7.216 -class BufferShiftRight : public BufferShiftFixture { 7.217 -}; 7.218 - 7.219 -TEST_F(BufferShiftRight, Zero) { 7.220 - ASSERT_EQ(buf.pos, 4); 7.221 - ASSERT_EQ(buf.size, 4); 7.222 - int ret = cxBufferShiftRight(&buf, 0); 7.223 - EXPECT_EQ(ret, 0); 7.224 - EXPECT_EQ(buf.pos, 4); 7.225 - EXPECT_EQ(buf.size, 4); 7.226 - EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 7.227 -} 7.228 - 7.229 -TEST_F(BufferShiftRight, ZeroOffsetInterface) { 7.230 - ASSERT_EQ(buf.pos, 4); 7.231 - ASSERT_EQ(buf.size, 4); 7.232 - int ret = cxBufferShift(&buf, +0); 7.233 - EXPECT_EQ(ret, 0); 7.234 - EXPECT_EQ(buf.pos, 4); 7.235 - EXPECT_EQ(buf.size, 4); 7.236 - EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 7.237 -} 7.238 - 7.239 -TEST_F(BufferShiftRight, Standard) { 7.240 - ASSERT_EQ(buf.pos, 4); 7.241 - ASSERT_EQ(buf.size, 4); 7.242 - int ret = cxBufferShiftRight(&buf, 3); 7.243 - EXPECT_EQ(ret, 0); 7.244 - EXPECT_EQ(buf.pos, 7); 7.245 - EXPECT_EQ(buf.size, 7); 7.246 - EXPECT_TRUE(memcmp(buf.space, "testest_____", 8) == 0); 7.247 -} 7.248 - 7.249 -TEST_F(BufferShiftRight, OvershiftDiscard) { 7.250 - ASSERT_EQ(buf.pos, 4); 7.251 - ASSERT_EQ(buf.size, 4); 7.252 - ASSERT_EQ(buf.capacity, 8); 7.253 - int ret = cxBufferShiftRight(&buf, 6); 7.254 - EXPECT_EQ(ret, 0); 7.255 - EXPECT_EQ(buf.pos, 8); 7.256 - EXPECT_EQ(buf.size, 8); 7.257 - EXPECT_EQ(buf.capacity, 8); 7.258 - EXPECT_TRUE(memcmp(buf.space, "test__te____", 8) == 0); 7.259 -} 7.260 - 7.261 -TEST_F(BufferShiftRight, OvershiftExtend) { 7.262 - ASSERT_EQ(buf.pos, 4); 7.263 - ASSERT_EQ(buf.size, 4); 7.264 - ASSERT_EQ(buf.capacity, 8); 7.265 - buf.flags |= CX_BUFFER_AUTO_EXTEND; 7.266 - int ret = cxBufferShiftRight(&buf, 6); 7.267 - EXPECT_EQ(ret, 0); 7.268 - EXPECT_EQ(buf.pos, 10); 7.269 - EXPECT_EQ(buf.size, 10); 7.270 - EXPECT_GE(buf.capacity, 10); 7.271 - EXPECT_TRUE(memcmp(buf.space, "test__test__", 8) == 0); 7.272 -} 7.273 - 7.274 -TEST_F(BufferShiftRight, OffsetInterface) { 7.275 - buf.pos = 3; 7.276 - ASSERT_EQ(buf.size, 4); 7.277 - int ret = cxBufferShift(&buf, 2); 7.278 - EXPECT_EQ(ret, 0); 7.279 - EXPECT_EQ(buf.pos, 5); 7.280 - EXPECT_EQ(buf.size, 6); 7.281 - EXPECT_TRUE(memcmp(buf.space, "tetest______", 8) == 0); 7.282 -} 7.283 - 7.284 -TEST(BufferMinimumCapacity, Sufficient) { 7.285 - CxTestingAllocator alloc; 7.286 - auto space = cxMalloc(&alloc, 8); 7.287 - CxBuffer buf; 7.288 - cxBufferInit(&buf, space, 8, &alloc, CX_BUFFER_FREE_CONTENTS); 7.289 - memcpy(space, "Testing", 8); 7.290 - buf.size = 8; 7.291 - cxBufferMinimumCapacity(&buf, 6); 7.292 - EXPECT_EQ(buf.capacity, 8); 7.293 - EXPECT_EQ(buf.size, 8); 7.294 - EXPECT_TRUE(memcmp(buf.space, "Testing", 8) == 0); 7.295 - cxBufferDestroy(&buf); 7.296 - EXPECT_TRUE(alloc.verify()); 7.297 -} 7.298 - 7.299 -TEST(BufferMinimumCapacity, Extend) { 7.300 - CxTestingAllocator alloc; 7.301 - auto space = cxMalloc(&alloc, 8); 7.302 - CxBuffer buf; 7.303 - cxBufferInit(&buf, space, 8, &alloc, CX_BUFFER_FREE_CONTENTS); // NO auto extend! 7.304 - memcpy(space, "Testing", 8); 7.305 - buf.size = 8; 7.306 - cxBufferMinimumCapacity(&buf, 16); 7.307 - EXPECT_EQ(buf.capacity, 16); 7.308 - EXPECT_EQ(buf.size, 8); 7.309 - EXPECT_TRUE(memcmp(buf.space, "Testing", 8) == 0); 7.310 - cxBufferDestroy(&buf); 7.311 - EXPECT_TRUE(alloc.verify()); 7.312 -} 7.313 - 7.314 -TEST(BufferClear, Test) { 7.315 - char space[16]; 7.316 - strcpy(space, "clear test"); 7.317 - CxBuffer buf; 7.318 - cxBufferInit(&buf, space, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT); 7.319 - ASSERT_EQ(buf.size, 0); 7.320 - // only clear the used part of the buffer 7.321 - cxBufferClear(&buf); 7.322 - EXPECT_EQ(memcmp(space, "clear test", 10), 0); 7.323 - buf.size = 5; 7.324 - buf.pos = 3; 7.325 - cxBufferClear(&buf); 7.326 - EXPECT_EQ(memcmp(space, "\0\0\0\0\0 test", 10), 0); 7.327 - EXPECT_EQ(buf.size, 0); 7.328 - EXPECT_EQ(buf.pos, 0); 7.329 - cxBufferDestroy(&buf); 7.330 -} 7.331 - 7.332 -class BufferWrite : public ::testing::Test { 7.333 -protected: 7.334 - CxBuffer buf{}, target{}; 7.335 - 7.336 - void SetUp() override { 7.337 - cxBufferInit(&target, nullptr, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND); 7.338 - cxBufferInit(&buf, nullptr, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT); 7.339 - buf.capacity = 8; // artificially reduce capacity to check OOB writes 7.340 - memset(buf.space, 0, 16); 7.341 - memcpy(buf.space, "prep", 4); 7.342 - buf.size = buf.pos = 4; 7.343 - } 7.344 - 7.345 - void TearDown() override { 7.346 - cxBufferDestroy(&buf); 7.347 - cxBufferDestroy(&target); 7.348 - } 7.349 - 7.350 - void enableFlushing() { 7.351 - buf.flush_target = ⌖ 7.352 - buf.flush_func = reinterpret_cast<cx_write_func>(cxBufferWrite); 7.353 - buf.flush_blkmax = 1; 7.354 - } 7.355 -}; 7.356 - 7.357 -static size_t mock_write_limited_rate( 7.358 - void const *ptr, 7.359 - size_t size, 7.360 - __attribute__((unused)) size_t nitems, 7.361 - CxBuffer *buffer 7.362 -) { 7.363 - // simulate limited target drain capacity 7.364 - static bool full = false; 7.365 - if (full) { 7.366 - full = false; 7.367 - return 0; 7.368 - } else { 7.369 - full = true; 7.370 - return cxBufferWrite(ptr, size, nitems > 2 ? 2 : nitems, buffer); 7.371 - } 7.372 -} 7.373 - 7.374 -TEST_F(BufferWrite, SizeOneFit) { 7.375 - const char *data = "test"; 7.376 - ASSERT_EQ(buf.capacity, 8); 7.377 - ASSERT_EQ(buf.pos, 4); 7.378 - ASSERT_EQ(buf.size, 4); 7.379 - size_t written = cxBufferWrite(data, 1, 4, &buf); 7.380 - EXPECT_EQ(written, 4); 7.381 - EXPECT_EQ(buf.size, 8); 7.382 - EXPECT_EQ(buf.pos, 8); 7.383 - EXPECT_EQ(buf.capacity, 8); 7.384 - EXPECT_EQ(memcmp(buf.space, "preptest", 8), 0); 7.385 -} 7.386 - 7.387 -TEST_F(BufferWrite, SizeOneDiscard) { 7.388 - const char *data = "testing"; 7.389 - ASSERT_EQ(buf.capacity, 8); 7.390 - ASSERT_EQ(buf.pos, 4); 7.391 - ASSERT_EQ(buf.size, 4); 7.392 - size_t written = cxBufferWrite(data, 1, 7, &buf); 7.393 - EXPECT_EQ(written, 4); 7.394 - EXPECT_EQ(buf.size, 8); 7.395 - EXPECT_EQ(buf.pos, 8); 7.396 - EXPECT_EQ(buf.capacity, 8); 7.397 - EXPECT_EQ(memcmp(buf.space, "preptest\0", 9), 0); 7.398 -} 7.399 - 7.400 -TEST_F(BufferWrite, SizeOneExtend) { 7.401 - buf.flags |= CX_BUFFER_AUTO_EXTEND; 7.402 - const char *data = "testing"; 7.403 - ASSERT_EQ(buf.capacity, 8); 7.404 - ASSERT_EQ(buf.pos, 4); 7.405 - ASSERT_EQ(buf.size, 4); 7.406 - size_t written = cxBufferWrite(data, 1, 7, &buf); 7.407 - EXPECT_EQ(written, 7); 7.408 - EXPECT_EQ(buf.size, 11); 7.409 - EXPECT_EQ(buf.pos, 11); 7.410 - EXPECT_GE(buf.capacity, 11); 7.411 - EXPECT_EQ(memcmp(buf.space, "preptesting", 11), 0); 7.412 -} 7.413 - 7.414 -TEST_F(BufferWrite, MultibyteFit) { 7.415 - const char *data = "test"; 7.416 - ASSERT_EQ(buf.capacity, 8); 7.417 - ASSERT_EQ(buf.pos, 4); 7.418 - ASSERT_EQ(buf.size, 4); 7.419 - size_t written = cxBufferWrite(data, 2, 2, &buf); 7.420 - EXPECT_EQ(written, 2); 7.421 - EXPECT_EQ(buf.size, 8); 7.422 - EXPECT_EQ(buf.pos, 8); 7.423 - EXPECT_EQ(buf.capacity, 8); 7.424 - EXPECT_EQ(memcmp(buf.space, "preptest", 8), 0); 7.425 -} 7.426 - 7.427 -TEST_F(BufferWrite, MultibyteDiscard) { 7.428 - const char *data = "testing"; 7.429 - ASSERT_EQ(buf.capacity, 8); 7.430 - ASSERT_EQ(buf.size, 4); 7.431 - buf.pos = 3; 7.432 - size_t written = cxBufferWrite(data, 2, 4, &buf); 7.433 - // remember: whole elements are discarded if they do not fit 7.434 - EXPECT_EQ(written, 2); 7.435 - EXPECT_EQ(buf.size, 7); 7.436 - EXPECT_EQ(buf.pos, 7); 7.437 - EXPECT_EQ(buf.capacity, 8); 7.438 - EXPECT_EQ(memcmp(buf.space, "pretest\0", 8), 0); 7.439 -} 7.440 - 7.441 -TEST_F(BufferWrite, MultibyteExtend) { 7.442 - buf.flags |= CX_BUFFER_AUTO_EXTEND; 7.443 - const char *data = "tester"; 7.444 - ASSERT_EQ(buf.capacity, 8); 7.445 - ASSERT_EQ(buf.size, 4); 7.446 - buf.pos = 3; 7.447 - size_t written = cxBufferWrite(data, 2, 3, &buf); 7.448 - // remember: whole elements are discarded if they do not fit 7.449 - EXPECT_EQ(written, 3); 7.450 - EXPECT_EQ(buf.size, 9); 7.451 - EXPECT_EQ(buf.pos, 9); 7.452 - EXPECT_GE(buf.capacity, 9); 7.453 - EXPECT_EQ(memcmp(buf.space, "pretester", 9), 0); 7.454 -} 7.455 - 7.456 -TEST_F(BufferWrite, PutcWrapperFit) { 7.457 - ASSERT_EQ(buf.capacity, 8); 7.458 - ASSERT_EQ(buf.pos, 4); 7.459 - ASSERT_EQ(buf.size, 4); 7.460 - int c = cxBufferPut(&buf, 0x200 | 'a'); 7.461 - EXPECT_EQ(c, 'a'); 7.462 - EXPECT_EQ(buf.size, 5); 7.463 - EXPECT_EQ(buf.pos, 5); 7.464 - EXPECT_EQ(buf.capacity, 8); 7.465 - EXPECT_EQ(memcmp(buf.space, "prepa\0", 6), 0); 7.466 -} 7.467 - 7.468 -TEST_F(BufferWrite, PutcWrapperDiscard) { 7.469 - ASSERT_EQ(buf.capacity, 8); 7.470 - ASSERT_EQ(buf.size, 4); 7.471 - buf.pos = 8; 7.472 - int c = cxBufferPut(&buf, 0x200 | 'a'); 7.473 - EXPECT_EQ(c, EOF); 7.474 - EXPECT_EQ(buf.size, 4); 7.475 - EXPECT_EQ(buf.pos, 8); 7.476 - EXPECT_EQ(buf.capacity, 8); 7.477 - EXPECT_EQ(memcmp(buf.space, "prep\0\0\0\0\0", 9), 0); 7.478 -} 7.479 - 7.480 -TEST_F(BufferWrite, PutcWrapperExtend) { 7.481 - buf.flags |= CX_BUFFER_AUTO_EXTEND; 7.482 - ASSERT_EQ(buf.capacity, 8); 7.483 - ASSERT_EQ(buf.size, 4); 7.484 - buf.pos = 8; 7.485 - int c = cxBufferPut(&buf, 0x200 | 'a'); 7.486 - EXPECT_EQ(c, 'a'); 7.487 - EXPECT_EQ(buf.size, 9); 7.488 - EXPECT_EQ(buf.pos, 9); 7.489 - EXPECT_GE(buf.capacity, 9); 7.490 - EXPECT_EQ(memcmp(buf.space, "prep\0\0\0\0a", 9), 0); 7.491 -} 7.492 - 7.493 -TEST_F(BufferWrite, PutStringWrapperFit) { 7.494 - const char *data = "test"; 7.495 - ASSERT_EQ(buf.capacity, 8); 7.496 - ASSERT_EQ(buf.pos, 4); 7.497 - ASSERT_EQ(buf.size, 4); 7.498 - size_t written = cxBufferPutString(&buf, data); 7.499 - EXPECT_EQ(written, 4); 7.500 - EXPECT_EQ(buf.size, 8); 7.501 - EXPECT_EQ(buf.pos, 8); 7.502 - EXPECT_EQ(buf.capacity, 8); 7.503 - EXPECT_EQ(memcmp(buf.space, "preptest", 8), 0); 7.504 -} 7.505 - 7.506 -TEST_F(BufferWrite, PutStringWrapperDiscard) { 7.507 - const char *data = "testing"; 7.508 - ASSERT_EQ(buf.capacity, 8); 7.509 - ASSERT_EQ(buf.pos, 4); 7.510 - ASSERT_EQ(buf.size, 4); 7.511 - size_t written = cxBufferPutString(&buf, data); 7.512 - EXPECT_EQ(written, 4); 7.513 - EXPECT_EQ(buf.size, 8); 7.514 - EXPECT_EQ(buf.pos, 8); 7.515 - EXPECT_EQ(buf.capacity, 8); 7.516 - EXPECT_EQ(memcmp(buf.space, "preptest\0", 9), 0); 7.517 -} 7.518 - 7.519 -TEST_F(BufferWrite, PutStringWrapperExtend) { 7.520 - buf.flags |= CX_BUFFER_AUTO_EXTEND; 7.521 - const char *data = "testing"; 7.522 - ASSERT_EQ(buf.capacity, 8); 7.523 - ASSERT_EQ(buf.pos, 4); 7.524 - ASSERT_EQ(buf.size, 4); 7.525 - size_t written = cxBufferPutString(&buf, data); 7.526 - EXPECT_EQ(written, 7); 7.527 - EXPECT_EQ(buf.size, 11); 7.528 - EXPECT_EQ(buf.pos, 11); 7.529 - EXPECT_GE(buf.capacity, 11); 7.530 - EXPECT_EQ(memcmp(buf.space, "preptesting", 11), 0); 7.531 -} 7.532 - 7.533 -TEST_F(BufferWrite, MultOverflow) { 7.534 - const char *data = "testing"; 7.535 - ASSERT_EQ(buf.capacity, 8); 7.536 - ASSERT_EQ(buf.pos, 4); 7.537 - ASSERT_EQ(buf.size, 4); 7.538 - size_t written = cxBufferWrite(data, 8, SIZE_MAX / 4, &buf); 7.539 - EXPECT_EQ(written, 0); 7.540 - EXPECT_EQ(buf.capacity, 8); 7.541 - EXPECT_EQ(buf.pos, 4); 7.542 - EXPECT_EQ(buf.size, 4); 7.543 - EXPECT_EQ(memcmp(buf.space, "prep\0", 5), 0); 7.544 -} 7.545 - 7.546 -TEST_F(BufferWrite, MaxCapaOverflow) { 7.547 - buf.flags |= CX_BUFFER_AUTO_EXTEND; 7.548 - const char *data = "testing"; 7.549 - ASSERT_EQ(buf.capacity, 8); 7.550 - ASSERT_EQ(buf.pos, 4); 7.551 - ASSERT_EQ(buf.size, 4); 7.552 - size_t written = cxBufferWrite(data, 1, SIZE_MAX - 2, &buf); 7.553 - EXPECT_EQ(written, 0); 7.554 - EXPECT_EQ(buf.capacity, 8); 7.555 - EXPECT_EQ(buf.pos, 4); 7.556 - EXPECT_EQ(buf.size, 4); 7.557 - EXPECT_EQ(memcmp(buf.space, "prep\0", 5), 0); 7.558 -} 7.559 - 7.560 -TEST_F(BufferWrite, OnlyOverwrite) { 7.561 - buf.flags |= CX_BUFFER_AUTO_EXTEND; 7.562 - ASSERT_EQ(buf.capacity, 8); 7.563 - memcpy(buf.space, "preptest", 8); 7.564 - buf.pos = 3; 7.565 - buf.size = 8; 7.566 - size_t written = cxBufferWrite("XXX", 2, 2, &buf); 7.567 - EXPECT_EQ(written, 2); 7.568 - EXPECT_EQ(buf.capacity, 8); 7.569 - EXPECT_EQ(buf.size, 8); 7.570 - EXPECT_EQ(buf.pos, 7); 7.571 - EXPECT_EQ(memcmp(buf.space, "preXXX\0t", 8), 0); 7.572 -} 7.573 - 7.574 -TEST_F(BufferWrite, FlushAtCapacity) { 7.575 - enableFlushing(); 7.576 - ASSERT_EQ(buf.capacity, 8); 7.577 - ASSERT_EQ(buf.pos, 4); 7.578 - size_t written = cxBufferWrite("foo", 1, 3, &buf); 7.579 - EXPECT_EQ(written, 3); 7.580 - ASSERT_EQ(buf.pos, 7); 7.581 - ASSERT_EQ(buf.size, 7); 7.582 - ASSERT_EQ(target.pos, 0); 7.583 - ASSERT_EQ(target.size, 0); 7.584 - written = cxBufferWrite("hello", 1, 5, &buf); 7.585 - EXPECT_EQ(written, 5); 7.586 - EXPECT_EQ(buf.pos, 0); 7.587 - EXPECT_EQ(buf.size, 0); 7.588 - EXPECT_EQ(buf.capacity, 8); 7.589 - EXPECT_EQ(target.pos, 12); 7.590 - ASSERT_EQ(target.size, 12); 7.591 - EXPECT_EQ(memcmp(target.space, "prepfoohello", 12), 0); 7.592 -} 7.593 - 7.594 -TEST_F(BufferWrite, FlushAtThreshold) { 7.595 - enableFlushing(); 7.596 - buf.flush_threshold = 12; 7.597 - buf.flags |= CX_BUFFER_AUTO_EXTEND; 7.598 - ASSERT_EQ(buf.capacity, 8); 7.599 - ASSERT_EQ(buf.pos, 4); 7.600 - size_t written = cxBufferWrite("foobar", 1, 6, &buf); 7.601 - EXPECT_EQ(written, 6); 7.602 - ASSERT_EQ(buf.pos, 10); 7.603 - ASSERT_EQ(buf.size, 10); 7.604 - ASSERT_GE(buf.capacity, 10); 7.605 - ASSERT_LE(buf.capacity, 12); 7.606 - ASSERT_EQ(target.pos, 0); 7.607 - ASSERT_EQ(target.size, 0); 7.608 - written = cxBufferWrite("hello", 1, 5, &buf); 7.609 - EXPECT_EQ(written, 5); 7.610 - EXPECT_EQ(buf.pos, 0); 7.611 - EXPECT_EQ(buf.size, 0); 7.612 - EXPECT_LE(buf.capacity, 12); 7.613 - EXPECT_EQ(target.pos, 15); 7.614 - ASSERT_EQ(target.size, 15); 7.615 - EXPECT_EQ(memcmp(target.space, "prepfoobarhello", 15), 0); 7.616 -} 7.617 - 7.618 -TEST_F(BufferWrite, FlushRateLimited) { 7.619 - enableFlushing(); 7.620 - // limit the rate of the flush function and the capacity of the target 7.621 - target.capacity = 16; 7.622 - target.flags &= ~CX_BUFFER_AUTO_EXTEND; 7.623 - buf.flush_func = (cx_write_func) mock_write_limited_rate; 7.624 - ASSERT_EQ(buf.capacity, 8); 7.625 - ASSERT_EQ(buf.pos, 4); 7.626 - size_t written = cxBufferWrite("foo", 1, 3, &buf); 7.627 - EXPECT_EQ(written, 3); 7.628 - ASSERT_EQ(buf.pos, 7); 7.629 - ASSERT_EQ(buf.size, 7); 7.630 - ASSERT_EQ(target.pos, 0); 7.631 - ASSERT_EQ(target.size, 0); 7.632 - written = cxBufferWrite("hello, world!", 1, 13, &buf); 7.633 - // " world!" fits into this buffer, the remaining stuff is flushed out 7.634 - EXPECT_EQ(written, 13); 7.635 - EXPECT_EQ(buf.pos, 7); 7.636 - EXPECT_EQ(buf.size, 7); 7.637 - EXPECT_EQ(buf.capacity, 8); 7.638 - EXPECT_EQ(memcmp(buf.space, " world!", 7), 0); 7.639 - EXPECT_EQ(target.pos, 13); 7.640 - ASSERT_EQ(target.size, 13); 7.641 - EXPECT_EQ(target.capacity, 16); 7.642 - EXPECT_EQ(memcmp(target.space, "prepfoohello,", 13), 0); 7.643 -} 7.644 - 7.645 -class BufferSeek : public BufferFixture { 7.646 -}; 7.647 - 7.648 -TEST_F(BufferSeek, SetZero) { 7.649 - int result = cxBufferSeek(&buf, 0, SEEK_SET); 7.650 - EXPECT_EQ(result, 0); 7.651 - EXPECT_EQ(buf.pos, 0); 7.652 -} 7.653 - 7.654 -TEST_F(BufferSeek, SetValid) { 7.655 - int result = cxBufferSeek(&buf, 5, SEEK_SET); 7.656 - EXPECT_EQ(result, 0); 7.657 - EXPECT_EQ(buf.pos, 5); 7.658 -} 7.659 - 7.660 -TEST_F(BufferSeek, SetInvalid) { 7.661 - ASSERT_EQ(buf.pos, 3); 7.662 - int result = cxBufferSeek(&buf, 6, SEEK_SET); 7.663 - EXPECT_NE(result, 0); 7.664 - EXPECT_EQ(buf.pos, 3); 7.665 -} 7.666 - 7.667 -TEST_F(BufferSeek, CurZero) { 7.668 - ASSERT_EQ(buf.pos, 3); 7.669 - int result = cxBufferSeek(&buf, 0, SEEK_CUR); 7.670 - EXPECT_EQ(result, 0); 7.671 - EXPECT_EQ(buf.pos, 3); 7.672 -} 7.673 - 7.674 -TEST_F(BufferSeek, CurValidPositive) { 7.675 - ASSERT_EQ(buf.pos, 3); 7.676 - int result = cxBufferSeek(&buf, 2, SEEK_CUR); 7.677 - EXPECT_EQ(result, 0); 7.678 - EXPECT_EQ(buf.pos, 5); 7.679 -} 7.680 - 7.681 -TEST_F(BufferSeek, CurValidNegative) { 7.682 - ASSERT_EQ(buf.pos, 3); 7.683 - int result = cxBufferSeek(&buf, -3, SEEK_CUR); 7.684 - EXPECT_EQ(result, 0); 7.685 - EXPECT_EQ(buf.pos, 0); 7.686 -} 7.687 - 7.688 -TEST_F(BufferSeek, CurInvalidPositive) { 7.689 - ASSERT_EQ(buf.pos, 3); 7.690 - int result = cxBufferSeek(&buf, 3, SEEK_CUR); 7.691 - EXPECT_NE(result, 0); 7.692 - EXPECT_EQ(buf.pos, 3); 7.693 -} 7.694 - 7.695 -TEST_F(BufferSeek, CurInvalidNegative) { 7.696 - ASSERT_EQ(buf.pos, 3); 7.697 - int result = cxBufferSeek(&buf, -4, SEEK_CUR); 7.698 - EXPECT_NE(result, 0); 7.699 - EXPECT_EQ(buf.pos, 3); 7.700 -} 7.701 - 7.702 -TEST_F(BufferSeek, EndZero) { 7.703 - ASSERT_EQ(buf.size, 6); 7.704 - int result = cxBufferSeek(&buf, 0, SEEK_END); 7.705 - // the (past-the-)end position is always invalid 7.706 - EXPECT_NE(result, 0); 7.707 - EXPECT_EQ(buf.pos, 3); 7.708 -} 7.709 - 7.710 -TEST_F(BufferSeek, EndValid) { 7.711 - ASSERT_EQ(buf.size, 6); 7.712 - int result = cxBufferSeek(&buf, -6, SEEK_END); 7.713 - EXPECT_EQ(result, 0); 7.714 - EXPECT_EQ(buf.pos, 0); 7.715 -} 7.716 - 7.717 -TEST_F(BufferSeek, EndInvalid) { 7.718 - ASSERT_EQ(buf.size, 6); 7.719 - int result = cxBufferSeek(&buf, 1, SEEK_END); 7.720 - EXPECT_NE(result, 0); 7.721 - EXPECT_EQ(buf.pos, 3); 7.722 -} 7.723 - 7.724 -TEST_F(BufferSeek, WhenceInvalid) { 7.725 - ASSERT_EQ(buf.size, 6); 7.726 - ASSERT_EQ(buf.pos, 3); 7.727 - int result = cxBufferSeek(&buf, 2, 9000); 7.728 - EXPECT_NE(result, 0); 7.729 - EXPECT_EQ(buf.size, 6); 7.730 - EXPECT_EQ(buf.pos, 3); 7.731 -} 7.732 - 7.733 -class BufferEof : public BufferFixture { 7.734 -}; 7.735 - 7.736 -TEST_F(BufferEof, Reached) { 7.737 - buf.pos = buf.size; 7.738 - EXPECT_TRUE(cxBufferEof(&buf)); 7.739 - buf.pos = buf.size - 1; 7.740 - ASSERT_FALSE(cxBufferEof(&buf)); 7.741 - cxBufferPut(&buf, 'a'); 7.742 - EXPECT_TRUE(cxBufferEof(&buf)); 7.743 -} 7.744 - 7.745 -TEST_F(BufferEof, NotReached) { 7.746 - buf.pos = buf.size - 1; 7.747 - EXPECT_FALSE(cxBufferEof(&buf)); 7.748 - buf.pos = 0; 7.749 - cxBufferWrite("test", 1, 5, &buf); 7.750 - EXPECT_FALSE(cxBufferEof(&buf)); 7.751 -} 7.752 - 7.753 -class BufferRead : public ::testing::Test { 7.754 -protected: 7.755 - CxBuffer buf{}; 7.756 - 7.757 - void SetUp() override { 7.758 - cxBufferInit(&buf, nullptr, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT); 7.759 - buf.capacity = 8; // artificially reduce capacity to check OOB writes 7.760 - memset(buf.space, 0, 16); 7.761 - memcpy(buf.space, "some data", 9); 7.762 - buf.size = 9; 7.763 - } 7.764 - 7.765 - void TearDown() override { 7.766 - cxBufferDestroy(&buf); 7.767 - } 7.768 -}; 7.769 - 7.770 -TEST_F(BufferRead, GetByte) { 7.771 - buf.pos = 2; 7.772 - EXPECT_EQ(cxBufferGet(&buf), 'm'); 7.773 - EXPECT_EQ(cxBufferGet(&buf), 'e'); 7.774 - EXPECT_EQ(cxBufferGet(&buf), ' '); 7.775 - EXPECT_EQ(cxBufferGet(&buf), 'd'); 7.776 - EXPECT_EQ(buf.pos, 6); 7.777 -} 7.778 - 7.779 -TEST_F(BufferRead, GetEof) { 7.780 - buf.pos = buf.size; 7.781 - EXPECT_EQ(cxBufferGet(&buf), EOF); 7.782 -} 7.783 - 7.784 -TEST_F(BufferRead, ReadWithinBounds) { 7.785 - buf.pos = 2; 7.786 - char target[4]; 7.787 - auto read = cxBufferRead(&target, 1, 4, &buf); 7.788 - ASSERT_EQ(read, 4); 7.789 - EXPECT_EQ(memcmp(&target, "me d", 4), 0); 7.790 - EXPECT_EQ(buf.pos, 6); 7.791 -} 7.792 - 7.793 -TEST_F(BufferRead, ReadOutOfBounds) { 7.794 - buf.pos = 6; 7.795 - char target[4]; 7.796 - auto read = cxBufferRead(&target, 1, 4, &buf); 7.797 - ASSERT_EQ(read, 3); 7.798 - EXPECT_EQ(memcmp(&target, "ata", 3), 0); 7.799 - EXPECT_EQ(buf.pos, 9); 7.800 -} 7.801 - 7.802 -TEST_F(BufferRead, ReadOutOfBoundsMultibyte) { 7.803 - buf.pos = 6; 7.804 - char target[4]; 7.805 - target[2] = '\0'; 7.806 - auto read = cxBufferRead(&target, 2, 2, &buf); 7.807 - ASSERT_EQ(read, 1); 7.808 - EXPECT_EQ(memcmp(&target, "at\0", 3), 0); 7.809 - EXPECT_EQ(buf.pos, 8); 7.810 -} 7.811 - 7.812 -TEST_F(BufferRead, ReadEof) { 7.813 - buf.pos = 9; 7.814 - char target[4]; 7.815 - auto read = cxBufferRead(&target, 1, 1, &buf); 7.816 - ASSERT_EQ(read, 0); 7.817 - EXPECT_EQ(buf.pos, 9); 7.818 -}
8.1 --- a/test/test_compare.cpp Tue Feb 07 21:53:06 2023 +0100 8.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 8.3 @@ -1,127 +0,0 @@ 8.4 -/* 8.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 8.6 - * 8.7 - * Copyright 2022 Mike Becker, Olaf Wintermann All rights reserved. 8.8 - * 8.9 - * Redistribution and use in source and binary forms, with or without 8.10 - * modification, are permitted provided that the following conditions are met: 8.11 - * 8.12 - * 1. Redistributions of source code must retain the above copyright 8.13 - * notice, this list of conditions and the following disclaimer. 8.14 - * 8.15 - * 2. Redistributions in binary form must reproduce the above copyright 8.16 - * notice, this list of conditions and the following disclaimer in the 8.17 - * documentation and/or other materials provided with the distribution. 8.18 - * 8.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 8.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 8.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 8.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 8.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 8.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 8.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 8.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 8.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 8.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 8.29 - * POSSIBILITY OF SUCH DAMAGE. 8.30 - */ 8.31 - 8.32 -#include "cx/compare.h" 8.33 - 8.34 -#include <gtest/gtest.h> 8.35 - 8.36 -template<typename T> 8.37 -static void test_compare( 8.38 - int (*fnc)( 8.39 - void const *, 8.40 - void const * 8.41 - ) 8.42 -) { 8.43 - auto m = std::numeric_limits<T>::max() / 400; 8.44 - T x, y; 8.45 - 8.46 - x = (std::is_signed_v<T> ? -3 : 3) * m; 8.47 - y = 5 * m; 8.48 - EXPECT_LT(fnc(&x, &y), 0); 8.49 - EXPECT_GT(fnc(&y, &x), 0); 8.50 - 8.51 - x = 120 * m; 8.52 - y = 348 * m; 8.53 - EXPECT_LT(fnc(&x, &y), 0); 8.54 - EXPECT_GT(fnc(&y, &x), 0); 8.55 - 8.56 - if constexpr (std::is_signed_v<T>) { 8.57 - x = -120 * m; 8.58 - y = -348 * m; 8.59 - EXPECT_GT(fnc(&x, &y), 0); 8.60 - EXPECT_LT(fnc(&y, &x), 0); 8.61 - } 8.62 - 8.63 - x = y; 8.64 - EXPECT_EQ(fnc(&x, &y), 0); 8.65 - EXPECT_EQ(fnc(&y, &x), 0); 8.66 -} 8.67 - 8.68 -TEST(Compare, Int) { 8.69 - test_compare<int>(cx_cmp_int); 8.70 -} 8.71 - 8.72 -TEST(Compare, Longint) { 8.73 - test_compare<long int>(cx_cmp_longint); 8.74 -} 8.75 - 8.76 -TEST(Compare, Longlong) { 8.77 - test_compare<long long>(cx_cmp_longlong); 8.78 -} 8.79 - 8.80 -TEST(Compare, Int16) { 8.81 - test_compare<int16_t>(cx_cmp_int16); 8.82 -} 8.83 - 8.84 -TEST(Compare, Int32) { 8.85 - test_compare<int32_t>(cx_cmp_int32); 8.86 -} 8.87 - 8.88 -TEST(Compare, Int64) { 8.89 - test_compare<int64_t>(cx_cmp_int64); 8.90 -} 8.91 - 8.92 -TEST(Compare, Uint) { 8.93 - test_compare<unsigned int>(cx_cmp_uint); 8.94 -} 8.95 - 8.96 -TEST(Compare, Ulongint) { 8.97 - test_compare<unsigned long int>(cx_cmp_ulongint); 8.98 -} 8.99 - 8.100 -TEST(Compare, Ulonglong) { 8.101 - test_compare<unsigned long long>(cx_cmp_ulonglong); 8.102 -} 8.103 - 8.104 -TEST(Compare, Uint16) { 8.105 - test_compare<uint16_t>(cx_cmp_uint16); 8.106 -} 8.107 - 8.108 -TEST(Compare, Uint32) { 8.109 - test_compare<uint32_t>(cx_cmp_uint32); 8.110 -} 8.111 - 8.112 -TEST(Compare, Uint64) { 8.113 - test_compare<uint64_t>(cx_cmp_uint64); 8.114 -} 8.115 - 8.116 -TEST(Compare, Float) { 8.117 - test_compare<float>(cx_cmp_float); 8.118 -} 8.119 - 8.120 -TEST(Compare, Double) { 8.121 - test_compare<double>(cx_cmp_double); 8.122 -} 8.123 - 8.124 -TEST(Compare, IntPtr) { 8.125 - test_compare<intptr_t>(cx_cmp_intptr); 8.126 -} 8.127 - 8.128 -TEST(Compare, UintPtr) { 8.129 - test_compare<uintptr_t>(cx_cmp_uintptr); 8.130 -}
9.1 --- a/test/test_hash_key.cpp Tue Feb 07 21:53:06 2023 +0100 9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 9.3 @@ -1,87 +0,0 @@ 9.4 -/* 9.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 9.6 - * 9.7 - * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 9.8 - * 9.9 - * Redistribution and use in source and binary forms, with or without 9.10 - * modification, are permitted provided that the following conditions are met: 9.11 - * 9.12 - * 1. Redistributions of source code must retain the above copyright 9.13 - * notice, this list of conditions and the following disclaimer. 9.14 - * 9.15 - * 2. Redistributions in binary form must reproduce the above copyright 9.16 - * notice, this list of conditions and the following disclaimer in the 9.17 - * documentation and/or other materials provided with the distribution. 9.18 - * 9.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 9.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 9.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 9.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 9.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 9.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 9.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 9.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 9.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 9.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 9.29 - * POSSIBILITY OF SUCH DAMAGE. 9.30 - */ 9.31 - 9.32 -#include "cx/hash_key.h" 9.33 - 9.34 -#include <gtest/gtest.h> 9.35 - 9.36 -TEST(cx_hash_key, functions) { 9.37 - auto str = "my key"; 9.38 - auto len = strlen(str); 9.39 - 9.40 - auto str_key = cx_hash_key_str(str); 9.41 - auto bytes_key = cx_hash_key_bytes( 9.42 - reinterpret_cast<unsigned char const *>(str), len); 9.43 - auto obj_key = cx_hash_key( 9.44 - reinterpret_cast<void const *>(str), len); 9.45 - 9.46 - EXPECT_EQ(str_key.hash, bytes_key.hash); 9.47 - EXPECT_EQ(obj_key.hash, bytes_key.hash); 9.48 - EXPECT_EQ(str_key.len, len); 9.49 - EXPECT_EQ(bytes_key.len, len); 9.50 - EXPECT_EQ(bytes_key.len, len); 9.51 - EXPECT_EQ(str_key.data.cstr, str); 9.52 - EXPECT_EQ(bytes_key.data.cbytes, reinterpret_cast<unsigned char const *>(str)); 9.53 - EXPECT_EQ(bytes_key.data.cobj, reinterpret_cast<void const *>(str)); 9.54 -} 9.55 - 9.56 -TEST(cx_hash_key, empty_string) { 9.57 - auto str = ""; 9.58 - 9.59 - auto str_key = cx_hash_key_str(str); 9.60 - auto bytes_key = cx_hash_key_bytes( 9.61 - reinterpret_cast<unsigned char const *>(str), 0); 9.62 - auto obj_key = cx_hash_key( 9.63 - reinterpret_cast<void const *>(str), 0); 9.64 - 9.65 - EXPECT_EQ(bytes_key.hash, 4152238450u); 9.66 - EXPECT_EQ(str_key.hash, 4152238450u); 9.67 - EXPECT_EQ(obj_key.hash, 4152238450u); 9.68 - EXPECT_EQ(str_key.len, 0); 9.69 - EXPECT_EQ(bytes_key.len, 0); 9.70 - EXPECT_EQ(bytes_key.len, 0); 9.71 - EXPECT_EQ(str_key.data.cstr, str); 9.72 - EXPECT_EQ(bytes_key.data.cbytes, reinterpret_cast<unsigned char const *>(str)); 9.73 - EXPECT_EQ(bytes_key.data.cobj, reinterpret_cast<void const *>(str)); 9.74 -} 9.75 - 9.76 -TEST(cx_hash_key, null_ptr) { 9.77 - auto str_key = cx_hash_key_str(nullptr); 9.78 - auto bytes_key = cx_hash_key_bytes(nullptr, 0); 9.79 - auto obj_key = cx_hash_key(nullptr, 0); 9.80 - 9.81 - EXPECT_EQ(bytes_key.hash, 1574210520u); 9.82 - EXPECT_EQ(str_key.hash, 1574210520u); 9.83 - EXPECT_EQ(obj_key.hash, 1574210520u); 9.84 - EXPECT_EQ(str_key.len, 0); 9.85 - EXPECT_EQ(bytes_key.len, 0); 9.86 - EXPECT_EQ(bytes_key.len, 0); 9.87 - EXPECT_EQ(str_key.data.cstr, nullptr); 9.88 - EXPECT_EQ(bytes_key.data.cbytes, nullptr); 9.89 - EXPECT_EQ(bytes_key.data.cobj, nullptr); 9.90 -}
10.1 --- a/test/test_list.cpp Tue Feb 07 21:53:06 2023 +0100 10.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 10.3 @@ -1,1077 +0,0 @@ 10.4 -/* 10.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 10.6 - * 10.7 - * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 10.8 - * 10.9 - * Redistribution and use in source and binary forms, with or without 10.10 - * modification, are permitted provided that the following conditions are met: 10.11 - * 10.12 - * 1. Redistributions of source code must retain the above copyright 10.13 - * notice, this list of conditions and the following disclaimer. 10.14 - * 10.15 - * 2. Redistributions in binary form must reproduce the above copyright 10.16 - * notice, this list of conditions and the following disclaimer in the 10.17 - * documentation and/or other materials provided with the distribution. 10.18 - * 10.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 10.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 10.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 10.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 10.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 10.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 10.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 10.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 10.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 10.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 10.29 - * POSSIBILITY OF SUCH DAMAGE. 10.30 - */ 10.31 - 10.32 -#include "cx/linked_list.h" 10.33 -#include "cx/array_list.h" 10.34 -#include "cx/utils.h" 10.35 -#include "cx/compare.h" 10.36 -#include "util_allocator.h" 10.37 - 10.38 -#include <gtest/gtest.h> 10.39 -#include <array> 10.40 -#include <vector> 10.41 -#include <unordered_set> 10.42 -#include <algorithm> 10.43 - 10.44 -struct node { 10.45 - node *next = nullptr; 10.46 - node *prev = nullptr; 10.47 - int data = 0; 10.48 -}; 10.49 - 10.50 -const ptrdiff_t loc_prev = offsetof(struct node, prev); 10.51 -const ptrdiff_t loc_next = offsetof(struct node, next); 10.52 -const ptrdiff_t loc_data = offsetof(struct node, data); 10.53 - 10.54 -struct node_test_data { 10.55 - node *begin = nullptr; 10.56 - 10.57 - explicit node_test_data(node *begin) : begin(begin) { 10.58 - auto n = begin; 10.59 - while (n != nullptr) { 10.60 - nodes.push_back(n); 10.61 - n = n->next; 10.62 - } 10.63 - } 10.64 - 10.65 - node_test_data(node_test_data &) = delete; 10.66 - 10.67 - node_test_data(node_test_data &&) = default; 10.68 - 10.69 - ~node_test_data() { 10.70 - for (auto &&n: nodes) delete n; 10.71 - } 10.72 - 10.73 -private: 10.74 - std::vector<node *> nodes; 10.75 -}; 10.76 - 10.77 -static node_test_data create_nodes_test_data(size_t len) { 10.78 - if (len == 0) return node_test_data{nullptr}; 10.79 - auto begin = new node; 10.80 - auto prev = begin; 10.81 - for (size_t i = 1; i < len; i++) { 10.82 - auto n = new node; 10.83 - cx_linked_list_link(prev, n, loc_prev, loc_next); 10.84 - prev = n; 10.85 - } 10.86 - return node_test_data{begin}; 10.87 -} 10.88 - 10.89 -template<typename InputIter> 10.90 -static node_test_data create_nodes_test_data( 10.91 - InputIter begin, 10.92 - InputIter end 10.93 -) { 10.94 - if (begin == end) return node_test_data{nullptr}; 10.95 - node *first = new node; 10.96 - first->data = *begin; 10.97 - node *prev = first; 10.98 - begin++; 10.99 - for (; begin != end; begin++) { 10.100 - auto n = new node; 10.101 - n->data = *begin; 10.102 - cx_linked_list_link(prev, n, loc_prev, loc_next); 10.103 - prev = n; 10.104 - } 10.105 - return node_test_data{first}; 10.106 -} 10.107 - 10.108 -static node_test_data create_nodes_test_data(std::initializer_list<int> data) { 10.109 - return create_nodes_test_data(data.begin(), data.end()); 10.110 -} 10.111 - 10.112 -template<size_t N> 10.113 -struct int_test_data { 10.114 - std::array<int, N> data; 10.115 - 10.116 - int_test_data() { 10.117 - cx_for_n (i, N) data[i] = ::rand(); // NOLINT(cert-msc50-cpp) 10.118 - } 10.119 -}; 10.120 - 10.121 -TEST(LinkedList_LowLevel, link_unlink) { 10.122 - node a, b, c; 10.123 - 10.124 - cx_linked_list_link(&a, &b, loc_prev, loc_next); 10.125 - EXPECT_EQ(a.prev, nullptr); 10.126 - EXPECT_EQ(a.next, &b); 10.127 - EXPECT_EQ(b.prev, &a); 10.128 - EXPECT_EQ(b.next, nullptr); 10.129 - 10.130 - cx_linked_list_unlink(&a, &b, loc_prev, loc_next); 10.131 - EXPECT_EQ(a.prev, nullptr); 10.132 - EXPECT_EQ(a.next, nullptr); 10.133 - EXPECT_EQ(b.prev, nullptr); 10.134 - EXPECT_EQ(b.next, nullptr); 10.135 - 10.136 - cx_linked_list_link(&b, &c, loc_prev, loc_next); 10.137 - cx_linked_list_link(&a, &b, loc_prev, loc_next); 10.138 - cx_linked_list_unlink(&b, &c, loc_prev, loc_next); 10.139 - EXPECT_EQ(a.prev, nullptr); 10.140 - EXPECT_EQ(a.next, &b); 10.141 - EXPECT_EQ(b.prev, &a); 10.142 - EXPECT_EQ(b.next, nullptr); 10.143 - EXPECT_EQ(c.prev, nullptr); 10.144 - EXPECT_EQ(c.next, nullptr); 10.145 -} 10.146 - 10.147 -TEST(LinkedList_LowLevel, cx_linked_list_at) { 10.148 - node a, b, c, d; 10.149 - cx_linked_list_link(&a, &b, loc_prev, loc_next); 10.150 - cx_linked_list_link(&b, &c, loc_prev, loc_next); 10.151 - cx_linked_list_link(&c, &d, loc_prev, loc_next); 10.152 - 10.153 - EXPECT_EQ(cx_linked_list_at(&a, 0, loc_next, 0), &a); 10.154 - EXPECT_EQ(cx_linked_list_at(&a, 0, loc_next, 1), &b); 10.155 - EXPECT_EQ(cx_linked_list_at(&a, 0, loc_next, 2), &c); 10.156 - EXPECT_EQ(cx_linked_list_at(&a, 0, loc_next, 3), &d); 10.157 - EXPECT_EQ(cx_linked_list_at(&a, 0, loc_next, 4), nullptr); 10.158 - 10.159 - EXPECT_EQ(cx_linked_list_at(&b, 1, loc_prev, 0), &a); 10.160 - EXPECT_EQ(cx_linked_list_at(&b, 1, loc_next, 1), &b); 10.161 - EXPECT_EQ(cx_linked_list_at(&b, 1, loc_next, 2), &c); 10.162 - EXPECT_EQ(cx_linked_list_at(&b, 1, loc_next, 3), &d); 10.163 - EXPECT_EQ(cx_linked_list_at(&b, 1, loc_next, 4), nullptr); 10.164 - 10.165 - EXPECT_EQ(cx_linked_list_at(&d, 3, loc_prev, 0), &a); 10.166 - EXPECT_EQ(cx_linked_list_at(&d, 3, loc_prev, 1), &b); 10.167 -} 10.168 - 10.169 -TEST(LinkedList_LowLevel, cx_linked_list_find) { 10.170 - auto testdata = create_nodes_test_data({2, 4, 6, 8}); 10.171 - auto list = testdata.begin; 10.172 - int s; 10.173 - 10.174 - s = 2; 10.175 - EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 0); 10.176 - s = 4; 10.177 - EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 1); 10.178 - s = 6; 10.179 - EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 2); 10.180 - s = 8; 10.181 - EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 3); 10.182 - s = 10; 10.183 - EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 4); 10.184 - s = -2; 10.185 - EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 4); 10.186 -} 10.187 - 10.188 -TEST(LinkedList_LowLevel, cx_linked_list_compare) { 10.189 - auto ta = create_nodes_test_data({2, 4, 6, 8}); 10.190 - auto tb = create_nodes_test_data({2, 4, 6}); 10.191 - auto tc = create_nodes_test_data({2, 4, 6, 9}); 10.192 - auto la = ta.begin, lb = tb.begin, lc = tc.begin; 10.193 - 10.194 - EXPECT_GT(cx_linked_list_compare(la, lb, loc_next, loc_data, cx_cmp_int), 0); 10.195 - EXPECT_LT(cx_linked_list_compare(lb, la, loc_next, loc_data, cx_cmp_int), 0); 10.196 - EXPECT_GT(cx_linked_list_compare(lc, la, loc_next, loc_data, cx_cmp_int), 0); 10.197 - EXPECT_LT(cx_linked_list_compare(la, lc, loc_next, loc_data, cx_cmp_int), 0); 10.198 - EXPECT_EQ(cx_linked_list_compare(la, la, loc_next, loc_data, cx_cmp_int), 0); 10.199 -} 10.200 - 10.201 -TEST(LinkedList_LowLevel, cx_linked_list_add) { 10.202 - // test with begin, end / prev, next 10.203 - { 10.204 - node nodes[4]; 10.205 - void *begin = nullptr, *end = nullptr; 10.206 - 10.207 - cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[0]); 10.208 - EXPECT_EQ(begin, &nodes[0]); 10.209 - EXPECT_EQ(end, &nodes[0]); 10.210 - EXPECT_EQ(nodes[0].prev, nullptr); 10.211 - EXPECT_EQ(nodes[0].next, nullptr); 10.212 - 10.213 - cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[1]); 10.214 - EXPECT_EQ(begin, &nodes[0]); 10.215 - EXPECT_EQ(end, &nodes[1]); 10.216 - EXPECT_EQ(nodes[0].next, &nodes[1]); 10.217 - EXPECT_EQ(nodes[1].prev, &nodes[0]); 10.218 - } 10.219 - 10.220 - // test with begin only / prev, next 10.221 - { 10.222 - node nodes[4]; 10.223 - void *begin = nullptr; 10.224 - 10.225 - cx_linked_list_add(&begin, nullptr, loc_prev, loc_next, &nodes[0]); 10.226 - EXPECT_EQ(begin, &nodes[0]); 10.227 - cx_linked_list_add(&begin, nullptr, loc_prev, loc_next, &nodes[1]); 10.228 - EXPECT_EQ(begin, &nodes[0]); 10.229 - EXPECT_EQ(nodes[0].next, &nodes[1]); 10.230 - EXPECT_EQ(nodes[1].prev, &nodes[0]); 10.231 - 10.232 - cx_linked_list_add(&begin, nullptr, loc_prev, loc_next, &nodes[2]); 10.233 - EXPECT_EQ(nodes[1].next, &nodes[2]); 10.234 - EXPECT_EQ(nodes[2].prev, &nodes[1]); 10.235 - } 10.236 - 10.237 - // test with end only / prev, next 10.238 - { 10.239 - node nodes[4]; 10.240 - void *end = nullptr; 10.241 - 10.242 - cx_linked_list_add(nullptr, &end, loc_prev, loc_next, &nodes[0]); 10.243 - EXPECT_EQ(end, &nodes[0]); 10.244 - cx_linked_list_add(nullptr, &end, loc_prev, loc_next, &nodes[1]); 10.245 - EXPECT_EQ(end, &nodes[1]); 10.246 - EXPECT_EQ(nodes[0].next, &nodes[1]); 10.247 - EXPECT_EQ(nodes[1].prev, &nodes[0]); 10.248 - 10.249 - cx_linked_list_add(nullptr, &end, loc_prev, loc_next, &nodes[2]); 10.250 - EXPECT_EQ(end, &nodes[2]); 10.251 - EXPECT_EQ(nodes[1].next, &nodes[2]); 10.252 - EXPECT_EQ(nodes[2].prev, &nodes[1]); 10.253 - } 10.254 - 10.255 - // test with begin, end / next 10.256 - { 10.257 - node nodes[4]; 10.258 - void *begin = nullptr, *end = nullptr; 10.259 - 10.260 - cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[0]); 10.261 - EXPECT_EQ(begin, &nodes[0]); 10.262 - EXPECT_EQ(end, &nodes[0]); 10.263 - cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[1]); 10.264 - EXPECT_EQ(end, &nodes[1]); 10.265 - EXPECT_EQ(nodes[0].next, &nodes[1]); 10.266 - EXPECT_EQ(nodes[1].prev, nullptr); 10.267 - } 10.268 -} 10.269 - 10.270 -TEST(LinkedList_LowLevel, cx_linked_list_prepend) { 10.271 - // test with begin, end / prev, next 10.272 - { 10.273 - node nodes[4]; 10.274 - void *begin = nullptr, *end = nullptr; 10.275 - 10.276 - cx_linked_list_prepend(&begin, &end, loc_prev, loc_next, &nodes[0]); 10.277 - EXPECT_EQ(begin, &nodes[0]); 10.278 - EXPECT_EQ(end, &nodes[0]); 10.279 - EXPECT_EQ(nodes[0].prev, nullptr); 10.280 - EXPECT_EQ(nodes[0].next, nullptr); 10.281 - 10.282 - cx_linked_list_prepend(&begin, &end, loc_prev, loc_next, &nodes[1]); 10.283 - EXPECT_EQ(begin, &nodes[1]); 10.284 - EXPECT_EQ(end, &nodes[0]); 10.285 - EXPECT_EQ(nodes[1].next, &nodes[0]); 10.286 - EXPECT_EQ(nodes[0].prev, &nodes[1]); 10.287 - } 10.288 - 10.289 - // test with begin only / prev, next 10.290 - { 10.291 - node nodes[4]; 10.292 - void *begin = nullptr; 10.293 - 10.294 - cx_linked_list_prepend(&begin, nullptr, loc_prev, loc_next, &nodes[0]); 10.295 - EXPECT_EQ(begin, &nodes[0]); 10.296 - cx_linked_list_prepend(&begin, nullptr, loc_prev, loc_next, &nodes[1]); 10.297 - EXPECT_EQ(begin, &nodes[1]); 10.298 - EXPECT_EQ(nodes[1].next, &nodes[0]); 10.299 - EXPECT_EQ(nodes[0].prev, &nodes[1]); 10.300 - 10.301 - cx_linked_list_prepend(&begin, nullptr, loc_prev, loc_next, &nodes[2]); 10.302 - EXPECT_EQ(begin, &nodes[2]); 10.303 - EXPECT_EQ(nodes[2].next, &nodes[1]); 10.304 - EXPECT_EQ(nodes[1].prev, &nodes[2]); 10.305 - } 10.306 - 10.307 - // test with end only / prev, next 10.308 - { 10.309 - node nodes[4]; 10.310 - void *end = nullptr; 10.311 - 10.312 - cx_linked_list_prepend(nullptr, &end, loc_prev, loc_next, &nodes[0]); 10.313 - EXPECT_EQ(end, &nodes[0]); 10.314 - cx_linked_list_prepend(nullptr, &end, loc_prev, loc_next, &nodes[1]); 10.315 - EXPECT_EQ(end, &nodes[0]); 10.316 - EXPECT_EQ(nodes[1].next, &nodes[0]); 10.317 - EXPECT_EQ(nodes[0].prev, &nodes[1]); 10.318 - 10.319 - cx_linked_list_prepend(nullptr, &end, loc_prev, loc_next, &nodes[2]); 10.320 - EXPECT_EQ(end, &nodes[0]); 10.321 - EXPECT_EQ(nodes[2].next, &nodes[1]); 10.322 - EXPECT_EQ(nodes[1].prev, &nodes[2]); 10.323 - } 10.324 - 10.325 - // test with begin, end / next 10.326 - { 10.327 - node nodes[4]; 10.328 - void *begin = nullptr, *end = nullptr; 10.329 - 10.330 - cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[0]); 10.331 - EXPECT_EQ(begin, &nodes[0]); 10.332 - EXPECT_EQ(end, &nodes[0]); 10.333 - cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[1]); 10.334 - cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[2]); 10.335 - EXPECT_EQ(begin, &nodes[2]); 10.336 - EXPECT_EQ(end, &nodes[0]); 10.337 - EXPECT_EQ(nodes[1].next, &nodes[0]); 10.338 - EXPECT_EQ(nodes[2].next, &nodes[1]); 10.339 - EXPECT_EQ(nodes[1].prev, nullptr); 10.340 - EXPECT_EQ(nodes[0].prev, nullptr); 10.341 - } 10.342 -} 10.343 - 10.344 -TEST(LinkedList_LowLevel, cx_linked_list_insert) { 10.345 - // insert mid list 10.346 - { 10.347 - node nodes[4]; 10.348 - void *begin = &nodes[0], *end = &nodes[2]; 10.349 - 10.350 - cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 10.351 - cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 10.352 - 10.353 - cx_linked_list_insert(&begin, &end, loc_prev, loc_next, &nodes[1], &nodes[3]); 10.354 - EXPECT_EQ(begin, &nodes[0]); 10.355 - EXPECT_EQ(end, &nodes[2]); 10.356 - EXPECT_EQ(nodes[1].next, &nodes[3]); 10.357 - EXPECT_EQ(nodes[2].prev, &nodes[3]); 10.358 - EXPECT_EQ(nodes[3].prev, &nodes[1]); 10.359 - EXPECT_EQ(nodes[3].next, &nodes[2]); 10.360 - } 10.361 - 10.362 - // insert end 10.363 - { 10.364 - node nodes[4]; 10.365 - void *begin = &nodes[0], *end = &nodes[2]; 10.366 - 10.367 - cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 10.368 - cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 10.369 - 10.370 - cx_linked_list_insert(&begin, &end, loc_prev, loc_next, &nodes[2], &nodes[3]); 10.371 - EXPECT_EQ(begin, &nodes[0]); 10.372 - EXPECT_EQ(end, &nodes[3]); 10.373 - EXPECT_EQ(nodes[2].next, &nodes[3]); 10.374 - EXPECT_EQ(nodes[3].prev, &nodes[2]); 10.375 - EXPECT_EQ(nodes[3].next, nullptr); 10.376 - } 10.377 - 10.378 - // insert begin 10.379 - { 10.380 - node nodes[4]; 10.381 - void *begin = &nodes[0], *end = &nodes[2]; 10.382 - 10.383 - cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 10.384 - cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 10.385 - 10.386 - cx_linked_list_insert(&begin, &end, loc_prev, loc_next, nullptr, &nodes[3]); 10.387 - EXPECT_EQ(begin, &nodes[3]); 10.388 - EXPECT_EQ(end, &nodes[2]); 10.389 - EXPECT_EQ(nodes[0].prev, &nodes[3]); 10.390 - EXPECT_EQ(nodes[3].prev, nullptr); 10.391 - EXPECT_EQ(nodes[3].next, &nodes[0]); 10.392 - } 10.393 -} 10.394 - 10.395 -TEST(LinkedList_LowLevel, cx_linked_list_insert_chain) { 10.396 - // insert mid list 10.397 - { 10.398 - node nodes[5]; 10.399 - void *begin = &nodes[0], *end = &nodes[2]; 10.400 - 10.401 - cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 10.402 - cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 10.403 - cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); 10.404 - 10.405 - cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, &nodes[1], &nodes[3], nullptr); 10.406 - EXPECT_EQ(begin, &nodes[0]); 10.407 - EXPECT_EQ(end, &nodes[2]); 10.408 - EXPECT_EQ(nodes[1].next, &nodes[3]); 10.409 - EXPECT_EQ(nodes[2].prev, &nodes[4]); 10.410 - EXPECT_EQ(nodes[3].prev, &nodes[1]); 10.411 - EXPECT_EQ(nodes[4].next, &nodes[2]); 10.412 - } 10.413 - 10.414 - // insert end 10.415 - { 10.416 - node nodes[5]; 10.417 - void *begin = &nodes[0], *end = &nodes[2]; 10.418 - 10.419 - cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 10.420 - cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 10.421 - cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); 10.422 - 10.423 - cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, &nodes[2], &nodes[3], nullptr); 10.424 - EXPECT_EQ(begin, &nodes[0]); 10.425 - EXPECT_EQ(end, &nodes[4]); 10.426 - EXPECT_EQ(nodes[2].next, &nodes[3]); 10.427 - EXPECT_EQ(nodes[3].prev, &nodes[2]); 10.428 - EXPECT_EQ(nodes[4].next, nullptr); 10.429 - } 10.430 - 10.431 - // insert begin 10.432 - { 10.433 - node nodes[5]; 10.434 - void *begin = &nodes[0], *end = &nodes[2]; 10.435 - 10.436 - cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 10.437 - cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 10.438 - cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); 10.439 - 10.440 - cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, nullptr, &nodes[3], nullptr); 10.441 - EXPECT_EQ(begin, &nodes[3]); 10.442 - EXPECT_EQ(end, &nodes[2]); 10.443 - EXPECT_EQ(nodes[0].prev, &nodes[4]); 10.444 - EXPECT_EQ(nodes[3].prev, nullptr); 10.445 - EXPECT_EQ(nodes[4].next, &nodes[0]); 10.446 - } 10.447 -} 10.448 - 10.449 -TEST(LinkedList_LowLevel, cx_linked_list_first) { 10.450 - auto testdata = create_nodes_test_data(3); 10.451 - auto begin = testdata.begin; 10.452 - EXPECT_EQ(cx_linked_list_first(begin, loc_prev), begin); 10.453 - EXPECT_EQ(cx_linked_list_first(begin->next, loc_prev), begin); 10.454 - EXPECT_EQ(cx_linked_list_first(begin->next->next, loc_prev), begin); 10.455 -} 10.456 - 10.457 -TEST(LinkedList_LowLevel, cx_linked_list_last) { 10.458 - auto testdata = create_nodes_test_data(3); 10.459 - auto begin = testdata.begin; 10.460 - auto end = begin->next->next; 10.461 - EXPECT_EQ(cx_linked_list_last(begin, loc_next), end); 10.462 - EXPECT_EQ(cx_linked_list_last(begin->next, loc_next), end); 10.463 - EXPECT_EQ(cx_linked_list_last(begin->next->next, loc_next), end); 10.464 -} 10.465 - 10.466 -TEST(LinkedList_LowLevel, cx_linked_list_prev) { 10.467 - auto testdata = create_nodes_test_data(3); 10.468 - auto begin = testdata.begin; 10.469 - EXPECT_EQ(cx_linked_list_prev(begin, loc_next, begin), nullptr); 10.470 - EXPECT_EQ(cx_linked_list_prev(begin, loc_next, begin->next), begin); 10.471 - EXPECT_EQ(cx_linked_list_prev(begin, loc_next, begin->next->next), begin->next); 10.472 -} 10.473 - 10.474 -TEST(LinkedList_LowLevel, cx_linked_list_remove) { 10.475 - auto testdata = create_nodes_test_data({2, 4, 6}); 10.476 - auto begin = reinterpret_cast<void *>(testdata.begin); 10.477 - auto first = testdata.begin; 10.478 - auto second = first->next; 10.479 - auto third = second->next; 10.480 - auto end = reinterpret_cast<void *>(third); 10.481 - 10.482 - cx_linked_list_remove(&begin, &end, loc_prev, loc_next, second); 10.483 - EXPECT_EQ(begin, first); 10.484 - EXPECT_EQ(end, third); 10.485 - EXPECT_EQ(first->prev, nullptr); 10.486 - EXPECT_EQ(first->next, third); 10.487 - EXPECT_EQ(third->prev, first); 10.488 - EXPECT_EQ(third->next, nullptr); 10.489 - 10.490 - cx_linked_list_remove(&begin, &end, loc_prev, loc_next, third); 10.491 - EXPECT_EQ(begin, first); 10.492 - EXPECT_EQ(end, first); 10.493 - EXPECT_EQ(first->prev, nullptr); 10.494 - EXPECT_EQ(first->next, nullptr); 10.495 - 10.496 - cx_linked_list_remove(&begin, &end, loc_prev, loc_next, first); 10.497 - EXPECT_EQ(begin, nullptr); 10.498 - EXPECT_EQ(end, nullptr); 10.499 -} 10.500 - 10.501 -TEST(LinkedList_LowLevel, cx_linked_list_size) { 10.502 - EXPECT_EQ(cx_linked_list_size(nullptr, loc_next), 0); 10.503 - 10.504 - { 10.505 - auto testdata = create_nodes_test_data(5); 10.506 - EXPECT_EQ(cx_linked_list_size(testdata.begin, loc_next), 5); 10.507 - } 10.508 - 10.509 - { 10.510 - auto testdata = create_nodes_test_data(13); 10.511 - EXPECT_EQ(cx_linked_list_size(testdata.begin, loc_next), 13); 10.512 - } 10.513 -} 10.514 - 10.515 -TEST(LinkedList_LowLevel, cx_linked_list_sort) { 10.516 - int_test_data<1500> testdata; 10.517 - std::array<int, 1500> sorted{}; 10.518 - std::partial_sort_copy(testdata.data.begin(), testdata.data.end(), sorted.begin(), sorted.end()); 10.519 - 10.520 - auto scrambled = create_nodes_test_data(testdata.data.begin(), testdata.data.end()); 10.521 - void *begin = scrambled.begin; 10.522 - void *end = cx_linked_list_last(begin, loc_next); 10.523 - 10.524 - cx_linked_list_sort(&begin, &end, loc_prev, loc_next, loc_data, cx_cmp_int); 10.525 - 10.526 - node *check = reinterpret_cast<node *>(begin); 10.527 - node *check_last = nullptr; 10.528 - cx_for_n (i, sorted.size()) { 10.529 - EXPECT_EQ(check->data, sorted[i]); 10.530 - EXPECT_EQ(check->prev, check_last); 10.531 - if (i < sorted.size() - 1) { 10.532 - ASSERT_NE(check->next, nullptr); 10.533 - } 10.534 - check_last = check; 10.535 - check = check->next; 10.536 - } 10.537 - EXPECT_EQ(check, nullptr); 10.538 - EXPECT_EQ(end, check_last); 10.539 -} 10.540 - 10.541 -TEST(LinkedList_LowLevel, cx_linked_list_reverse) { 10.542 - auto testdata = create_nodes_test_data({2, 4, 6, 8}); 10.543 - auto expected = create_nodes_test_data({8, 6, 4, 2}); 10.544 - 10.545 - auto begin = reinterpret_cast<void *>(testdata.begin); 10.546 - auto end = cx_linked_list_last(begin, loc_next); 10.547 - auto orig_begin = begin, orig_end = end; 10.548 - 10.549 - cx_linked_list_reverse(&begin, &end, loc_prev, loc_next); 10.550 - EXPECT_EQ(end, orig_begin); 10.551 - EXPECT_EQ(begin, orig_end); 10.552 - EXPECT_EQ(cx_linked_list_compare(begin, expected.begin, loc_next, loc_data, cx_cmp_int), 0); 10.553 -} 10.554 - 10.555 -class HighLevelTest : public ::testing::Test { 10.556 - mutable std::unordered_set<CxList *> lists; 10.557 -protected: 10.558 - CxTestingAllocator testingAllocator; 10.559 - 10.560 - void TearDown() override { 10.561 - for (auto &&l: lists) cxListDestroy(l); 10.562 - EXPECT_TRUE(testingAllocator.verify()); 10.563 - } 10.564 - 10.565 - static constexpr size_t testdata_len = 250; 10.566 - int_test_data<testdata_len> testdata; 10.567 - 10.568 - auto autofree(CxList *list) const -> CxList * { 10.569 - if (list != nullptr) lists.insert(list); 10.570 - return list; 10.571 - } 10.572 - 10.573 - auto linkedListFromTestData() const -> CxList * { 10.574 - auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 10.575 - cxListAddArray(list, testdata.data.data(), testdata_len); 10.576 - return list; 10.577 - } 10.578 - 10.579 - auto pointerLinkedListFromTestData() const -> CxList * { 10.580 - auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 10.581 - cxListStorePointers(list); 10.582 - // note: cannot use cxListAddArray() because we don't have a list of pointers 10.583 - cx_for_n(i, testdata_len) cxListAdd(list, &testdata.data[i]); 10.584 - return list; 10.585 - } 10.586 - 10.587 - auto arrayListFromTestData() const -> CxList * { 10.588 - auto list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), testdata_len)); 10.589 - cxListAddArray(list, testdata.data.data(), testdata_len); 10.590 - return list; 10.591 - } 10.592 - 10.593 - void verifyCreate(CxList *list) const { 10.594 - EXPECT_EQ(list->content_destructor_type, CX_DESTRUCTOR_NONE); 10.595 - EXPECT_EQ(list->size, 0); 10.596 - EXPECT_EQ(list->allocator, &testingAllocator); 10.597 - EXPECT_EQ(list->cmpfunc, cx_cmp_int); 10.598 - } 10.599 - 10.600 - void verifyAdd( 10.601 - CxList *list, 10.602 - bool as_pointer 10.603 - ) { 10.604 - auto len = testdata_len; 10.605 - cx_for_n (i, len) EXPECT_EQ(cxListAdd(list, &testdata.data[i]), 0); 10.606 - EXPECT_EQ(list->size, len); 10.607 - EXPECT_GE(list->capacity, list->size); 10.608 - cx_for_n (i, len) EXPECT_EQ(*(int *) cxListAt(list, i), testdata.data[i]); 10.609 - cx_for_n (i, len) ++testdata.data[i]; 10.610 - if (as_pointer) { 10.611 - cx_for_n (i, len) EXPECT_EQ(*(int *) cxListAt(list, i), testdata.data[i]); 10.612 - } else { 10.613 - cx_for_n (i, len) EXPECT_EQ(*(int *) cxListAt(list, i), testdata.data[i] - 1); 10.614 - } 10.615 - } 10.616 - 10.617 - static void verifyInsert(CxList *list) { 10.618 - int a = 5, b = 47, c = 13, d = 42; 10.619 - 10.620 - EXPECT_NE(cxListInsert(list, 1, &a), 0); 10.621 - EXPECT_EQ(list->size, 0); 10.622 - EXPECT_EQ(cxListInsert(list, 0, &a), 0); 10.623 - EXPECT_EQ(list->size, 1); 10.624 - EXPECT_EQ(cxListInsert(list, 0, &b), 0); 10.625 - EXPECT_EQ(list->size, 2); 10.626 - EXPECT_EQ(cxListInsert(list, 1, &c), 0); 10.627 - EXPECT_EQ(list->size, 3); 10.628 - EXPECT_EQ(cxListInsert(list, 3, &d), 0); 10.629 - 10.630 - ASSERT_EQ(list->size, 4); 10.631 - EXPECT_GE(list->capacity, list->size); 10.632 - 10.633 - EXPECT_EQ(*(int *) cxListAt(list, 0), 47); 10.634 - EXPECT_EQ(*(int *) cxListAt(list, 1), 13); 10.635 - EXPECT_EQ(*(int *) cxListAt(list, 2), 5); 10.636 - EXPECT_EQ(*(int *) cxListAt(list, 3), 42); 10.637 - } 10.638 - 10.639 - static void verifyInsertArray( 10.640 - CxList *list, 10.641 - bool pointers = false 10.642 - ) { 10.643 - int a[5] = {5, 47, 11, 13, 42}; 10.644 - int b[5] = {9, 18, 72, 50, 7}; 10.645 - int *aptr[5]; 10.646 - int *bptr[5]; 10.647 - cx_for_n(i, 5) { 10.648 - aptr[i] = &a[i]; 10.649 - bptr[i] = &b[i]; 10.650 - } 10.651 - 10.652 - size_t inserted; 10.653 - 10.654 - if (pointers) { 10.655 - inserted = cxListInsertArray(list, 0, aptr, 5); 10.656 - } else { 10.657 - inserted = cxListInsertArray(list, 0, a, 5); 10.658 - } 10.659 - EXPECT_EQ(inserted, 5); 10.660 - EXPECT_EQ(*(int *) cxListAt(list, 0), 5); 10.661 - EXPECT_EQ(*(int *) cxListAt(list, 1), 47); 10.662 - EXPECT_EQ(*(int *) cxListAt(list, 2), 11); 10.663 - EXPECT_EQ(*(int *) cxListAt(list, 3), 13); 10.664 - EXPECT_EQ(*(int *) cxListAt(list, 4), 42); 10.665 - if (pointers) { 10.666 - inserted = cxListInsertArray(list, 3, bptr, 5); 10.667 - } else { 10.668 - inserted = cxListInsertArray(list, 3, b, 5); 10.669 - } 10.670 - EXPECT_EQ(inserted, 5); 10.671 - EXPECT_EQ(*(int *) cxListAt(list, 0), 5); 10.672 - EXPECT_EQ(*(int *) cxListAt(list, 1), 47); 10.673 - EXPECT_EQ(*(int *) cxListAt(list, 2), 11); 10.674 - EXPECT_EQ(*(int *) cxListAt(list, 3), 9); 10.675 - EXPECT_EQ(*(int *) cxListAt(list, 4), 18); 10.676 - EXPECT_EQ(*(int *) cxListAt(list, 5), 72); 10.677 - EXPECT_EQ(*(int *) cxListAt(list, 6), 50); 10.678 - EXPECT_EQ(*(int *) cxListAt(list, 7), 7); 10.679 - EXPECT_EQ(*(int *) cxListAt(list, 8), 13); 10.680 - EXPECT_EQ(*(int *) cxListAt(list, 9), 42); 10.681 - } 10.682 - 10.683 - void verifyRemove(CxList *list) const { 10.684 - EXPECT_EQ(cxListRemove(list, 2), 0); 10.685 - EXPECT_EQ(cxListRemove(list, 4), 0); 10.686 - EXPECT_EQ(list->size, testdata_len - 2); 10.687 - EXPECT_GE(list->capacity, list->size); 10.688 - EXPECT_EQ(*(int *) cxListAt(list, 0), testdata.data[0]); 10.689 - EXPECT_EQ(*(int *) cxListAt(list, 1), testdata.data[1]); 10.690 - EXPECT_EQ(*(int *) cxListAt(list, 2), testdata.data[3]); 10.691 - EXPECT_EQ(*(int *) cxListAt(list, 3), testdata.data[4]); 10.692 - EXPECT_EQ(*(int *) cxListAt(list, 4), testdata.data[6]); 10.693 - 10.694 - EXPECT_EQ(cxListRemove(list, 0), 0); 10.695 - EXPECT_EQ(list->size, testdata_len - 3); 10.696 - EXPECT_GE(list->capacity, list->size); 10.697 - EXPECT_EQ(*(int *) cxListAt(list, 0), testdata.data[1]); 10.698 - EXPECT_EQ(*(int *) cxListAt(list, 1), testdata.data[3]); 10.699 - 10.700 - EXPECT_NE(cxListRemove(list, testdata_len), 0); 10.701 - } 10.702 - 10.703 - void verifyAt(CxList *list) const { 10.704 - auto len = testdata_len; 10.705 - EXPECT_EQ(list->size, len); 10.706 - cx_for_n (i, len) { 10.707 - EXPECT_EQ(*(int *) cxListAt(list, i), testdata.data[i]); 10.708 - } 10.709 - EXPECT_EQ(cxListAt(list, list->size), nullptr); 10.710 - } 10.711 - 10.712 - void verifyFind(CxList *list) const { 10.713 - cx_for_n (attempt, 25) { 10.714 - size_t exp = rand() % testdata_len; // NOLINT(cert-msc50-cpp) 10.715 - int val = testdata.data[exp]; 10.716 - // randomly picked number could occur earlier in list - find first position 10.717 - cx_for_n (i, exp) { 10.718 - if (testdata.data[i] == val) { 10.719 - exp = i; 10.720 - break; 10.721 - } 10.722 - } 10.723 - EXPECT_EQ(cxListFind(list, &val), exp); 10.724 - } 10.725 - } 10.726 - 10.727 - void verifySort(CxList *list) const { 10.728 - std::array<int, testdata_len> expected{}; 10.729 - std::partial_sort_copy(testdata.data.begin(), testdata.data.end(), expected.begin(), expected.end()); 10.730 - cxListSort(list); 10.731 - cx_for_n (i, testdata_len) ASSERT_EQ(*(int *) cxListAt(list, i), expected[i]); 10.732 - } 10.733 - 10.734 - void verifyIterator(CxList *list) const { 10.735 - int i = 0; 10.736 - auto iter = cxListBeginMut(list); 10.737 - cx_foreach(int*, x, iter) { 10.738 - ASSERT_EQ(iter.index, (size_t) (i + 1) / 2); 10.739 - ASSERT_EQ(*x, testdata.data[i]); 10.740 - if (i % 2 == 1) cxIteratorFlagRemoval(iter); 10.741 - i++; 10.742 - } 10.743 - auto len = testdata_len; 10.744 - EXPECT_EQ(i, len); 10.745 - ASSERT_EQ(list->size, len / 2); 10.746 - cx_for_n(j, len / 2) ASSERT_EQ(*(int *) cxListAt(list, j), testdata.data[j * 2]); 10.747 - } 10.748 - 10.749 - static void verifyInsertViaIterator(CxList *list) { 10.750 - int newdata[] = {10, 20, 30, 40, 50}; 10.751 - 10.752 - auto iter = cxListMutIterator(list, 2); 10.753 - EXPECT_TRUE(cxIteratorValid(iter)); 10.754 - EXPECT_EQ(iter.index, 2); 10.755 - EXPECT_EQ(*(int *) cxIteratorCurrent(iter), 2); 10.756 - cxListInsertAfter(&iter, &newdata[0]); 10.757 - EXPECT_TRUE(cxIteratorValid(iter)); 10.758 - EXPECT_EQ(iter.index, 2); 10.759 - EXPECT_EQ(*(int *) cxIteratorCurrent(iter), 2); 10.760 - cxListInsertBefore(&iter, &newdata[1]); 10.761 - EXPECT_TRUE(cxIteratorValid(iter)); 10.762 - EXPECT_EQ(iter.index, 3); 10.763 - EXPECT_EQ(*(int *) cxIteratorCurrent(iter), 2); 10.764 - 10.765 - iter = cxListBeginMut(list); 10.766 - cxListInsertBefore(&iter, &newdata[2]); 10.767 - EXPECT_TRUE(cxIteratorValid(iter)); 10.768 - EXPECT_EQ(iter.index, 1); 10.769 - EXPECT_EQ(*(int *) cxIteratorCurrent(iter), 0); 10.770 - iter = cxListMutIterator(list, list->size); 10.771 - cxListInsertBefore(&iter, &newdata[3]); 10.772 - EXPECT_FALSE(cxIteratorValid(iter)); 10.773 - EXPECT_EQ(iter.index, 9); 10.774 - iter = cxListMutIterator(list, list->size); 10.775 - cxListInsertAfter(&iter, &newdata[4]); 10.776 - EXPECT_FALSE(cxIteratorValid(iter)); 10.777 - EXPECT_EQ(iter.index, 10); 10.778 - 10.779 - int expdata[] = {30, 0, 1, 20, 2, 10, 3, 4, 40, 50}; 10.780 - cx_for_n (j, 10) EXPECT_EQ(*(int *) cxListAt(list, j), expdata[j]); 10.781 - } 10.782 - 10.783 - void verifyReverse(CxList *list) const { 10.784 - cxListReverse(list); 10.785 - cx_for_n(i, testdata_len) { 10.786 - ASSERT_EQ(*(int *) cxListAt(list, i), testdata.data[testdata_len - 1 - i]); 10.787 - } 10.788 - } 10.789 - 10.790 - static void verifyCompare( 10.791 - CxList *left, 10.792 - CxList *right 10.793 - ) { 10.794 - EXPECT_EQ(cxListCompare(left, right), 0); 10.795 - int x = 42; 10.796 - cxListAdd(left, &x); 10.797 - ASSERT_GT(left->size, right->size); 10.798 - EXPECT_GT(cxListCompare(left, right), 0); 10.799 - EXPECT_LT(cxListCompare(right, left), 0); 10.800 - cxListAdd(right, &x); 10.801 - ASSERT_EQ(left->size, right->size); 10.802 - EXPECT_EQ(cxListCompare(left, right), 0); 10.803 - int a = 5, b = 10; 10.804 - cxListInsert(left, 15, &a); 10.805 - cxListInsert(right, 15, &b); 10.806 - ASSERT_EQ(left->size, right->size); 10.807 - EXPECT_LT(cxListCompare(left, right), 0); 10.808 - EXPECT_GT(cxListCompare(right, left), 0); 10.809 - *(int *) cxListAt(left, 15) = 10; 10.810 - EXPECT_EQ(cxListCompare(left, right), 0); 10.811 - } 10.812 -}; 10.813 - 10.814 -class LinkedList : public HighLevelTest { 10.815 -}; 10.816 - 10.817 -class PointerLinkedList : public HighLevelTest { 10.818 -}; 10.819 - 10.820 -class ArrayList : public HighLevelTest { 10.821 -}; 10.822 - 10.823 -TEST_F(PointerLinkedList, cxListStorePointers) { 10.824 - auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, 47)); 10.825 - EXPECT_FALSE(cxListIsStoringPointers(list)); 10.826 - cxListStorePointers(list); 10.827 - EXPECT_EQ(list->itemsize, sizeof(void *)); 10.828 - EXPECT_NE(list->cl, nullptr); 10.829 - EXPECT_NE(list->climpl, nullptr); 10.830 - EXPECT_TRUE(cxListIsStoringPointers(list)); 10.831 - cxListStoreObjects(list); 10.832 - EXPECT_NE(list->cl, nullptr); 10.833 - EXPECT_EQ(list->climpl, nullptr); 10.834 - EXPECT_FALSE(cxListIsStoringPointers(list)); 10.835 -} 10.836 - 10.837 -TEST_F(LinkedList, cxLinkedListCreate) { 10.838 - CxList *list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 10.839 - ASSERT_NE(list, nullptr); 10.840 - EXPECT_EQ(list->itemsize, sizeof(int)); 10.841 - EXPECT_EQ(list->capacity, (size_t) -1); 10.842 - verifyCreate(list); 10.843 -} 10.844 - 10.845 -TEST_F(ArrayList, cxArrayListCreate) { 10.846 - CxList *list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 8)); 10.847 - ASSERT_NE(list, nullptr); 10.848 - EXPECT_EQ(list->itemsize, sizeof(int)); 10.849 - EXPECT_EQ(list->capacity, 8); 10.850 - verifyCreate(list); 10.851 -} 10.852 - 10.853 -TEST_F(LinkedList, cxListAdd) { 10.854 - auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 10.855 - verifyAdd(list, false); 10.856 -} 10.857 - 10.858 -TEST_F(PointerLinkedList, cxListAdd) { 10.859 - auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 10.860 - cxListStorePointers(list); 10.861 - verifyAdd(list, true); 10.862 -} 10.863 - 10.864 -TEST_F(ArrayList, cxListAdd) { 10.865 - auto list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 8)); 10.866 - verifyAdd(list, false); 10.867 -} 10.868 - 10.869 -TEST_F(LinkedList, cxListInsert) { 10.870 - verifyInsert(autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)))); 10.871 -} 10.872 - 10.873 -TEST_F(PointerLinkedList, cxListInsert) { 10.874 - auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 10.875 - cxListStorePointers(list); 10.876 - verifyInsert(list); 10.877 -} 10.878 - 10.879 -TEST_F(ArrayList, cxListInsert) { 10.880 - verifyInsert(autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 2))); 10.881 -} 10.882 - 10.883 -TEST_F(LinkedList, cxListInsertArray) { 10.884 - verifyInsertArray(autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)))); 10.885 -} 10.886 - 10.887 -TEST_F(PointerLinkedList, cxListInsertArray) { 10.888 - auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 10.889 - cxListStorePointers(list); 10.890 - verifyInsertArray(list, true); 10.891 -} 10.892 - 10.893 -TEST_F(ArrayList, cxListInsertArray) { 10.894 - verifyInsertArray(autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 4))); 10.895 -} 10.896 - 10.897 -TEST_F(LinkedList, cxListRemove) { 10.898 - verifyRemove(linkedListFromTestData()); 10.899 -} 10.900 - 10.901 -TEST_F(PointerLinkedList, cxListRemove) { 10.902 - verifyRemove(pointerLinkedListFromTestData()); 10.903 -} 10.904 - 10.905 -TEST_F(ArrayList, cxListRemove) { 10.906 - verifyRemove(arrayListFromTestData()); 10.907 -} 10.908 - 10.909 -TEST_F(LinkedList, cxListAt) { 10.910 - verifyAt(linkedListFromTestData()); 10.911 -} 10.912 - 10.913 -TEST_F(PointerLinkedList, cxListAt) { 10.914 - verifyAt(pointerLinkedListFromTestData()); 10.915 -} 10.916 - 10.917 -TEST_F(ArrayList, cxListAt) { 10.918 - verifyAt(arrayListFromTestData()); 10.919 -} 10.920 - 10.921 -TEST_F(LinkedList, cxListFind) { 10.922 - verifyFind(linkedListFromTestData()); 10.923 -} 10.924 - 10.925 -TEST_F(PointerLinkedList, cxListFind) { 10.926 - verifyFind(pointerLinkedListFromTestData()); 10.927 -} 10.928 - 10.929 -TEST_F(ArrayList, cxListFind) { 10.930 - verifyFind(arrayListFromTestData()); 10.931 -} 10.932 - 10.933 -TEST_F(LinkedList, cxListSort) { 10.934 - verifySort(linkedListFromTestData()); 10.935 -} 10.936 - 10.937 -TEST_F(PointerLinkedList, cxListSort) { 10.938 - verifySort(pointerLinkedListFromTestData()); 10.939 -} 10.940 - 10.941 -TEST_F(ArrayList, cxListSort) { 10.942 - verifySort(arrayListFromTestData()); 10.943 -} 10.944 - 10.945 -TEST_F(LinkedList, Iterator) { 10.946 - verifyIterator(linkedListFromTestData()); 10.947 -} 10.948 - 10.949 -TEST_F(PointerLinkedList, Iterator) { 10.950 - verifyIterator(pointerLinkedListFromTestData()); 10.951 -} 10.952 - 10.953 -TEST_F(ArrayList, Iterator) { 10.954 - verifyIterator(arrayListFromTestData()); 10.955 -} 10.956 - 10.957 -TEST_F(LinkedList, InsertViaIterator) { 10.958 - int fivenums[] = {0, 1, 2, 3, 4, 5}; 10.959 - CxList *list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 10.960 - cxListAddArray(list, fivenums, 5); 10.961 - verifyInsertViaIterator(list); 10.962 -} 10.963 - 10.964 -TEST_F(PointerLinkedList, InsertViaIterator) { 10.965 - int fivenums[] = {0, 1, 2, 3, 4, 5}; 10.966 - auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 10.967 - cxListStorePointers(list); 10.968 - // note: cannot use cxListAddArray() because we don't have a list of pointers 10.969 - cx_for_n(i, 5) cxListAdd(list, &fivenums[i]); 10.970 - verifyInsertViaIterator(list); 10.971 -} 10.972 - 10.973 -TEST_F(ArrayList, InsertViaIterator) { 10.974 - int fivenums[] = {0, 1, 2, 3, 4, 5}; 10.975 - CxList *list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 4)); 10.976 - cxListAddArray(list, fivenums, 5); 10.977 - verifyInsertViaIterator(list); 10.978 -} 10.979 - 10.980 -TEST_F(LinkedList, cxListReverse) { 10.981 - verifyReverse(linkedListFromTestData()); 10.982 -} 10.983 - 10.984 -TEST_F(PointerLinkedList, cxListReverse) { 10.985 - verifyReverse(pointerLinkedListFromTestData()); 10.986 -} 10.987 - 10.988 -TEST_F(ArrayList, cxListReverse) { 10.989 - verifyReverse(arrayListFromTestData()); 10.990 -} 10.991 - 10.992 -TEST_F(LinkedList, cxListCompare) { 10.993 - auto left = linkedListFromTestData(); 10.994 - auto right = linkedListFromTestData(); 10.995 - verifyCompare(left, right); 10.996 -} 10.997 - 10.998 -TEST_F(LinkedList, cxListCompareWithPtrList) { 10.999 - auto left = linkedListFromTestData(); 10.1000 - auto right = pointerLinkedListFromTestData(); 10.1001 - verifyCompare(left, right); 10.1002 -} 10.1003 - 10.1004 -TEST_F(LinkedList, cxListCompareWithArrayList) { 10.1005 - auto left = linkedListFromTestData(); 10.1006 - auto right = arrayListFromTestData(); 10.1007 - verifyCompare(left, right); 10.1008 -} 10.1009 - 10.1010 -TEST_F(PointerLinkedList, cxListCompare) { 10.1011 - auto left = pointerLinkedListFromTestData(); 10.1012 - auto right = pointerLinkedListFromTestData(); 10.1013 - verifyCompare(left, right); 10.1014 -} 10.1015 - 10.1016 -TEST_F(PointerLinkedList, cxListCompareWithNormalList) { 10.1017 - auto left = pointerLinkedListFromTestData(); 10.1018 - auto right = linkedListFromTestData(); 10.1019 - verifyCompare(left, right); 10.1020 -} 10.1021 - 10.1022 -TEST_F(PointerLinkedList, cxListCompareWithArrayList) { 10.1023 - auto left = pointerLinkedListFromTestData(); 10.1024 - auto right = arrayListFromTestData(); 10.1025 - verifyCompare(left, right); 10.1026 -} 10.1027 - 10.1028 -TEST_F(ArrayList, cxListCompare) { 10.1029 - auto left = arrayListFromTestData(); 10.1030 - auto right = arrayListFromTestData(); 10.1031 - verifyCompare(left, right); 10.1032 -} 10.1033 - 10.1034 -TEST_F(ArrayList, cxListCompareWithPtrList) { 10.1035 - auto left = arrayListFromTestData(); 10.1036 - auto right = pointerLinkedListFromTestData(); 10.1037 - verifyCompare(left, right); 10.1038 -} 10.1039 - 10.1040 -TEST_F(ArrayList, cxListCompareWithNormalList) { 10.1041 - auto left = arrayListFromTestData(); 10.1042 - auto right = linkedListFromTestData(); 10.1043 - verifyCompare(left, right); 10.1044 -} 10.1045 - 10.1046 -TEST_F(PointerLinkedList, NoDestructor) { 10.1047 - void *item = cxMalloc(&testingAllocator, sizeof(int)); 10.1048 - auto list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int *)); 10.1049 - cxListStorePointers(list); 10.1050 - cxListAdd(list, item); 10.1051 - ASSERT_FALSE(testingAllocator.verify()); 10.1052 - cxListDestroy(list); 10.1053 - EXPECT_FALSE(testingAllocator.verify()); 10.1054 - cxFree(&testingAllocator, item); 10.1055 - EXPECT_TRUE(testingAllocator.verify()); 10.1056 -} 10.1057 - 10.1058 -TEST_F(PointerLinkedList, SimpleDestructor) { 10.1059 - int item = 0; 10.1060 - auto list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int *)); 10.1061 - cxListStorePointers(list); 10.1062 - list->content_destructor_type = CX_DESTRUCTOR_SIMPLE; 10.1063 - list->simple_destructor = [](void *elem) { *(int *) elem = 42; }; 10.1064 - cxListAdd(list, &item); 10.1065 - cxListDestroy(list); 10.1066 - EXPECT_EQ(item, 42); 10.1067 -} 10.1068 - 10.1069 -TEST_F(PointerLinkedList, AdvancedDestructor) { 10.1070 - void *item = cxMalloc(&testingAllocator, sizeof(int)); 10.1071 - auto list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int *)); 10.1072 - cxListStorePointers(list); 10.1073 - list->content_destructor_type = CX_DESTRUCTOR_ADVANCED; 10.1074 - list->advanced_destructor.data = &testingAllocator; 10.1075 - list->advanced_destructor.func = (cx_destructor_func2) cxFree; 10.1076 - cxListAdd(list, item); 10.1077 - ASSERT_FALSE(testingAllocator.verify()); 10.1078 - cxListDestroy(list); 10.1079 - EXPECT_TRUE(testingAllocator.verify()); 10.1080 -}
11.1 --- a/test/test_map.cpp Tue Feb 07 21:53:06 2023 +0100 11.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 11.3 @@ -1,272 +0,0 @@ 11.4 -/* 11.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 11.6 - * 11.7 - * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 11.8 - * 11.9 - * Redistribution and use in source and binary forms, with or without 11.10 - * modification, are permitted provided that the following conditions are met: 11.11 - * 11.12 - * 1. Redistributions of source code must retain the above copyright 11.13 - * notice, this list of conditions and the following disclaimer. 11.14 - * 11.15 - * 2. Redistributions in binary form must reproduce the above copyright 11.16 - * notice, this list of conditions and the following disclaimer in the 11.17 - * documentation and/or other materials provided with the distribution. 11.18 - * 11.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 11.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 11.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 11.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 11.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 11.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 11.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 11.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 11.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 11.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 11.29 - * POSSIBILITY OF SUCH DAMAGE. 11.30 - */ 11.31 - 11.32 -#include "cx/hash_map.h" 11.33 -#include "cx/utils.h" 11.34 -#include "util_allocator.h" 11.35 - 11.36 -#include <gtest/gtest.h> 11.37 -#include <unordered_map> 11.38 -#include <unordered_set> 11.39 - 11.40 -struct map_operation { 11.41 - enum { 11.42 - put, rm 11.43 - } op; 11.44 - char const *key; 11.45 - char const *value; 11.46 -}; 11.47 - 11.48 -auto generate_map_operations() -> std::vector<map_operation> { 11.49 - return { 11.50 - {map_operation::put, "key 1", "test"}, 11.51 - {map_operation::put, "key 2", "blub"}, 11.52 - {map_operation::put, "key 3", "hallo"}, 11.53 - {map_operation::put, "key 2", "foobar"}, 11.54 - {map_operation::put, "key 4", "value 4"}, 11.55 - {map_operation::put, "key 5", "value 5"}, 11.56 - {map_operation::put, "key 6", "value 6"}, 11.57 - {map_operation::rm, "key 4", nullptr}, 11.58 - {map_operation::put, "key 7", "value 7"}, 11.59 - {map_operation::put, "key 8", "value 8"}, 11.60 - {map_operation::rm, "does not exist", nullptr}, 11.61 - {map_operation::put, "key 9", "value 9"}, 11.62 - {map_operation::put, "key 6", "other value"}, 11.63 - {map_operation::put, "key 7", "something else"}, 11.64 - {map_operation::rm, "key 8", nullptr}, 11.65 - {map_operation::rm, "key 2", nullptr}, 11.66 - {map_operation::put, "key 8", "new value"}, 11.67 - }; 11.68 -} 11.69 - 11.70 -static void verify_map_contents( 11.71 - CxMap *map, 11.72 - std::unordered_map<std::string, std::string> const &refmap 11.73 -) { 11.74 - // verify key iterator 11.75 - { 11.76 - auto keyiter = cxMapIteratorKeys(map); 11.77 - std::unordered_set<std::string> keys; 11.78 - cx_foreach(CxHashKey*, elem, keyiter) { 11.79 - keys.insert(std::string(elem->data.cstr, elem->len)); 11.80 - } 11.81 - EXPECT_EQ(keyiter.index, map->size); 11.82 - ASSERT_EQ(keys.size(), map->size); 11.83 - for (auto &&k: keys) { 11.84 - EXPECT_NE(refmap.find(k), refmap.end()); 11.85 - } 11.86 - } 11.87 - 11.88 - // verify value iterator 11.89 - { 11.90 - auto valiter = cxMapIteratorValues(map); 11.91 - std::unordered_set<std::string> values; // we use that the values in our test data are unique strings 11.92 - cx_foreach(char const*, elem, valiter) { 11.93 - values.insert(std::string(elem)); 11.94 - } 11.95 - EXPECT_EQ(valiter.index, map->size); 11.96 - ASSERT_EQ(values.size(), map->size); 11.97 - for (auto &&v: values) { 11.98 - EXPECT_NE(std::find_if(refmap.begin(), refmap.end(), 11.99 - [v](auto const &e) { return e.second == v; }), refmap.end()); 11.100 - } 11.101 - } 11.102 - 11.103 - // verify pair iterator 11.104 - { 11.105 - auto pairiter = cxMapIterator(map); 11.106 - std::unordered_map<std::string, std::string> pairs; 11.107 - cx_foreach(CxMapEntry*, entry, pairiter) { 11.108 - pairs[std::string(entry->key->data.cstr, entry->key->len)] = std::string((char *) entry->value); 11.109 - } 11.110 - EXPECT_EQ(pairiter.index, map->size); 11.111 - ASSERT_EQ(pairs.size(), refmap.size()); 11.112 - for (auto &&p: pairs) { 11.113 - ASSERT_EQ(p.second, refmap.at(p.first)); 11.114 - } 11.115 - } 11.116 -} 11.117 - 11.118 -TEST(CxHashMap, Create) { 11.119 - CxTestingAllocator allocator; 11.120 - auto map = cxHashMapCreate(&allocator, 0); 11.121 - auto hmap = reinterpret_cast<struct cx_hash_map_s *>(map); 11.122 - EXPECT_GT(hmap->bucket_count, 0); 11.123 - cx_for_n(i, hmap->bucket_count) { 11.124 - EXPECT_EQ(hmap->buckets[i], nullptr); 11.125 - } 11.126 - EXPECT_EQ(map->size, 0); 11.127 - EXPECT_EQ(map->allocator, &allocator); 11.128 - 11.129 - cxMapDestroy(map); 11.130 - EXPECT_TRUE(allocator.verify()); 11.131 -} 11.132 - 11.133 -TEST(CxHashMap, BasicOperations) { 11.134 - // create the map 11.135 - CxTestingAllocator allocator; 11.136 - auto map = cxHashMapCreate(&allocator, 8); 11.137 - 11.138 - // create a reference map 11.139 - std::unordered_map<std::string, std::string> refmap; 11.140 - 11.141 - // generate operations 11.142 - auto ops = generate_map_operations(); 11.143 - 11.144 - // verify iterators for empty map 11.145 - verify_map_contents(map, refmap); 11.146 - 11.147 - // execute operations and verify results 11.148 - for (auto &&op: ops) { 11.149 - CxHashKey key = cx_hash_key_str(op.key); 11.150 - key.hash = 0; // force the hash map to compute the hash 11.151 - if (op.op == map_operation::put) { 11.152 - // execute a put operation and verify that the exact value can be read back 11.153 - refmap[std::string(op.key)] = std::string(op.value); 11.154 - int result = cxMapPut(map, key, (void *) op.value); 11.155 - EXPECT_EQ(result, 0); 11.156 - auto added = cxMapGet(map, key); 11.157 - EXPECT_EQ(memcmp(op.value, added, strlen(op.value)), 0); 11.158 - } else { 11.159 - // execute a remove and verify that the removed element was returned (or nullptr) 11.160 - auto found = refmap.find(op.key); 11.161 - auto removed = cxMapRemove(map, key); 11.162 - if (found == refmap.end()) { 11.163 - EXPECT_EQ(removed, nullptr); 11.164 - } else { 11.165 - EXPECT_EQ(std::string((char *) removed), found->second); 11.166 - refmap.erase(found); 11.167 - } 11.168 - } 11.169 - // compare the current map state with the reference map 11.170 - verify_map_contents(map, refmap); 11.171 - } 11.172 - 11.173 - // destroy the map and verify the memory (de)allocations 11.174 - cxMapDestroy(map); 11.175 - EXPECT_TRUE(allocator.verify()); 11.176 -} 11.177 - 11.178 -TEST(CxHashMap, RemoveViaIterator) { 11.179 - CxTestingAllocator allocator; 11.180 - auto map = cxHashMapCreate(&allocator, 4); 11.181 - 11.182 - cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); 11.183 - cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); 11.184 - cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); 11.185 - cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); 11.186 - cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5"); 11.187 - cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6"); 11.188 - 11.189 - auto iter = cxMapMutIterator(map); 11.190 - cx_foreach(CxMapEntry*, entry, iter) { 11.191 - if (entry->key->data.cstr[4] % 2 == 1) cxIteratorFlagRemoval(iter); 11.192 - } 11.193 - EXPECT_EQ(map->size, 3); 11.194 - EXPECT_EQ(iter.index, map->size); 11.195 - 11.196 - EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 1")), nullptr); 11.197 - EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 2")), nullptr); 11.198 - EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 3")), nullptr); 11.199 - EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 4")), nullptr); 11.200 - EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 5")), nullptr); 11.201 - EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 6")), nullptr); 11.202 - 11.203 - cxMapDestroy(map); 11.204 - EXPECT_TRUE(allocator.verify()); 11.205 -} 11.206 - 11.207 -TEST(CxHashMap, RehashNotRequired) { 11.208 - CxTestingAllocator allocator; 11.209 - auto map = cxHashMapCreate(&allocator, 8); 11.210 - 11.211 - cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); 11.212 - cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); 11.213 - cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); 11.214 - cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); 11.215 - cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5"); 11.216 - cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6"); 11.217 - 11.218 - // 6/8 does not exceed 0.75, therefore the function should not rehash 11.219 - int result = cxMapRehash(map); 11.220 - EXPECT_EQ(result, 0); 11.221 - EXPECT_EQ(reinterpret_cast<struct cx_hash_map_s *>(map)->bucket_count, 8); 11.222 - 11.223 - cxMapDestroy(map); 11.224 - EXPECT_TRUE(allocator.verify()); 11.225 -} 11.226 - 11.227 -TEST(CxHashMap, Rehash) { 11.228 - CxTestingAllocator allocator; 11.229 - auto map = cxHashMapCreate(&allocator, 8); 11.230 - 11.231 - cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); 11.232 - cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); 11.233 - cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); 11.234 - cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); 11.235 - cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5"); 11.236 - cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6"); 11.237 - cxMapPut(map, cx_hash_key_str("key 7"), (void *) "val 7"); 11.238 - 11.239 - int result = cxMapRehash(map); 11.240 - EXPECT_EQ(result, 0); 11.241 - EXPECT_EQ(reinterpret_cast<struct cx_hash_map_s *>(map)->bucket_count, 17); 11.242 - EXPECT_EQ(map->size, 7); 11.243 - 11.244 - EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 1")), "val 1"), 0); 11.245 - EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 2")), "val 2"), 0); 11.246 - EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 3")), "val 3"), 0); 11.247 - EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 4")), "val 4"), 0); 11.248 - EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 5")), "val 5"), 0); 11.249 - EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 6")), "val 6"), 0); 11.250 - EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 7")), "val 7"), 0); 11.251 - 11.252 - cxMapDestroy(map); 11.253 - EXPECT_TRUE(allocator.verify()); 11.254 -} 11.255 - 11.256 -TEST(CxHashMap, Clear) { 11.257 - CxTestingAllocator allocator; 11.258 - auto map = cxHashMapCreate(&allocator, 0); 11.259 - 11.260 - cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); 11.261 - cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); 11.262 - cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); 11.263 - 11.264 - EXPECT_EQ(map->size, 3); 11.265 - 11.266 - cxMapClear(map); 11.267 - 11.268 - EXPECT_EQ(map->size, 0); 11.269 - EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 1")), nullptr); 11.270 - EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 2")), nullptr); 11.271 - EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 3")), nullptr); 11.272 - 11.273 - cxMapDestroy(map); 11.274 - EXPECT_TRUE(allocator.verify()); 11.275 -} 11.276 \ No newline at end of file
12.1 --- a/test/test_printf.cpp Tue Feb 07 21:53:06 2023 +0100 12.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 12.3 @@ -1,248 +0,0 @@ 12.4 -/* 12.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 12.6 - * 12.7 - * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 12.8 - * 12.9 - * Redistribution and use in source and binary forms, with or without 12.10 - * modification, are permitted provided that the following conditions are met: 12.11 - * 12.12 - * 1. Redistributions of source code must retain the above copyright 12.13 - * notice, this list of conditions and the following disclaimer. 12.14 - * 12.15 - * 2. Redistributions in binary form must reproduce the above copyright 12.16 - * notice, this list of conditions and the following disclaimer in the 12.17 - * documentation and/or other materials provided with the distribution. 12.18 - * 12.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 12.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 12.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 12.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 12.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 12.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 12.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 12.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 12.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 12.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 12.29 - * POSSIBILITY OF SUCH DAMAGE. 12.30 - */ 12.31 - 12.32 -#include "cx/printf.h" 12.33 -#include "cx/buffer.h" 12.34 - 12.35 -#include <gtest/gtest.h> 12.36 -#include "util_allocator.h" 12.37 - 12.38 -class PrintfFixture : public ::testing::Test { 12.39 -protected: 12.40 - std::string buf; 12.41 - CxTestingAllocator alloc; 12.42 - 12.43 - void TearDown() override { 12.44 - buf.clear(); 12.45 - ASSERT_TRUE(alloc.verify()); 12.46 - } 12.47 - 12.48 - static size_t write_func( 12.49 - void const *src, 12.50 - size_t esize, 12.51 - size_t ecount, 12.52 - void *target 12.53 - ) { 12.54 - auto str = reinterpret_cast<char const *>(src); 12.55 - auto buf = reinterpret_cast<std::string *>(target); 12.56 - EXPECT_EQ(esize, 1); 12.57 - EXPECT_EQ(strlen(str), ecount); 12.58 - *buf = str; 12.59 - return ecount; 12.60 - } 12.61 -}; 12.62 - 12.63 - 12.64 -TEST_F(PrintfFixture, BPrintf) { 12.65 - CxBuffer buf; 12.66 - cxBufferInit(&buf, nullptr, 64, &alloc, 0); 12.67 - 12.68 - auto r = cx_bprintf(&buf, "This %s aged %u years in a %2XSK.", "Test", 10, 0xca); 12.69 - EXPECT_EQ(r, 34); 12.70 - EXPECT_EQ(buf.size, 34); 12.71 - buf.space[r] = '\0'; 12.72 - EXPECT_STREQ(buf.space, "This Test aged 10 years in a CASK."); 12.73 - 12.74 - cxBufferDestroy(&buf); 12.75 -} 12.76 - 12.77 -TEST_F(PrintfFixture, FPrintf) { 12.78 - auto h = "Hello"; 12.79 - size_t r; 12.80 - 12.81 - r = cx_fprintf(&buf, PrintfFixture::write_func, "teststring"); 12.82 - EXPECT_EQ(r, 10); 12.83 - EXPECT_EQ(buf, "teststring"); 12.84 - 12.85 - r = cx_fprintf(&buf, PrintfFixture::write_func, "[%10s]", h); 12.86 - EXPECT_EQ(r, 12); 12.87 - EXPECT_EQ(buf, "[ Hello]"); 12.88 - 12.89 - r = cx_fprintf(&buf, PrintfFixture::write_func, "[%-10s]", h); 12.90 - EXPECT_EQ(r, 12); 12.91 - EXPECT_EQ(buf, "[Hello ]"); 12.92 - 12.93 - r = cx_fprintf(&buf, PrintfFixture::write_func, "[%*s]", 10, h); 12.94 - EXPECT_EQ(r, 12); 12.95 - EXPECT_EQ(buf, "[ Hello]"); 12.96 - 12.97 - r = cx_fprintf(&buf, PrintfFixture::write_func, "[%-10.*s]", 4, h); 12.98 - EXPECT_EQ(r, 12); 12.99 - EXPECT_EQ(buf, "[Hell ]"); 12.100 - 12.101 - r = cx_fprintf(&buf, PrintfFixture::write_func, "[%-*.*s]", 10, 4, h); 12.102 - EXPECT_EQ(r, 12); 12.103 - EXPECT_EQ(buf, "[Hell ]"); 12.104 - 12.105 - r = cx_fprintf(&buf, PrintfFixture::write_func, "%c", 'A'); 12.106 - EXPECT_EQ(r, 1); 12.107 - EXPECT_EQ(buf, "A"); 12.108 - 12.109 - r = cx_fprintf(&buf, PrintfFixture::write_func, "%i %d %.6i %i %.0i %+i %i", 1, 2, 3, 0, 0, 4, -4); 12.110 - EXPECT_EQ(r, 19); 12.111 - EXPECT_EQ(buf, "1 2 000003 0 +4 -4"); 12.112 - 12.113 - r = cx_fprintf(&buf, PrintfFixture::write_func, "%x %x %X %#x", 5, 10, 10, 6); 12.114 - EXPECT_EQ(r, 9); 12.115 - EXPECT_EQ(buf, "5 a A 0x6"); 12.116 - 12.117 - r = cx_fprintf(&buf, PrintfFixture::write_func, "%o %#o %#o", 10, 10, 4); 12.118 - EXPECT_EQ(r, 9); 12.119 - EXPECT_EQ(buf, "12 012 04"); 12.120 - 12.121 - r = cx_fprintf(&buf, PrintfFixture::write_func, "%05.2f %.2f %5.2f", 1.5, 1.5, 1.5); 12.122 - EXPECT_EQ(r, 16); 12.123 - EXPECT_EQ(buf, "01.50 1.50 1.50"); 12.124 - 12.125 - r = cx_fprintf(&buf, PrintfFixture::write_func, "'%*c'", 5, 'x'); 12.126 - EXPECT_EQ(r, 7); 12.127 - EXPECT_EQ(buf, "' x'"); 12.128 - 12.129 - r = cx_fprintf(&buf, PrintfFixture::write_func, "'%*c'", -5, 'x'); 12.130 - EXPECT_EQ(r, 7); 12.131 - EXPECT_EQ(buf, "'x '"); 12.132 -} 12.133 - 12.134 -TEST_F(PrintfFixture, BPrintfLargeString) { 12.135 - CxBuffer buf; 12.136 - cxBufferInit(&buf, nullptr, 64, &alloc, CX_BUFFER_AUTO_EXTEND); 12.137 - 12.138 - auto aaa = std::string(512, 'a'); 12.139 - auto bbb = std::string(512, 'b'); 12.140 - 12.141 - auto r = cx_bprintf(&buf, "After %s comes %s.", aaa.data(), bbb.data()); 12.142 - EXPECT_EQ(r, 1038); 12.143 - EXPECT_EQ(buf.size, 1038); 12.144 - cxBufferPut(&buf, 0); 12.145 - EXPECT_EQ(buf.space, std::string("After ") + aaa + " comes " + bbb + "."); 12.146 - 12.147 - cxBufferDestroy(&buf); 12.148 -} 12.149 - 12.150 -TEST_F(PrintfFixture, BPrintfNoCap) { 12.151 - CxBuffer buf; 12.152 - char space[20]; 12.153 - memset(space, 'a', 20); 12.154 - cxBufferInit(&buf, space, 16, &alloc, 0); 12.155 - 12.156 - auto r = cx_bprintf(&buf, "Hello %s with more than %d chars.", "string", 16); 12.157 - EXPECT_EQ(r, 16); 12.158 - EXPECT_EQ(buf.size, 16); 12.159 - EXPECT_EQ(0, memcmp(space, "Hello string witaaaa", 20)); 12.160 - 12.161 - cxBufferDestroy(&buf); 12.162 -} 12.163 - 12.164 -TEST_F(PrintfFixture, SPrintf) { 12.165 - auto h = "Hello"; 12.166 - 12.167 - std::vector<char *> fl; 12.168 - cxmutstr r; 12.169 - 12.170 - r = cx_asprintf_a(&alloc, "teststring"); 12.171 - EXPECT_EQ(r.length, 10); 12.172 - EXPECT_STREQ(r.ptr, "teststring"); 12.173 - fl.push_back(r.ptr); 12.174 - 12.175 - r = cx_asprintf_a(&alloc, "[%10s]", h); 12.176 - EXPECT_EQ(r.length, 12); 12.177 - EXPECT_STREQ(r.ptr, "[ Hello]"); 12.178 - fl.push_back(r.ptr); 12.179 - 12.180 - r = cx_asprintf_a(&alloc, "[%-10s]", h); 12.181 - EXPECT_EQ(r.length, 12); 12.182 - EXPECT_STREQ(r.ptr, "[Hello ]"); 12.183 - fl.push_back(r.ptr); 12.184 - 12.185 - r = cx_asprintf_a(&alloc, "[%*s]", 10, h); 12.186 - EXPECT_EQ(r.length, 12); 12.187 - EXPECT_STREQ(r.ptr, "[ Hello]"); 12.188 - fl.push_back(r.ptr); 12.189 - 12.190 - r = cx_asprintf_a(&alloc, "[%-10.*s]", 4, h); 12.191 - EXPECT_EQ(r.length, 12); 12.192 - EXPECT_STREQ(r.ptr, "[Hell ]"); 12.193 - fl.push_back(r.ptr); 12.194 - 12.195 - r = cx_asprintf_a(&alloc, "[%-*.*s]", 10, 4, h); 12.196 - EXPECT_EQ(r.length, 12); 12.197 - EXPECT_STREQ(r.ptr, "[Hell ]"); 12.198 - fl.push_back(r.ptr); 12.199 - 12.200 - r = cx_asprintf_a(&alloc, "%c", 'A'); 12.201 - EXPECT_EQ(r.length, 1); 12.202 - EXPECT_STREQ(r.ptr, "A"); 12.203 - fl.push_back(r.ptr); 12.204 - 12.205 - r = cx_asprintf_a(&alloc, "%i %d %.6i %i %.0i %+i %i", 1, 2, 3, 0, 0, 4, -4); 12.206 - EXPECT_EQ(r.length, 19); 12.207 - EXPECT_STREQ(r.ptr, "1 2 000003 0 +4 -4"); 12.208 - fl.push_back(r.ptr); 12.209 - 12.210 - r = cx_asprintf_a(&alloc, "%x %x %X %#x", 5, 10, 10, 6); 12.211 - EXPECT_EQ(r.length, 9); 12.212 - EXPECT_STREQ(r.ptr, "5 a A 0x6"); 12.213 - fl.push_back(r.ptr); 12.214 - 12.215 - r = cx_asprintf_a(&alloc, "%o %#o %#o", 10, 10, 4); 12.216 - EXPECT_EQ(r.length, 9); 12.217 - EXPECT_STREQ(r.ptr, "12 012 04"); 12.218 - fl.push_back(r.ptr); 12.219 - 12.220 - r = cx_asprintf_a(&alloc, "%05.2f %.2f %5.2f", 1.5, 1.5, 1.5); 12.221 - EXPECT_EQ(r.length, 16); 12.222 - EXPECT_STREQ(r.ptr, "01.50 1.50 1.50"); 12.223 - fl.push_back(r.ptr); 12.224 - 12.225 - r = cx_asprintf_a(&alloc, "'%*c'", 5, 'x'); 12.226 - EXPECT_EQ(r.length, 7); 12.227 - EXPECT_STREQ(r.ptr, "' x'"); 12.228 - fl.push_back(r.ptr); 12.229 - 12.230 - r = cx_asprintf_a(&alloc, "'%*c'", -5, 'x'); 12.231 - EXPECT_EQ(r.length, 7); 12.232 - EXPECT_STREQ(r.ptr, "'x '"); 12.233 - fl.push_back(r.ptr); 12.234 - 12.235 - for (auto c: fl) { 12.236 - auto s = cx_mutstrn(c, 0); 12.237 - cx_strfree_a(&alloc, &s); 12.238 - } 12.239 -} 12.240 - 12.241 -TEST_F(PrintfFixture, SPrintfLargeString) { 12.242 - auto aaa = std::string(512, 'a'); 12.243 - auto bbb = std::string(512, 'b'); 12.244 - 12.245 - auto r = cx_asprintf_a(&alloc, "After %s comes %s.", aaa.data(), bbb.data()); 12.246 - EXPECT_EQ(r.length, 1038); 12.247 - EXPECT_EQ(r.ptr, std::string("After ") + aaa + " comes " + bbb + "."); 12.248 - EXPECT_EQ(r.ptr[1038], '\0'); 12.249 - 12.250 - cx_strfree_a(&alloc, &r); 12.251 -} 12.252 \ No newline at end of file
13.1 --- a/test/test_string.cpp Tue Feb 07 21:53:06 2023 +0100 13.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 13.3 @@ -1,865 +0,0 @@ 13.4 -/* 13.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 13.6 - * 13.7 - * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 13.8 - * 13.9 - * Redistribution and use in source and binary forms, with or without 13.10 - * modification, are permitted provided that the following conditions are met: 13.11 - * 13.12 - * 1. Redistributions of source code must retain the above copyright 13.13 - * notice, this list of conditions and the following disclaimer. 13.14 - * 13.15 - * 2. Redistributions in binary form must reproduce the above copyright 13.16 - * notice, this list of conditions and the following disclaimer in the 13.17 - * documentation and/or other materials provided with the distribution. 13.18 - * 13.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 13.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 13.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 13.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 13.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 13.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 13.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 13.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 13.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 13.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 13.29 - * POSSIBILITY OF SUCH DAMAGE. 13.30 - */ 13.31 - 13.32 -#include "cx/string.h" 13.33 -#include "util_allocator.h" 13.34 - 13.35 -#include <gtest/gtest.h> 13.36 - 13.37 -#define EXPECT_ZERO_TERMINATED(str) EXPECT_EQ((str).ptr[(str).length], '\0') 13.38 - 13.39 -TEST(String, construct) { 13.40 - cxstring s1 = cx_str("1234"); 13.41 - cxstring s2 = cx_strn("abcd", 2); 13.42 - cxmutstr s3 = cx_mutstr((char *) "1234"); 13.43 - cxmutstr s4 = cx_mutstrn((char *) "abcd", 2); 13.44 - 13.45 - EXPECT_EQ(s1.length, 4); 13.46 - EXPECT_EQ(s2.length, 2); 13.47 - EXPECT_EQ(s3.length, 4); 13.48 - EXPECT_EQ(s4.length, 2); 13.49 -} 13.50 - 13.51 -TEST(String, strfree) { 13.52 - CxTestingAllocator alloc; 13.53 - auto test = (char *) cxMalloc(&alloc, 16); 13.54 - cxmutstr str = cx_mutstrn(test, 16); 13.55 - ASSERT_EQ(str.ptr, test); 13.56 - EXPECT_EQ(str.length, 16); 13.57 - cx_strfree_a(&alloc, &str); 13.58 - EXPECT_EQ(str.ptr, nullptr); 13.59 - EXPECT_EQ(str.length, 0); 13.60 - EXPECT_TRUE(alloc.verify()); 13.61 -} 13.62 - 13.63 -TEST(String, strdup) { 13.64 - cxstring str = CX_STR("test"); 13.65 - cxmutstr dup = cx_strdup(str); 13.66 - ASSERT_EQ(dup.length, str.length); 13.67 - EXPECT_STREQ(dup.ptr, str.ptr); 13.68 - EXPECT_ZERO_TERMINATED(dup); 13.69 - cx_strfree(&dup); 13.70 - 13.71 - str.length = 2; 13.72 - dup = cx_strdup(str); 13.73 - ASSERT_EQ(dup.length, str.length); 13.74 - EXPECT_STREQ(dup.ptr, "te"); 13.75 - EXPECT_ZERO_TERMINATED(dup); 13.76 - cx_strfree(&dup); 13.77 -} 13.78 - 13.79 -TEST(String, strlen) { 13.80 - cxstring s1 = CX_STR("1234"); 13.81 - cxstring s2 = CX_STR(".:.:."); 13.82 - cxstring s3 = CX_STR("X"); 13.83 - 13.84 - size_t len0 = cx_strlen(0); 13.85 - size_t len1 = cx_strlen(1, s1); 13.86 - size_t len2 = cx_strlen(2, s1, s2); 13.87 - size_t len3 = cx_strlen(3, s1, s2, s3); 13.88 - 13.89 - EXPECT_EQ(len0, 0); 13.90 - EXPECT_EQ(len1, 4); 13.91 - EXPECT_EQ(len2, 9); 13.92 - EXPECT_EQ(len3, 10); 13.93 -} 13.94 - 13.95 -TEST(String, strsubs) { 13.96 - cxstring str = CX_STR("A test string"); 13.97 - 13.98 - cxstring sub = cx_strsubs(str, 0); 13.99 - EXPECT_EQ(cx_strcmp(sub, str), 0); 13.100 - 13.101 - sub = cx_strsubs(str, 2); 13.102 - EXPECT_EQ(cx_strcmp(sub, cx_str("test string")), 0); 13.103 - 13.104 - sub = cx_strsubs(str, 7); 13.105 - EXPECT_EQ(cx_strcmp(sub, cx_str("string")), 0); 13.106 - 13.107 - sub = cx_strsubs(str, 15); 13.108 - EXPECT_EQ(cx_strcmp(sub, cx_str("")), 0); 13.109 - 13.110 - sub = cx_strsubsl(str, 2, 4); 13.111 - EXPECT_EQ(cx_strcmp(sub, cx_str("test")), 0); 13.112 - 13.113 - sub = cx_strsubsl(str, 7, 3); 13.114 - EXPECT_EQ(cx_strcmp(sub, cx_str("str")), 0); 13.115 - 13.116 - sub = cx_strsubsl(str, 7, 20); 13.117 - EXPECT_EQ(cx_strcmp(sub, cx_str("string")), 0); 13.118 - 13.119 - // just for coverage, call the _m variant 13.120 - auto m = cx_strsubs_m(cx_mutstrn(nullptr, 0), 0); 13.121 - EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0); 13.122 -} 13.123 - 13.124 -TEST(String, strchr) { 13.125 - cxstring str = CX_STR("I will find you - and I will kill you"); 13.126 - 13.127 - cxstring notfound = cx_strchr(str, 'x'); 13.128 - EXPECT_EQ(notfound.length, 0); 13.129 - 13.130 - cxstring result = cx_strchr(str, 'w'); 13.131 - EXPECT_EQ(result.length, 35); 13.132 - EXPECT_STREQ(result.ptr, "will find you - and I will kill you"); 13.133 - 13.134 - // just for coverage, call the _m variant 13.135 - auto m = cx_strchr_m(cx_mutstrn(nullptr, 0), 'a'); 13.136 - EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0); 13.137 -} 13.138 - 13.139 -TEST(String, strrchr) { 13.140 - cxstring str = CX_STR("I will find you - and I will kill you"); 13.141 - 13.142 - cxstring notfound = cx_strrchr(str, 'x'); 13.143 - EXPECT_EQ(notfound.length, 0); 13.144 - 13.145 - cxstring result = cx_strrchr(str, 'w'); 13.146 - EXPECT_EQ(result.length, 13); 13.147 - EXPECT_STREQ(result.ptr, "will kill you"); 13.148 - 13.149 - // just for coverage, call the _m variant 13.150 - auto m = cx_strrchr_m(cx_mutstrn(nullptr, 0), 'a'); 13.151 - EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0); 13.152 -} 13.153 - 13.154 -TEST(String, strstr) { 13.155 - cxstring str = CX_STR("find the match in this string"); 13.156 - cxstring longstr = CX_STR( 13.157 - "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl" 13.158 - "mnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx" 13.159 - "yzabcdeababababnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij" 13.160 - "klmnopqrstuvwxyzaababababababababrstuvwxyzabcdefghijklmnopqrstuv" 13.161 - "abababababababababababababababababababababababababababababababab" 13.162 - "abababababababababababababababababababababababababababababababab" 13.163 - "abababababababababababababababababababababababababababababababab" 13.164 - "abababababababababababababababababababababababababababababababab" 13.165 - "abababababababababababababababababababababababababababababababab" 13.166 - "abababababababababababababababababababababababababababababababab" 13.167 - "wxyz1234567890"); 13.168 - cxstring longstrpattern = CX_STR( 13.169 - "abababababababababababababababababababababababababababababababab" 13.170 - "abababababababababababababababababababababababababababababababab" 13.171 - "abababababababababababababababababababababababababababababababab" 13.172 - "abababababababababababababababababababababababababababababababab" 13.173 - "abababababababababababababababababababababababababababababababab" 13.174 - ); 13.175 - cxstring longstrresult = CX_STR( 13.176 - "abababababababababababababababababababababababababababababababab" 13.177 - "abababababababababababababababababababababababababababababababab" 13.178 - "abababababababababababababababababababababababababababababababab" 13.179 - "abababababababababababababababababababababababababababababababab" 13.180 - "abababababababababababababababababababababababababababababababab" 13.181 - "abababababababababababababababababababababababababababababababab" 13.182 - "wxyz1234567890" 13.183 - ); 13.184 - 13.185 - cxstring notfound = cx_strstr(str, cx_str("no match")); 13.186 - EXPECT_EQ(notfound.length, 0); 13.187 - 13.188 - cxstring result = cx_strstr(str, cx_str("match")); 13.189 - EXPECT_EQ(result.length, 20); 13.190 - EXPECT_STREQ(result.ptr, "match in this string"); 13.191 - 13.192 - result = cx_strstr(str, cx_str("")); 13.193 - EXPECT_EQ(result.length, str.length); 13.194 - EXPECT_STREQ(result.ptr, str.ptr); 13.195 - 13.196 - result = cx_strstr(longstr, longstrpattern); 13.197 - EXPECT_EQ(result.length, longstrresult.length); 13.198 - EXPECT_STREQ(result.ptr, longstrresult.ptr); 13.199 - 13.200 - // just for coverage, call the _m variant 13.201 - auto mstr = cx_strdup(longstr); 13.202 - auto m = cx_strstr_m(mstr, longstrpattern); 13.203 - EXPECT_EQ(m.length, longstrresult.length); 13.204 - EXPECT_STREQ(m.ptr, longstrresult.ptr); 13.205 - cx_strfree(&mstr); 13.206 -} 13.207 - 13.208 -TEST(String, strcmp) { 13.209 - cxstring str = CX_STR("compare this"); 13.210 - 13.211 - EXPECT_EQ(cx_strcmp(cx_str(""), cx_str("")), 0); 13.212 - EXPECT_GT(cx_strcmp(str, cx_str("")), 0); 13.213 - EXPECT_EQ(cx_strcmp(str, cx_str("compare this")), 0); 13.214 - EXPECT_NE(cx_strcmp(str, cx_str("Compare This")), 0); 13.215 - EXPECT_LT(cx_strcmp(str, cx_str("compare tool")), 0); 13.216 - EXPECT_GT(cx_strcmp(str, cx_str("compare shit")), 0); 13.217 - EXPECT_LT(cx_strcmp(str, cx_str("compare this not")), 0); 13.218 - EXPECT_GT(cx_strcmp(str, cx_str("compare")), 0); 13.219 -} 13.220 - 13.221 -TEST(String, strcasecmp) { 13.222 - cxstring str = CX_STR("compare this"); 13.223 - 13.224 - EXPECT_EQ(cx_strcasecmp(cx_str(""), cx_str("")), 0); 13.225 - EXPECT_GT(cx_strcasecmp(str, cx_str("")), 0); 13.226 - EXPECT_EQ(cx_strcasecmp(str, cx_str("compare this")), 0); 13.227 - EXPECT_EQ(cx_strcasecmp(str, cx_str("Compare This")), 0); 13.228 - EXPECT_LT(cx_strcasecmp(str, cx_str("compare tool")), 0); 13.229 - EXPECT_GT(cx_strcasecmp(str, cx_str("compare shit")), 0); 13.230 - EXPECT_LT(cx_strcasecmp(str, cx_str("compare this not")), 0); 13.231 - EXPECT_GT(cx_strcasecmp(str, cx_str("compare")), 0); 13.232 -} 13.233 - 13.234 -TEST(String, strcat) { 13.235 - cxstring s1 = CX_STR("12"); 13.236 - cxstring s2 = CX_STR("34"); 13.237 - cxstring s3 = CX_STR("56"); 13.238 - cxstring sn = {nullptr, 0}; 13.239 - 13.240 - CxTestingAllocator alloc; 13.241 - 13.242 - cxmutstr t1 = cx_strcat_a(&alloc, 2, s1, s2); 13.243 - EXPECT_EQ(cx_strcmp(cx_strcast(t1), cx_str("1234")), 0); 13.244 - EXPECT_ZERO_TERMINATED(t1); 13.245 - cx_strfree_a(&alloc, &t1); 13.246 - 13.247 - cxmutstr t2 = cx_strcat_a(&alloc, 3, s1, s2, s3); 13.248 - EXPECT_EQ(cx_strcmp(cx_strcast(t2), cx_str("123456")), 0); 13.249 - EXPECT_ZERO_TERMINATED(t2); 13.250 - cx_strfree_a(&alloc, &t2); 13.251 - 13.252 - cxmutstr t3 = cx_strcat_a(&alloc, 6, s1, sn, s2, sn, s3, sn); 13.253 - EXPECT_EQ(cx_strcmp(cx_strcast(t3), cx_str("123456")), 0); 13.254 - EXPECT_ZERO_TERMINATED(t3); 13.255 - cx_strfree_a(&alloc, &t3); 13.256 - 13.257 - cxmutstr t4 = cx_strcat_a(&alloc, 2, sn, sn); 13.258 - EXPECT_EQ(cx_strcmp(cx_strcast(t4), cx_str("")), 0); 13.259 - EXPECT_ZERO_TERMINATED(t4); 13.260 - cx_strfree_a(&alloc, &t4); 13.261 - 13.262 - EXPECT_TRUE(alloc.verify()); 13.263 - 13.264 - // use the macro 13.265 - cxmutstr t5 = cx_strcat(3, s3, s1, s2); 13.266 - EXPECT_EQ(cx_strcmp(cx_strcast(t5), cx_str("561234")), 0); 13.267 - EXPECT_ZERO_TERMINATED(t5); 13.268 - cx_strfree(&t5); 13.269 -} 13.270 - 13.271 -TEST(String, strsplit) { 13.272 - 13.273 - cxstring test = cx_str("this,is,a,csv,string"); 13.274 - size_t capa = 8; 13.275 - cxstring list[8]; 13.276 - size_t n; 13.277 - 13.278 - // special case: empty string 13.279 - n = cx_strsplit(test, cx_str(""), capa, list); 13.280 - ASSERT_EQ(n, 1); 13.281 - EXPECT_EQ(cx_strcmp(list[0], test), 0); 13.282 - 13.283 - // no delimiter occurrence 13.284 - n = cx_strsplit(test, cx_str("z"), capa, list); 13.285 - ASSERT_EQ(n, 1); 13.286 - EXPECT_EQ(cx_strcmp(list[0], test), 0); 13.287 - 13.288 - // partially matching delimiter 13.289 - n = cx_strsplit(test, cx_str("is,not"), capa, list); 13.290 - ASSERT_EQ(n, 1); 13.291 - EXPECT_EQ(cx_strcmp(list[0], test), 0); 13.292 - 13.293 - // matching single-char delimiter 13.294 - n = cx_strsplit(test, cx_str(","), capa, list); 13.295 - ASSERT_EQ(n, 5); 13.296 - EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0); 13.297 - EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0); 13.298 - EXPECT_EQ(cx_strcmp(list[2], cx_str("a")), 0); 13.299 - EXPECT_EQ(cx_strcmp(list[3], cx_str("csv")), 0); 13.300 - EXPECT_EQ(cx_strcmp(list[4], cx_str("string")), 0); 13.301 - 13.302 - // matching multi-char delimiter 13.303 - n = cx_strsplit(test, cx_str("is"), capa, list); 13.304 - ASSERT_EQ(n, 3); 13.305 - EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 13.306 - EXPECT_EQ(cx_strcmp(list[1], cx_str(",")), 0); 13.307 - EXPECT_EQ(cx_strcmp(list[2], cx_str(",a,csv,string")), 0); 13.308 - 13.309 - // bounded list using single-char delimiter 13.310 - n = cx_strsplit(test, cx_str(","), 3, list); 13.311 - ASSERT_EQ(n, 3); 13.312 - EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0); 13.313 - EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0); 13.314 - EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0); 13.315 - 13.316 - // bounded list using multi-char delimiter 13.317 - n = cx_strsplit(test, cx_str("is"), 2, list); 13.318 - ASSERT_EQ(n, 2); 13.319 - EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 13.320 - EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0); 13.321 - 13.322 - // start with delimiter 13.323 - n = cx_strsplit(test, cx_str("this"), capa, list); 13.324 - ASSERT_EQ(n, 2); 13.325 - EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0); 13.326 - EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0); 13.327 - 13.328 - // end with delimiter 13.329 - n = cx_strsplit(test, cx_str("string"), capa, list); 13.330 - ASSERT_EQ(n, 2); 13.331 - EXPECT_EQ(cx_strcmp(list[0], cx_str("this,is,a,csv,")), 0); 13.332 - EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 13.333 - 13.334 - 13.335 - // end with delimiter exceed bound 13.336 - n = cx_strsplit(cx_str("a,b,c,"), cx_str(","), 3, list); 13.337 - ASSERT_EQ(n, 3); 13.338 - EXPECT_EQ(cx_strcmp(list[0], cx_str("a")), 0); 13.339 - EXPECT_EQ(cx_strcmp(list[1], cx_str("b")), 0); 13.340 - EXPECT_EQ(cx_strcmp(list[2], cx_str("c,")), 0); 13.341 - 13.342 - // exact match 13.343 - n = cx_strsplit(test, cx_str("this,is,a,csv,string"), capa, list); 13.344 - ASSERT_EQ(n, 2); 13.345 - EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0); 13.346 - EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 13.347 - 13.348 - // string to be split is only substring 13.349 - n = cx_strsplit(test, cx_str("this,is,a,csv,string,with,extension"), capa, list); 13.350 - ASSERT_EQ(n, 1); 13.351 - EXPECT_EQ(cx_strcmp(list[0], test), 0); 13.352 - 13.353 - // subsequent encounter of delimiter (the string between is empty) 13.354 - n = cx_strsplit(test, cx_str("is,"), capa, list); 13.355 - ASSERT_EQ(n, 3); 13.356 - EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 13.357 - EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 13.358 - EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0); 13.359 - 13.360 - // call the _m variant just for coverage 13.361 - auto mtest = cx_strdup(test); 13.362 - cxmutstr mlist[4]; 13.363 - n = cx_strsplit_m(mtest, cx_str("is,"), 4, mlist); 13.364 - ASSERT_EQ(n, 3); 13.365 - EXPECT_EQ(cx_strcmp(cx_strcast(mlist[0]), cx_str("th")), 0); 13.366 - EXPECT_EQ(cx_strcmp(cx_strcast(mlist[1]), cx_str("")), 0); 13.367 - EXPECT_EQ(cx_strcmp(cx_strcast(mlist[2]), cx_str("a,csv,string")), 0); 13.368 - cx_strfree(&mtest); 13.369 -} 13.370 - 13.371 -TEST(String, strsplit_a) { 13.372 - CxTestingAllocator alloc; 13.373 - 13.374 - cxstring test = cx_str("this,is,a,csv,string"); 13.375 - size_t capa = 8; 13.376 - cxstring *list; 13.377 - size_t n; 13.378 - 13.379 - // special case: empty string 13.380 - n = cx_strsplit_a(&alloc, test, cx_str(""), capa, &list); 13.381 - ASSERT_EQ(n, 1); 13.382 - EXPECT_EQ(cx_strcmp(list[0], test), 0); 13.383 - cxFree(&alloc, list); 13.384 - 13.385 - // no delimiter occurrence 13.386 - n = cx_strsplit_a(&alloc, test, cx_str("z"), capa, &list); 13.387 - ASSERT_EQ(n, 1); 13.388 - EXPECT_EQ(cx_strcmp(list[0], test), 0); 13.389 - cxFree(&alloc, list); 13.390 - 13.391 - // partially matching delimiter 13.392 - n = cx_strsplit_a(&alloc, test, cx_str("is,not"), capa, &list); 13.393 - ASSERT_EQ(n, 1); 13.394 - EXPECT_EQ(cx_strcmp(list[0], test), 0); 13.395 - cxFree(&alloc, list); 13.396 - 13.397 - // matching single-char delimiter 13.398 - n = cx_strsplit_a(&alloc, test, cx_str(","), capa, &list); 13.399 - ASSERT_EQ(n, 5); 13.400 - EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0); 13.401 - EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0); 13.402 - EXPECT_EQ(cx_strcmp(list[2], cx_str("a")), 0); 13.403 - EXPECT_EQ(cx_strcmp(list[3], cx_str("csv")), 0); 13.404 - EXPECT_EQ(cx_strcmp(list[4], cx_str("string")), 0); 13.405 - cxFree(&alloc, list); 13.406 - 13.407 - // matching multi-char delimiter 13.408 - n = cx_strsplit_a(&alloc, test, cx_str("is"), capa, &list); 13.409 - ASSERT_EQ(n, 3); 13.410 - EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 13.411 - EXPECT_EQ(cx_strcmp(list[1], cx_str(",")), 0); 13.412 - EXPECT_EQ(cx_strcmp(list[2], cx_str(",a,csv,string")), 0); 13.413 - cxFree(&alloc, list); 13.414 - 13.415 - // bounded list using single-char delimiter 13.416 - n = cx_strsplit_a(&alloc, test, cx_str(","), 3, &list); 13.417 - ASSERT_EQ(n, 3); 13.418 - EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0); 13.419 - EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0); 13.420 - EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0); 13.421 - cxFree(&alloc, list); 13.422 - 13.423 - // bounded list using multi-char delimiter 13.424 - n = cx_strsplit_a(&alloc, test, cx_str("is"), 2, &list); 13.425 - ASSERT_EQ(n, 2); 13.426 - EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 13.427 - EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0); 13.428 - cxFree(&alloc, list); 13.429 - 13.430 - // start with delimiter 13.431 - n = cx_strsplit_a(&alloc, test, cx_str("this"), capa, &list); 13.432 - ASSERT_EQ(n, 2); 13.433 - EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0); 13.434 - EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0); 13.435 - cxFree(&alloc, list); 13.436 - 13.437 - // end with delimiter 13.438 - n = cx_strsplit_a(&alloc, test, cx_str("string"), capa, &list); 13.439 - ASSERT_EQ(n, 2); 13.440 - EXPECT_EQ(cx_strcmp(list[0], cx_str("this,is,a,csv,")), 0); 13.441 - EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 13.442 - cxFree(&alloc, list); 13.443 - 13.444 - // end with delimiter exceed bound 13.445 - n = cx_strsplit_a(&alloc, cx_str("a,b,c,"), cx_str(","), 3, &list); 13.446 - ASSERT_EQ(n, 3); 13.447 - EXPECT_EQ(cx_strcmp(list[0], cx_str("a")), 0); 13.448 - EXPECT_EQ(cx_strcmp(list[1], cx_str("b")), 0); 13.449 - EXPECT_EQ(cx_strcmp(list[2], cx_str("c,")), 0); 13.450 - cxFree(&alloc, list); 13.451 - 13.452 - // exact match 13.453 - n = cx_strsplit_a(&alloc, test, cx_str("this,is,a,csv,string"), capa, &list); 13.454 - ASSERT_EQ(n, 2); 13.455 - EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0); 13.456 - EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 13.457 - cxFree(&alloc, list); 13.458 - 13.459 - // string to be split is only substring 13.460 - n = cx_strsplit_a(&alloc, test, cx_str("this,is,a,csv,string,with,extension"), capa, &list); 13.461 - ASSERT_EQ(n, 1); 13.462 - EXPECT_EQ(cx_strcmp(list[0], test), 0); 13.463 - cxFree(&alloc, list); 13.464 - 13.465 - // subsequent encounter of delimiter (the string between is empty) 13.466 - n = cx_strsplit_a(&alloc, test, cx_str("is,"), capa, &list); 13.467 - ASSERT_EQ(n, 3); 13.468 - EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 13.469 - EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 13.470 - EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0); 13.471 - cxFree(&alloc, list); 13.472 - 13.473 - // call the _m variant just for coverage 13.474 - auto mtest = cx_strdup(test); 13.475 - cxmutstr *mlist; 13.476 - n = cx_strsplit_ma(&alloc, mtest, cx_str("is,"), 4, &mlist); 13.477 - ASSERT_EQ(n, 3); 13.478 - EXPECT_EQ(cx_strcmp(cx_strcast(mlist[0]), cx_str("th")), 0); 13.479 - EXPECT_EQ(cx_strcmp(cx_strcast(mlist[1]), cx_str("")), 0); 13.480 - EXPECT_EQ(cx_strcmp(cx_strcast(mlist[2]), cx_str("a,csv,string")), 0); 13.481 - cxFree(&alloc, mlist); 13.482 - cx_strfree(&mtest); 13.483 - 13.484 - EXPECT_TRUE(alloc.verify()); 13.485 -} 13.486 - 13.487 -TEST(String, strtrim) { 13.488 - cxstring t1 = cx_strtrim(cx_str(" ein test \t ")); 13.489 - cxstring t2 = cx_strtrim(cx_str("abc")); 13.490 - cxstring t3 = cx_strtrim(cx_str(" 123")); 13.491 - cxstring t4 = cx_strtrim(cx_str("xyz ")); 13.492 - cxstring t5 = cx_strtrim(cx_str(" ")); 13.493 - cxstring empty = cx_strtrim(cx_str("")); 13.494 - 13.495 - EXPECT_EQ(cx_strcmp(t1, cx_str("ein test")), 0); 13.496 - EXPECT_EQ(cx_strcmp(t2, cx_str("abc")), 0); 13.497 - EXPECT_EQ(cx_strcmp(t3, cx_str("123")), 0); 13.498 - EXPECT_EQ(cx_strcmp(t4, cx_str("xyz")), 0); 13.499 - EXPECT_EQ(cx_strcmp(t5, cx_str("")), 0); 13.500 - EXPECT_EQ(cx_strcmp(empty, cx_str("")), 0); 13.501 - 13.502 - // call the _m variant just for coverage 13.503 - cxmutstr m1 = cx_strtrim_m(cx_mutstr((char *) " ein test \t ")); 13.504 - EXPECT_EQ(cx_strcmp(cx_strcast(m1), cx_str("ein test")), 0); 13.505 -} 13.506 - 13.507 -TEST(String, strprefix) { 13.508 - cxstring str = CX_STR("test my prefix and my suffix"); 13.509 - cxstring empty = CX_STR(""); 13.510 - EXPECT_FALSE(cx_strprefix(empty, cx_str("pref"))); 13.511 - EXPECT_TRUE(cx_strprefix(str, empty)); 13.512 - EXPECT_TRUE(cx_strprefix(empty, empty)); 13.513 - EXPECT_TRUE(cx_strprefix(str, cx_str("test "))); 13.514 - EXPECT_FALSE(cx_strprefix(str, cx_str("8-) fsck "))); 13.515 -} 13.516 - 13.517 -TEST(String, strsuffix) { 13.518 - cxstring str = CX_STR("test my prefix and my suffix"); 13.519 - cxstring empty = CX_STR(""); 13.520 - EXPECT_FALSE(cx_strsuffix(empty, cx_str("suf"))); 13.521 - EXPECT_TRUE(cx_strsuffix(str, empty)); 13.522 - EXPECT_TRUE(cx_strsuffix(empty, empty)); 13.523 - EXPECT_TRUE(cx_strsuffix(str, cx_str("fix"))); 13.524 - EXPECT_FALSE(cx_strsuffix(str, cx_str("fox"))); 13.525 -} 13.526 - 13.527 -TEST(String, strcaseprefix) { 13.528 - cxstring str = CX_STR("test my prefix and my suffix"); 13.529 - cxstring empty = CX_STR(""); 13.530 - EXPECT_FALSE(cx_strcaseprefix(empty, cx_str("pREf"))); 13.531 - EXPECT_TRUE(cx_strcaseprefix(str, empty)); 13.532 - EXPECT_TRUE(cx_strcaseprefix(empty, empty)); 13.533 - EXPECT_TRUE(cx_strcaseprefix(str, cx_str("TEST "))); 13.534 - EXPECT_FALSE(cx_strcaseprefix(str, cx_str("8-) fsck "))); 13.535 -} 13.536 - 13.537 -TEST(String, strcasesuffix) { 13.538 - cxstring str = CX_STR("test my prefix and my suffix"); 13.539 - cxstring empty = CX_STR(""); 13.540 - EXPECT_FALSE(cx_strcasesuffix(empty, cx_str("sUf"))); 13.541 - EXPECT_TRUE(cx_strcasesuffix(str, empty)); 13.542 - EXPECT_TRUE(cx_strcasesuffix(empty, empty)); 13.543 - EXPECT_TRUE(cx_strcasesuffix(str, cx_str("FIX"))); 13.544 - EXPECT_FALSE(cx_strcasesuffix(str, cx_str("fox"))); 13.545 -} 13.546 - 13.547 -TEST(String, strreplace) { 13.548 - CxTestingAllocator alloc; 13.549 - cxstring str = CX_STR("test ababab string aba"); 13.550 - cxstring longstr = CX_STR( 13.551 - "xyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacd"); 13.552 - cxstring notrail = CX_STR("test abab"); 13.553 - cxstring empty = CX_STR(""); 13.554 - cxstring astr = CX_STR("aaaaaaaaaa"); 13.555 - cxstring csstr = CX_STR("test AB ab TEST xyz"); 13.556 - 13.557 - cxmutstr repl = cx_strreplace(str, cx_str("abab"), cx_str("muchlonger")); 13.558 - auto expected = "test muchlongerab string aba"; 13.559 - 13.560 - cxmutstr repln = cx_strreplacen(str, cx_str("ab"), cx_str("c"), 2); 13.561 - auto expectedn = "test ccab string aba"; 13.562 - 13.563 - cxmutstr longrepl = cx_strreplace(longstr, cx_str("a"), cx_str("z")); 13.564 - auto longexpect = "xyzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzcd"; 13.565 - 13.566 - cxmutstr replnotrail = cx_strreplace(notrail, cx_str("ab"), cx_str("z")); 13.567 - auto notrailexpect = "test zz"; 13.568 - 13.569 - cxmutstr repleq = cx_strreplace(str, str, cx_str("hello")); 13.570 - auto eqexpect = "hello"; 13.571 - 13.572 - cxmutstr replempty1 = cx_strreplace(empty, cx_str("ab"), cx_str("c")); // expect: empty 13.573 - cxmutstr replempty2 = cx_strreplace(str, cx_str("abab"), empty); 13.574 - auto emptyexpect2 = "test ab string aba"; 13.575 - 13.576 - cxmutstr replpre = cx_strreplace(str, cx_str("test "), cx_str("TEST ")); 13.577 - auto preexpected = "TEST ababab string aba"; 13.578 - 13.579 - cxmutstr replan1 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 1); 13.580 - auto an1expected = "xaaaaaaaaa"; 13.581 - 13.582 - cxmutstr replan4 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 4); 13.583 - auto an4expected = "xxxxaaaaaa"; 13.584 - 13.585 - cxmutstr replan9 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 9); 13.586 - auto an9expected = "xxxxxxxxxa"; 13.587 - 13.588 - cxmutstr replan10 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 10); 13.589 - auto an10expected = "xxxxxxxxxx"; 13.590 - 13.591 - cxmutstr repl1_a = cx_strreplace_a(&alloc, csstr, cx_str("AB"), cx_str("*")); 13.592 - auto expeced1_a = "test * ab TEST xyz"; 13.593 - 13.594 - cxmutstr repl2_a = cx_strreplace_a(&alloc, csstr, cx_str("test"), cx_str("TEST")); 13.595 - auto expected2_a = "TEST AB ab TEST xyz"; 13.596 - 13.597 - 13.598 - EXPECT_NE(repl.ptr, str.ptr); 13.599 - EXPECT_ZERO_TERMINATED(repl); 13.600 - EXPECT_STREQ(repl.ptr, expected); 13.601 - EXPECT_ZERO_TERMINATED(repln); 13.602 - EXPECT_STREQ(repln.ptr, expectedn); 13.603 - EXPECT_ZERO_TERMINATED(longrepl); 13.604 - EXPECT_STREQ(longrepl.ptr, longexpect); 13.605 - EXPECT_ZERO_TERMINATED(replnotrail); 13.606 - EXPECT_STREQ(replnotrail.ptr, notrailexpect); 13.607 - EXPECT_ZERO_TERMINATED(repleq); 13.608 - EXPECT_STREQ(repleq.ptr, eqexpect); 13.609 - EXPECT_ZERO_TERMINATED(replempty1); 13.610 - EXPECT_STREQ(replempty1.ptr, ""); 13.611 - EXPECT_ZERO_TERMINATED(replempty2); 13.612 - EXPECT_STREQ(replempty2.ptr, emptyexpect2); 13.613 - EXPECT_ZERO_TERMINATED(replpre); 13.614 - EXPECT_STREQ(replpre.ptr, preexpected); 13.615 - EXPECT_ZERO_TERMINATED(replan1); 13.616 - EXPECT_STREQ(replan1.ptr, an1expected); 13.617 - EXPECT_ZERO_TERMINATED(replan4); 13.618 - EXPECT_STREQ(replan4.ptr, an4expected); 13.619 - EXPECT_ZERO_TERMINATED(replan9); 13.620 - EXPECT_STREQ(replan9.ptr, an9expected); 13.621 - EXPECT_ZERO_TERMINATED(replan10); 13.622 - EXPECT_STREQ(replan10.ptr, an10expected); 13.623 - EXPECT_ZERO_TERMINATED(repl1_a); 13.624 - EXPECT_STREQ(repl1_a.ptr, expeced1_a); 13.625 - EXPECT_ZERO_TERMINATED(repl2_a); 13.626 - EXPECT_STREQ(repl2_a.ptr, expected2_a); 13.627 - 13.628 - cx_strfree(&repl); 13.629 - cx_strfree(&repln); 13.630 - cx_strfree(&longrepl); 13.631 - cx_strfree(&replnotrail); 13.632 - cx_strfree(&repleq); 13.633 - cx_strfree(&replempty1); 13.634 - cx_strfree(&replempty2); 13.635 - cx_strfree(&replpre); 13.636 - cx_strfree(&replan1); 13.637 - cx_strfree(&replan4); 13.638 - cx_strfree(&replan9); 13.639 - cx_strfree(&replan10); 13.640 - 13.641 - cx_strfree_a(&alloc, &repl1_a); 13.642 - cx_strfree_a(&alloc, &repl2_a); 13.643 - EXPECT_TRUE(alloc.verify()); 13.644 -} 13.645 - 13.646 -TEST(String, strupper) { 13.647 - cxmutstr str = cx_strdup(cx_str("thIs 1s @ Te$t")); 13.648 - cx_strupper(str); 13.649 - EXPECT_STREQ(str.ptr, "THIS 1S @ TE$T"); 13.650 - cx_strfree(&str); 13.651 -} 13.652 - 13.653 -TEST(String, strlower) { 13.654 - cxmutstr str = cx_strdup(cx_str("thIs 1s @ Te$t")); 13.655 - cx_strlower(str); 13.656 - EXPECT_STREQ(str.ptr, "this 1s @ te$t"); 13.657 - cx_strfree(&str); 13.658 -} 13.659 - 13.660 -TEST(String, strtok) { 13.661 - cxstring str = cx_str("a,comma,separated,string"); 13.662 - cxstring delim = cx_str(","); 13.663 - CxStrtokCtx ctx = cx_strtok(str, delim, 3); 13.664 - EXPECT_EQ(ctx.str.ptr, str.ptr); 13.665 - EXPECT_EQ(ctx.str.length, str.length); 13.666 - EXPECT_EQ(ctx.delim.ptr, delim.ptr); 13.667 - EXPECT_EQ(ctx.delim.length, delim.length); 13.668 - EXPECT_EQ(ctx.limit, 3); 13.669 - EXPECT_EQ(ctx.found, 0); 13.670 - EXPECT_EQ(ctx.pos, 0); 13.671 - EXPECT_EQ(ctx.next_pos, 0); 13.672 - EXPECT_EQ(ctx.delim_more, nullptr); 13.673 - EXPECT_EQ(ctx.delim_more_count, 0); 13.674 -} 13.675 - 13.676 -TEST(String, strtok_m) { 13.677 - cxmutstr str = cx_strdup(cx_str("a,comma,separated,string")); 13.678 - cxstring delim = cx_str(","); 13.679 - CxStrtokCtx ctx = cx_strtok_m(str, delim, 3); 13.680 - EXPECT_EQ(ctx.str.ptr, str.ptr); 13.681 - EXPECT_EQ(ctx.str.length, str.length); 13.682 - EXPECT_EQ(ctx.delim.ptr, delim.ptr); 13.683 - EXPECT_EQ(ctx.delim.length, delim.length); 13.684 - EXPECT_EQ(ctx.limit, 3); 13.685 - EXPECT_EQ(ctx.found, 0); 13.686 - EXPECT_EQ(ctx.pos, 0); 13.687 - EXPECT_EQ(ctx.next_pos, 0); 13.688 - EXPECT_EQ(ctx.delim_more, nullptr); 13.689 - EXPECT_EQ(ctx.delim_more_count, 0); 13.690 - cx_strfree(&str); 13.691 -} 13.692 - 13.693 -TEST(String, strtok_delim) { 13.694 - cxstring str = cx_str("an,arbitrarily|separated;string"); 13.695 - cxstring delim = cx_str(","); 13.696 - cxstring delim_more[2] = {CX_STR("|"), CX_STR(";")}; 13.697 - CxStrtokCtx ctx = cx_strtok(str, delim, 3); 13.698 - cx_strtok_delim(&ctx, delim_more, 2); 13.699 - EXPECT_EQ(ctx.str.ptr, str.ptr); 13.700 - EXPECT_EQ(ctx.str.length, str.length); 13.701 - EXPECT_EQ(ctx.delim.ptr, delim.ptr); 13.702 - EXPECT_EQ(ctx.delim.length, delim.length); 13.703 - EXPECT_EQ(ctx.limit, 3); 13.704 - EXPECT_EQ(ctx.found, 0); 13.705 - EXPECT_EQ(ctx.pos, 0); 13.706 - EXPECT_EQ(ctx.next_pos, 0); 13.707 - EXPECT_EQ(ctx.delim_more, delim_more); 13.708 - EXPECT_EQ(ctx.delim_more_count, 2); 13.709 -} 13.710 - 13.711 -TEST(String, strtok_next_easy) { 13.712 - cxstring str = cx_str("a,comma,separated,string"); 13.713 - cxstring delim = cx_str(","); 13.714 - CxStrtokCtx ctx = cx_strtok(str, delim, 3); 13.715 - bool ret; 13.716 - cxstring tok; 13.717 - 13.718 - ret = cx_strtok_next(&ctx, &tok); 13.719 - ASSERT_TRUE(ret); 13.720 - EXPECT_EQ(cx_strcmp(tok, cx_str("a")), 0); 13.721 - EXPECT_EQ(ctx.pos, 0); 13.722 - EXPECT_EQ(ctx.next_pos, 2); 13.723 - EXPECT_EQ(ctx.delim_pos, 1); 13.724 - EXPECT_EQ(ctx.found, 1); 13.725 - 13.726 - ret = cx_strtok_next(&ctx, &tok); 13.727 - ASSERT_TRUE(ret); 13.728 - EXPECT_EQ(cx_strcmp(tok, cx_str("comma")), 0); 13.729 - EXPECT_EQ(ctx.pos, 2); 13.730 - EXPECT_EQ(ctx.next_pos, 8); 13.731 - EXPECT_EQ(ctx.delim_pos, 7); 13.732 - EXPECT_EQ(ctx.found, 2); 13.733 - 13.734 - ret = cx_strtok_next(&ctx, &tok); 13.735 - ASSERT_TRUE(ret); 13.736 - EXPECT_EQ(cx_strcmp(tok, cx_str("separated")), 0); 13.737 - EXPECT_EQ(ctx.pos, 8); 13.738 - EXPECT_EQ(ctx.next_pos, 18); 13.739 - EXPECT_EQ(ctx.delim_pos, 17); 13.740 - EXPECT_EQ(ctx.found, 3); 13.741 - 13.742 - ret = cx_strtok_next(&ctx, &tok); 13.743 - ASSERT_FALSE(ret); 13.744 - EXPECT_EQ(ctx.pos, 8); 13.745 - EXPECT_EQ(ctx.next_pos, 18); 13.746 - EXPECT_EQ(ctx.delim_pos, 17); 13.747 - EXPECT_EQ(ctx.found, 3); 13.748 -} 13.749 - 13.750 -TEST(String, strtok_next_unlimited) { 13.751 - cxstring str = cx_str("some;-;otherwise;-;separated;-;string;-;"); 13.752 - cxstring delim = cx_str(";-;"); 13.753 - CxStrtokCtx ctx = cx_strtok(str, delim, SIZE_MAX); 13.754 - bool ret; 13.755 - cxstring tok; 13.756 - 13.757 - ret = cx_strtok_next(&ctx, &tok); 13.758 - ASSERT_TRUE(ret); 13.759 - EXPECT_EQ(cx_strcmp(tok, cx_str("some")), 0); 13.760 - EXPECT_EQ(ctx.pos, 0); 13.761 - EXPECT_EQ(ctx.next_pos, 7); 13.762 - EXPECT_EQ(ctx.delim_pos, 4); 13.763 - EXPECT_EQ(ctx.found, 1); 13.764 - 13.765 - ret = cx_strtok_next(&ctx, &tok); 13.766 - ASSERT_TRUE(ret); 13.767 - EXPECT_EQ(cx_strcmp(tok, cx_str("otherwise")), 0); 13.768 - EXPECT_EQ(ctx.pos, 7); 13.769 - EXPECT_EQ(ctx.next_pos, 19); 13.770 - EXPECT_EQ(ctx.delim_pos, 16); 13.771 - EXPECT_EQ(ctx.found, 2); 13.772 - 13.773 - ret = cx_strtok_next(&ctx, &tok); 13.774 - ASSERT_TRUE(ret); 13.775 - EXPECT_EQ(cx_strcmp(tok, cx_str("separated")), 0); 13.776 - EXPECT_EQ(ctx.pos, 19); 13.777 - EXPECT_EQ(ctx.next_pos, 31); 13.778 - EXPECT_EQ(ctx.delim_pos, 28); 13.779 - EXPECT_EQ(ctx.found, 3); 13.780 - 13.781 - ret = cx_strtok_next(&ctx, &tok); 13.782 - ASSERT_TRUE(ret); 13.783 - EXPECT_EQ(cx_strcmp(tok, cx_str("string")), 0); 13.784 - EXPECT_EQ(ctx.pos, 31); 13.785 - EXPECT_EQ(ctx.next_pos, 40); 13.786 - EXPECT_EQ(ctx.delim_pos, 37); 13.787 - EXPECT_EQ(ctx.found, 4); 13.788 - 13.789 - ret = cx_strtok_next(&ctx, &tok); 13.790 - ASSERT_TRUE(ret); 13.791 - EXPECT_EQ(cx_strcmp(tok, cx_str("")), 0); 13.792 - EXPECT_EQ(ctx.pos, 40); 13.793 - EXPECT_EQ(ctx.next_pos, 40); 13.794 - EXPECT_EQ(ctx.delim_pos, 40); 13.795 - EXPECT_EQ(ctx.found, 5); 13.796 - 13.797 - ret = cx_strtok_next(&ctx, &tok); 13.798 - ASSERT_FALSE(ret); 13.799 - EXPECT_EQ(ctx.pos, 40); 13.800 - EXPECT_EQ(ctx.delim_pos, 40); 13.801 - EXPECT_EQ(ctx.found, 5); 13.802 -} 13.803 - 13.804 -TEST(String, strtok_next_advanced) { 13.805 - cxmutstr str = cx_strdup(cx_str("an,arbitrarily;||separated;string")); 13.806 - cxstring delim = cx_str(","); 13.807 - cxstring delim_more[2] = {CX_STR("||"), CX_STR(";")}; 13.808 - CxStrtokCtx ctx = cx_strtok_m(str, delim, 10); 13.809 - cx_strtok_delim(&ctx, delim_more, 2); 13.810 - bool ret; 13.811 - cxmutstr tok; 13.812 - 13.813 - ret = cx_strtok_next_m(&ctx, &tok); 13.814 - ASSERT_TRUE(ret); 13.815 - EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("an")), 0); 13.816 - EXPECT_EQ(ctx.pos, 0); 13.817 - EXPECT_EQ(ctx.next_pos, 3); 13.818 - EXPECT_EQ(ctx.delim_pos, 2); 13.819 - EXPECT_EQ(ctx.found, 1); 13.820 - cx_strupper(tok); 13.821 - 13.822 - ret = cx_strtok_next_m(&ctx, &tok); 13.823 - ASSERT_TRUE(ret); 13.824 - EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("arbitrarily")), 0); 13.825 - EXPECT_EQ(ctx.pos, 3); 13.826 - EXPECT_EQ(ctx.next_pos, 15); 13.827 - EXPECT_EQ(ctx.delim_pos, 14); 13.828 - EXPECT_EQ(ctx.found, 2); 13.829 - cx_strupper(tok); 13.830 - 13.831 - ret = cx_strtok_next_m(&ctx, &tok); 13.832 - ASSERT_TRUE(ret); 13.833 - EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("")), 0); 13.834 - EXPECT_EQ(ctx.pos, 15); 13.835 - EXPECT_EQ(ctx.next_pos, 17); 13.836 - EXPECT_EQ(ctx.delim_pos, 15); 13.837 - EXPECT_EQ(ctx.found, 3); 13.838 - cx_strupper(tok); 13.839 - 13.840 - ret = cx_strtok_next_m(&ctx, &tok); 13.841 - ASSERT_TRUE(ret); 13.842 - EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("separated")), 0); 13.843 - EXPECT_EQ(ctx.pos, 17); 13.844 - EXPECT_EQ(ctx.next_pos, 27); 13.845 - EXPECT_EQ(ctx.delim_pos, 26); 13.846 - EXPECT_EQ(ctx.found, 4); 13.847 - cx_strupper(tok); 13.848 - 13.849 - ret = cx_strtok_next_m(&ctx, &tok); 13.850 - ASSERT_TRUE(ret); 13.851 - EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("string")), 0); 13.852 - EXPECT_EQ(ctx.pos, 27); 13.853 - EXPECT_EQ(ctx.next_pos, 33); 13.854 - EXPECT_EQ(ctx.delim_pos, 33); 13.855 - EXPECT_EQ(ctx.found, 5); 13.856 - cx_strupper(tok); 13.857 - 13.858 - ret = cx_strtok_next_m(&ctx, &tok); 13.859 - ASSERT_FALSE(ret); 13.860 - EXPECT_EQ(ctx.pos, 27); 13.861 - EXPECT_EQ(ctx.next_pos, 33); 13.862 - EXPECT_EQ(ctx.delim_pos, 33); 13.863 - EXPECT_EQ(ctx.found, 5); 13.864 - 13.865 - EXPECT_EQ(cx_strcmp(cx_strcast(str), cx_str("AN,ARBITRARILY;||SEPARATED;STRING")), 0); 13.866 - 13.867 - cx_strfree(&str); 13.868 -}
14.1 --- a/test/test_tree.cpp Tue Feb 07 21:53:06 2023 +0100 14.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 14.3 @@ -1,122 +0,0 @@ 14.4 -/* 14.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 14.6 - * 14.7 - * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 14.8 - * 14.9 - * Redistribution and use in source and binary forms, with or without 14.10 - * modification, are permitted provided that the following conditions are met: 14.11 - * 14.12 - * 1. Redistributions of source code must retain the above copyright 14.13 - * notice, this list of conditions and the following disclaimer. 14.14 - * 14.15 - * 2. Redistributions in binary form must reproduce the above copyright 14.16 - * notice, this list of conditions and the following disclaimer in the 14.17 - * documentation and/or other materials provided with the distribution. 14.18 - * 14.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 14.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 14.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 14.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 14.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 14.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 14.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 14.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 14.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 14.29 - * POSSIBILITY OF SUCH DAMAGE. 14.30 - */ 14.31 - 14.32 -#include "cx/tree.h" 14.33 -#include <gtest/gtest.h> 14.34 - 14.35 -struct TestNode { 14.36 - TestNode *parent = nullptr; 14.37 - TestNode *prev = nullptr; 14.38 - TestNode *next = nullptr; 14.39 - 14.40 - TestNode *children_begin = nullptr; 14.41 - TestNode *children_end = nullptr; 14.42 -}; 14.43 - 14.44 -TEST(Tree, cx_tree_add_sibling) { 14.45 - // prepare test tree 14.46 - TestNode root, a; 14.47 - root.children_begin = &a; 14.48 - root.children_end = &a; 14.49 - a.parent = &root; 14.50 - 14.51 - // new test nodes 14.52 - TestNode b, c; 14.53 - 14.54 - // test 14.55 - cx_tree_add_sibling(&a, offsetof(TestNode, prev), offsetof(TestNode, next), offsetof(TestNode, parent), &b); 14.56 - EXPECT_EQ(b.parent, &root); 14.57 - EXPECT_EQ(b.prev, &a); 14.58 - EXPECT_EQ(b.next, nullptr); 14.59 - EXPECT_EQ(a.next, &b); 14.60 - 14.61 - cx_tree_add_sibling(&a, -1, offsetof(TestNode, next), -1, &c); 14.62 - EXPECT_EQ(c.parent, nullptr); 14.63 - EXPECT_EQ(c.prev, nullptr); 14.64 - EXPECT_EQ(c.next, nullptr); 14.65 - EXPECT_EQ(b.next, &c); 14.66 -} 14.67 - 14.68 -TEST(Tree, cx_tree_add_child) { 14.69 - TestNode root, a, b, c, a1; 14.70 - 14.71 - cx_tree_add_child( 14.72 - (void **) &root.children_begin, 14.73 - (void **) &root.children_end, 14.74 - offsetof(TestNode, prev), 14.75 - offsetof(TestNode, next), 14.76 - &a, 14.77 - offsetof(TestNode, parent), 14.78 - &root); 14.79 - EXPECT_EQ(root.children_begin, &a); 14.80 - EXPECT_EQ(root.children_end, &a); 14.81 - EXPECT_EQ(a.parent, &root); 14.82 - EXPECT_EQ(a.prev, nullptr); 14.83 - EXPECT_EQ(a.next, nullptr); 14.84 - 14.85 - cx_tree_add_child( 14.86 - (void **) &root.children_begin, 14.87 - (void **) &root.children_end, 14.88 - offsetof(TestNode, prev), 14.89 - offsetof(TestNode, next), 14.90 - &b, 14.91 - offsetof(TestNode, parent), 14.92 - &root); 14.93 - EXPECT_EQ(root.children_begin, &a); 14.94 - EXPECT_EQ(root.children_begin->next, &b); 14.95 - EXPECT_EQ(root.children_end, &b); 14.96 - EXPECT_EQ(b.parent, &root); 14.97 - EXPECT_EQ(b.prev, &a); 14.98 - 14.99 - cx_tree_add_child( 14.100 - (void **) &root.children_begin, 14.101 - nullptr, 14.102 - -1, 14.103 - offsetof(TestNode, next), 14.104 - &c, 14.105 - -1, 14.106 - &root); 14.107 - EXPECT_EQ(root.children_end, &b); // children_end unchanged 14.108 - EXPECT_EQ(b.next, &c); 14.109 - EXPECT_EQ(c.prev, nullptr); 14.110 - EXPECT_EQ(c.next, nullptr); 14.111 - EXPECT_EQ(c.parent, nullptr); 14.112 - 14.113 - cx_tree_add_child( 14.114 - (void **) &a.children_begin, 14.115 - (void **) &a.children_end, 14.116 - offsetof(TestNode, prev), 14.117 - offsetof(TestNode, next), 14.118 - &a1, 14.119 - offsetof(TestNode, parent), 14.120 - &a); 14.121 - EXPECT_EQ(a.children_begin, &a1); 14.122 - EXPECT_EQ(a1.parent, &a); 14.123 - EXPECT_EQ(root.children_begin, &a); 14.124 - EXPECT_EQ(root.children_begin->children_begin, &a1); 14.125 -}
15.1 --- a/test/test_utils.cpp Tue Feb 07 21:53:06 2023 +0100 15.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 15.3 @@ -1,155 +0,0 @@ 15.4 -/* 15.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 15.6 - * 15.7 - * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 15.8 - * 15.9 - * Redistribution and use in source and binary forms, with or without 15.10 - * modification, are permitted provided that the following conditions are met: 15.11 - * 15.12 - * 1. Redistributions of source code must retain the above copyright 15.13 - * notice, this list of conditions and the following disclaimer. 15.14 - * 15.15 - * 2. Redistributions in binary form must reproduce the above copyright 15.16 - * notice, this list of conditions and the following disclaimer in the 15.17 - * documentation and/or other materials provided with the distribution. 15.18 - * 15.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 15.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 15.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 15.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 15.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 15.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 15.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 15.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 15.29 - * POSSIBILITY OF SUCH DAMAGE. 15.30 - */ 15.31 - 15.32 -#include "cx/utils.h" 15.33 - 15.34 -#include <gtest/gtest.h> 15.35 - 15.36 -TEST(Utils, ForN) { 15.37 - unsigned j; 15.38 - j = 0; 15.39 - cx_for_n(i, 50) { 15.40 - EXPECT_EQ(i, j); 15.41 - j++; 15.42 - } 15.43 -} 15.44 - 15.45 -TEST(Utils, szmul) { 15.46 - size_t r; 15.47 - int e; 15.48 - e = cx_szmul(5, 7, &r); 15.49 - EXPECT_EQ(0, e); 15.50 - EXPECT_EQ(35, r); 15.51 - 15.52 - size_t s = SIZE_MAX & ~3; 15.53 - 15.54 - e = cx_szmul(s / 4, 2, &r); 15.55 - EXPECT_EQ(0, e); 15.56 - EXPECT_EQ(s / 2, r); 15.57 - e = cx_szmul(2, s / 4, &r); 15.58 - EXPECT_EQ(0, e); 15.59 - EXPECT_EQ(s / 2, r); 15.60 - 15.61 - e = cx_szmul(s / 4, 4, &r); 15.62 - EXPECT_EQ(0, e); 15.63 - EXPECT_EQ(s, r); 15.64 - 15.65 - e = cx_szmul(4, s / 4, &r); 15.66 - EXPECT_EQ(0, e); 15.67 - EXPECT_EQ(s, r); 15.68 - 15.69 - e = cx_szmul(s / 4, 5, &r); 15.70 - EXPECT_NE(0, e); 15.71 - 15.72 - e = cx_szmul(5, s / 4, &r); 15.73 - EXPECT_NE(0, e); 15.74 - 15.75 - e = cx_szmul(SIZE_MAX - 4, 0, &r); 15.76 - EXPECT_EQ(0, e); 15.77 - EXPECT_EQ(0, r); 15.78 - 15.79 - e = cx_szmul(0, SIZE_MAX - 1, &r); 15.80 - EXPECT_EQ(0, e); 15.81 - EXPECT_EQ(0, r); 15.82 - 15.83 - e = cx_szmul(SIZE_MAX, 0, &r); 15.84 - EXPECT_EQ(0, e); 15.85 - EXPECT_EQ(0, r); 15.86 - 15.87 - e = cx_szmul(0, SIZE_MAX, &r); 15.88 - EXPECT_EQ(0, e); 15.89 - EXPECT_EQ(0, r); 15.90 - 15.91 - e = cx_szmul(0, 0, &r); 15.92 - EXPECT_EQ(0, e); 15.93 - EXPECT_EQ(0, r); 15.94 -} 15.95 - 15.96 -#ifdef CX_SZMUL_BUILTIN 15.97 - 15.98 -// also test the custom implementation 15.99 -struct Utils_szmul_impl : ::testing::Test { 15.100 -#undef CX_SZMUL_BUILTIN 15.101 - 15.102 -#include "../src/utils.c" 15.103 - 15.104 -#define CX_SZMUL_BUILTIN 15.105 -}; 15.106 - 15.107 -TEST_F(Utils_szmul_impl, Test) { 15.108 - size_t r; 15.109 - int e; 15.110 - e = cx_szmul_impl(5, 7, &r); 15.111 - EXPECT_EQ(0, e); 15.112 - EXPECT_EQ(35, r); 15.113 - 15.114 - size_t s = SIZE_MAX & ~3; 15.115 - 15.116 - e = cx_szmul_impl(s / 4, 2, &r); 15.117 - EXPECT_EQ(0, e); 15.118 - EXPECT_EQ(s / 2, r); 15.119 - e = cx_szmul_impl(2, s / 4, &r); 15.120 - EXPECT_EQ(0, e); 15.121 - EXPECT_EQ(s / 2, r); 15.122 - 15.123 - e = cx_szmul_impl(s / 4, 4, &r); 15.124 - EXPECT_EQ(0, e); 15.125 - EXPECT_EQ(s, r); 15.126 - 15.127 - e = cx_szmul_impl(4, s / 4, &r); 15.128 - EXPECT_EQ(0, e); 15.129 - EXPECT_EQ(s, r); 15.130 - 15.131 - e = cx_szmul_impl(s / 4, 5, &r); 15.132 - EXPECT_NE(0, e); 15.133 - 15.134 - e = cx_szmul_impl(5, s / 4, &r); 15.135 - EXPECT_NE(0, e); 15.136 - 15.137 - e = cx_szmul_impl(SIZE_MAX - 4, 0, &r); 15.138 - EXPECT_EQ(0, e); 15.139 - EXPECT_EQ(0, r); 15.140 - 15.141 - e = cx_szmul_impl(0, SIZE_MAX - 1, &r); 15.142 - EXPECT_EQ(0, e); 15.143 - EXPECT_EQ(0, r); 15.144 - 15.145 - e = cx_szmul_impl(SIZE_MAX, 0, &r); 15.146 - EXPECT_EQ(0, e); 15.147 - EXPECT_EQ(0, r); 15.148 - 15.149 - e = cx_szmul_impl(0, SIZE_MAX, &r); 15.150 - EXPECT_EQ(0, e); 15.151 - EXPECT_EQ(0, r); 15.152 - 15.153 - e = cx_szmul_impl(0, 0, &r); 15.154 - EXPECT_EQ(0, e); 15.155 - EXPECT_EQ(0, r); 15.156 -} 15.157 - 15.158 -#endif // CX_SZMUL_BUILTIN
16.1 --- a/test/util_allocator.cpp Tue Feb 07 21:53:06 2023 +0100 16.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 16.3 @@ -1,167 +0,0 @@ 16.4 -/* 16.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 16.6 - * 16.7 - * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 16.8 - * 16.9 - * Redistribution and use in source and binary forms, with or without 16.10 - * modification, are permitted provided that the following conditions are met: 16.11 - * 16.12 - * 1. Redistributions of source code must retain the above copyright 16.13 - * notice, this list of conditions and the following disclaimer. 16.14 - * 16.15 - * 2. Redistributions in binary form must reproduce the above copyright 16.16 - * notice, this list of conditions and the following disclaimer in the 16.17 - * documentation and/or other materials provided with the distribution. 16.18 - * 16.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 16.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 16.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 16.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 16.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 16.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 16.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 16.29 - * POSSIBILITY OF SUCH DAMAGE. 16.30 - */ 16.31 - 16.32 -#include "util_allocator.h" 16.33 - 16.34 -void *cx_malloc_testing(void *d, size_t n) { 16.35 - auto data = reinterpret_cast<CxTestingAllocator *>(d); 16.36 - void *ptr = malloc(n); 16.37 - data->alloc_total++; 16.38 - if (ptr == nullptr) { 16.39 - data->alloc_failed++; 16.40 - } else { 16.41 - data->tracked.insert(ptr); 16.42 - } 16.43 - return ptr; 16.44 -} 16.45 - 16.46 -void *cx_realloc_testing(void *d, void *mem, size_t n) { 16.47 - auto data = reinterpret_cast<CxTestingAllocator *>(d); 16.48 - void *ptr = realloc(mem, n); 16.49 - if (ptr == mem) { 16.50 - return ptr; 16.51 - } else { 16.52 - data->alloc_total++; 16.53 - if (ptr == nullptr) { 16.54 - data->alloc_failed++; 16.55 - } else { 16.56 - data->free_total++; 16.57 - if (data->tracked.erase(mem) == 0) { 16.58 - data->free_failed++; 16.59 - } 16.60 - data->tracked.insert(ptr); 16.61 - } 16.62 - return ptr; 16.63 - } 16.64 -} 16.65 - 16.66 -void *cx_calloc_testing(void *d, size_t nelem, size_t n) { 16.67 - auto data = reinterpret_cast<CxTestingAllocator *>(d); 16.68 - void *ptr = calloc(nelem, n); 16.69 - data->alloc_total++; 16.70 - if (ptr == nullptr) { 16.71 - data->alloc_failed++; 16.72 - } else { 16.73 - data->tracked.insert(ptr); 16.74 - } 16.75 - return ptr; 16.76 -} 16.77 - 16.78 -void cx_free_testing(void *d, void *mem) { 16.79 - auto data = reinterpret_cast<CxTestingAllocator *>(d); 16.80 - data->free_total++; 16.81 - if (data->tracked.erase(mem) == 0) { 16.82 - data->free_failed++; 16.83 - // do not even attempt to free mem, because it is likely to segfault 16.84 - } else { 16.85 - free(mem); 16.86 - } 16.87 -} 16.88 - 16.89 -cx_allocator_class cx_testing_allocator_class = { 16.90 - cx_malloc_testing, 16.91 - cx_realloc_testing, 16.92 - cx_calloc_testing, 16.93 - cx_free_testing 16.94 -}; 16.95 - 16.96 -CxTestingAllocator::CxTestingAllocator() : CxAllocator() { 16.97 - cl = &cx_testing_allocator_class; 16.98 - data = this; 16.99 -} 16.100 - 16.101 -bool CxTestingAllocator::used() const { 16.102 - return alloc_total > 0; 16.103 -} 16.104 - 16.105 -bool CxTestingAllocator::verify() const { 16.106 - return tracked.empty() && alloc_failed == 0 && free_failed == 0 && alloc_total == free_total; 16.107 -} 16.108 - 16.109 -// SELF-TEST 16.110 - 16.111 -#include <gtest/gtest.h> 16.112 - 16.113 -TEST(TestingAllocator, ExpectFree) { 16.114 - CxTestingAllocator allocator; 16.115 - 16.116 - ASSERT_TRUE(allocator.verify()); 16.117 - EXPECT_FALSE(allocator.used()); 16.118 - auto ptr = cxMalloc(&allocator, 16); 16.119 - EXPECT_TRUE(allocator.used()); 16.120 - ASSERT_NE(ptr, nullptr); 16.121 - EXPECT_FALSE(allocator.verify()); 16.122 - 16.123 - cxFree(&allocator, ptr); 16.124 - EXPECT_TRUE(allocator.verify()); 16.125 -} 16.126 - 16.127 -TEST(TestingAllocator, DetectDoubleFree) { 16.128 - CxTestingAllocator allocator; 16.129 - 16.130 - ASSERT_TRUE(allocator.verify()); 16.131 - auto ptr = cxMalloc(&allocator, 16); 16.132 - ASSERT_NE(ptr, nullptr); 16.133 - 16.134 - cxFree(&allocator, ptr); 16.135 - EXPECT_TRUE(allocator.verify()); 16.136 - ASSERT_NO_FATAL_FAILURE(cxFree(&allocator, ptr)); 16.137 - EXPECT_FALSE(allocator.verify()); 16.138 -} 16.139 - 16.140 -TEST(TestingAllocator, FreeUntracked) { 16.141 - CxTestingAllocator allocator; 16.142 - 16.143 - auto ptr = malloc(16); 16.144 - ASSERT_TRUE(allocator.verify()); 16.145 - ASSERT_NO_FATAL_FAILURE(cxFree(&allocator, ptr)); 16.146 - EXPECT_FALSE(allocator.verify()); 16.147 - ASSERT_NO_FATAL_FAILURE(free(ptr)); 16.148 -} 16.149 - 16.150 -TEST(TestingAllocator, FullLifecycleWithRealloc) { 16.151 - CxTestingAllocator allocator; 16.152 - ASSERT_TRUE(allocator.verify()); 16.153 - auto ptr = cxMalloc(&allocator, 16); 16.154 - ASSERT_NE(ptr, nullptr); 16.155 - EXPECT_EQ(allocator.tracked.size(), 1); 16.156 - ptr = cxRealloc(&allocator, ptr, 256); 16.157 - ASSERT_NE(ptr, nullptr); 16.158 - EXPECT_EQ(allocator.tracked.size(), 1); 16.159 - cxFree(&allocator, ptr); 16.160 - EXPECT_TRUE(allocator.verify()); 16.161 -} 16.162 - 16.163 -TEST(TestingAllocator, CallocInitializes) { 16.164 - CxTestingAllocator allocator; 16.165 - const char zeros[16] = {0}; 16.166 - auto ptr = cxCalloc(&allocator, 16, 1); 16.167 - EXPECT_EQ(memcmp(ptr, zeros, 16), 0); 16.168 - cxFree(&allocator, ptr); 16.169 - EXPECT_TRUE(allocator.verify()); 16.170 -}
17.1 --- a/test/util_allocator.h Tue Feb 07 21:53:06 2023 +0100 17.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 17.3 @@ -1,81 +0,0 @@ 17.4 -/* 17.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 17.6 - * 17.7 - * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 17.8 - * 17.9 - * Redistribution and use in source and binary forms, with or without 17.10 - * modification, are permitted provided that the following conditions are met: 17.11 - * 17.12 - * 1. Redistributions of source code must retain the above copyright 17.13 - * notice, this list of conditions and the following disclaimer. 17.14 - * 17.15 - * 2. Redistributions in binary form must reproduce the above copyright 17.16 - * notice, this list of conditions and the following disclaimer in the 17.17 - * documentation and/or other materials provided with the distribution. 17.18 - * 17.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 17.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 17.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 17.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 17.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 17.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 17.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 17.29 - * POSSIBILITY OF SUCH DAMAGE. 17.30 - */ 17.31 - 17.32 -#ifndef UCX_UTIL_ALLOCATOR_H 17.33 -#define UCX_UTIL_ALLOCATOR_H 17.34 - 17.35 -#include "cx/allocator.h" 17.36 - 17.37 -#include <set> 17.38 - 17.39 -struct CxTestingAllocator : public CxAllocator { 17.40 - /** 17.41 - * Total number of all allocations (malloc, calloc, realloc). 17.42 - * A realloc() does only count when the memory has to be moved. 17.43 - */ 17.44 - unsigned alloc_total = 0; 17.45 - /** 17.46 - * Number of failed allocations (malloc, calloc, realloc). 17.47 - */ 17.48 - unsigned alloc_failed = 0; 17.49 - /** 17.50 - * Total number of freed pointers. 17.51 - * A reallocation also counts as a free when the memory has to be moved. 17.52 - */ 17.53 - unsigned free_total = 0; 17.54 - /** 17.55 - * Number of failed free invocations. 17.56 - * A free() is considered failed, if it has not been performed on tracked memory. 17.57 - */ 17.58 - unsigned free_failed = 0; 17.59 - /** 17.60 - * The set of tracked memory blocks. 17.61 - */ 17.62 - std::set<void *> tracked; 17.63 - 17.64 - /** 17.65 - * Constructs a new testing allocator. 17.66 - */ 17.67 - CxTestingAllocator(); 17.68 - 17.69 - /** 17.70 - * Verifies that this allocator has been used. 17.71 - * 17.72 - * @return true if any allocation was attempted using this allocator 17.73 - */ 17.74 - [[nodiscard]] bool used() const; 17.75 - 17.76 - /** 17.77 - * Verifies that all allocated memory blocks are freed and no free occurred twice. 17.78 - * 17.79 - * @return true iff all tracked allocations / deallocations were valid 17.80 - */ 17.81 - [[nodiscard]] bool verify() const; 17.82 -}; 17.83 - 17.84 -#endif // UCX_UTIL_ALLOCATOR_H
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/tests/.clang-tidy Tue Feb 07 21:55:37 2023 +0100 18.3 @@ -0,0 +1,2 @@ 18.4 +# Disable static initialization warning for test code 18.5 +Checks: '-cert-err58-cpp'
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/tests/CMakeLists.txt Tue Feb 07 21:55:37 2023 +0100 19.3 @@ -0,0 +1,32 @@ 19.4 +# Load Google Test Framework 19.5 +set(CMAKE_CXX_STANDARD 17) 19.6 + 19.7 +include(FetchContent) 19.8 +FetchContent_Declare( 19.9 + googletest 19.10 + GIT_REPOSITORY https://github.com/google/googletest.git 19.11 + GIT_TAG e2239ee6043f73722e7aa812a459f54a28552929 # release 1.11.0 19.12 +) 19.13 +# For Windows: Prevent overriding the parent project's compiler/linker settings 19.14 +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 19.15 +FetchContent_MakeAvailable(googletest) 19.16 +include(GoogleTest) 19.17 +message(STATUS "Google Test made available") 19.18 + 19.19 +add_executable(ucxtest 19.20 + test_utils.cpp 19.21 + test_allocator.cpp 19.22 + test_compare.cpp 19.23 + test_string.cpp 19.24 + test_buffer.cpp 19.25 + test_list.cpp 19.26 + test_tree.cpp 19.27 + test_hash_key.cpp 19.28 + test_map.cpp 19.29 + test_basic_mempool.cpp 19.30 + test_printf.cpp 19.31 + selftest.cpp 19.32 + util_allocator.cpp 19.33 + ) 19.34 +target_link_libraries(ucxtest PRIVATE ucx_static gtest_main) 19.35 +gtest_discover_tests(ucxtest)
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/tests/selftest.cpp Tue Feb 07 21:55:37 2023 +0100 20.3 @@ -0,0 +1,39 @@ 20.4 +/* 20.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 20.6 + * 20.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 20.8 + * 20.9 + * Redistribution and use in source and binary forms, with or without 20.10 + * modification, are permitted provided that the following conditions are met: 20.11 + * 20.12 + * 1. Redistributions of source code must retain the above copyright 20.13 + * notice, this list of conditions and the following disclaimer. 20.14 + * 20.15 + * 2. Redistributions in binary form must reproduce the above copyright 20.16 + * notice, this list of conditions and the following disclaimer in the 20.17 + * documentation and/or other materials provided with the distribution. 20.18 + * 20.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 20.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 20.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 20.29 + * POSSIBILITY OF SUCH DAMAGE. 20.30 + */ 20.31 + 20.32 +#include <gtest/gtest.h> 20.33 +#include <cx/common.h> 20.34 + 20.35 +TEST(SelfTest, BasicAssertion) { 20.36 + EXPECT_EQ(7 * 6, 42); 20.37 +} 20.38 + 20.39 +TEST(SelfTest, UcxVersion) { 20.40 + EXPECT_GE(UCX_VERSION_MAJOR, 3); 20.41 + EXPECT_GE(UCX_VERSION, 3 << 16); 20.42 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/tests/test_allocator.cpp Tue Feb 07 21:55:37 2023 +0100 21.3 @@ -0,0 +1,96 @@ 21.4 +/* 21.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 21.6 + * 21.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 21.8 + * 21.9 + * Redistribution and use in source and binary forms, with or without 21.10 + * modification, are permitted provided that the following conditions are met: 21.11 + * 21.12 + * 1. Redistributions of source code must retain the above copyright 21.13 + * notice, this list of conditions and the following disclaimer. 21.14 + * 21.15 + * 2. Redistributions in binary form must reproduce the above copyright 21.16 + * notice, this list of conditions and the following disclaimer in the 21.17 + * documentation and/or other materials provided with the distribution. 21.18 + * 21.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 21.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 21.29 + * POSSIBILITY OF SUCH DAMAGE. 21.30 + */ 21.31 + 21.32 +#include "cx/allocator.h" 21.33 +#include <gtest/gtest.h> 21.34 + 21.35 +TEST(Allocator, DefaultAllocator) { 21.36 + cx_allocator_class *clazz = cxDefaultAllocator->cl; 21.37 + ASSERT_NE(clazz, nullptr); 21.38 +} 21.39 + 21.40 +TEST(Allocator, DefaultMalloc) { 21.41 + void *test = cxMalloc(cxDefaultAllocator, 16); 21.42 + ASSERT_NE(test, nullptr); 21.43 + free(test); 21.44 +} 21.45 + 21.46 +TEST(Allocator, DefaultRealloc) { 21.47 + void *test = calloc(8, 1); 21.48 + memcpy(test, "Test", 5); 21.49 + test = cxRealloc(cxDefaultAllocator, test, 16); 21.50 + ASSERT_NE(test, nullptr); 21.51 + EXPECT_STREQ(reinterpret_cast<char *>(test), "Test"); 21.52 + free(test); 21.53 +} 21.54 + 21.55 +TEST(Allocator, Reallocate) { 21.56 + void *test = calloc(8, 1); 21.57 + memcpy(test, "Test", 5); 21.58 + int ret = cxReallocate(cxDefaultAllocator, &test, 16); 21.59 + EXPECT_EQ(ret, 0); 21.60 + ASSERT_NE(test, nullptr); 21.61 + EXPECT_STREQ(reinterpret_cast<char *>(test), "Test"); 21.62 + free(test); 21.63 +} 21.64 + 21.65 +TEST(Allocator, DefaultCalloc) { 21.66 + char *test = reinterpret_cast<char *>(cxCalloc(cxDefaultAllocator, 8, 2)); 21.67 + ASSERT_NE(test, nullptr); 21.68 + for (int i = 0; i < 16; i++) ASSERT_EQ(test[i], 0); 21.69 + free(test); 21.70 +} 21.71 + 21.72 +TEST(Allocator, DefaultFree) { 21.73 + void *test = malloc(16); 21.74 + EXPECT_NO_FATAL_FAILURE( 21.75 + cxFree(cxDefaultAllocator, test); 21.76 + ); 21.77 +} 21.78 + 21.79 +TEST(Allocator, FailingReallocate) { 21.80 + // Mock an allocator that always returns nullptr on realloc 21.81 + cx_allocator_class mock_cl; 21.82 + mock_cl.realloc = []( 21.83 + [[maybe_unused]]void *p, 21.84 + [[maybe_unused]]void *d, 21.85 + [[maybe_unused]]size_t n 21.86 + ) -> void * { return nullptr; }; 21.87 + cx_allocator_s mock{&mock_cl, nullptr}; 21.88 + 21.89 + void *test = calloc(8, 1); 21.90 + memcpy(test, "Test", 5); 21.91 + void *original = test; 21.92 + int ret = cxReallocate(&mock, &test, 16); 21.93 + // non-zero return code because of the failure 21.94 + EXPECT_NE(ret, 0); 21.95 + // the test pointer was not changed and still points to the same memory 21.96 + EXPECT_EQ(test, original); 21.97 + EXPECT_STREQ(reinterpret_cast<char *>(test), "Test"); 21.98 + free(test); 21.99 +}
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 22.2 +++ b/tests/test_basic_mempool.cpp Tue Feb 07 21:55:37 2023 +0100 22.3 @@ -0,0 +1,154 @@ 22.4 +/* 22.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 22.6 + * 22.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 22.8 + * 22.9 + * Redistribution and use in source and binary forms, with or without 22.10 + * modification, are permitted provided that the following conditions are met: 22.11 + * 22.12 + * 1. Redistributions of source code must retain the above copyright 22.13 + * notice, this list of conditions and the following disclaimer. 22.14 + * 22.15 + * 2. Redistributions in binary form must reproduce the above copyright 22.16 + * notice, this list of conditions and the following disclaimer in the 22.17 + * documentation and/or other materials provided with the distribution. 22.18 + * 22.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 22.29 + * POSSIBILITY OF SUCH DAMAGE. 22.30 + */ 22.31 + 22.32 +#include "cx/basic_mempool.h" 22.33 +#include "util_allocator.h" 22.34 +#include <gtest/gtest.h> 22.35 + 22.36 +class CxBasicMempool : public ::testing::Test { 22.37 +protected: 22.38 + CxMempool *pool = nullptr; 22.39 + 22.40 + void TearDown() override { 22.41 + if (pool != nullptr) { 22.42 + cxMempoolDestroy(pool); 22.43 + } 22.44 + } 22.45 +}; 22.46 + 22.47 +TEST_F(CxBasicMempool, Create) { 22.48 + pool = cxBasicMempoolCreate(16); 22.49 + ASSERT_NE(pool->allocator, nullptr); 22.50 + ASSERT_NE(pool->cl, nullptr); 22.51 + EXPECT_NE(pool->cl->destroy, nullptr); 22.52 + ASSERT_NE(pool->allocator->cl, nullptr); 22.53 + EXPECT_EQ(pool->allocator->data, pool); 22.54 + EXPECT_NE(pool->allocator->cl->malloc, nullptr); 22.55 + EXPECT_NE(pool->allocator->cl->calloc, nullptr); 22.56 + EXPECT_NE(pool->allocator->cl->realloc, nullptr); 22.57 + EXPECT_NE(pool->allocator->cl->free, nullptr); 22.58 + 22.59 + auto basic_pool = reinterpret_cast<cx_basic_mempool_s *>(pool); 22.60 + EXPECT_EQ(basic_pool->size, 16); 22.61 + EXPECT_EQ(basic_pool->ndata, 0); 22.62 + EXPECT_NE(basic_pool->data, nullptr); 22.63 +} 22.64 + 22.65 +TEST_F(CxBasicMempool, malloc) { 22.66 + pool = cxBasicMempoolCreate(4); 22.67 + auto basic_pool = reinterpret_cast<cx_basic_mempool_s *>(pool); 22.68 + EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 22.69 + EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 22.70 + EXPECT_EQ(basic_pool->ndata, 2); 22.71 + EXPECT_EQ(basic_pool->size, 4); 22.72 + EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 22.73 + EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 22.74 + EXPECT_EQ(basic_pool->ndata, 4); 22.75 + EXPECT_EQ(basic_pool->size, 4); 22.76 + EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 22.77 + EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 22.78 + EXPECT_EQ(basic_pool->ndata, 6); 22.79 + EXPECT_GE(basic_pool->size, 6); 22.80 +} 22.81 + 22.82 +TEST_F(CxBasicMempool, calloc) { 22.83 + pool = cxBasicMempoolCreate(4); 22.84 + 22.85 + auto test = (int *) cxCalloc(pool->allocator, 2, sizeof(int)); 22.86 + ASSERT_NE(test, nullptr); 22.87 + EXPECT_EQ(test[0], 0); 22.88 + EXPECT_EQ(test[1], 0); 22.89 +} 22.90 + 22.91 +static unsigned test_destructor_called = 0; 22.92 + 22.93 +static void test_destructor([[maybe_unused]] void *mem) { 22.94 + test_destructor_called++; 22.95 +} 22.96 + 22.97 +TEST_F(CxBasicMempool, destructor) { 22.98 + pool = cxBasicMempoolCreate(4); 22.99 + auto data = cxMalloc(pool->allocator, sizeof(int)); 22.100 + *((int *) data) = 13; 22.101 + cxMempoolSetDestructor(pool, data, test_destructor); 22.102 + EXPECT_EQ(*((int *) data), 13); 22.103 + test_destructor_called = 0; 22.104 + cxFree(pool->allocator, data); 22.105 + EXPECT_EQ(test_destructor_called, 1); 22.106 + data = cxMalloc(pool->allocator, sizeof(int)); 22.107 + cxMempoolSetDestructor(pool, data, test_destructor); 22.108 + cxMempoolDestroy(pool); 22.109 + pool = nullptr; 22.110 + EXPECT_EQ(test_destructor_called, 2); 22.111 +} 22.112 + 22.113 +TEST_F(CxBasicMempool, realloc) { 22.114 + pool = cxBasicMempoolCreate(4); 22.115 + auto data = cxMalloc(pool->allocator, sizeof(int)); 22.116 + *((int *) data) = 13; 22.117 + cxMempoolSetDestructor(pool, data, test_destructor); 22.118 + 22.119 + void *rdata = data; 22.120 + unsigned n = 1; 22.121 + while (rdata == data) { 22.122 + n <<= 1; 22.123 + ASSERT_LT(n, 65536); // eventually the memory should be moved elsewhere 22.124 + rdata = cxRealloc(pool->allocator, data, n * sizeof(intptr_t)); 22.125 + } 22.126 + 22.127 + EXPECT_EQ(*((int *) rdata), 13); 22.128 + // test if destructor is still intact 22.129 + test_destructor_called = 0; 22.130 + cxFree(pool->allocator, rdata); 22.131 + EXPECT_EQ(test_destructor_called, 1); 22.132 +} 22.133 + 22.134 + 22.135 +TEST_F(CxBasicMempool, free) { 22.136 + pool = cxBasicMempoolCreate(4); 22.137 + auto basic_pool = reinterpret_cast<cx_basic_mempool_s *>(pool); 22.138 + 22.139 + void *mem1; 22.140 + void *mem2; 22.141 + 22.142 + mem1 = cxMalloc(pool->allocator, 16); 22.143 + cxFree(pool->allocator, mem1); 22.144 + EXPECT_EQ(basic_pool->ndata, 0); 22.145 + 22.146 + cxMalloc(pool->allocator, 16); 22.147 + cxMalloc(pool->allocator, 16); 22.148 + mem1 = cxMalloc(pool->allocator, 16); 22.149 + cxMalloc(pool->allocator, 16); 22.150 + mem2 = cxMalloc(pool->allocator, 16); 22.151 + 22.152 + EXPECT_EQ(basic_pool->ndata, 5); 22.153 + cxFree(pool->allocator, mem1); 22.154 + EXPECT_EQ(basic_pool->ndata, 4); 22.155 + cxFree(pool->allocator, mem2); 22.156 + EXPECT_EQ(basic_pool->ndata, 3); 22.157 +} 22.158 \ No newline at end of file
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 23.2 +++ b/tests/test_buffer.cpp Tue Feb 07 21:55:37 2023 +0100 23.3 @@ -0,0 +1,815 @@ 23.4 +/* 23.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 23.6 + * 23.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 23.8 + * 23.9 + * Redistribution and use in source and binary forms, with or without 23.10 + * modification, are permitted provided that the following conditions are met: 23.11 + * 23.12 + * 1. Redistributions of source code must retain the above copyright 23.13 + * notice, this list of conditions and the following disclaimer. 23.14 + * 23.15 + * 2. Redistributions in binary form must reproduce the above copyright 23.16 + * notice, this list of conditions and the following disclaimer in the 23.17 + * documentation and/or other materials provided with the distribution. 23.18 + * 23.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 23.29 + * POSSIBILITY OF SUCH DAMAGE. 23.30 + */ 23.31 + 23.32 +#include "cx/buffer.h" 23.33 + 23.34 +#include <gtest/gtest.h> 23.35 +#include "util_allocator.h" 23.36 + 23.37 +class BufferFixture : public ::testing::Test { 23.38 +protected: 23.39 + void SetUp() override { 23.40 + cxBufferInit(&buf, nullptr, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT); 23.41 + buf.size = 6; 23.42 + buf.pos = 3; 23.43 + } 23.44 + 23.45 + void TearDown() override { 23.46 + cxBufferDestroy(&buf); 23.47 + } 23.48 + 23.49 + CxBuffer buf{}; 23.50 +}; 23.51 + 23.52 +static void expect_default_flush_config(CxBuffer *buf) { 23.53 + EXPECT_EQ(buf->flush_blkmax, 0); 23.54 + EXPECT_EQ(buf->flush_blksize, 4096); 23.55 + EXPECT_EQ(buf->flush_threshold, SIZE_MAX); 23.56 + EXPECT_EQ(buf->flush_func, nullptr); 23.57 + EXPECT_EQ(buf->flush_target, nullptr); 23.58 +} 23.59 + 23.60 +TEST(BufferInit, WrapSpace) { 23.61 + CxTestingAllocator alloc; 23.62 + CxBuffer buf; 23.63 + void *space = cxMalloc(&alloc, 16); 23.64 + cxBufferInit(&buf, space, 16, &alloc, CX_BUFFER_DEFAULT); 23.65 + expect_default_flush_config(&buf); 23.66 + EXPECT_EQ(buf.space, space); 23.67 + EXPECT_EQ(buf.flags & CX_BUFFER_AUTO_EXTEND, 0); 23.68 + EXPECT_EQ(buf.flags & CX_BUFFER_FREE_CONTENTS, 0); 23.69 + EXPECT_EQ(buf.pos, 0); 23.70 + EXPECT_EQ(buf.size, 0); 23.71 + EXPECT_EQ(buf.capacity, 16); 23.72 + EXPECT_EQ(buf.allocator, &alloc); 23.73 + cxBufferDestroy(&buf); 23.74 + EXPECT_FALSE(alloc.verify()); 23.75 + cxFree(&alloc, space); 23.76 + EXPECT_TRUE(alloc.verify()); 23.77 +} 23.78 + 23.79 +TEST(BufferInit, WrapSpaceAutoExtend) { 23.80 + CxTestingAllocator alloc; 23.81 + CxBuffer buf; 23.82 + void *space = cxMalloc(&alloc, 16); 23.83 + cxBufferInit(&buf, space, 16, &alloc, CX_BUFFER_AUTO_EXTEND); 23.84 + expect_default_flush_config(&buf); 23.85 + EXPECT_EQ(buf.space, space); 23.86 + EXPECT_EQ(buf.flags & CX_BUFFER_AUTO_EXTEND, CX_BUFFER_AUTO_EXTEND); 23.87 + EXPECT_EQ(buf.flags & CX_BUFFER_FREE_CONTENTS, 0); 23.88 + EXPECT_EQ(buf.pos, 0); 23.89 + EXPECT_EQ(buf.size, 0); 23.90 + EXPECT_EQ(buf.capacity, 16); 23.91 + EXPECT_EQ(buf.allocator, &alloc); 23.92 + cxBufferDestroy(&buf); 23.93 + EXPECT_FALSE(alloc.verify()); 23.94 + cxFree(&alloc, space); 23.95 + EXPECT_TRUE(alloc.verify()); 23.96 +} 23.97 + 23.98 +TEST(BufferInit, WrapSpaceAutoFree) { 23.99 + CxTestingAllocator alloc; 23.100 + CxBuffer buf; 23.101 + void *space = cxMalloc(&alloc, 16); 23.102 + cxBufferInit(&buf, space, 16, &alloc, CX_BUFFER_FREE_CONTENTS); 23.103 + expect_default_flush_config(&buf); 23.104 + EXPECT_EQ(buf.space, space); 23.105 + EXPECT_EQ(buf.flags & CX_BUFFER_AUTO_EXTEND, 0); 23.106 + EXPECT_EQ(buf.flags & CX_BUFFER_FREE_CONTENTS, CX_BUFFER_FREE_CONTENTS); 23.107 + EXPECT_EQ(buf.pos, 0); 23.108 + EXPECT_EQ(buf.size, 0); 23.109 + EXPECT_EQ(buf.capacity, 16); 23.110 + EXPECT_EQ(buf.allocator, &alloc); 23.111 + EXPECT_FALSE(alloc.verify()); 23.112 + cxBufferDestroy(&buf); 23.113 + EXPECT_TRUE(alloc.verify()); 23.114 +} 23.115 + 23.116 +TEST(BufferInit, FreshSpace) { 23.117 + CxTestingAllocator alloc; 23.118 + CxBuffer buf; 23.119 + cxBufferInit(&buf, nullptr, 8, &alloc, CX_BUFFER_DEFAULT); 23.120 + expect_default_flush_config(&buf); 23.121 + EXPECT_NE(buf.space, nullptr); 23.122 + EXPECT_EQ(buf.flags & CX_BUFFER_AUTO_EXTEND, 0); 23.123 + EXPECT_EQ(buf.flags & CX_BUFFER_FREE_CONTENTS, CX_BUFFER_FREE_CONTENTS); 23.124 + EXPECT_EQ(buf.pos, 0); 23.125 + EXPECT_EQ(buf.size, 0); 23.126 + EXPECT_EQ(buf.capacity, 8); 23.127 + EXPECT_EQ(buf.allocator, &alloc); 23.128 + EXPECT_FALSE(alloc.verify()); // space is still allocated 23.129 + cxBufferDestroy(&buf); 23.130 + EXPECT_TRUE(alloc.verify()); 23.131 +} 23.132 + 23.133 +class BufferShiftFixture : public ::testing::Test { 23.134 +protected: 23.135 + void SetUp() override { 23.136 + ASSERT_TRUE(alloc.verify()); 23.137 + cxBufferInit(&buf, nullptr, 16, &alloc, CX_BUFFER_DEFAULT); 23.138 + memcpy(buf.space, "test____________", 16); 23.139 + buf.capacity = 8; // purposely pretend that the buffer has less capacity s.t. we can test beyond the range 23.140 + buf.pos = 4; 23.141 + buf.size = 4; 23.142 + } 23.143 + 23.144 + void TearDown() override { 23.145 + cxBufferDestroy(&buf); 23.146 + EXPECT_TRUE(alloc.verify()); 23.147 + } 23.148 + 23.149 + CxTestingAllocator alloc; 23.150 + CxBuffer buf{}; 23.151 +}; 23.152 + 23.153 +class BufferShiftLeft : public BufferShiftFixture { 23.154 +}; 23.155 + 23.156 +TEST_F(BufferShiftLeft, Zero) { 23.157 + ASSERT_EQ(buf.pos, 4); 23.158 + ASSERT_EQ(buf.size, 4); 23.159 + int ret = cxBufferShiftLeft(&buf, 0); 23.160 + EXPECT_EQ(ret, 0); 23.161 + EXPECT_EQ(buf.pos, 4); 23.162 + EXPECT_EQ(buf.size, 4); 23.163 + EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 23.164 +} 23.165 + 23.166 +TEST_F(BufferShiftLeft, ZeroOffsetInterface) { 23.167 + ASSERT_EQ(buf.pos, 4); 23.168 + ASSERT_EQ(buf.size, 4); 23.169 + int ret = cxBufferShift(&buf, -0); 23.170 + EXPECT_EQ(ret, 0); 23.171 + EXPECT_EQ(buf.pos, 4); 23.172 + EXPECT_EQ(buf.size, 4); 23.173 + EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 23.174 +} 23.175 + 23.176 +TEST_F(BufferShiftLeft, Standard) { 23.177 + ASSERT_EQ(buf.pos, 4); 23.178 + ASSERT_EQ(buf.size, 4); 23.179 + int ret = cxBufferShiftLeft(&buf, 2); 23.180 + EXPECT_EQ(ret, 0); 23.181 + EXPECT_EQ(buf.pos, 2); 23.182 + EXPECT_EQ(buf.size, 2); 23.183 + EXPECT_TRUE(memcmp(buf.space, "stst________", 8) == 0); 23.184 +} 23.185 + 23.186 +TEST_F(BufferShiftLeft, Overshift) { 23.187 + ASSERT_LT(buf.pos, 6); 23.188 + ASSERT_LT(buf.size, 6); 23.189 + int ret = cxBufferShiftLeft(&buf, 6); 23.190 + EXPECT_EQ(ret, 0); 23.191 + EXPECT_EQ(buf.pos, 0); 23.192 + EXPECT_EQ(buf.size, 0); 23.193 + EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 23.194 +} 23.195 + 23.196 +TEST_F(BufferShiftLeft, OvershiftPosOnly) { 23.197 + buf.pos = 2; 23.198 + ASSERT_EQ(buf.size, 4); 23.199 + int ret = cxBufferShiftLeft(&buf, 3); 23.200 + EXPECT_EQ(ret, 0); 23.201 + EXPECT_EQ(buf.pos, 0); 23.202 + EXPECT_EQ(buf.size, 1); 23.203 + EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 23.204 +} 23.205 + 23.206 +TEST_F(BufferShiftLeft, OffsetInterface) { 23.207 + buf.pos = 3; 23.208 + ASSERT_EQ(buf.size, 4); 23.209 + int ret = cxBufferShift(&buf, -2); 23.210 + EXPECT_EQ(ret, 0); 23.211 + EXPECT_EQ(buf.pos, 1); 23.212 + EXPECT_EQ(buf.size, 2); 23.213 + EXPECT_TRUE(memcmp(buf.space, "stst________", 8) == 0); 23.214 +} 23.215 + 23.216 +class BufferShiftRight : public BufferShiftFixture { 23.217 +}; 23.218 + 23.219 +TEST_F(BufferShiftRight, Zero) { 23.220 + ASSERT_EQ(buf.pos, 4); 23.221 + ASSERT_EQ(buf.size, 4); 23.222 + int ret = cxBufferShiftRight(&buf, 0); 23.223 + EXPECT_EQ(ret, 0); 23.224 + EXPECT_EQ(buf.pos, 4); 23.225 + EXPECT_EQ(buf.size, 4); 23.226 + EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 23.227 +} 23.228 + 23.229 +TEST_F(BufferShiftRight, ZeroOffsetInterface) { 23.230 + ASSERT_EQ(buf.pos, 4); 23.231 + ASSERT_EQ(buf.size, 4); 23.232 + int ret = cxBufferShift(&buf, +0); 23.233 + EXPECT_EQ(ret, 0); 23.234 + EXPECT_EQ(buf.pos, 4); 23.235 + EXPECT_EQ(buf.size, 4); 23.236 + EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 23.237 +} 23.238 + 23.239 +TEST_F(BufferShiftRight, Standard) { 23.240 + ASSERT_EQ(buf.pos, 4); 23.241 + ASSERT_EQ(buf.size, 4); 23.242 + int ret = cxBufferShiftRight(&buf, 3); 23.243 + EXPECT_EQ(ret, 0); 23.244 + EXPECT_EQ(buf.pos, 7); 23.245 + EXPECT_EQ(buf.size, 7); 23.246 + EXPECT_TRUE(memcmp(buf.space, "testest_____", 8) == 0); 23.247 +} 23.248 + 23.249 +TEST_F(BufferShiftRight, OvershiftDiscard) { 23.250 + ASSERT_EQ(buf.pos, 4); 23.251 + ASSERT_EQ(buf.size, 4); 23.252 + ASSERT_EQ(buf.capacity, 8); 23.253 + int ret = cxBufferShiftRight(&buf, 6); 23.254 + EXPECT_EQ(ret, 0); 23.255 + EXPECT_EQ(buf.pos, 8); 23.256 + EXPECT_EQ(buf.size, 8); 23.257 + EXPECT_EQ(buf.capacity, 8); 23.258 + EXPECT_TRUE(memcmp(buf.space, "test__te____", 8) == 0); 23.259 +} 23.260 + 23.261 +TEST_F(BufferShiftRight, OvershiftExtend) { 23.262 + ASSERT_EQ(buf.pos, 4); 23.263 + ASSERT_EQ(buf.size, 4); 23.264 + ASSERT_EQ(buf.capacity, 8); 23.265 + buf.flags |= CX_BUFFER_AUTO_EXTEND; 23.266 + int ret = cxBufferShiftRight(&buf, 6); 23.267 + EXPECT_EQ(ret, 0); 23.268 + EXPECT_EQ(buf.pos, 10); 23.269 + EXPECT_EQ(buf.size, 10); 23.270 + EXPECT_GE(buf.capacity, 10); 23.271 + EXPECT_TRUE(memcmp(buf.space, "test__test__", 8) == 0); 23.272 +} 23.273 + 23.274 +TEST_F(BufferShiftRight, OffsetInterface) { 23.275 + buf.pos = 3; 23.276 + ASSERT_EQ(buf.size, 4); 23.277 + int ret = cxBufferShift(&buf, 2); 23.278 + EXPECT_EQ(ret, 0); 23.279 + EXPECT_EQ(buf.pos, 5); 23.280 + EXPECT_EQ(buf.size, 6); 23.281 + EXPECT_TRUE(memcmp(buf.space, "tetest______", 8) == 0); 23.282 +} 23.283 + 23.284 +TEST(BufferMinimumCapacity, Sufficient) { 23.285 + CxTestingAllocator alloc; 23.286 + auto space = cxMalloc(&alloc, 8); 23.287 + CxBuffer buf; 23.288 + cxBufferInit(&buf, space, 8, &alloc, CX_BUFFER_FREE_CONTENTS); 23.289 + memcpy(space, "Testing", 8); 23.290 + buf.size = 8; 23.291 + cxBufferMinimumCapacity(&buf, 6); 23.292 + EXPECT_EQ(buf.capacity, 8); 23.293 + EXPECT_EQ(buf.size, 8); 23.294 + EXPECT_TRUE(memcmp(buf.space, "Testing", 8) == 0); 23.295 + cxBufferDestroy(&buf); 23.296 + EXPECT_TRUE(alloc.verify()); 23.297 +} 23.298 + 23.299 +TEST(BufferMinimumCapacity, Extend) { 23.300 + CxTestingAllocator alloc; 23.301 + auto space = cxMalloc(&alloc, 8); 23.302 + CxBuffer buf; 23.303 + cxBufferInit(&buf, space, 8, &alloc, CX_BUFFER_FREE_CONTENTS); // NO auto extend! 23.304 + memcpy(space, "Testing", 8); 23.305 + buf.size = 8; 23.306 + cxBufferMinimumCapacity(&buf, 16); 23.307 + EXPECT_EQ(buf.capacity, 16); 23.308 + EXPECT_EQ(buf.size, 8); 23.309 + EXPECT_TRUE(memcmp(buf.space, "Testing", 8) == 0); 23.310 + cxBufferDestroy(&buf); 23.311 + EXPECT_TRUE(alloc.verify()); 23.312 +} 23.313 + 23.314 +TEST(BufferClear, Test) { 23.315 + char space[16]; 23.316 + strcpy(space, "clear test"); 23.317 + CxBuffer buf; 23.318 + cxBufferInit(&buf, space, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT); 23.319 + ASSERT_EQ(buf.size, 0); 23.320 + // only clear the used part of the buffer 23.321 + cxBufferClear(&buf); 23.322 + EXPECT_EQ(memcmp(space, "clear test", 10), 0); 23.323 + buf.size = 5; 23.324 + buf.pos = 3; 23.325 + cxBufferClear(&buf); 23.326 + EXPECT_EQ(memcmp(space, "\0\0\0\0\0 test", 10), 0); 23.327 + EXPECT_EQ(buf.size, 0); 23.328 + EXPECT_EQ(buf.pos, 0); 23.329 + cxBufferDestroy(&buf); 23.330 +} 23.331 + 23.332 +class BufferWrite : public ::testing::Test { 23.333 +protected: 23.334 + CxBuffer buf{}, target{}; 23.335 + 23.336 + void SetUp() override { 23.337 + cxBufferInit(&target, nullptr, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND); 23.338 + cxBufferInit(&buf, nullptr, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT); 23.339 + buf.capacity = 8; // artificially reduce capacity to check OOB writes 23.340 + memset(buf.space, 0, 16); 23.341 + memcpy(buf.space, "prep", 4); 23.342 + buf.size = buf.pos = 4; 23.343 + } 23.344 + 23.345 + void TearDown() override { 23.346 + cxBufferDestroy(&buf); 23.347 + cxBufferDestroy(&target); 23.348 + } 23.349 + 23.350 + void enableFlushing() { 23.351 + buf.flush_target = ⌖ 23.352 + buf.flush_func = reinterpret_cast<cx_write_func>(cxBufferWrite); 23.353 + buf.flush_blkmax = 1; 23.354 + } 23.355 +}; 23.356 + 23.357 +static size_t mock_write_limited_rate( 23.358 + void const *ptr, 23.359 + size_t size, 23.360 + __attribute__((unused)) size_t nitems, 23.361 + CxBuffer *buffer 23.362 +) { 23.363 + // simulate limited target drain capacity 23.364 + static bool full = false; 23.365 + if (full) { 23.366 + full = false; 23.367 + return 0; 23.368 + } else { 23.369 + full = true; 23.370 + return cxBufferWrite(ptr, size, nitems > 2 ? 2 : nitems, buffer); 23.371 + } 23.372 +} 23.373 + 23.374 +TEST_F(BufferWrite, SizeOneFit) { 23.375 + const char *data = "test"; 23.376 + ASSERT_EQ(buf.capacity, 8); 23.377 + ASSERT_EQ(buf.pos, 4); 23.378 + ASSERT_EQ(buf.size, 4); 23.379 + size_t written = cxBufferWrite(data, 1, 4, &buf); 23.380 + EXPECT_EQ(written, 4); 23.381 + EXPECT_EQ(buf.size, 8); 23.382 + EXPECT_EQ(buf.pos, 8); 23.383 + EXPECT_EQ(buf.capacity, 8); 23.384 + EXPECT_EQ(memcmp(buf.space, "preptest", 8), 0); 23.385 +} 23.386 + 23.387 +TEST_F(BufferWrite, SizeOneDiscard) { 23.388 + const char *data = "testing"; 23.389 + ASSERT_EQ(buf.capacity, 8); 23.390 + ASSERT_EQ(buf.pos, 4); 23.391 + ASSERT_EQ(buf.size, 4); 23.392 + size_t written = cxBufferWrite(data, 1, 7, &buf); 23.393 + EXPECT_EQ(written, 4); 23.394 + EXPECT_EQ(buf.size, 8); 23.395 + EXPECT_EQ(buf.pos, 8); 23.396 + EXPECT_EQ(buf.capacity, 8); 23.397 + EXPECT_EQ(memcmp(buf.space, "preptest\0", 9), 0); 23.398 +} 23.399 + 23.400 +TEST_F(BufferWrite, SizeOneExtend) { 23.401 + buf.flags |= CX_BUFFER_AUTO_EXTEND; 23.402 + const char *data = "testing"; 23.403 + ASSERT_EQ(buf.capacity, 8); 23.404 + ASSERT_EQ(buf.pos, 4); 23.405 + ASSERT_EQ(buf.size, 4); 23.406 + size_t written = cxBufferWrite(data, 1, 7, &buf); 23.407 + EXPECT_EQ(written, 7); 23.408 + EXPECT_EQ(buf.size, 11); 23.409 + EXPECT_EQ(buf.pos, 11); 23.410 + EXPECT_GE(buf.capacity, 11); 23.411 + EXPECT_EQ(memcmp(buf.space, "preptesting", 11), 0); 23.412 +} 23.413 + 23.414 +TEST_F(BufferWrite, MultibyteFit) { 23.415 + const char *data = "test"; 23.416 + ASSERT_EQ(buf.capacity, 8); 23.417 + ASSERT_EQ(buf.pos, 4); 23.418 + ASSERT_EQ(buf.size, 4); 23.419 + size_t written = cxBufferWrite(data, 2, 2, &buf); 23.420 + EXPECT_EQ(written, 2); 23.421 + EXPECT_EQ(buf.size, 8); 23.422 + EXPECT_EQ(buf.pos, 8); 23.423 + EXPECT_EQ(buf.capacity, 8); 23.424 + EXPECT_EQ(memcmp(buf.space, "preptest", 8), 0); 23.425 +} 23.426 + 23.427 +TEST_F(BufferWrite, MultibyteDiscard) { 23.428 + const char *data = "testing"; 23.429 + ASSERT_EQ(buf.capacity, 8); 23.430 + ASSERT_EQ(buf.size, 4); 23.431 + buf.pos = 3; 23.432 + size_t written = cxBufferWrite(data, 2, 4, &buf); 23.433 + // remember: whole elements are discarded if they do not fit 23.434 + EXPECT_EQ(written, 2); 23.435 + EXPECT_EQ(buf.size, 7); 23.436 + EXPECT_EQ(buf.pos, 7); 23.437 + EXPECT_EQ(buf.capacity, 8); 23.438 + EXPECT_EQ(memcmp(buf.space, "pretest\0", 8), 0); 23.439 +} 23.440 + 23.441 +TEST_F(BufferWrite, MultibyteExtend) { 23.442 + buf.flags |= CX_BUFFER_AUTO_EXTEND; 23.443 + const char *data = "tester"; 23.444 + ASSERT_EQ(buf.capacity, 8); 23.445 + ASSERT_EQ(buf.size, 4); 23.446 + buf.pos = 3; 23.447 + size_t written = cxBufferWrite(data, 2, 3, &buf); 23.448 + // remember: whole elements are discarded if they do not fit 23.449 + EXPECT_EQ(written, 3); 23.450 + EXPECT_EQ(buf.size, 9); 23.451 + EXPECT_EQ(buf.pos, 9); 23.452 + EXPECT_GE(buf.capacity, 9); 23.453 + EXPECT_EQ(memcmp(buf.space, "pretester", 9), 0); 23.454 +} 23.455 + 23.456 +TEST_F(BufferWrite, PutcWrapperFit) { 23.457 + ASSERT_EQ(buf.capacity, 8); 23.458 + ASSERT_EQ(buf.pos, 4); 23.459 + ASSERT_EQ(buf.size, 4); 23.460 + int c = cxBufferPut(&buf, 0x200 | 'a'); 23.461 + EXPECT_EQ(c, 'a'); 23.462 + EXPECT_EQ(buf.size, 5); 23.463 + EXPECT_EQ(buf.pos, 5); 23.464 + EXPECT_EQ(buf.capacity, 8); 23.465 + EXPECT_EQ(memcmp(buf.space, "prepa\0", 6), 0); 23.466 +} 23.467 + 23.468 +TEST_F(BufferWrite, PutcWrapperDiscard) { 23.469 + ASSERT_EQ(buf.capacity, 8); 23.470 + ASSERT_EQ(buf.size, 4); 23.471 + buf.pos = 8; 23.472 + int c = cxBufferPut(&buf, 0x200 | 'a'); 23.473 + EXPECT_EQ(c, EOF); 23.474 + EXPECT_EQ(buf.size, 4); 23.475 + EXPECT_EQ(buf.pos, 8); 23.476 + EXPECT_EQ(buf.capacity, 8); 23.477 + EXPECT_EQ(memcmp(buf.space, "prep\0\0\0\0\0", 9), 0); 23.478 +} 23.479 + 23.480 +TEST_F(BufferWrite, PutcWrapperExtend) { 23.481 + buf.flags |= CX_BUFFER_AUTO_EXTEND; 23.482 + ASSERT_EQ(buf.capacity, 8); 23.483 + ASSERT_EQ(buf.size, 4); 23.484 + buf.pos = 8; 23.485 + int c = cxBufferPut(&buf, 0x200 | 'a'); 23.486 + EXPECT_EQ(c, 'a'); 23.487 + EXPECT_EQ(buf.size, 9); 23.488 + EXPECT_EQ(buf.pos, 9); 23.489 + EXPECT_GE(buf.capacity, 9); 23.490 + EXPECT_EQ(memcmp(buf.space, "prep\0\0\0\0a", 9), 0); 23.491 +} 23.492 + 23.493 +TEST_F(BufferWrite, PutStringWrapperFit) { 23.494 + const char *data = "test"; 23.495 + ASSERT_EQ(buf.capacity, 8); 23.496 + ASSERT_EQ(buf.pos, 4); 23.497 + ASSERT_EQ(buf.size, 4); 23.498 + size_t written = cxBufferPutString(&buf, data); 23.499 + EXPECT_EQ(written, 4); 23.500 + EXPECT_EQ(buf.size, 8); 23.501 + EXPECT_EQ(buf.pos, 8); 23.502 + EXPECT_EQ(buf.capacity, 8); 23.503 + EXPECT_EQ(memcmp(buf.space, "preptest", 8), 0); 23.504 +} 23.505 + 23.506 +TEST_F(BufferWrite, PutStringWrapperDiscard) { 23.507 + const char *data = "testing"; 23.508 + ASSERT_EQ(buf.capacity, 8); 23.509 + ASSERT_EQ(buf.pos, 4); 23.510 + ASSERT_EQ(buf.size, 4); 23.511 + size_t written = cxBufferPutString(&buf, data); 23.512 + EXPECT_EQ(written, 4); 23.513 + EXPECT_EQ(buf.size, 8); 23.514 + EXPECT_EQ(buf.pos, 8); 23.515 + EXPECT_EQ(buf.capacity, 8); 23.516 + EXPECT_EQ(memcmp(buf.space, "preptest\0", 9), 0); 23.517 +} 23.518 + 23.519 +TEST_F(BufferWrite, PutStringWrapperExtend) { 23.520 + buf.flags |= CX_BUFFER_AUTO_EXTEND; 23.521 + const char *data = "testing"; 23.522 + ASSERT_EQ(buf.capacity, 8); 23.523 + ASSERT_EQ(buf.pos, 4); 23.524 + ASSERT_EQ(buf.size, 4); 23.525 + size_t written = cxBufferPutString(&buf, data); 23.526 + EXPECT_EQ(written, 7); 23.527 + EXPECT_EQ(buf.size, 11); 23.528 + EXPECT_EQ(buf.pos, 11); 23.529 + EXPECT_GE(buf.capacity, 11); 23.530 + EXPECT_EQ(memcmp(buf.space, "preptesting", 11), 0); 23.531 +} 23.532 + 23.533 +TEST_F(BufferWrite, MultOverflow) { 23.534 + const char *data = "testing"; 23.535 + ASSERT_EQ(buf.capacity, 8); 23.536 + ASSERT_EQ(buf.pos, 4); 23.537 + ASSERT_EQ(buf.size, 4); 23.538 + size_t written = cxBufferWrite(data, 8, SIZE_MAX / 4, &buf); 23.539 + EXPECT_EQ(written, 0); 23.540 + EXPECT_EQ(buf.capacity, 8); 23.541 + EXPECT_EQ(buf.pos, 4); 23.542 + EXPECT_EQ(buf.size, 4); 23.543 + EXPECT_EQ(memcmp(buf.space, "prep\0", 5), 0); 23.544 +} 23.545 + 23.546 +TEST_F(BufferWrite, MaxCapaOverflow) { 23.547 + buf.flags |= CX_BUFFER_AUTO_EXTEND; 23.548 + const char *data = "testing"; 23.549 + ASSERT_EQ(buf.capacity, 8); 23.550 + ASSERT_EQ(buf.pos, 4); 23.551 + ASSERT_EQ(buf.size, 4); 23.552 + size_t written = cxBufferWrite(data, 1, SIZE_MAX - 2, &buf); 23.553 + EXPECT_EQ(written, 0); 23.554 + EXPECT_EQ(buf.capacity, 8); 23.555 + EXPECT_EQ(buf.pos, 4); 23.556 + EXPECT_EQ(buf.size, 4); 23.557 + EXPECT_EQ(memcmp(buf.space, "prep\0", 5), 0); 23.558 +} 23.559 + 23.560 +TEST_F(BufferWrite, OnlyOverwrite) { 23.561 + buf.flags |= CX_BUFFER_AUTO_EXTEND; 23.562 + ASSERT_EQ(buf.capacity, 8); 23.563 + memcpy(buf.space, "preptest", 8); 23.564 + buf.pos = 3; 23.565 + buf.size = 8; 23.566 + size_t written = cxBufferWrite("XXX", 2, 2, &buf); 23.567 + EXPECT_EQ(written, 2); 23.568 + EXPECT_EQ(buf.capacity, 8); 23.569 + EXPECT_EQ(buf.size, 8); 23.570 + EXPECT_EQ(buf.pos, 7); 23.571 + EXPECT_EQ(memcmp(buf.space, "preXXX\0t", 8), 0); 23.572 +} 23.573 + 23.574 +TEST_F(BufferWrite, FlushAtCapacity) { 23.575 + enableFlushing(); 23.576 + ASSERT_EQ(buf.capacity, 8); 23.577 + ASSERT_EQ(buf.pos, 4); 23.578 + size_t written = cxBufferWrite("foo", 1, 3, &buf); 23.579 + EXPECT_EQ(written, 3); 23.580 + ASSERT_EQ(buf.pos, 7); 23.581 + ASSERT_EQ(buf.size, 7); 23.582 + ASSERT_EQ(target.pos, 0); 23.583 + ASSERT_EQ(target.size, 0); 23.584 + written = cxBufferWrite("hello", 1, 5, &buf); 23.585 + EXPECT_EQ(written, 5); 23.586 + EXPECT_EQ(buf.pos, 0); 23.587 + EXPECT_EQ(buf.size, 0); 23.588 + EXPECT_EQ(buf.capacity, 8); 23.589 + EXPECT_EQ(target.pos, 12); 23.590 + ASSERT_EQ(target.size, 12); 23.591 + EXPECT_EQ(memcmp(target.space, "prepfoohello", 12), 0); 23.592 +} 23.593 + 23.594 +TEST_F(BufferWrite, FlushAtThreshold) { 23.595 + enableFlushing(); 23.596 + buf.flush_threshold = 12; 23.597 + buf.flags |= CX_BUFFER_AUTO_EXTEND; 23.598 + ASSERT_EQ(buf.capacity, 8); 23.599 + ASSERT_EQ(buf.pos, 4); 23.600 + size_t written = cxBufferWrite("foobar", 1, 6, &buf); 23.601 + EXPECT_EQ(written, 6); 23.602 + ASSERT_EQ(buf.pos, 10); 23.603 + ASSERT_EQ(buf.size, 10); 23.604 + ASSERT_GE(buf.capacity, 10); 23.605 + ASSERT_LE(buf.capacity, 12); 23.606 + ASSERT_EQ(target.pos, 0); 23.607 + ASSERT_EQ(target.size, 0); 23.608 + written = cxBufferWrite("hello", 1, 5, &buf); 23.609 + EXPECT_EQ(written, 5); 23.610 + EXPECT_EQ(buf.pos, 0); 23.611 + EXPECT_EQ(buf.size, 0); 23.612 + EXPECT_LE(buf.capacity, 12); 23.613 + EXPECT_EQ(target.pos, 15); 23.614 + ASSERT_EQ(target.size, 15); 23.615 + EXPECT_EQ(memcmp(target.space, "prepfoobarhello", 15), 0); 23.616 +} 23.617 + 23.618 +TEST_F(BufferWrite, FlushRateLimited) { 23.619 + enableFlushing(); 23.620 + // limit the rate of the flush function and the capacity of the target 23.621 + target.capacity = 16; 23.622 + target.flags &= ~CX_BUFFER_AUTO_EXTEND; 23.623 + buf.flush_func = (cx_write_func) mock_write_limited_rate; 23.624 + ASSERT_EQ(buf.capacity, 8); 23.625 + ASSERT_EQ(buf.pos, 4); 23.626 + size_t written = cxBufferWrite("foo", 1, 3, &buf); 23.627 + EXPECT_EQ(written, 3); 23.628 + ASSERT_EQ(buf.pos, 7); 23.629 + ASSERT_EQ(buf.size, 7); 23.630 + ASSERT_EQ(target.pos, 0); 23.631 + ASSERT_EQ(target.size, 0); 23.632 + written = cxBufferWrite("hello, world!", 1, 13, &buf); 23.633 + // " world!" fits into this buffer, the remaining stuff is flushed out 23.634 + EXPECT_EQ(written, 13); 23.635 + EXPECT_EQ(buf.pos, 7); 23.636 + EXPECT_EQ(buf.size, 7); 23.637 + EXPECT_EQ(buf.capacity, 8); 23.638 + EXPECT_EQ(memcmp(buf.space, " world!", 7), 0); 23.639 + EXPECT_EQ(target.pos, 13); 23.640 + ASSERT_EQ(target.size, 13); 23.641 + EXPECT_EQ(target.capacity, 16); 23.642 + EXPECT_EQ(memcmp(target.space, "prepfoohello,", 13), 0); 23.643 +} 23.644 + 23.645 +class BufferSeek : public BufferFixture { 23.646 +}; 23.647 + 23.648 +TEST_F(BufferSeek, SetZero) { 23.649 + int result = cxBufferSeek(&buf, 0, SEEK_SET); 23.650 + EXPECT_EQ(result, 0); 23.651 + EXPECT_EQ(buf.pos, 0); 23.652 +} 23.653 + 23.654 +TEST_F(BufferSeek, SetValid) { 23.655 + int result = cxBufferSeek(&buf, 5, SEEK_SET); 23.656 + EXPECT_EQ(result, 0); 23.657 + EXPECT_EQ(buf.pos, 5); 23.658 +} 23.659 + 23.660 +TEST_F(BufferSeek, SetInvalid) { 23.661 + ASSERT_EQ(buf.pos, 3); 23.662 + int result = cxBufferSeek(&buf, 6, SEEK_SET); 23.663 + EXPECT_NE(result, 0); 23.664 + EXPECT_EQ(buf.pos, 3); 23.665 +} 23.666 + 23.667 +TEST_F(BufferSeek, CurZero) { 23.668 + ASSERT_EQ(buf.pos, 3); 23.669 + int result = cxBufferSeek(&buf, 0, SEEK_CUR); 23.670 + EXPECT_EQ(result, 0); 23.671 + EXPECT_EQ(buf.pos, 3); 23.672 +} 23.673 + 23.674 +TEST_F(BufferSeek, CurValidPositive) { 23.675 + ASSERT_EQ(buf.pos, 3); 23.676 + int result = cxBufferSeek(&buf, 2, SEEK_CUR); 23.677 + EXPECT_EQ(result, 0); 23.678 + EXPECT_EQ(buf.pos, 5); 23.679 +} 23.680 + 23.681 +TEST_F(BufferSeek, CurValidNegative) { 23.682 + ASSERT_EQ(buf.pos, 3); 23.683 + int result = cxBufferSeek(&buf, -3, SEEK_CUR); 23.684 + EXPECT_EQ(result, 0); 23.685 + EXPECT_EQ(buf.pos, 0); 23.686 +} 23.687 + 23.688 +TEST_F(BufferSeek, CurInvalidPositive) { 23.689 + ASSERT_EQ(buf.pos, 3); 23.690 + int result = cxBufferSeek(&buf, 3, SEEK_CUR); 23.691 + EXPECT_NE(result, 0); 23.692 + EXPECT_EQ(buf.pos, 3); 23.693 +} 23.694 + 23.695 +TEST_F(BufferSeek, CurInvalidNegative) { 23.696 + ASSERT_EQ(buf.pos, 3); 23.697 + int result = cxBufferSeek(&buf, -4, SEEK_CUR); 23.698 + EXPECT_NE(result, 0); 23.699 + EXPECT_EQ(buf.pos, 3); 23.700 +} 23.701 + 23.702 +TEST_F(BufferSeek, EndZero) { 23.703 + ASSERT_EQ(buf.size, 6); 23.704 + int result = cxBufferSeek(&buf, 0, SEEK_END); 23.705 + // the (past-the-)end position is always invalid 23.706 + EXPECT_NE(result, 0); 23.707 + EXPECT_EQ(buf.pos, 3); 23.708 +} 23.709 + 23.710 +TEST_F(BufferSeek, EndValid) { 23.711 + ASSERT_EQ(buf.size, 6); 23.712 + int result = cxBufferSeek(&buf, -6, SEEK_END); 23.713 + EXPECT_EQ(result, 0); 23.714 + EXPECT_EQ(buf.pos, 0); 23.715 +} 23.716 + 23.717 +TEST_F(BufferSeek, EndInvalid) { 23.718 + ASSERT_EQ(buf.size, 6); 23.719 + int result = cxBufferSeek(&buf, 1, SEEK_END); 23.720 + EXPECT_NE(result, 0); 23.721 + EXPECT_EQ(buf.pos, 3); 23.722 +} 23.723 + 23.724 +TEST_F(BufferSeek, WhenceInvalid) { 23.725 + ASSERT_EQ(buf.size, 6); 23.726 + ASSERT_EQ(buf.pos, 3); 23.727 + int result = cxBufferSeek(&buf, 2, 9000); 23.728 + EXPECT_NE(result, 0); 23.729 + EXPECT_EQ(buf.size, 6); 23.730 + EXPECT_EQ(buf.pos, 3); 23.731 +} 23.732 + 23.733 +class BufferEof : public BufferFixture { 23.734 +}; 23.735 + 23.736 +TEST_F(BufferEof, Reached) { 23.737 + buf.pos = buf.size; 23.738 + EXPECT_TRUE(cxBufferEof(&buf)); 23.739 + buf.pos = buf.size - 1; 23.740 + ASSERT_FALSE(cxBufferEof(&buf)); 23.741 + cxBufferPut(&buf, 'a'); 23.742 + EXPECT_TRUE(cxBufferEof(&buf)); 23.743 +} 23.744 + 23.745 +TEST_F(BufferEof, NotReached) { 23.746 + buf.pos = buf.size - 1; 23.747 + EXPECT_FALSE(cxBufferEof(&buf)); 23.748 + buf.pos = 0; 23.749 + cxBufferWrite("test", 1, 5, &buf); 23.750 + EXPECT_FALSE(cxBufferEof(&buf)); 23.751 +} 23.752 + 23.753 +class BufferRead : public ::testing::Test { 23.754 +protected: 23.755 + CxBuffer buf{}; 23.756 + 23.757 + void SetUp() override { 23.758 + cxBufferInit(&buf, nullptr, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT); 23.759 + buf.capacity = 8; // artificially reduce capacity to check OOB writes 23.760 + memset(buf.space, 0, 16); 23.761 + memcpy(buf.space, "some data", 9); 23.762 + buf.size = 9; 23.763 + } 23.764 + 23.765 + void TearDown() override { 23.766 + cxBufferDestroy(&buf); 23.767 + } 23.768 +}; 23.769 + 23.770 +TEST_F(BufferRead, GetByte) { 23.771 + buf.pos = 2; 23.772 + EXPECT_EQ(cxBufferGet(&buf), 'm'); 23.773 + EXPECT_EQ(cxBufferGet(&buf), 'e'); 23.774 + EXPECT_EQ(cxBufferGet(&buf), ' '); 23.775 + EXPECT_EQ(cxBufferGet(&buf), 'd'); 23.776 + EXPECT_EQ(buf.pos, 6); 23.777 +} 23.778 + 23.779 +TEST_F(BufferRead, GetEof) { 23.780 + buf.pos = buf.size; 23.781 + EXPECT_EQ(cxBufferGet(&buf), EOF); 23.782 +} 23.783 + 23.784 +TEST_F(BufferRead, ReadWithinBounds) { 23.785 + buf.pos = 2; 23.786 + char target[4]; 23.787 + auto read = cxBufferRead(&target, 1, 4, &buf); 23.788 + ASSERT_EQ(read, 4); 23.789 + EXPECT_EQ(memcmp(&target, "me d", 4), 0); 23.790 + EXPECT_EQ(buf.pos, 6); 23.791 +} 23.792 + 23.793 +TEST_F(BufferRead, ReadOutOfBounds) { 23.794 + buf.pos = 6; 23.795 + char target[4]; 23.796 + auto read = cxBufferRead(&target, 1, 4, &buf); 23.797 + ASSERT_EQ(read, 3); 23.798 + EXPECT_EQ(memcmp(&target, "ata", 3), 0); 23.799 + EXPECT_EQ(buf.pos, 9); 23.800 +} 23.801 + 23.802 +TEST_F(BufferRead, ReadOutOfBoundsMultibyte) { 23.803 + buf.pos = 6; 23.804 + char target[4]; 23.805 + target[2] = '\0'; 23.806 + auto read = cxBufferRead(&target, 2, 2, &buf); 23.807 + ASSERT_EQ(read, 1); 23.808 + EXPECT_EQ(memcmp(&target, "at\0", 3), 0); 23.809 + EXPECT_EQ(buf.pos, 8); 23.810 +} 23.811 + 23.812 +TEST_F(BufferRead, ReadEof) { 23.813 + buf.pos = 9; 23.814 + char target[4]; 23.815 + auto read = cxBufferRead(&target, 1, 1, &buf); 23.816 + ASSERT_EQ(read, 0); 23.817 + EXPECT_EQ(buf.pos, 9); 23.818 +}
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/tests/test_compare.cpp Tue Feb 07 21:55:37 2023 +0100 24.3 @@ -0,0 +1,127 @@ 24.4 +/* 24.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 24.6 + * 24.7 + * Copyright 2022 Mike Becker, Olaf Wintermann All rights reserved. 24.8 + * 24.9 + * Redistribution and use in source and binary forms, with or without 24.10 + * modification, are permitted provided that the following conditions are met: 24.11 + * 24.12 + * 1. Redistributions of source code must retain the above copyright 24.13 + * notice, this list of conditions and the following disclaimer. 24.14 + * 24.15 + * 2. Redistributions in binary form must reproduce the above copyright 24.16 + * notice, this list of conditions and the following disclaimer in the 24.17 + * documentation and/or other materials provided with the distribution. 24.18 + * 24.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 24.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 24.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24.29 + * POSSIBILITY OF SUCH DAMAGE. 24.30 + */ 24.31 + 24.32 +#include "cx/compare.h" 24.33 + 24.34 +#include <gtest/gtest.h> 24.35 + 24.36 +template<typename T> 24.37 +static void test_compare( 24.38 + int (*fnc)( 24.39 + void const *, 24.40 + void const * 24.41 + ) 24.42 +) { 24.43 + auto m = std::numeric_limits<T>::max() / 400; 24.44 + T x, y; 24.45 + 24.46 + x = (std::is_signed_v<T> ? -3 : 3) * m; 24.47 + y = 5 * m; 24.48 + EXPECT_LT(fnc(&x, &y), 0); 24.49 + EXPECT_GT(fnc(&y, &x), 0); 24.50 + 24.51 + x = 120 * m; 24.52 + y = 348 * m; 24.53 + EXPECT_LT(fnc(&x, &y), 0); 24.54 + EXPECT_GT(fnc(&y, &x), 0); 24.55 + 24.56 + if constexpr (std::is_signed_v<T>) { 24.57 + x = -120 * m; 24.58 + y = -348 * m; 24.59 + EXPECT_GT(fnc(&x, &y), 0); 24.60 + EXPECT_LT(fnc(&y, &x), 0); 24.61 + } 24.62 + 24.63 + x = y; 24.64 + EXPECT_EQ(fnc(&x, &y), 0); 24.65 + EXPECT_EQ(fnc(&y, &x), 0); 24.66 +} 24.67 + 24.68 +TEST(Compare, Int) { 24.69 + test_compare<int>(cx_cmp_int); 24.70 +} 24.71 + 24.72 +TEST(Compare, Longint) { 24.73 + test_compare<long int>(cx_cmp_longint); 24.74 +} 24.75 + 24.76 +TEST(Compare, Longlong) { 24.77 + test_compare<long long>(cx_cmp_longlong); 24.78 +} 24.79 + 24.80 +TEST(Compare, Int16) { 24.81 + test_compare<int16_t>(cx_cmp_int16); 24.82 +} 24.83 + 24.84 +TEST(Compare, Int32) { 24.85 + test_compare<int32_t>(cx_cmp_int32); 24.86 +} 24.87 + 24.88 +TEST(Compare, Int64) { 24.89 + test_compare<int64_t>(cx_cmp_int64); 24.90 +} 24.91 + 24.92 +TEST(Compare, Uint) { 24.93 + test_compare<unsigned int>(cx_cmp_uint); 24.94 +} 24.95 + 24.96 +TEST(Compare, Ulongint) { 24.97 + test_compare<unsigned long int>(cx_cmp_ulongint); 24.98 +} 24.99 + 24.100 +TEST(Compare, Ulonglong) { 24.101 + test_compare<unsigned long long>(cx_cmp_ulonglong); 24.102 +} 24.103 + 24.104 +TEST(Compare, Uint16) { 24.105 + test_compare<uint16_t>(cx_cmp_uint16); 24.106 +} 24.107 + 24.108 +TEST(Compare, Uint32) { 24.109 + test_compare<uint32_t>(cx_cmp_uint32); 24.110 +} 24.111 + 24.112 +TEST(Compare, Uint64) { 24.113 + test_compare<uint64_t>(cx_cmp_uint64); 24.114 +} 24.115 + 24.116 +TEST(Compare, Float) { 24.117 + test_compare<float>(cx_cmp_float); 24.118 +} 24.119 + 24.120 +TEST(Compare, Double) { 24.121 + test_compare<double>(cx_cmp_double); 24.122 +} 24.123 + 24.124 +TEST(Compare, IntPtr) { 24.125 + test_compare<intptr_t>(cx_cmp_intptr); 24.126 +} 24.127 + 24.128 +TEST(Compare, UintPtr) { 24.129 + test_compare<uintptr_t>(cx_cmp_uintptr); 24.130 +}
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/tests/test_hash_key.cpp Tue Feb 07 21:55:37 2023 +0100 25.3 @@ -0,0 +1,87 @@ 25.4 +/* 25.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 25.6 + * 25.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 25.8 + * 25.9 + * Redistribution and use in source and binary forms, with or without 25.10 + * modification, are permitted provided that the following conditions are met: 25.11 + * 25.12 + * 1. Redistributions of source code must retain the above copyright 25.13 + * notice, this list of conditions and the following disclaimer. 25.14 + * 25.15 + * 2. Redistributions in binary form must reproduce the above copyright 25.16 + * notice, this list of conditions and the following disclaimer in the 25.17 + * documentation and/or other materials provided with the distribution. 25.18 + * 25.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 25.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25.29 + * POSSIBILITY OF SUCH DAMAGE. 25.30 + */ 25.31 + 25.32 +#include "cx/hash_key.h" 25.33 + 25.34 +#include <gtest/gtest.h> 25.35 + 25.36 +TEST(cx_hash_key, functions) { 25.37 + auto str = "my key"; 25.38 + auto len = strlen(str); 25.39 + 25.40 + auto str_key = cx_hash_key_str(str); 25.41 + auto bytes_key = cx_hash_key_bytes( 25.42 + reinterpret_cast<unsigned char const *>(str), len); 25.43 + auto obj_key = cx_hash_key( 25.44 + reinterpret_cast<void const *>(str), len); 25.45 + 25.46 + EXPECT_EQ(str_key.hash, bytes_key.hash); 25.47 + EXPECT_EQ(obj_key.hash, bytes_key.hash); 25.48 + EXPECT_EQ(str_key.len, len); 25.49 + EXPECT_EQ(bytes_key.len, len); 25.50 + EXPECT_EQ(bytes_key.len, len); 25.51 + EXPECT_EQ(str_key.data.cstr, str); 25.52 + EXPECT_EQ(bytes_key.data.cbytes, reinterpret_cast<unsigned char const *>(str)); 25.53 + EXPECT_EQ(bytes_key.data.cobj, reinterpret_cast<void const *>(str)); 25.54 +} 25.55 + 25.56 +TEST(cx_hash_key, empty_string) { 25.57 + auto str = ""; 25.58 + 25.59 + auto str_key = cx_hash_key_str(str); 25.60 + auto bytes_key = cx_hash_key_bytes( 25.61 + reinterpret_cast<unsigned char const *>(str), 0); 25.62 + auto obj_key = cx_hash_key( 25.63 + reinterpret_cast<void const *>(str), 0); 25.64 + 25.65 + EXPECT_EQ(bytes_key.hash, 4152238450u); 25.66 + EXPECT_EQ(str_key.hash, 4152238450u); 25.67 + EXPECT_EQ(obj_key.hash, 4152238450u); 25.68 + EXPECT_EQ(str_key.len, 0); 25.69 + EXPECT_EQ(bytes_key.len, 0); 25.70 + EXPECT_EQ(bytes_key.len, 0); 25.71 + EXPECT_EQ(str_key.data.cstr, str); 25.72 + EXPECT_EQ(bytes_key.data.cbytes, reinterpret_cast<unsigned char const *>(str)); 25.73 + EXPECT_EQ(bytes_key.data.cobj, reinterpret_cast<void const *>(str)); 25.74 +} 25.75 + 25.76 +TEST(cx_hash_key, null_ptr) { 25.77 + auto str_key = cx_hash_key_str(nullptr); 25.78 + auto bytes_key = cx_hash_key_bytes(nullptr, 0); 25.79 + auto obj_key = cx_hash_key(nullptr, 0); 25.80 + 25.81 + EXPECT_EQ(bytes_key.hash, 1574210520u); 25.82 + EXPECT_EQ(str_key.hash, 1574210520u); 25.83 + EXPECT_EQ(obj_key.hash, 1574210520u); 25.84 + EXPECT_EQ(str_key.len, 0); 25.85 + EXPECT_EQ(bytes_key.len, 0); 25.86 + EXPECT_EQ(bytes_key.len, 0); 25.87 + EXPECT_EQ(str_key.data.cstr, nullptr); 25.88 + EXPECT_EQ(bytes_key.data.cbytes, nullptr); 25.89 + EXPECT_EQ(bytes_key.data.cobj, nullptr); 25.90 +}
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/tests/test_list.cpp Tue Feb 07 21:55:37 2023 +0100 26.3 @@ -0,0 +1,1077 @@ 26.4 +/* 26.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 26.6 + * 26.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 26.8 + * 26.9 + * Redistribution and use in source and binary forms, with or without 26.10 + * modification, are permitted provided that the following conditions are met: 26.11 + * 26.12 + * 1. Redistributions of source code must retain the above copyright 26.13 + * notice, this list of conditions and the following disclaimer. 26.14 + * 26.15 + * 2. Redistributions in binary form must reproduce the above copyright 26.16 + * notice, this list of conditions and the following disclaimer in the 26.17 + * documentation and/or other materials provided with the distribution. 26.18 + * 26.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 26.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26.29 + * POSSIBILITY OF SUCH DAMAGE. 26.30 + */ 26.31 + 26.32 +#include "cx/linked_list.h" 26.33 +#include "cx/array_list.h" 26.34 +#include "cx/utils.h" 26.35 +#include "cx/compare.h" 26.36 +#include "util_allocator.h" 26.37 + 26.38 +#include <gtest/gtest.h> 26.39 +#include <array> 26.40 +#include <vector> 26.41 +#include <unordered_set> 26.42 +#include <algorithm> 26.43 + 26.44 +struct node { 26.45 + node *next = nullptr; 26.46 + node *prev = nullptr; 26.47 + int data = 0; 26.48 +}; 26.49 + 26.50 +const ptrdiff_t loc_prev = offsetof(struct node, prev); 26.51 +const ptrdiff_t loc_next = offsetof(struct node, next); 26.52 +const ptrdiff_t loc_data = offsetof(struct node, data); 26.53 + 26.54 +struct node_test_data { 26.55 + node *begin = nullptr; 26.56 + 26.57 + explicit node_test_data(node *begin) : begin(begin) { 26.58 + auto n = begin; 26.59 + while (n != nullptr) { 26.60 + nodes.push_back(n); 26.61 + n = n->next; 26.62 + } 26.63 + } 26.64 + 26.65 + node_test_data(node_test_data &) = delete; 26.66 + 26.67 + node_test_data(node_test_data &&) = default; 26.68 + 26.69 + ~node_test_data() { 26.70 + for (auto &&n: nodes) delete n; 26.71 + } 26.72 + 26.73 +private: 26.74 + std::vector<node *> nodes; 26.75 +}; 26.76 + 26.77 +static node_test_data create_nodes_test_data(size_t len) { 26.78 + if (len == 0) return node_test_data{nullptr}; 26.79 + auto begin = new node; 26.80 + auto prev = begin; 26.81 + for (size_t i = 1; i < len; i++) { 26.82 + auto n = new node; 26.83 + cx_linked_list_link(prev, n, loc_prev, loc_next); 26.84 + prev = n; 26.85 + } 26.86 + return node_test_data{begin}; 26.87 +} 26.88 + 26.89 +template<typename InputIter> 26.90 +static node_test_data create_nodes_test_data( 26.91 + InputIter begin, 26.92 + InputIter end 26.93 +) { 26.94 + if (begin == end) return node_test_data{nullptr}; 26.95 + node *first = new node; 26.96 + first->data = *begin; 26.97 + node *prev = first; 26.98 + begin++; 26.99 + for (; begin != end; begin++) { 26.100 + auto n = new node; 26.101 + n->data = *begin; 26.102 + cx_linked_list_link(prev, n, loc_prev, loc_next); 26.103 + prev = n; 26.104 + } 26.105 + return node_test_data{first}; 26.106 +} 26.107 + 26.108 +static node_test_data create_nodes_test_data(std::initializer_list<int> data) { 26.109 + return create_nodes_test_data(data.begin(), data.end()); 26.110 +} 26.111 + 26.112 +template<size_t N> 26.113 +struct int_test_data { 26.114 + std::array<int, N> data; 26.115 + 26.116 + int_test_data() { 26.117 + cx_for_n (i, N) data[i] = ::rand(); // NOLINT(cert-msc50-cpp) 26.118 + } 26.119 +}; 26.120 + 26.121 +TEST(LinkedList_LowLevel, link_unlink) { 26.122 + node a, b, c; 26.123 + 26.124 + cx_linked_list_link(&a, &b, loc_prev, loc_next); 26.125 + EXPECT_EQ(a.prev, nullptr); 26.126 + EXPECT_EQ(a.next, &b); 26.127 + EXPECT_EQ(b.prev, &a); 26.128 + EXPECT_EQ(b.next, nullptr); 26.129 + 26.130 + cx_linked_list_unlink(&a, &b, loc_prev, loc_next); 26.131 + EXPECT_EQ(a.prev, nullptr); 26.132 + EXPECT_EQ(a.next, nullptr); 26.133 + EXPECT_EQ(b.prev, nullptr); 26.134 + EXPECT_EQ(b.next, nullptr); 26.135 + 26.136 + cx_linked_list_link(&b, &c, loc_prev, loc_next); 26.137 + cx_linked_list_link(&a, &b, loc_prev, loc_next); 26.138 + cx_linked_list_unlink(&b, &c, loc_prev, loc_next); 26.139 + EXPECT_EQ(a.prev, nullptr); 26.140 + EXPECT_EQ(a.next, &b); 26.141 + EXPECT_EQ(b.prev, &a); 26.142 + EXPECT_EQ(b.next, nullptr); 26.143 + EXPECT_EQ(c.prev, nullptr); 26.144 + EXPECT_EQ(c.next, nullptr); 26.145 +} 26.146 + 26.147 +TEST(LinkedList_LowLevel, cx_linked_list_at) { 26.148 + node a, b, c, d; 26.149 + cx_linked_list_link(&a, &b, loc_prev, loc_next); 26.150 + cx_linked_list_link(&b, &c, loc_prev, loc_next); 26.151 + cx_linked_list_link(&c, &d, loc_prev, loc_next); 26.152 + 26.153 + EXPECT_EQ(cx_linked_list_at(&a, 0, loc_next, 0), &a); 26.154 + EXPECT_EQ(cx_linked_list_at(&a, 0, loc_next, 1), &b); 26.155 + EXPECT_EQ(cx_linked_list_at(&a, 0, loc_next, 2), &c); 26.156 + EXPECT_EQ(cx_linked_list_at(&a, 0, loc_next, 3), &d); 26.157 + EXPECT_EQ(cx_linked_list_at(&a, 0, loc_next, 4), nullptr); 26.158 + 26.159 + EXPECT_EQ(cx_linked_list_at(&b, 1, loc_prev, 0), &a); 26.160 + EXPECT_EQ(cx_linked_list_at(&b, 1, loc_next, 1), &b); 26.161 + EXPECT_EQ(cx_linked_list_at(&b, 1, loc_next, 2), &c); 26.162 + EXPECT_EQ(cx_linked_list_at(&b, 1, loc_next, 3), &d); 26.163 + EXPECT_EQ(cx_linked_list_at(&b, 1, loc_next, 4), nullptr); 26.164 + 26.165 + EXPECT_EQ(cx_linked_list_at(&d, 3, loc_prev, 0), &a); 26.166 + EXPECT_EQ(cx_linked_list_at(&d, 3, loc_prev, 1), &b); 26.167 +} 26.168 + 26.169 +TEST(LinkedList_LowLevel, cx_linked_list_find) { 26.170 + auto testdata = create_nodes_test_data({2, 4, 6, 8}); 26.171 + auto list = testdata.begin; 26.172 + int s; 26.173 + 26.174 + s = 2; 26.175 + EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 0); 26.176 + s = 4; 26.177 + EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 1); 26.178 + s = 6; 26.179 + EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 2); 26.180 + s = 8; 26.181 + EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 3); 26.182 + s = 10; 26.183 + EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 4); 26.184 + s = -2; 26.185 + EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 4); 26.186 +} 26.187 + 26.188 +TEST(LinkedList_LowLevel, cx_linked_list_compare) { 26.189 + auto ta = create_nodes_test_data({2, 4, 6, 8}); 26.190 + auto tb = create_nodes_test_data({2, 4, 6}); 26.191 + auto tc = create_nodes_test_data({2, 4, 6, 9}); 26.192 + auto la = ta.begin, lb = tb.begin, lc = tc.begin; 26.193 + 26.194 + EXPECT_GT(cx_linked_list_compare(la, lb, loc_next, loc_data, cx_cmp_int), 0); 26.195 + EXPECT_LT(cx_linked_list_compare(lb, la, loc_next, loc_data, cx_cmp_int), 0); 26.196 + EXPECT_GT(cx_linked_list_compare(lc, la, loc_next, loc_data, cx_cmp_int), 0); 26.197 + EXPECT_LT(cx_linked_list_compare(la, lc, loc_next, loc_data, cx_cmp_int), 0); 26.198 + EXPECT_EQ(cx_linked_list_compare(la, la, loc_next, loc_data, cx_cmp_int), 0); 26.199 +} 26.200 + 26.201 +TEST(LinkedList_LowLevel, cx_linked_list_add) { 26.202 + // test with begin, end / prev, next 26.203 + { 26.204 + node nodes[4]; 26.205 + void *begin = nullptr, *end = nullptr; 26.206 + 26.207 + cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[0]); 26.208 + EXPECT_EQ(begin, &nodes[0]); 26.209 + EXPECT_EQ(end, &nodes[0]); 26.210 + EXPECT_EQ(nodes[0].prev, nullptr); 26.211 + EXPECT_EQ(nodes[0].next, nullptr); 26.212 + 26.213 + cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[1]); 26.214 + EXPECT_EQ(begin, &nodes[0]); 26.215 + EXPECT_EQ(end, &nodes[1]); 26.216 + EXPECT_EQ(nodes[0].next, &nodes[1]); 26.217 + EXPECT_EQ(nodes[1].prev, &nodes[0]); 26.218 + } 26.219 + 26.220 + // test with begin only / prev, next 26.221 + { 26.222 + node nodes[4]; 26.223 + void *begin = nullptr; 26.224 + 26.225 + cx_linked_list_add(&begin, nullptr, loc_prev, loc_next, &nodes[0]); 26.226 + EXPECT_EQ(begin, &nodes[0]); 26.227 + cx_linked_list_add(&begin, nullptr, loc_prev, loc_next, &nodes[1]); 26.228 + EXPECT_EQ(begin, &nodes[0]); 26.229 + EXPECT_EQ(nodes[0].next, &nodes[1]); 26.230 + EXPECT_EQ(nodes[1].prev, &nodes[0]); 26.231 + 26.232 + cx_linked_list_add(&begin, nullptr, loc_prev, loc_next, &nodes[2]); 26.233 + EXPECT_EQ(nodes[1].next, &nodes[2]); 26.234 + EXPECT_EQ(nodes[2].prev, &nodes[1]); 26.235 + } 26.236 + 26.237 + // test with end only / prev, next 26.238 + { 26.239 + node nodes[4]; 26.240 + void *end = nullptr; 26.241 + 26.242 + cx_linked_list_add(nullptr, &end, loc_prev, loc_next, &nodes[0]); 26.243 + EXPECT_EQ(end, &nodes[0]); 26.244 + cx_linked_list_add(nullptr, &end, loc_prev, loc_next, &nodes[1]); 26.245 + EXPECT_EQ(end, &nodes[1]); 26.246 + EXPECT_EQ(nodes[0].next, &nodes[1]); 26.247 + EXPECT_EQ(nodes[1].prev, &nodes[0]); 26.248 + 26.249 + cx_linked_list_add(nullptr, &end, loc_prev, loc_next, &nodes[2]); 26.250 + EXPECT_EQ(end, &nodes[2]); 26.251 + EXPECT_EQ(nodes[1].next, &nodes[2]); 26.252 + EXPECT_EQ(nodes[2].prev, &nodes[1]); 26.253 + } 26.254 + 26.255 + // test with begin, end / next 26.256 + { 26.257 + node nodes[4]; 26.258 + void *begin = nullptr, *end = nullptr; 26.259 + 26.260 + cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[0]); 26.261 + EXPECT_EQ(begin, &nodes[0]); 26.262 + EXPECT_EQ(end, &nodes[0]); 26.263 + cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[1]); 26.264 + EXPECT_EQ(end, &nodes[1]); 26.265 + EXPECT_EQ(nodes[0].next, &nodes[1]); 26.266 + EXPECT_EQ(nodes[1].prev, nullptr); 26.267 + } 26.268 +} 26.269 + 26.270 +TEST(LinkedList_LowLevel, cx_linked_list_prepend) { 26.271 + // test with begin, end / prev, next 26.272 + { 26.273 + node nodes[4]; 26.274 + void *begin = nullptr, *end = nullptr; 26.275 + 26.276 + cx_linked_list_prepend(&begin, &end, loc_prev, loc_next, &nodes[0]); 26.277 + EXPECT_EQ(begin, &nodes[0]); 26.278 + EXPECT_EQ(end, &nodes[0]); 26.279 + EXPECT_EQ(nodes[0].prev, nullptr); 26.280 + EXPECT_EQ(nodes[0].next, nullptr); 26.281 + 26.282 + cx_linked_list_prepend(&begin, &end, loc_prev, loc_next, &nodes[1]); 26.283 + EXPECT_EQ(begin, &nodes[1]); 26.284 + EXPECT_EQ(end, &nodes[0]); 26.285 + EXPECT_EQ(nodes[1].next, &nodes[0]); 26.286 + EXPECT_EQ(nodes[0].prev, &nodes[1]); 26.287 + } 26.288 + 26.289 + // test with begin only / prev, next 26.290 + { 26.291 + node nodes[4]; 26.292 + void *begin = nullptr; 26.293 + 26.294 + cx_linked_list_prepend(&begin, nullptr, loc_prev, loc_next, &nodes[0]); 26.295 + EXPECT_EQ(begin, &nodes[0]); 26.296 + cx_linked_list_prepend(&begin, nullptr, loc_prev, loc_next, &nodes[1]); 26.297 + EXPECT_EQ(begin, &nodes[1]); 26.298 + EXPECT_EQ(nodes[1].next, &nodes[0]); 26.299 + EXPECT_EQ(nodes[0].prev, &nodes[1]); 26.300 + 26.301 + cx_linked_list_prepend(&begin, nullptr, loc_prev, loc_next, &nodes[2]); 26.302 + EXPECT_EQ(begin, &nodes[2]); 26.303 + EXPECT_EQ(nodes[2].next, &nodes[1]); 26.304 + EXPECT_EQ(nodes[1].prev, &nodes[2]); 26.305 + } 26.306 + 26.307 + // test with end only / prev, next 26.308 + { 26.309 + node nodes[4]; 26.310 + void *end = nullptr; 26.311 + 26.312 + cx_linked_list_prepend(nullptr, &end, loc_prev, loc_next, &nodes[0]); 26.313 + EXPECT_EQ(end, &nodes[0]); 26.314 + cx_linked_list_prepend(nullptr, &end, loc_prev, loc_next, &nodes[1]); 26.315 + EXPECT_EQ(end, &nodes[0]); 26.316 + EXPECT_EQ(nodes[1].next, &nodes[0]); 26.317 + EXPECT_EQ(nodes[0].prev, &nodes[1]); 26.318 + 26.319 + cx_linked_list_prepend(nullptr, &end, loc_prev, loc_next, &nodes[2]); 26.320 + EXPECT_EQ(end, &nodes[0]); 26.321 + EXPECT_EQ(nodes[2].next, &nodes[1]); 26.322 + EXPECT_EQ(nodes[1].prev, &nodes[2]); 26.323 + } 26.324 + 26.325 + // test with begin, end / next 26.326 + { 26.327 + node nodes[4]; 26.328 + void *begin = nullptr, *end = nullptr; 26.329 + 26.330 + cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[0]); 26.331 + EXPECT_EQ(begin, &nodes[0]); 26.332 + EXPECT_EQ(end, &nodes[0]); 26.333 + cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[1]); 26.334 + cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[2]); 26.335 + EXPECT_EQ(begin, &nodes[2]); 26.336 + EXPECT_EQ(end, &nodes[0]); 26.337 + EXPECT_EQ(nodes[1].next, &nodes[0]); 26.338 + EXPECT_EQ(nodes[2].next, &nodes[1]); 26.339 + EXPECT_EQ(nodes[1].prev, nullptr); 26.340 + EXPECT_EQ(nodes[0].prev, nullptr); 26.341 + } 26.342 +} 26.343 + 26.344 +TEST(LinkedList_LowLevel, cx_linked_list_insert) { 26.345 + // insert mid list 26.346 + { 26.347 + node nodes[4]; 26.348 + void *begin = &nodes[0], *end = &nodes[2]; 26.349 + 26.350 + cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 26.351 + cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 26.352 + 26.353 + cx_linked_list_insert(&begin, &end, loc_prev, loc_next, &nodes[1], &nodes[3]); 26.354 + EXPECT_EQ(begin, &nodes[0]); 26.355 + EXPECT_EQ(end, &nodes[2]); 26.356 + EXPECT_EQ(nodes[1].next, &nodes[3]); 26.357 + EXPECT_EQ(nodes[2].prev, &nodes[3]); 26.358 + EXPECT_EQ(nodes[3].prev, &nodes[1]); 26.359 + EXPECT_EQ(nodes[3].next, &nodes[2]); 26.360 + } 26.361 + 26.362 + // insert end 26.363 + { 26.364 + node nodes[4]; 26.365 + void *begin = &nodes[0], *end = &nodes[2]; 26.366 + 26.367 + cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 26.368 + cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 26.369 + 26.370 + cx_linked_list_insert(&begin, &end, loc_prev, loc_next, &nodes[2], &nodes[3]); 26.371 + EXPECT_EQ(begin, &nodes[0]); 26.372 + EXPECT_EQ(end, &nodes[3]); 26.373 + EXPECT_EQ(nodes[2].next, &nodes[3]); 26.374 + EXPECT_EQ(nodes[3].prev, &nodes[2]); 26.375 + EXPECT_EQ(nodes[3].next, nullptr); 26.376 + } 26.377 + 26.378 + // insert begin 26.379 + { 26.380 + node nodes[4]; 26.381 + void *begin = &nodes[0], *end = &nodes[2]; 26.382 + 26.383 + cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 26.384 + cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 26.385 + 26.386 + cx_linked_list_insert(&begin, &end, loc_prev, loc_next, nullptr, &nodes[3]); 26.387 + EXPECT_EQ(begin, &nodes[3]); 26.388 + EXPECT_EQ(end, &nodes[2]); 26.389 + EXPECT_EQ(nodes[0].prev, &nodes[3]); 26.390 + EXPECT_EQ(nodes[3].prev, nullptr); 26.391 + EXPECT_EQ(nodes[3].next, &nodes[0]); 26.392 + } 26.393 +} 26.394 + 26.395 +TEST(LinkedList_LowLevel, cx_linked_list_insert_chain) { 26.396 + // insert mid list 26.397 + { 26.398 + node nodes[5]; 26.399 + void *begin = &nodes[0], *end = &nodes[2]; 26.400 + 26.401 + cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 26.402 + cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 26.403 + cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); 26.404 + 26.405 + cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, &nodes[1], &nodes[3], nullptr); 26.406 + EXPECT_EQ(begin, &nodes[0]); 26.407 + EXPECT_EQ(end, &nodes[2]); 26.408 + EXPECT_EQ(nodes[1].next, &nodes[3]); 26.409 + EXPECT_EQ(nodes[2].prev, &nodes[4]); 26.410 + EXPECT_EQ(nodes[3].prev, &nodes[1]); 26.411 + EXPECT_EQ(nodes[4].next, &nodes[2]); 26.412 + } 26.413 + 26.414 + // insert end 26.415 + { 26.416 + node nodes[5]; 26.417 + void *begin = &nodes[0], *end = &nodes[2]; 26.418 + 26.419 + cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 26.420 + cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 26.421 + cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); 26.422 + 26.423 + cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, &nodes[2], &nodes[3], nullptr); 26.424 + EXPECT_EQ(begin, &nodes[0]); 26.425 + EXPECT_EQ(end, &nodes[4]); 26.426 + EXPECT_EQ(nodes[2].next, &nodes[3]); 26.427 + EXPECT_EQ(nodes[3].prev, &nodes[2]); 26.428 + EXPECT_EQ(nodes[4].next, nullptr); 26.429 + } 26.430 + 26.431 + // insert begin 26.432 + { 26.433 + node nodes[5]; 26.434 + void *begin = &nodes[0], *end = &nodes[2]; 26.435 + 26.436 + cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 26.437 + cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 26.438 + cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); 26.439 + 26.440 + cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, nullptr, &nodes[3], nullptr); 26.441 + EXPECT_EQ(begin, &nodes[3]); 26.442 + EXPECT_EQ(end, &nodes[2]); 26.443 + EXPECT_EQ(nodes[0].prev, &nodes[4]); 26.444 + EXPECT_EQ(nodes[3].prev, nullptr); 26.445 + EXPECT_EQ(nodes[4].next, &nodes[0]); 26.446 + } 26.447 +} 26.448 + 26.449 +TEST(LinkedList_LowLevel, cx_linked_list_first) { 26.450 + auto testdata = create_nodes_test_data(3); 26.451 + auto begin = testdata.begin; 26.452 + EXPECT_EQ(cx_linked_list_first(begin, loc_prev), begin); 26.453 + EXPECT_EQ(cx_linked_list_first(begin->next, loc_prev), begin); 26.454 + EXPECT_EQ(cx_linked_list_first(begin->next->next, loc_prev), begin); 26.455 +} 26.456 + 26.457 +TEST(LinkedList_LowLevel, cx_linked_list_last) { 26.458 + auto testdata = create_nodes_test_data(3); 26.459 + auto begin = testdata.begin; 26.460 + auto end = begin->next->next; 26.461 + EXPECT_EQ(cx_linked_list_last(begin, loc_next), end); 26.462 + EXPECT_EQ(cx_linked_list_last(begin->next, loc_next), end); 26.463 + EXPECT_EQ(cx_linked_list_last(begin->next->next, loc_next), end); 26.464 +} 26.465 + 26.466 +TEST(LinkedList_LowLevel, cx_linked_list_prev) { 26.467 + auto testdata = create_nodes_test_data(3); 26.468 + auto begin = testdata.begin; 26.469 + EXPECT_EQ(cx_linked_list_prev(begin, loc_next, begin), nullptr); 26.470 + EXPECT_EQ(cx_linked_list_prev(begin, loc_next, begin->next), begin); 26.471 + EXPECT_EQ(cx_linked_list_prev(begin, loc_next, begin->next->next), begin->next); 26.472 +} 26.473 + 26.474 +TEST(LinkedList_LowLevel, cx_linked_list_remove) { 26.475 + auto testdata = create_nodes_test_data({2, 4, 6}); 26.476 + auto begin = reinterpret_cast<void *>(testdata.begin); 26.477 + auto first = testdata.begin; 26.478 + auto second = first->next; 26.479 + auto third = second->next; 26.480 + auto end = reinterpret_cast<void *>(third); 26.481 + 26.482 + cx_linked_list_remove(&begin, &end, loc_prev, loc_next, second); 26.483 + EXPECT_EQ(begin, first); 26.484 + EXPECT_EQ(end, third); 26.485 + EXPECT_EQ(first->prev, nullptr); 26.486 + EXPECT_EQ(first->next, third); 26.487 + EXPECT_EQ(third->prev, first); 26.488 + EXPECT_EQ(third->next, nullptr); 26.489 + 26.490 + cx_linked_list_remove(&begin, &end, loc_prev, loc_next, third); 26.491 + EXPECT_EQ(begin, first); 26.492 + EXPECT_EQ(end, first); 26.493 + EXPECT_EQ(first->prev, nullptr); 26.494 + EXPECT_EQ(first->next, nullptr); 26.495 + 26.496 + cx_linked_list_remove(&begin, &end, loc_prev, loc_next, first); 26.497 + EXPECT_EQ(begin, nullptr); 26.498 + EXPECT_EQ(end, nullptr); 26.499 +} 26.500 + 26.501 +TEST(LinkedList_LowLevel, cx_linked_list_size) { 26.502 + EXPECT_EQ(cx_linked_list_size(nullptr, loc_next), 0); 26.503 + 26.504 + { 26.505 + auto testdata = create_nodes_test_data(5); 26.506 + EXPECT_EQ(cx_linked_list_size(testdata.begin, loc_next), 5); 26.507 + } 26.508 + 26.509 + { 26.510 + auto testdata = create_nodes_test_data(13); 26.511 + EXPECT_EQ(cx_linked_list_size(testdata.begin, loc_next), 13); 26.512 + } 26.513 +} 26.514 + 26.515 +TEST(LinkedList_LowLevel, cx_linked_list_sort) { 26.516 + int_test_data<1500> testdata; 26.517 + std::array<int, 1500> sorted{}; 26.518 + std::partial_sort_copy(testdata.data.begin(), testdata.data.end(), sorted.begin(), sorted.end()); 26.519 + 26.520 + auto scrambled = create_nodes_test_data(testdata.data.begin(), testdata.data.end()); 26.521 + void *begin = scrambled.begin; 26.522 + void *end = cx_linked_list_last(begin, loc_next); 26.523 + 26.524 + cx_linked_list_sort(&begin, &end, loc_prev, loc_next, loc_data, cx_cmp_int); 26.525 + 26.526 + node *check = reinterpret_cast<node *>(begin); 26.527 + node *check_last = nullptr; 26.528 + cx_for_n (i, sorted.size()) { 26.529 + EXPECT_EQ(check->data, sorted[i]); 26.530 + EXPECT_EQ(check->prev, check_last); 26.531 + if (i < sorted.size() - 1) { 26.532 + ASSERT_NE(check->next, nullptr); 26.533 + } 26.534 + check_last = check; 26.535 + check = check->next; 26.536 + } 26.537 + EXPECT_EQ(check, nullptr); 26.538 + EXPECT_EQ(end, check_last); 26.539 +} 26.540 + 26.541 +TEST(LinkedList_LowLevel, cx_linked_list_reverse) { 26.542 + auto testdata = create_nodes_test_data({2, 4, 6, 8}); 26.543 + auto expected = create_nodes_test_data({8, 6, 4, 2}); 26.544 + 26.545 + auto begin = reinterpret_cast<void *>(testdata.begin); 26.546 + auto end = cx_linked_list_last(begin, loc_next); 26.547 + auto orig_begin = begin, orig_end = end; 26.548 + 26.549 + cx_linked_list_reverse(&begin, &end, loc_prev, loc_next); 26.550 + EXPECT_EQ(end, orig_begin); 26.551 + EXPECT_EQ(begin, orig_end); 26.552 + EXPECT_EQ(cx_linked_list_compare(begin, expected.begin, loc_next, loc_data, cx_cmp_int), 0); 26.553 +} 26.554 + 26.555 +class HighLevelTest : public ::testing::Test { 26.556 + mutable std::unordered_set<CxList *> lists; 26.557 +protected: 26.558 + CxTestingAllocator testingAllocator; 26.559 + 26.560 + void TearDown() override { 26.561 + for (auto &&l: lists) cxListDestroy(l); 26.562 + EXPECT_TRUE(testingAllocator.verify()); 26.563 + } 26.564 + 26.565 + static constexpr size_t testdata_len = 250; 26.566 + int_test_data<testdata_len> testdata; 26.567 + 26.568 + auto autofree(CxList *list) const -> CxList * { 26.569 + if (list != nullptr) lists.insert(list); 26.570 + return list; 26.571 + } 26.572 + 26.573 + auto linkedListFromTestData() const -> CxList * { 26.574 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 26.575 + cxListAddArray(list, testdata.data.data(), testdata_len); 26.576 + return list; 26.577 + } 26.578 + 26.579 + auto pointerLinkedListFromTestData() const -> CxList * { 26.580 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 26.581 + cxListStorePointers(list); 26.582 + // note: cannot use cxListAddArray() because we don't have a list of pointers 26.583 + cx_for_n(i, testdata_len) cxListAdd(list, &testdata.data[i]); 26.584 + return list; 26.585 + } 26.586 + 26.587 + auto arrayListFromTestData() const -> CxList * { 26.588 + auto list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), testdata_len)); 26.589 + cxListAddArray(list, testdata.data.data(), testdata_len); 26.590 + return list; 26.591 + } 26.592 + 26.593 + void verifyCreate(CxList *list) const { 26.594 + EXPECT_EQ(list->content_destructor_type, CX_DESTRUCTOR_NONE); 26.595 + EXPECT_EQ(list->size, 0); 26.596 + EXPECT_EQ(list->allocator, &testingAllocator); 26.597 + EXPECT_EQ(list->cmpfunc, cx_cmp_int); 26.598 + } 26.599 + 26.600 + void verifyAdd( 26.601 + CxList *list, 26.602 + bool as_pointer 26.603 + ) { 26.604 + auto len = testdata_len; 26.605 + cx_for_n (i, len) EXPECT_EQ(cxListAdd(list, &testdata.data[i]), 0); 26.606 + EXPECT_EQ(list->size, len); 26.607 + EXPECT_GE(list->capacity, list->size); 26.608 + cx_for_n (i, len) EXPECT_EQ(*(int *) cxListAt(list, i), testdata.data[i]); 26.609 + cx_for_n (i, len) ++testdata.data[i]; 26.610 + if (as_pointer) { 26.611 + cx_for_n (i, len) EXPECT_EQ(*(int *) cxListAt(list, i), testdata.data[i]); 26.612 + } else { 26.613 + cx_for_n (i, len) EXPECT_EQ(*(int *) cxListAt(list, i), testdata.data[i] - 1); 26.614 + } 26.615 + } 26.616 + 26.617 + static void verifyInsert(CxList *list) { 26.618 + int a = 5, b = 47, c = 13, d = 42; 26.619 + 26.620 + EXPECT_NE(cxListInsert(list, 1, &a), 0); 26.621 + EXPECT_EQ(list->size, 0); 26.622 + EXPECT_EQ(cxListInsert(list, 0, &a), 0); 26.623 + EXPECT_EQ(list->size, 1); 26.624 + EXPECT_EQ(cxListInsert(list, 0, &b), 0); 26.625 + EXPECT_EQ(list->size, 2); 26.626 + EXPECT_EQ(cxListInsert(list, 1, &c), 0); 26.627 + EXPECT_EQ(list->size, 3); 26.628 + EXPECT_EQ(cxListInsert(list, 3, &d), 0); 26.629 + 26.630 + ASSERT_EQ(list->size, 4); 26.631 + EXPECT_GE(list->capacity, list->size); 26.632 + 26.633 + EXPECT_EQ(*(int *) cxListAt(list, 0), 47); 26.634 + EXPECT_EQ(*(int *) cxListAt(list, 1), 13); 26.635 + EXPECT_EQ(*(int *) cxListAt(list, 2), 5); 26.636 + EXPECT_EQ(*(int *) cxListAt(list, 3), 42); 26.637 + } 26.638 + 26.639 + static void verifyInsertArray( 26.640 + CxList *list, 26.641 + bool pointers = false 26.642 + ) { 26.643 + int a[5] = {5, 47, 11, 13, 42}; 26.644 + int b[5] = {9, 18, 72, 50, 7}; 26.645 + int *aptr[5]; 26.646 + int *bptr[5]; 26.647 + cx_for_n(i, 5) { 26.648 + aptr[i] = &a[i]; 26.649 + bptr[i] = &b[i]; 26.650 + } 26.651 + 26.652 + size_t inserted; 26.653 + 26.654 + if (pointers) { 26.655 + inserted = cxListInsertArray(list, 0, aptr, 5); 26.656 + } else { 26.657 + inserted = cxListInsertArray(list, 0, a, 5); 26.658 + } 26.659 + EXPECT_EQ(inserted, 5); 26.660 + EXPECT_EQ(*(int *) cxListAt(list, 0), 5); 26.661 + EXPECT_EQ(*(int *) cxListAt(list, 1), 47); 26.662 + EXPECT_EQ(*(int *) cxListAt(list, 2), 11); 26.663 + EXPECT_EQ(*(int *) cxListAt(list, 3), 13); 26.664 + EXPECT_EQ(*(int *) cxListAt(list, 4), 42); 26.665 + if (pointers) { 26.666 + inserted = cxListInsertArray(list, 3, bptr, 5); 26.667 + } else { 26.668 + inserted = cxListInsertArray(list, 3, b, 5); 26.669 + } 26.670 + EXPECT_EQ(inserted, 5); 26.671 + EXPECT_EQ(*(int *) cxListAt(list, 0), 5); 26.672 + EXPECT_EQ(*(int *) cxListAt(list, 1), 47); 26.673 + EXPECT_EQ(*(int *) cxListAt(list, 2), 11); 26.674 + EXPECT_EQ(*(int *) cxListAt(list, 3), 9); 26.675 + EXPECT_EQ(*(int *) cxListAt(list, 4), 18); 26.676 + EXPECT_EQ(*(int *) cxListAt(list, 5), 72); 26.677 + EXPECT_EQ(*(int *) cxListAt(list, 6), 50); 26.678 + EXPECT_EQ(*(int *) cxListAt(list, 7), 7); 26.679 + EXPECT_EQ(*(int *) cxListAt(list, 8), 13); 26.680 + EXPECT_EQ(*(int *) cxListAt(list, 9), 42); 26.681 + } 26.682 + 26.683 + void verifyRemove(CxList *list) const { 26.684 + EXPECT_EQ(cxListRemove(list, 2), 0); 26.685 + EXPECT_EQ(cxListRemove(list, 4), 0); 26.686 + EXPECT_EQ(list->size, testdata_len - 2); 26.687 + EXPECT_GE(list->capacity, list->size); 26.688 + EXPECT_EQ(*(int *) cxListAt(list, 0), testdata.data[0]); 26.689 + EXPECT_EQ(*(int *) cxListAt(list, 1), testdata.data[1]); 26.690 + EXPECT_EQ(*(int *) cxListAt(list, 2), testdata.data[3]); 26.691 + EXPECT_EQ(*(int *) cxListAt(list, 3), testdata.data[4]); 26.692 + EXPECT_EQ(*(int *) cxListAt(list, 4), testdata.data[6]); 26.693 + 26.694 + EXPECT_EQ(cxListRemove(list, 0), 0); 26.695 + EXPECT_EQ(list->size, testdata_len - 3); 26.696 + EXPECT_GE(list->capacity, list->size); 26.697 + EXPECT_EQ(*(int *) cxListAt(list, 0), testdata.data[1]); 26.698 + EXPECT_EQ(*(int *) cxListAt(list, 1), testdata.data[3]); 26.699 + 26.700 + EXPECT_NE(cxListRemove(list, testdata_len), 0); 26.701 + } 26.702 + 26.703 + void verifyAt(CxList *list) const { 26.704 + auto len = testdata_len; 26.705 + EXPECT_EQ(list->size, len); 26.706 + cx_for_n (i, len) { 26.707 + EXPECT_EQ(*(int *) cxListAt(list, i), testdata.data[i]); 26.708 + } 26.709 + EXPECT_EQ(cxListAt(list, list->size), nullptr); 26.710 + } 26.711 + 26.712 + void verifyFind(CxList *list) const { 26.713 + cx_for_n (attempt, 25) { 26.714 + size_t exp = rand() % testdata_len; // NOLINT(cert-msc50-cpp) 26.715 + int val = testdata.data[exp]; 26.716 + // randomly picked number could occur earlier in list - find first position 26.717 + cx_for_n (i, exp) { 26.718 + if (testdata.data[i] == val) { 26.719 + exp = i; 26.720 + break; 26.721 + } 26.722 + } 26.723 + EXPECT_EQ(cxListFind(list, &val), exp); 26.724 + } 26.725 + } 26.726 + 26.727 + void verifySort(CxList *list) const { 26.728 + std::array<int, testdata_len> expected{}; 26.729 + std::partial_sort_copy(testdata.data.begin(), testdata.data.end(), expected.begin(), expected.end()); 26.730 + cxListSort(list); 26.731 + cx_for_n (i, testdata_len) ASSERT_EQ(*(int *) cxListAt(list, i), expected[i]); 26.732 + } 26.733 + 26.734 + void verifyIterator(CxList *list) const { 26.735 + int i = 0; 26.736 + auto iter = cxListBeginMut(list); 26.737 + cx_foreach(int*, x, iter) { 26.738 + ASSERT_EQ(iter.index, (size_t) (i + 1) / 2); 26.739 + ASSERT_EQ(*x, testdata.data[i]); 26.740 + if (i % 2 == 1) cxIteratorFlagRemoval(iter); 26.741 + i++; 26.742 + } 26.743 + auto len = testdata_len; 26.744 + EXPECT_EQ(i, len); 26.745 + ASSERT_EQ(list->size, len / 2); 26.746 + cx_for_n(j, len / 2) ASSERT_EQ(*(int *) cxListAt(list, j), testdata.data[j * 2]); 26.747 + } 26.748 + 26.749 + static void verifyInsertViaIterator(CxList *list) { 26.750 + int newdata[] = {10, 20, 30, 40, 50}; 26.751 + 26.752 + auto iter = cxListMutIterator(list, 2); 26.753 + EXPECT_TRUE(cxIteratorValid(iter)); 26.754 + EXPECT_EQ(iter.index, 2); 26.755 + EXPECT_EQ(*(int *) cxIteratorCurrent(iter), 2); 26.756 + cxListInsertAfter(&iter, &newdata[0]); 26.757 + EXPECT_TRUE(cxIteratorValid(iter)); 26.758 + EXPECT_EQ(iter.index, 2); 26.759 + EXPECT_EQ(*(int *) cxIteratorCurrent(iter), 2); 26.760 + cxListInsertBefore(&iter, &newdata[1]); 26.761 + EXPECT_TRUE(cxIteratorValid(iter)); 26.762 + EXPECT_EQ(iter.index, 3); 26.763 + EXPECT_EQ(*(int *) cxIteratorCurrent(iter), 2); 26.764 + 26.765 + iter = cxListBeginMut(list); 26.766 + cxListInsertBefore(&iter, &newdata[2]); 26.767 + EXPECT_TRUE(cxIteratorValid(iter)); 26.768 + EXPECT_EQ(iter.index, 1); 26.769 + EXPECT_EQ(*(int *) cxIteratorCurrent(iter), 0); 26.770 + iter = cxListMutIterator(list, list->size); 26.771 + cxListInsertBefore(&iter, &newdata[3]); 26.772 + EXPECT_FALSE(cxIteratorValid(iter)); 26.773 + EXPECT_EQ(iter.index, 9); 26.774 + iter = cxListMutIterator(list, list->size); 26.775 + cxListInsertAfter(&iter, &newdata[4]); 26.776 + EXPECT_FALSE(cxIteratorValid(iter)); 26.777 + EXPECT_EQ(iter.index, 10); 26.778 + 26.779 + int expdata[] = {30, 0, 1, 20, 2, 10, 3, 4, 40, 50}; 26.780 + cx_for_n (j, 10) EXPECT_EQ(*(int *) cxListAt(list, j), expdata[j]); 26.781 + } 26.782 + 26.783 + void verifyReverse(CxList *list) const { 26.784 + cxListReverse(list); 26.785 + cx_for_n(i, testdata_len) { 26.786 + ASSERT_EQ(*(int *) cxListAt(list, i), testdata.data[testdata_len - 1 - i]); 26.787 + } 26.788 + } 26.789 + 26.790 + static void verifyCompare( 26.791 + CxList *left, 26.792 + CxList *right 26.793 + ) { 26.794 + EXPECT_EQ(cxListCompare(left, right), 0); 26.795 + int x = 42; 26.796 + cxListAdd(left, &x); 26.797 + ASSERT_GT(left->size, right->size); 26.798 + EXPECT_GT(cxListCompare(left, right), 0); 26.799 + EXPECT_LT(cxListCompare(right, left), 0); 26.800 + cxListAdd(right, &x); 26.801 + ASSERT_EQ(left->size, right->size); 26.802 + EXPECT_EQ(cxListCompare(left, right), 0); 26.803 + int a = 5, b = 10; 26.804 + cxListInsert(left, 15, &a); 26.805 + cxListInsert(right, 15, &b); 26.806 + ASSERT_EQ(left->size, right->size); 26.807 + EXPECT_LT(cxListCompare(left, right), 0); 26.808 + EXPECT_GT(cxListCompare(right, left), 0); 26.809 + *(int *) cxListAt(left, 15) = 10; 26.810 + EXPECT_EQ(cxListCompare(left, right), 0); 26.811 + } 26.812 +}; 26.813 + 26.814 +class LinkedList : public HighLevelTest { 26.815 +}; 26.816 + 26.817 +class PointerLinkedList : public HighLevelTest { 26.818 +}; 26.819 + 26.820 +class ArrayList : public HighLevelTest { 26.821 +}; 26.822 + 26.823 +TEST_F(PointerLinkedList, cxListStorePointers) { 26.824 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, 47)); 26.825 + EXPECT_FALSE(cxListIsStoringPointers(list)); 26.826 + cxListStorePointers(list); 26.827 + EXPECT_EQ(list->itemsize, sizeof(void *)); 26.828 + EXPECT_NE(list->cl, nullptr); 26.829 + EXPECT_NE(list->climpl, nullptr); 26.830 + EXPECT_TRUE(cxListIsStoringPointers(list)); 26.831 + cxListStoreObjects(list); 26.832 + EXPECT_NE(list->cl, nullptr); 26.833 + EXPECT_EQ(list->climpl, nullptr); 26.834 + EXPECT_FALSE(cxListIsStoringPointers(list)); 26.835 +} 26.836 + 26.837 +TEST_F(LinkedList, cxLinkedListCreate) { 26.838 + CxList *list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 26.839 + ASSERT_NE(list, nullptr); 26.840 + EXPECT_EQ(list->itemsize, sizeof(int)); 26.841 + EXPECT_EQ(list->capacity, (size_t) -1); 26.842 + verifyCreate(list); 26.843 +} 26.844 + 26.845 +TEST_F(ArrayList, cxArrayListCreate) { 26.846 + CxList *list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 8)); 26.847 + ASSERT_NE(list, nullptr); 26.848 + EXPECT_EQ(list->itemsize, sizeof(int)); 26.849 + EXPECT_EQ(list->capacity, 8); 26.850 + verifyCreate(list); 26.851 +} 26.852 + 26.853 +TEST_F(LinkedList, cxListAdd) { 26.854 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 26.855 + verifyAdd(list, false); 26.856 +} 26.857 + 26.858 +TEST_F(PointerLinkedList, cxListAdd) { 26.859 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 26.860 + cxListStorePointers(list); 26.861 + verifyAdd(list, true); 26.862 +} 26.863 + 26.864 +TEST_F(ArrayList, cxListAdd) { 26.865 + auto list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 8)); 26.866 + verifyAdd(list, false); 26.867 +} 26.868 + 26.869 +TEST_F(LinkedList, cxListInsert) { 26.870 + verifyInsert(autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)))); 26.871 +} 26.872 + 26.873 +TEST_F(PointerLinkedList, cxListInsert) { 26.874 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 26.875 + cxListStorePointers(list); 26.876 + verifyInsert(list); 26.877 +} 26.878 + 26.879 +TEST_F(ArrayList, cxListInsert) { 26.880 + verifyInsert(autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 2))); 26.881 +} 26.882 + 26.883 +TEST_F(LinkedList, cxListInsertArray) { 26.884 + verifyInsertArray(autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)))); 26.885 +} 26.886 + 26.887 +TEST_F(PointerLinkedList, cxListInsertArray) { 26.888 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 26.889 + cxListStorePointers(list); 26.890 + verifyInsertArray(list, true); 26.891 +} 26.892 + 26.893 +TEST_F(ArrayList, cxListInsertArray) { 26.894 + verifyInsertArray(autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 4))); 26.895 +} 26.896 + 26.897 +TEST_F(LinkedList, cxListRemove) { 26.898 + verifyRemove(linkedListFromTestData()); 26.899 +} 26.900 + 26.901 +TEST_F(PointerLinkedList, cxListRemove) { 26.902 + verifyRemove(pointerLinkedListFromTestData()); 26.903 +} 26.904 + 26.905 +TEST_F(ArrayList, cxListRemove) { 26.906 + verifyRemove(arrayListFromTestData()); 26.907 +} 26.908 + 26.909 +TEST_F(LinkedList, cxListAt) { 26.910 + verifyAt(linkedListFromTestData()); 26.911 +} 26.912 + 26.913 +TEST_F(PointerLinkedList, cxListAt) { 26.914 + verifyAt(pointerLinkedListFromTestData()); 26.915 +} 26.916 + 26.917 +TEST_F(ArrayList, cxListAt) { 26.918 + verifyAt(arrayListFromTestData()); 26.919 +} 26.920 + 26.921 +TEST_F(LinkedList, cxListFind) { 26.922 + verifyFind(linkedListFromTestData()); 26.923 +} 26.924 + 26.925 +TEST_F(PointerLinkedList, cxListFind) { 26.926 + verifyFind(pointerLinkedListFromTestData()); 26.927 +} 26.928 + 26.929 +TEST_F(ArrayList, cxListFind) { 26.930 + verifyFind(arrayListFromTestData()); 26.931 +} 26.932 + 26.933 +TEST_F(LinkedList, cxListSort) { 26.934 + verifySort(linkedListFromTestData()); 26.935 +} 26.936 + 26.937 +TEST_F(PointerLinkedList, cxListSort) { 26.938 + verifySort(pointerLinkedListFromTestData()); 26.939 +} 26.940 + 26.941 +TEST_F(ArrayList, cxListSort) { 26.942 + verifySort(arrayListFromTestData()); 26.943 +} 26.944 + 26.945 +TEST_F(LinkedList, Iterator) { 26.946 + verifyIterator(linkedListFromTestData()); 26.947 +} 26.948 + 26.949 +TEST_F(PointerLinkedList, Iterator) { 26.950 + verifyIterator(pointerLinkedListFromTestData()); 26.951 +} 26.952 + 26.953 +TEST_F(ArrayList, Iterator) { 26.954 + verifyIterator(arrayListFromTestData()); 26.955 +} 26.956 + 26.957 +TEST_F(LinkedList, InsertViaIterator) { 26.958 + int fivenums[] = {0, 1, 2, 3, 4, 5}; 26.959 + CxList *list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 26.960 + cxListAddArray(list, fivenums, 5); 26.961 + verifyInsertViaIterator(list); 26.962 +} 26.963 + 26.964 +TEST_F(PointerLinkedList, InsertViaIterator) { 26.965 + int fivenums[] = {0, 1, 2, 3, 4, 5}; 26.966 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 26.967 + cxListStorePointers(list); 26.968 + // note: cannot use cxListAddArray() because we don't have a list of pointers 26.969 + cx_for_n(i, 5) cxListAdd(list, &fivenums[i]); 26.970 + verifyInsertViaIterator(list); 26.971 +} 26.972 + 26.973 +TEST_F(ArrayList, InsertViaIterator) { 26.974 + int fivenums[] = {0, 1, 2, 3, 4, 5}; 26.975 + CxList *list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 4)); 26.976 + cxListAddArray(list, fivenums, 5); 26.977 + verifyInsertViaIterator(list); 26.978 +} 26.979 + 26.980 +TEST_F(LinkedList, cxListReverse) { 26.981 + verifyReverse(linkedListFromTestData()); 26.982 +} 26.983 + 26.984 +TEST_F(PointerLinkedList, cxListReverse) { 26.985 + verifyReverse(pointerLinkedListFromTestData()); 26.986 +} 26.987 + 26.988 +TEST_F(ArrayList, cxListReverse) { 26.989 + verifyReverse(arrayListFromTestData()); 26.990 +} 26.991 + 26.992 +TEST_F(LinkedList, cxListCompare) { 26.993 + auto left = linkedListFromTestData(); 26.994 + auto right = linkedListFromTestData(); 26.995 + verifyCompare(left, right); 26.996 +} 26.997 + 26.998 +TEST_F(LinkedList, cxListCompareWithPtrList) { 26.999 + auto left = linkedListFromTestData(); 26.1000 + auto right = pointerLinkedListFromTestData(); 26.1001 + verifyCompare(left, right); 26.1002 +} 26.1003 + 26.1004 +TEST_F(LinkedList, cxListCompareWithArrayList) { 26.1005 + auto left = linkedListFromTestData(); 26.1006 + auto right = arrayListFromTestData(); 26.1007 + verifyCompare(left, right); 26.1008 +} 26.1009 + 26.1010 +TEST_F(PointerLinkedList, cxListCompare) { 26.1011 + auto left = pointerLinkedListFromTestData(); 26.1012 + auto right = pointerLinkedListFromTestData(); 26.1013 + verifyCompare(left, right); 26.1014 +} 26.1015 + 26.1016 +TEST_F(PointerLinkedList, cxListCompareWithNormalList) { 26.1017 + auto left = pointerLinkedListFromTestData(); 26.1018 + auto right = linkedListFromTestData(); 26.1019 + verifyCompare(left, right); 26.1020 +} 26.1021 + 26.1022 +TEST_F(PointerLinkedList, cxListCompareWithArrayList) { 26.1023 + auto left = pointerLinkedListFromTestData(); 26.1024 + auto right = arrayListFromTestData(); 26.1025 + verifyCompare(left, right); 26.1026 +} 26.1027 + 26.1028 +TEST_F(ArrayList, cxListCompare) { 26.1029 + auto left = arrayListFromTestData(); 26.1030 + auto right = arrayListFromTestData(); 26.1031 + verifyCompare(left, right); 26.1032 +} 26.1033 + 26.1034 +TEST_F(ArrayList, cxListCompareWithPtrList) { 26.1035 + auto left = arrayListFromTestData(); 26.1036 + auto right = pointerLinkedListFromTestData(); 26.1037 + verifyCompare(left, right); 26.1038 +} 26.1039 + 26.1040 +TEST_F(ArrayList, cxListCompareWithNormalList) { 26.1041 + auto left = arrayListFromTestData(); 26.1042 + auto right = linkedListFromTestData(); 26.1043 + verifyCompare(left, right); 26.1044 +} 26.1045 + 26.1046 +TEST_F(PointerLinkedList, NoDestructor) { 26.1047 + void *item = cxMalloc(&testingAllocator, sizeof(int)); 26.1048 + auto list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int *)); 26.1049 + cxListStorePointers(list); 26.1050 + cxListAdd(list, item); 26.1051 + ASSERT_FALSE(testingAllocator.verify()); 26.1052 + cxListDestroy(list); 26.1053 + EXPECT_FALSE(testingAllocator.verify()); 26.1054 + cxFree(&testingAllocator, item); 26.1055 + EXPECT_TRUE(testingAllocator.verify()); 26.1056 +} 26.1057 + 26.1058 +TEST_F(PointerLinkedList, SimpleDestructor) { 26.1059 + int item = 0; 26.1060 + auto list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int *)); 26.1061 + cxListStorePointers(list); 26.1062 + list->content_destructor_type = CX_DESTRUCTOR_SIMPLE; 26.1063 + list->simple_destructor = [](void *elem) { *(int *) elem = 42; }; 26.1064 + cxListAdd(list, &item); 26.1065 + cxListDestroy(list); 26.1066 + EXPECT_EQ(item, 42); 26.1067 +} 26.1068 + 26.1069 +TEST_F(PointerLinkedList, AdvancedDestructor) { 26.1070 + void *item = cxMalloc(&testingAllocator, sizeof(int)); 26.1071 + auto list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int *)); 26.1072 + cxListStorePointers(list); 26.1073 + list->content_destructor_type = CX_DESTRUCTOR_ADVANCED; 26.1074 + list->advanced_destructor.data = &testingAllocator; 26.1075 + list->advanced_destructor.func = (cx_destructor_func2) cxFree; 26.1076 + cxListAdd(list, item); 26.1077 + ASSERT_FALSE(testingAllocator.verify()); 26.1078 + cxListDestroy(list); 26.1079 + EXPECT_TRUE(testingAllocator.verify()); 26.1080 +}
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/tests/test_map.cpp Tue Feb 07 21:55:37 2023 +0100 27.3 @@ -0,0 +1,272 @@ 27.4 +/* 27.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 27.6 + * 27.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 27.8 + * 27.9 + * Redistribution and use in source and binary forms, with or without 27.10 + * modification, are permitted provided that the following conditions are met: 27.11 + * 27.12 + * 1. Redistributions of source code must retain the above copyright 27.13 + * notice, this list of conditions and the following disclaimer. 27.14 + * 27.15 + * 2. Redistributions in binary form must reproduce the above copyright 27.16 + * notice, this list of conditions and the following disclaimer in the 27.17 + * documentation and/or other materials provided with the distribution. 27.18 + * 27.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 27.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 27.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27.29 + * POSSIBILITY OF SUCH DAMAGE. 27.30 + */ 27.31 + 27.32 +#include "cx/hash_map.h" 27.33 +#include "cx/utils.h" 27.34 +#include "util_allocator.h" 27.35 + 27.36 +#include <gtest/gtest.h> 27.37 +#include <unordered_map> 27.38 +#include <unordered_set> 27.39 + 27.40 +struct map_operation { 27.41 + enum { 27.42 + put, rm 27.43 + } op; 27.44 + char const *key; 27.45 + char const *value; 27.46 +}; 27.47 + 27.48 +auto generate_map_operations() -> std::vector<map_operation> { 27.49 + return { 27.50 + {map_operation::put, "key 1", "test"}, 27.51 + {map_operation::put, "key 2", "blub"}, 27.52 + {map_operation::put, "key 3", "hallo"}, 27.53 + {map_operation::put, "key 2", "foobar"}, 27.54 + {map_operation::put, "key 4", "value 4"}, 27.55 + {map_operation::put, "key 5", "value 5"}, 27.56 + {map_operation::put, "key 6", "value 6"}, 27.57 + {map_operation::rm, "key 4", nullptr}, 27.58 + {map_operation::put, "key 7", "value 7"}, 27.59 + {map_operation::put, "key 8", "value 8"}, 27.60 + {map_operation::rm, "does not exist", nullptr}, 27.61 + {map_operation::put, "key 9", "value 9"}, 27.62 + {map_operation::put, "key 6", "other value"}, 27.63 + {map_operation::put, "key 7", "something else"}, 27.64 + {map_operation::rm, "key 8", nullptr}, 27.65 + {map_operation::rm, "key 2", nullptr}, 27.66 + {map_operation::put, "key 8", "new value"}, 27.67 + }; 27.68 +} 27.69 + 27.70 +static void verify_map_contents( 27.71 + CxMap *map, 27.72 + std::unordered_map<std::string, std::string> const &refmap 27.73 +) { 27.74 + // verify key iterator 27.75 + { 27.76 + auto keyiter = cxMapIteratorKeys(map); 27.77 + std::unordered_set<std::string> keys; 27.78 + cx_foreach(CxHashKey*, elem, keyiter) { 27.79 + keys.insert(std::string(elem->data.cstr, elem->len)); 27.80 + } 27.81 + EXPECT_EQ(keyiter.index, map->size); 27.82 + ASSERT_EQ(keys.size(), map->size); 27.83 + for (auto &&k: keys) { 27.84 + EXPECT_NE(refmap.find(k), refmap.end()); 27.85 + } 27.86 + } 27.87 + 27.88 + // verify value iterator 27.89 + { 27.90 + auto valiter = cxMapIteratorValues(map); 27.91 + std::unordered_set<std::string> values; // we use that the values in our test data are unique strings 27.92 + cx_foreach(char const*, elem, valiter) { 27.93 + values.insert(std::string(elem)); 27.94 + } 27.95 + EXPECT_EQ(valiter.index, map->size); 27.96 + ASSERT_EQ(values.size(), map->size); 27.97 + for (auto &&v: values) { 27.98 + EXPECT_NE(std::find_if(refmap.begin(), refmap.end(), 27.99 + [v](auto const &e) { return e.second == v; }), refmap.end()); 27.100 + } 27.101 + } 27.102 + 27.103 + // verify pair iterator 27.104 + { 27.105 + auto pairiter = cxMapIterator(map); 27.106 + std::unordered_map<std::string, std::string> pairs; 27.107 + cx_foreach(CxMapEntry*, entry, pairiter) { 27.108 + pairs[std::string(entry->key->data.cstr, entry->key->len)] = std::string((char *) entry->value); 27.109 + } 27.110 + EXPECT_EQ(pairiter.index, map->size); 27.111 + ASSERT_EQ(pairs.size(), refmap.size()); 27.112 + for (auto &&p: pairs) { 27.113 + ASSERT_EQ(p.second, refmap.at(p.first)); 27.114 + } 27.115 + } 27.116 +} 27.117 + 27.118 +TEST(CxHashMap, Create) { 27.119 + CxTestingAllocator allocator; 27.120 + auto map = cxHashMapCreate(&allocator, 0); 27.121 + auto hmap = reinterpret_cast<struct cx_hash_map_s *>(map); 27.122 + EXPECT_GT(hmap->bucket_count, 0); 27.123 + cx_for_n(i, hmap->bucket_count) { 27.124 + EXPECT_EQ(hmap->buckets[i], nullptr); 27.125 + } 27.126 + EXPECT_EQ(map->size, 0); 27.127 + EXPECT_EQ(map->allocator, &allocator); 27.128 + 27.129 + cxMapDestroy(map); 27.130 + EXPECT_TRUE(allocator.verify()); 27.131 +} 27.132 + 27.133 +TEST(CxHashMap, BasicOperations) { 27.134 + // create the map 27.135 + CxTestingAllocator allocator; 27.136 + auto map = cxHashMapCreate(&allocator, 8); 27.137 + 27.138 + // create a reference map 27.139 + std::unordered_map<std::string, std::string> refmap; 27.140 + 27.141 + // generate operations 27.142 + auto ops = generate_map_operations(); 27.143 + 27.144 + // verify iterators for empty map 27.145 + verify_map_contents(map, refmap); 27.146 + 27.147 + // execute operations and verify results 27.148 + for (auto &&op: ops) { 27.149 + CxHashKey key = cx_hash_key_str(op.key); 27.150 + key.hash = 0; // force the hash map to compute the hash 27.151 + if (op.op == map_operation::put) { 27.152 + // execute a put operation and verify that the exact value can be read back 27.153 + refmap[std::string(op.key)] = std::string(op.value); 27.154 + int result = cxMapPut(map, key, (void *) op.value); 27.155 + EXPECT_EQ(result, 0); 27.156 + auto added = cxMapGet(map, key); 27.157 + EXPECT_EQ(memcmp(op.value, added, strlen(op.value)), 0); 27.158 + } else { 27.159 + // execute a remove and verify that the removed element was returned (or nullptr) 27.160 + auto found = refmap.find(op.key); 27.161 + auto removed = cxMapRemove(map, key); 27.162 + if (found == refmap.end()) { 27.163 + EXPECT_EQ(removed, nullptr); 27.164 + } else { 27.165 + EXPECT_EQ(std::string((char *) removed), found->second); 27.166 + refmap.erase(found); 27.167 + } 27.168 + } 27.169 + // compare the current map state with the reference map 27.170 + verify_map_contents(map, refmap); 27.171 + } 27.172 + 27.173 + // destroy the map and verify the memory (de)allocations 27.174 + cxMapDestroy(map); 27.175 + EXPECT_TRUE(allocator.verify()); 27.176 +} 27.177 + 27.178 +TEST(CxHashMap, RemoveViaIterator) { 27.179 + CxTestingAllocator allocator; 27.180 + auto map = cxHashMapCreate(&allocator, 4); 27.181 + 27.182 + cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); 27.183 + cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); 27.184 + cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); 27.185 + cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); 27.186 + cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5"); 27.187 + cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6"); 27.188 + 27.189 + auto iter = cxMapMutIterator(map); 27.190 + cx_foreach(CxMapEntry*, entry, iter) { 27.191 + if (entry->key->data.cstr[4] % 2 == 1) cxIteratorFlagRemoval(iter); 27.192 + } 27.193 + EXPECT_EQ(map->size, 3); 27.194 + EXPECT_EQ(iter.index, map->size); 27.195 + 27.196 + EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 1")), nullptr); 27.197 + EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 2")), nullptr); 27.198 + EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 3")), nullptr); 27.199 + EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 4")), nullptr); 27.200 + EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 5")), nullptr); 27.201 + EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 6")), nullptr); 27.202 + 27.203 + cxMapDestroy(map); 27.204 + EXPECT_TRUE(allocator.verify()); 27.205 +} 27.206 + 27.207 +TEST(CxHashMap, RehashNotRequired) { 27.208 + CxTestingAllocator allocator; 27.209 + auto map = cxHashMapCreate(&allocator, 8); 27.210 + 27.211 + cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); 27.212 + cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); 27.213 + cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); 27.214 + cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); 27.215 + cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5"); 27.216 + cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6"); 27.217 + 27.218 + // 6/8 does not exceed 0.75, therefore the function should not rehash 27.219 + int result = cxMapRehash(map); 27.220 + EXPECT_EQ(result, 0); 27.221 + EXPECT_EQ(reinterpret_cast<struct cx_hash_map_s *>(map)->bucket_count, 8); 27.222 + 27.223 + cxMapDestroy(map); 27.224 + EXPECT_TRUE(allocator.verify()); 27.225 +} 27.226 + 27.227 +TEST(CxHashMap, Rehash) { 27.228 + CxTestingAllocator allocator; 27.229 + auto map = cxHashMapCreate(&allocator, 8); 27.230 + 27.231 + cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); 27.232 + cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); 27.233 + cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); 27.234 + cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); 27.235 + cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5"); 27.236 + cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6"); 27.237 + cxMapPut(map, cx_hash_key_str("key 7"), (void *) "val 7"); 27.238 + 27.239 + int result = cxMapRehash(map); 27.240 + EXPECT_EQ(result, 0); 27.241 + EXPECT_EQ(reinterpret_cast<struct cx_hash_map_s *>(map)->bucket_count, 17); 27.242 + EXPECT_EQ(map->size, 7); 27.243 + 27.244 + EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 1")), "val 1"), 0); 27.245 + EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 2")), "val 2"), 0); 27.246 + EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 3")), "val 3"), 0); 27.247 + EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 4")), "val 4"), 0); 27.248 + EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 5")), "val 5"), 0); 27.249 + EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 6")), "val 6"), 0); 27.250 + EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 7")), "val 7"), 0); 27.251 + 27.252 + cxMapDestroy(map); 27.253 + EXPECT_TRUE(allocator.verify()); 27.254 +} 27.255 + 27.256 +TEST(CxHashMap, Clear) { 27.257 + CxTestingAllocator allocator; 27.258 + auto map = cxHashMapCreate(&allocator, 0); 27.259 + 27.260 + cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); 27.261 + cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); 27.262 + cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); 27.263 + 27.264 + EXPECT_EQ(map->size, 3); 27.265 + 27.266 + cxMapClear(map); 27.267 + 27.268 + EXPECT_EQ(map->size, 0); 27.269 + EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 1")), nullptr); 27.270 + EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 2")), nullptr); 27.271 + EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 3")), nullptr); 27.272 + 27.273 + cxMapDestroy(map); 27.274 + EXPECT_TRUE(allocator.verify()); 27.275 +} 27.276 \ No newline at end of file
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/tests/test_printf.cpp Tue Feb 07 21:55:37 2023 +0100 28.3 @@ -0,0 +1,248 @@ 28.4 +/* 28.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 28.6 + * 28.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 28.8 + * 28.9 + * Redistribution and use in source and binary forms, with or without 28.10 + * modification, are permitted provided that the following conditions are met: 28.11 + * 28.12 + * 1. Redistributions of source code must retain the above copyright 28.13 + * notice, this list of conditions and the following disclaimer. 28.14 + * 28.15 + * 2. Redistributions in binary form must reproduce the above copyright 28.16 + * notice, this list of conditions and the following disclaimer in the 28.17 + * documentation and/or other materials provided with the distribution. 28.18 + * 28.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 28.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 28.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28.29 + * POSSIBILITY OF SUCH DAMAGE. 28.30 + */ 28.31 + 28.32 +#include "cx/printf.h" 28.33 +#include "cx/buffer.h" 28.34 + 28.35 +#include <gtest/gtest.h> 28.36 +#include "util_allocator.h" 28.37 + 28.38 +class PrintfFixture : public ::testing::Test { 28.39 +protected: 28.40 + std::string buf; 28.41 + CxTestingAllocator alloc; 28.42 + 28.43 + void TearDown() override { 28.44 + buf.clear(); 28.45 + ASSERT_TRUE(alloc.verify()); 28.46 + } 28.47 + 28.48 + static size_t write_func( 28.49 + void const *src, 28.50 + size_t esize, 28.51 + size_t ecount, 28.52 + void *target 28.53 + ) { 28.54 + auto str = reinterpret_cast<char const *>(src); 28.55 + auto buf = reinterpret_cast<std::string *>(target); 28.56 + EXPECT_EQ(esize, 1); 28.57 + EXPECT_EQ(strlen(str), ecount); 28.58 + *buf = str; 28.59 + return ecount; 28.60 + } 28.61 +}; 28.62 + 28.63 + 28.64 +TEST_F(PrintfFixture, BPrintf) { 28.65 + CxBuffer buf; 28.66 + cxBufferInit(&buf, nullptr, 64, &alloc, 0); 28.67 + 28.68 + auto r = cx_bprintf(&buf, "This %s aged %u years in a %2XSK.", "Test", 10, 0xca); 28.69 + EXPECT_EQ(r, 34); 28.70 + EXPECT_EQ(buf.size, 34); 28.71 + buf.space[r] = '\0'; 28.72 + EXPECT_STREQ(buf.space, "This Test aged 10 years in a CASK."); 28.73 + 28.74 + cxBufferDestroy(&buf); 28.75 +} 28.76 + 28.77 +TEST_F(PrintfFixture, FPrintf) { 28.78 + auto h = "Hello"; 28.79 + size_t r; 28.80 + 28.81 + r = cx_fprintf(&buf, PrintfFixture::write_func, "teststring"); 28.82 + EXPECT_EQ(r, 10); 28.83 + EXPECT_EQ(buf, "teststring"); 28.84 + 28.85 + r = cx_fprintf(&buf, PrintfFixture::write_func, "[%10s]", h); 28.86 + EXPECT_EQ(r, 12); 28.87 + EXPECT_EQ(buf, "[ Hello]"); 28.88 + 28.89 + r = cx_fprintf(&buf, PrintfFixture::write_func, "[%-10s]", h); 28.90 + EXPECT_EQ(r, 12); 28.91 + EXPECT_EQ(buf, "[Hello ]"); 28.92 + 28.93 + r = cx_fprintf(&buf, PrintfFixture::write_func, "[%*s]", 10, h); 28.94 + EXPECT_EQ(r, 12); 28.95 + EXPECT_EQ(buf, "[ Hello]"); 28.96 + 28.97 + r = cx_fprintf(&buf, PrintfFixture::write_func, "[%-10.*s]", 4, h); 28.98 + EXPECT_EQ(r, 12); 28.99 + EXPECT_EQ(buf, "[Hell ]"); 28.100 + 28.101 + r = cx_fprintf(&buf, PrintfFixture::write_func, "[%-*.*s]", 10, 4, h); 28.102 + EXPECT_EQ(r, 12); 28.103 + EXPECT_EQ(buf, "[Hell ]"); 28.104 + 28.105 + r = cx_fprintf(&buf, PrintfFixture::write_func, "%c", 'A'); 28.106 + EXPECT_EQ(r, 1); 28.107 + EXPECT_EQ(buf, "A"); 28.108 + 28.109 + r = cx_fprintf(&buf, PrintfFixture::write_func, "%i %d %.6i %i %.0i %+i %i", 1, 2, 3, 0, 0, 4, -4); 28.110 + EXPECT_EQ(r, 19); 28.111 + EXPECT_EQ(buf, "1 2 000003 0 +4 -4"); 28.112 + 28.113 + r = cx_fprintf(&buf, PrintfFixture::write_func, "%x %x %X %#x", 5, 10, 10, 6); 28.114 + EXPECT_EQ(r, 9); 28.115 + EXPECT_EQ(buf, "5 a A 0x6"); 28.116 + 28.117 + r = cx_fprintf(&buf, PrintfFixture::write_func, "%o %#o %#o", 10, 10, 4); 28.118 + EXPECT_EQ(r, 9); 28.119 + EXPECT_EQ(buf, "12 012 04"); 28.120 + 28.121 + r = cx_fprintf(&buf, PrintfFixture::write_func, "%05.2f %.2f %5.2f", 1.5, 1.5, 1.5); 28.122 + EXPECT_EQ(r, 16); 28.123 + EXPECT_EQ(buf, "01.50 1.50 1.50"); 28.124 + 28.125 + r = cx_fprintf(&buf, PrintfFixture::write_func, "'%*c'", 5, 'x'); 28.126 + EXPECT_EQ(r, 7); 28.127 + EXPECT_EQ(buf, "' x'"); 28.128 + 28.129 + r = cx_fprintf(&buf, PrintfFixture::write_func, "'%*c'", -5, 'x'); 28.130 + EXPECT_EQ(r, 7); 28.131 + EXPECT_EQ(buf, "'x '"); 28.132 +} 28.133 + 28.134 +TEST_F(PrintfFixture, BPrintfLargeString) { 28.135 + CxBuffer buf; 28.136 + cxBufferInit(&buf, nullptr, 64, &alloc, CX_BUFFER_AUTO_EXTEND); 28.137 + 28.138 + auto aaa = std::string(512, 'a'); 28.139 + auto bbb = std::string(512, 'b'); 28.140 + 28.141 + auto r = cx_bprintf(&buf, "After %s comes %s.", aaa.data(), bbb.data()); 28.142 + EXPECT_EQ(r, 1038); 28.143 + EXPECT_EQ(buf.size, 1038); 28.144 + cxBufferPut(&buf, 0); 28.145 + EXPECT_EQ(buf.space, std::string("After ") + aaa + " comes " + bbb + "."); 28.146 + 28.147 + cxBufferDestroy(&buf); 28.148 +} 28.149 + 28.150 +TEST_F(PrintfFixture, BPrintfNoCap) { 28.151 + CxBuffer buf; 28.152 + char space[20]; 28.153 + memset(space, 'a', 20); 28.154 + cxBufferInit(&buf, space, 16, &alloc, 0); 28.155 + 28.156 + auto r = cx_bprintf(&buf, "Hello %s with more than %d chars.", "string", 16); 28.157 + EXPECT_EQ(r, 16); 28.158 + EXPECT_EQ(buf.size, 16); 28.159 + EXPECT_EQ(0, memcmp(space, "Hello string witaaaa", 20)); 28.160 + 28.161 + cxBufferDestroy(&buf); 28.162 +} 28.163 + 28.164 +TEST_F(PrintfFixture, SPrintf) { 28.165 + auto h = "Hello"; 28.166 + 28.167 + std::vector<char *> fl; 28.168 + cxmutstr r; 28.169 + 28.170 + r = cx_asprintf_a(&alloc, "teststring"); 28.171 + EXPECT_EQ(r.length, 10); 28.172 + EXPECT_STREQ(r.ptr, "teststring"); 28.173 + fl.push_back(r.ptr); 28.174 + 28.175 + r = cx_asprintf_a(&alloc, "[%10s]", h); 28.176 + EXPECT_EQ(r.length, 12); 28.177 + EXPECT_STREQ(r.ptr, "[ Hello]"); 28.178 + fl.push_back(r.ptr); 28.179 + 28.180 + r = cx_asprintf_a(&alloc, "[%-10s]", h); 28.181 + EXPECT_EQ(r.length, 12); 28.182 + EXPECT_STREQ(r.ptr, "[Hello ]"); 28.183 + fl.push_back(r.ptr); 28.184 + 28.185 + r = cx_asprintf_a(&alloc, "[%*s]", 10, h); 28.186 + EXPECT_EQ(r.length, 12); 28.187 + EXPECT_STREQ(r.ptr, "[ Hello]"); 28.188 + fl.push_back(r.ptr); 28.189 + 28.190 + r = cx_asprintf_a(&alloc, "[%-10.*s]", 4, h); 28.191 + EXPECT_EQ(r.length, 12); 28.192 + EXPECT_STREQ(r.ptr, "[Hell ]"); 28.193 + fl.push_back(r.ptr); 28.194 + 28.195 + r = cx_asprintf_a(&alloc, "[%-*.*s]", 10, 4, h); 28.196 + EXPECT_EQ(r.length, 12); 28.197 + EXPECT_STREQ(r.ptr, "[Hell ]"); 28.198 + fl.push_back(r.ptr); 28.199 + 28.200 + r = cx_asprintf_a(&alloc, "%c", 'A'); 28.201 + EXPECT_EQ(r.length, 1); 28.202 + EXPECT_STREQ(r.ptr, "A"); 28.203 + fl.push_back(r.ptr); 28.204 + 28.205 + r = cx_asprintf_a(&alloc, "%i %d %.6i %i %.0i %+i %i", 1, 2, 3, 0, 0, 4, -4); 28.206 + EXPECT_EQ(r.length, 19); 28.207 + EXPECT_STREQ(r.ptr, "1 2 000003 0 +4 -4"); 28.208 + fl.push_back(r.ptr); 28.209 + 28.210 + r = cx_asprintf_a(&alloc, "%x %x %X %#x", 5, 10, 10, 6); 28.211 + EXPECT_EQ(r.length, 9); 28.212 + EXPECT_STREQ(r.ptr, "5 a A 0x6"); 28.213 + fl.push_back(r.ptr); 28.214 + 28.215 + r = cx_asprintf_a(&alloc, "%o %#o %#o", 10, 10, 4); 28.216 + EXPECT_EQ(r.length, 9); 28.217 + EXPECT_STREQ(r.ptr, "12 012 04"); 28.218 + fl.push_back(r.ptr); 28.219 + 28.220 + r = cx_asprintf_a(&alloc, "%05.2f %.2f %5.2f", 1.5, 1.5, 1.5); 28.221 + EXPECT_EQ(r.length, 16); 28.222 + EXPECT_STREQ(r.ptr, "01.50 1.50 1.50"); 28.223 + fl.push_back(r.ptr); 28.224 + 28.225 + r = cx_asprintf_a(&alloc, "'%*c'", 5, 'x'); 28.226 + EXPECT_EQ(r.length, 7); 28.227 + EXPECT_STREQ(r.ptr, "' x'"); 28.228 + fl.push_back(r.ptr); 28.229 + 28.230 + r = cx_asprintf_a(&alloc, "'%*c'", -5, 'x'); 28.231 + EXPECT_EQ(r.length, 7); 28.232 + EXPECT_STREQ(r.ptr, "'x '"); 28.233 + fl.push_back(r.ptr); 28.234 + 28.235 + for (auto c: fl) { 28.236 + auto s = cx_mutstrn(c, 0); 28.237 + cx_strfree_a(&alloc, &s); 28.238 + } 28.239 +} 28.240 + 28.241 +TEST_F(PrintfFixture, SPrintfLargeString) { 28.242 + auto aaa = std::string(512, 'a'); 28.243 + auto bbb = std::string(512, 'b'); 28.244 + 28.245 + auto r = cx_asprintf_a(&alloc, "After %s comes %s.", aaa.data(), bbb.data()); 28.246 + EXPECT_EQ(r.length, 1038); 28.247 + EXPECT_EQ(r.ptr, std::string("After ") + aaa + " comes " + bbb + "."); 28.248 + EXPECT_EQ(r.ptr[1038], '\0'); 28.249 + 28.250 + cx_strfree_a(&alloc, &r); 28.251 +} 28.252 \ No newline at end of file
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 29.2 +++ b/tests/test_string.cpp Tue Feb 07 21:55:37 2023 +0100 29.3 @@ -0,0 +1,865 @@ 29.4 +/* 29.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 29.6 + * 29.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 29.8 + * 29.9 + * Redistribution and use in source and binary forms, with or without 29.10 + * modification, are permitted provided that the following conditions are met: 29.11 + * 29.12 + * 1. Redistributions of source code must retain the above copyright 29.13 + * notice, this list of conditions and the following disclaimer. 29.14 + * 29.15 + * 2. Redistributions in binary form must reproduce the above copyright 29.16 + * notice, this list of conditions and the following disclaimer in the 29.17 + * documentation and/or other materials provided with the distribution. 29.18 + * 29.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 29.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 29.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29.29 + * POSSIBILITY OF SUCH DAMAGE. 29.30 + */ 29.31 + 29.32 +#include "cx/string.h" 29.33 +#include "util_allocator.h" 29.34 + 29.35 +#include <gtest/gtest.h> 29.36 + 29.37 +#define EXPECT_ZERO_TERMINATED(str) EXPECT_EQ((str).ptr[(str).length], '\0') 29.38 + 29.39 +TEST(String, construct) { 29.40 + cxstring s1 = cx_str("1234"); 29.41 + cxstring s2 = cx_strn("abcd", 2); 29.42 + cxmutstr s3 = cx_mutstr((char *) "1234"); 29.43 + cxmutstr s4 = cx_mutstrn((char *) "abcd", 2); 29.44 + 29.45 + EXPECT_EQ(s1.length, 4); 29.46 + EXPECT_EQ(s2.length, 2); 29.47 + EXPECT_EQ(s3.length, 4); 29.48 + EXPECT_EQ(s4.length, 2); 29.49 +} 29.50 + 29.51 +TEST(String, strfree) { 29.52 + CxTestingAllocator alloc; 29.53 + auto test = (char *) cxMalloc(&alloc, 16); 29.54 + cxmutstr str = cx_mutstrn(test, 16); 29.55 + ASSERT_EQ(str.ptr, test); 29.56 + EXPECT_EQ(str.length, 16); 29.57 + cx_strfree_a(&alloc, &str); 29.58 + EXPECT_EQ(str.ptr, nullptr); 29.59 + EXPECT_EQ(str.length, 0); 29.60 + EXPECT_TRUE(alloc.verify()); 29.61 +} 29.62 + 29.63 +TEST(String, strdup) { 29.64 + cxstring str = CX_STR("test"); 29.65 + cxmutstr dup = cx_strdup(str); 29.66 + ASSERT_EQ(dup.length, str.length); 29.67 + EXPECT_STREQ(dup.ptr, str.ptr); 29.68 + EXPECT_ZERO_TERMINATED(dup); 29.69 + cx_strfree(&dup); 29.70 + 29.71 + str.length = 2; 29.72 + dup = cx_strdup(str); 29.73 + ASSERT_EQ(dup.length, str.length); 29.74 + EXPECT_STREQ(dup.ptr, "te"); 29.75 + EXPECT_ZERO_TERMINATED(dup); 29.76 + cx_strfree(&dup); 29.77 +} 29.78 + 29.79 +TEST(String, strlen) { 29.80 + cxstring s1 = CX_STR("1234"); 29.81 + cxstring s2 = CX_STR(".:.:."); 29.82 + cxstring s3 = CX_STR("X"); 29.83 + 29.84 + size_t len0 = cx_strlen(0); 29.85 + size_t len1 = cx_strlen(1, s1); 29.86 + size_t len2 = cx_strlen(2, s1, s2); 29.87 + size_t len3 = cx_strlen(3, s1, s2, s3); 29.88 + 29.89 + EXPECT_EQ(len0, 0); 29.90 + EXPECT_EQ(len1, 4); 29.91 + EXPECT_EQ(len2, 9); 29.92 + EXPECT_EQ(len3, 10); 29.93 +} 29.94 + 29.95 +TEST(String, strsubs) { 29.96 + cxstring str = CX_STR("A test string"); 29.97 + 29.98 + cxstring sub = cx_strsubs(str, 0); 29.99 + EXPECT_EQ(cx_strcmp(sub, str), 0); 29.100 + 29.101 + sub = cx_strsubs(str, 2); 29.102 + EXPECT_EQ(cx_strcmp(sub, cx_str("test string")), 0); 29.103 + 29.104 + sub = cx_strsubs(str, 7); 29.105 + EXPECT_EQ(cx_strcmp(sub, cx_str("string")), 0); 29.106 + 29.107 + sub = cx_strsubs(str, 15); 29.108 + EXPECT_EQ(cx_strcmp(sub, cx_str("")), 0); 29.109 + 29.110 + sub = cx_strsubsl(str, 2, 4); 29.111 + EXPECT_EQ(cx_strcmp(sub, cx_str("test")), 0); 29.112 + 29.113 + sub = cx_strsubsl(str, 7, 3); 29.114 + EXPECT_EQ(cx_strcmp(sub, cx_str("str")), 0); 29.115 + 29.116 + sub = cx_strsubsl(str, 7, 20); 29.117 + EXPECT_EQ(cx_strcmp(sub, cx_str("string")), 0); 29.118 + 29.119 + // just for coverage, call the _m variant 29.120 + auto m = cx_strsubs_m(cx_mutstrn(nullptr, 0), 0); 29.121 + EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0); 29.122 +} 29.123 + 29.124 +TEST(String, strchr) { 29.125 + cxstring str = CX_STR("I will find you - and I will kill you"); 29.126 + 29.127 + cxstring notfound = cx_strchr(str, 'x'); 29.128 + EXPECT_EQ(notfound.length, 0); 29.129 + 29.130 + cxstring result = cx_strchr(str, 'w'); 29.131 + EXPECT_EQ(result.length, 35); 29.132 + EXPECT_STREQ(result.ptr, "will find you - and I will kill you"); 29.133 + 29.134 + // just for coverage, call the _m variant 29.135 + auto m = cx_strchr_m(cx_mutstrn(nullptr, 0), 'a'); 29.136 + EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0); 29.137 +} 29.138 + 29.139 +TEST(String, strrchr) { 29.140 + cxstring str = CX_STR("I will find you - and I will kill you"); 29.141 + 29.142 + cxstring notfound = cx_strrchr(str, 'x'); 29.143 + EXPECT_EQ(notfound.length, 0); 29.144 + 29.145 + cxstring result = cx_strrchr(str, 'w'); 29.146 + EXPECT_EQ(result.length, 13); 29.147 + EXPECT_STREQ(result.ptr, "will kill you"); 29.148 + 29.149 + // just for coverage, call the _m variant 29.150 + auto m = cx_strrchr_m(cx_mutstrn(nullptr, 0), 'a'); 29.151 + EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0); 29.152 +} 29.153 + 29.154 +TEST(String, strstr) { 29.155 + cxstring str = CX_STR("find the match in this string"); 29.156 + cxstring longstr = CX_STR( 29.157 + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl" 29.158 + "mnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx" 29.159 + "yzabcdeababababnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij" 29.160 + "klmnopqrstuvwxyzaababababababababrstuvwxyzabcdefghijklmnopqrstuv" 29.161 + "abababababababababababababababababababababababababababababababab" 29.162 + "abababababababababababababababababababababababababababababababab" 29.163 + "abababababababababababababababababababababababababababababababab" 29.164 + "abababababababababababababababababababababababababababababababab" 29.165 + "abababababababababababababababababababababababababababababababab" 29.166 + "abababababababababababababababababababababababababababababababab" 29.167 + "wxyz1234567890"); 29.168 + cxstring longstrpattern = CX_STR( 29.169 + "abababababababababababababababababababababababababababababababab" 29.170 + "abababababababababababababababababababababababababababababababab" 29.171 + "abababababababababababababababababababababababababababababababab" 29.172 + "abababababababababababababababababababababababababababababababab" 29.173 + "abababababababababababababababababababababababababababababababab" 29.174 + ); 29.175 + cxstring longstrresult = CX_STR( 29.176 + "abababababababababababababababababababababababababababababababab" 29.177 + "abababababababababababababababababababababababababababababababab" 29.178 + "abababababababababababababababababababababababababababababababab" 29.179 + "abababababababababababababababababababababababababababababababab" 29.180 + "abababababababababababababababababababababababababababababababab" 29.181 + "abababababababababababababababababababababababababababababababab" 29.182 + "wxyz1234567890" 29.183 + ); 29.184 + 29.185 + cxstring notfound = cx_strstr(str, cx_str("no match")); 29.186 + EXPECT_EQ(notfound.length, 0); 29.187 + 29.188 + cxstring result = cx_strstr(str, cx_str("match")); 29.189 + EXPECT_EQ(result.length, 20); 29.190 + EXPECT_STREQ(result.ptr, "match in this string"); 29.191 + 29.192 + result = cx_strstr(str, cx_str("")); 29.193 + EXPECT_EQ(result.length, str.length); 29.194 + EXPECT_STREQ(result.ptr, str.ptr); 29.195 + 29.196 + result = cx_strstr(longstr, longstrpattern); 29.197 + EXPECT_EQ(result.length, longstrresult.length); 29.198 + EXPECT_STREQ(result.ptr, longstrresult.ptr); 29.199 + 29.200 + // just for coverage, call the _m variant 29.201 + auto mstr = cx_strdup(longstr); 29.202 + auto m = cx_strstr_m(mstr, longstrpattern); 29.203 + EXPECT_EQ(m.length, longstrresult.length); 29.204 + EXPECT_STREQ(m.ptr, longstrresult.ptr); 29.205 + cx_strfree(&mstr); 29.206 +} 29.207 + 29.208 +TEST(String, strcmp) { 29.209 + cxstring str = CX_STR("compare this"); 29.210 + 29.211 + EXPECT_EQ(cx_strcmp(cx_str(""), cx_str("")), 0); 29.212 + EXPECT_GT(cx_strcmp(str, cx_str("")), 0); 29.213 + EXPECT_EQ(cx_strcmp(str, cx_str("compare this")), 0); 29.214 + EXPECT_NE(cx_strcmp(str, cx_str("Compare This")), 0); 29.215 + EXPECT_LT(cx_strcmp(str, cx_str("compare tool")), 0); 29.216 + EXPECT_GT(cx_strcmp(str, cx_str("compare shit")), 0); 29.217 + EXPECT_LT(cx_strcmp(str, cx_str("compare this not")), 0); 29.218 + EXPECT_GT(cx_strcmp(str, cx_str("compare")), 0); 29.219 +} 29.220 + 29.221 +TEST(String, strcasecmp) { 29.222 + cxstring str = CX_STR("compare this"); 29.223 + 29.224 + EXPECT_EQ(cx_strcasecmp(cx_str(""), cx_str("")), 0); 29.225 + EXPECT_GT(cx_strcasecmp(str, cx_str("")), 0); 29.226 + EXPECT_EQ(cx_strcasecmp(str, cx_str("compare this")), 0); 29.227 + EXPECT_EQ(cx_strcasecmp(str, cx_str("Compare This")), 0); 29.228 + EXPECT_LT(cx_strcasecmp(str, cx_str("compare tool")), 0); 29.229 + EXPECT_GT(cx_strcasecmp(str, cx_str("compare shit")), 0); 29.230 + EXPECT_LT(cx_strcasecmp(str, cx_str("compare this not")), 0); 29.231 + EXPECT_GT(cx_strcasecmp(str, cx_str("compare")), 0); 29.232 +} 29.233 + 29.234 +TEST(String, strcat) { 29.235 + cxstring s1 = CX_STR("12"); 29.236 + cxstring s2 = CX_STR("34"); 29.237 + cxstring s3 = CX_STR("56"); 29.238 + cxstring sn = {nullptr, 0}; 29.239 + 29.240 + CxTestingAllocator alloc; 29.241 + 29.242 + cxmutstr t1 = cx_strcat_a(&alloc, 2, s1, s2); 29.243 + EXPECT_EQ(cx_strcmp(cx_strcast(t1), cx_str("1234")), 0); 29.244 + EXPECT_ZERO_TERMINATED(t1); 29.245 + cx_strfree_a(&alloc, &t1); 29.246 + 29.247 + cxmutstr t2 = cx_strcat_a(&alloc, 3, s1, s2, s3); 29.248 + EXPECT_EQ(cx_strcmp(cx_strcast(t2), cx_str("123456")), 0); 29.249 + EXPECT_ZERO_TERMINATED(t2); 29.250 + cx_strfree_a(&alloc, &t2); 29.251 + 29.252 + cxmutstr t3 = cx_strcat_a(&alloc, 6, s1, sn, s2, sn, s3, sn); 29.253 + EXPECT_EQ(cx_strcmp(cx_strcast(t3), cx_str("123456")), 0); 29.254 + EXPECT_ZERO_TERMINATED(t3); 29.255 + cx_strfree_a(&alloc, &t3); 29.256 + 29.257 + cxmutstr t4 = cx_strcat_a(&alloc, 2, sn, sn); 29.258 + EXPECT_EQ(cx_strcmp(cx_strcast(t4), cx_str("")), 0); 29.259 + EXPECT_ZERO_TERMINATED(t4); 29.260 + cx_strfree_a(&alloc, &t4); 29.261 + 29.262 + EXPECT_TRUE(alloc.verify()); 29.263 + 29.264 + // use the macro 29.265 + cxmutstr t5 = cx_strcat(3, s3, s1, s2); 29.266 + EXPECT_EQ(cx_strcmp(cx_strcast(t5), cx_str("561234")), 0); 29.267 + EXPECT_ZERO_TERMINATED(t5); 29.268 + cx_strfree(&t5); 29.269 +} 29.270 + 29.271 +TEST(String, strsplit) { 29.272 + 29.273 + cxstring test = cx_str("this,is,a,csv,string"); 29.274 + size_t capa = 8; 29.275 + cxstring list[8]; 29.276 + size_t n; 29.277 + 29.278 + // special case: empty string 29.279 + n = cx_strsplit(test, cx_str(""), capa, list); 29.280 + ASSERT_EQ(n, 1); 29.281 + EXPECT_EQ(cx_strcmp(list[0], test), 0); 29.282 + 29.283 + // no delimiter occurrence 29.284 + n = cx_strsplit(test, cx_str("z"), capa, list); 29.285 + ASSERT_EQ(n, 1); 29.286 + EXPECT_EQ(cx_strcmp(list[0], test), 0); 29.287 + 29.288 + // partially matching delimiter 29.289 + n = cx_strsplit(test, cx_str("is,not"), capa, list); 29.290 + ASSERT_EQ(n, 1); 29.291 + EXPECT_EQ(cx_strcmp(list[0], test), 0); 29.292 + 29.293 + // matching single-char delimiter 29.294 + n = cx_strsplit(test, cx_str(","), capa, list); 29.295 + ASSERT_EQ(n, 5); 29.296 + EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0); 29.297 + EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0); 29.298 + EXPECT_EQ(cx_strcmp(list[2], cx_str("a")), 0); 29.299 + EXPECT_EQ(cx_strcmp(list[3], cx_str("csv")), 0); 29.300 + EXPECT_EQ(cx_strcmp(list[4], cx_str("string")), 0); 29.301 + 29.302 + // matching multi-char delimiter 29.303 + n = cx_strsplit(test, cx_str("is"), capa, list); 29.304 + ASSERT_EQ(n, 3); 29.305 + EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 29.306 + EXPECT_EQ(cx_strcmp(list[1], cx_str(",")), 0); 29.307 + EXPECT_EQ(cx_strcmp(list[2], cx_str(",a,csv,string")), 0); 29.308 + 29.309 + // bounded list using single-char delimiter 29.310 + n = cx_strsplit(test, cx_str(","), 3, list); 29.311 + ASSERT_EQ(n, 3); 29.312 + EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0); 29.313 + EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0); 29.314 + EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0); 29.315 + 29.316 + // bounded list using multi-char delimiter 29.317 + n = cx_strsplit(test, cx_str("is"), 2, list); 29.318 + ASSERT_EQ(n, 2); 29.319 + EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 29.320 + EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0); 29.321 + 29.322 + // start with delimiter 29.323 + n = cx_strsplit(test, cx_str("this"), capa, list); 29.324 + ASSERT_EQ(n, 2); 29.325 + EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0); 29.326 + EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0); 29.327 + 29.328 + // end with delimiter 29.329 + n = cx_strsplit(test, cx_str("string"), capa, list); 29.330 + ASSERT_EQ(n, 2); 29.331 + EXPECT_EQ(cx_strcmp(list[0], cx_str("this,is,a,csv,")), 0); 29.332 + EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 29.333 + 29.334 + 29.335 + // end with delimiter exceed bound 29.336 + n = cx_strsplit(cx_str("a,b,c,"), cx_str(","), 3, list); 29.337 + ASSERT_EQ(n, 3); 29.338 + EXPECT_EQ(cx_strcmp(list[0], cx_str("a")), 0); 29.339 + EXPECT_EQ(cx_strcmp(list[1], cx_str("b")), 0); 29.340 + EXPECT_EQ(cx_strcmp(list[2], cx_str("c,")), 0); 29.341 + 29.342 + // exact match 29.343 + n = cx_strsplit(test, cx_str("this,is,a,csv,string"), capa, list); 29.344 + ASSERT_EQ(n, 2); 29.345 + EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0); 29.346 + EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 29.347 + 29.348 + // string to be split is only substring 29.349 + n = cx_strsplit(test, cx_str("this,is,a,csv,string,with,extension"), capa, list); 29.350 + ASSERT_EQ(n, 1); 29.351 + EXPECT_EQ(cx_strcmp(list[0], test), 0); 29.352 + 29.353 + // subsequent encounter of delimiter (the string between is empty) 29.354 + n = cx_strsplit(test, cx_str("is,"), capa, list); 29.355 + ASSERT_EQ(n, 3); 29.356 + EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 29.357 + EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 29.358 + EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0); 29.359 + 29.360 + // call the _m variant just for coverage 29.361 + auto mtest = cx_strdup(test); 29.362 + cxmutstr mlist[4]; 29.363 + n = cx_strsplit_m(mtest, cx_str("is,"), 4, mlist); 29.364 + ASSERT_EQ(n, 3); 29.365 + EXPECT_EQ(cx_strcmp(cx_strcast(mlist[0]), cx_str("th")), 0); 29.366 + EXPECT_EQ(cx_strcmp(cx_strcast(mlist[1]), cx_str("")), 0); 29.367 + EXPECT_EQ(cx_strcmp(cx_strcast(mlist[2]), cx_str("a,csv,string")), 0); 29.368 + cx_strfree(&mtest); 29.369 +} 29.370 + 29.371 +TEST(String, strsplit_a) { 29.372 + CxTestingAllocator alloc; 29.373 + 29.374 + cxstring test = cx_str("this,is,a,csv,string"); 29.375 + size_t capa = 8; 29.376 + cxstring *list; 29.377 + size_t n; 29.378 + 29.379 + // special case: empty string 29.380 + n = cx_strsplit_a(&alloc, test, cx_str(""), capa, &list); 29.381 + ASSERT_EQ(n, 1); 29.382 + EXPECT_EQ(cx_strcmp(list[0], test), 0); 29.383 + cxFree(&alloc, list); 29.384 + 29.385 + // no delimiter occurrence 29.386 + n = cx_strsplit_a(&alloc, test, cx_str("z"), capa, &list); 29.387 + ASSERT_EQ(n, 1); 29.388 + EXPECT_EQ(cx_strcmp(list[0], test), 0); 29.389 + cxFree(&alloc, list); 29.390 + 29.391 + // partially matching delimiter 29.392 + n = cx_strsplit_a(&alloc, test, cx_str("is,not"), capa, &list); 29.393 + ASSERT_EQ(n, 1); 29.394 + EXPECT_EQ(cx_strcmp(list[0], test), 0); 29.395 + cxFree(&alloc, list); 29.396 + 29.397 + // matching single-char delimiter 29.398 + n = cx_strsplit_a(&alloc, test, cx_str(","), capa, &list); 29.399 + ASSERT_EQ(n, 5); 29.400 + EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0); 29.401 + EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0); 29.402 + EXPECT_EQ(cx_strcmp(list[2], cx_str("a")), 0); 29.403 + EXPECT_EQ(cx_strcmp(list[3], cx_str("csv")), 0); 29.404 + EXPECT_EQ(cx_strcmp(list[4], cx_str("string")), 0); 29.405 + cxFree(&alloc, list); 29.406 + 29.407 + // matching multi-char delimiter 29.408 + n = cx_strsplit_a(&alloc, test, cx_str("is"), capa, &list); 29.409 + ASSERT_EQ(n, 3); 29.410 + EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 29.411 + EXPECT_EQ(cx_strcmp(list[1], cx_str(",")), 0); 29.412 + EXPECT_EQ(cx_strcmp(list[2], cx_str(",a,csv,string")), 0); 29.413 + cxFree(&alloc, list); 29.414 + 29.415 + // bounded list using single-char delimiter 29.416 + n = cx_strsplit_a(&alloc, test, cx_str(","), 3, &list); 29.417 + ASSERT_EQ(n, 3); 29.418 + EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0); 29.419 + EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0); 29.420 + EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0); 29.421 + cxFree(&alloc, list); 29.422 + 29.423 + // bounded list using multi-char delimiter 29.424 + n = cx_strsplit_a(&alloc, test, cx_str("is"), 2, &list); 29.425 + ASSERT_EQ(n, 2); 29.426 + EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 29.427 + EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0); 29.428 + cxFree(&alloc, list); 29.429 + 29.430 + // start with delimiter 29.431 + n = cx_strsplit_a(&alloc, test, cx_str("this"), capa, &list); 29.432 + ASSERT_EQ(n, 2); 29.433 + EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0); 29.434 + EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0); 29.435 + cxFree(&alloc, list); 29.436 + 29.437 + // end with delimiter 29.438 + n = cx_strsplit_a(&alloc, test, cx_str("string"), capa, &list); 29.439 + ASSERT_EQ(n, 2); 29.440 + EXPECT_EQ(cx_strcmp(list[0], cx_str("this,is,a,csv,")), 0); 29.441 + EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 29.442 + cxFree(&alloc, list); 29.443 + 29.444 + // end with delimiter exceed bound 29.445 + n = cx_strsplit_a(&alloc, cx_str("a,b,c,"), cx_str(","), 3, &list); 29.446 + ASSERT_EQ(n, 3); 29.447 + EXPECT_EQ(cx_strcmp(list[0], cx_str("a")), 0); 29.448 + EXPECT_EQ(cx_strcmp(list[1], cx_str("b")), 0); 29.449 + EXPECT_EQ(cx_strcmp(list[2], cx_str("c,")), 0); 29.450 + cxFree(&alloc, list); 29.451 + 29.452 + // exact match 29.453 + n = cx_strsplit_a(&alloc, test, cx_str("this,is,a,csv,string"), capa, &list); 29.454 + ASSERT_EQ(n, 2); 29.455 + EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0); 29.456 + EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 29.457 + cxFree(&alloc, list); 29.458 + 29.459 + // string to be split is only substring 29.460 + n = cx_strsplit_a(&alloc, test, cx_str("this,is,a,csv,string,with,extension"), capa, &list); 29.461 + ASSERT_EQ(n, 1); 29.462 + EXPECT_EQ(cx_strcmp(list[0], test), 0); 29.463 + cxFree(&alloc, list); 29.464 + 29.465 + // subsequent encounter of delimiter (the string between is empty) 29.466 + n = cx_strsplit_a(&alloc, test, cx_str("is,"), capa, &list); 29.467 + ASSERT_EQ(n, 3); 29.468 + EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 29.469 + EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 29.470 + EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0); 29.471 + cxFree(&alloc, list); 29.472 + 29.473 + // call the _m variant just for coverage 29.474 + auto mtest = cx_strdup(test); 29.475 + cxmutstr *mlist; 29.476 + n = cx_strsplit_ma(&alloc, mtest, cx_str("is,"), 4, &mlist); 29.477 + ASSERT_EQ(n, 3); 29.478 + EXPECT_EQ(cx_strcmp(cx_strcast(mlist[0]), cx_str("th")), 0); 29.479 + EXPECT_EQ(cx_strcmp(cx_strcast(mlist[1]), cx_str("")), 0); 29.480 + EXPECT_EQ(cx_strcmp(cx_strcast(mlist[2]), cx_str("a,csv,string")), 0); 29.481 + cxFree(&alloc, mlist); 29.482 + cx_strfree(&mtest); 29.483 + 29.484 + EXPECT_TRUE(alloc.verify()); 29.485 +} 29.486 + 29.487 +TEST(String, strtrim) { 29.488 + cxstring t1 = cx_strtrim(cx_str(" ein test \t ")); 29.489 + cxstring t2 = cx_strtrim(cx_str("abc")); 29.490 + cxstring t3 = cx_strtrim(cx_str(" 123")); 29.491 + cxstring t4 = cx_strtrim(cx_str("xyz ")); 29.492 + cxstring t5 = cx_strtrim(cx_str(" ")); 29.493 + cxstring empty = cx_strtrim(cx_str("")); 29.494 + 29.495 + EXPECT_EQ(cx_strcmp(t1, cx_str("ein test")), 0); 29.496 + EXPECT_EQ(cx_strcmp(t2, cx_str("abc")), 0); 29.497 + EXPECT_EQ(cx_strcmp(t3, cx_str("123")), 0); 29.498 + EXPECT_EQ(cx_strcmp(t4, cx_str("xyz")), 0); 29.499 + EXPECT_EQ(cx_strcmp(t5, cx_str("")), 0); 29.500 + EXPECT_EQ(cx_strcmp(empty, cx_str("")), 0); 29.501 + 29.502 + // call the _m variant just for coverage 29.503 + cxmutstr m1 = cx_strtrim_m(cx_mutstr((char *) " ein test \t ")); 29.504 + EXPECT_EQ(cx_strcmp(cx_strcast(m1), cx_str("ein test")), 0); 29.505 +} 29.506 + 29.507 +TEST(String, strprefix) { 29.508 + cxstring str = CX_STR("test my prefix and my suffix"); 29.509 + cxstring empty = CX_STR(""); 29.510 + EXPECT_FALSE(cx_strprefix(empty, cx_str("pref"))); 29.511 + EXPECT_TRUE(cx_strprefix(str, empty)); 29.512 + EXPECT_TRUE(cx_strprefix(empty, empty)); 29.513 + EXPECT_TRUE(cx_strprefix(str, cx_str("test "))); 29.514 + EXPECT_FALSE(cx_strprefix(str, cx_str("8-) fsck "))); 29.515 +} 29.516 + 29.517 +TEST(String, strsuffix) { 29.518 + cxstring str = CX_STR("test my prefix and my suffix"); 29.519 + cxstring empty = CX_STR(""); 29.520 + EXPECT_FALSE(cx_strsuffix(empty, cx_str("suf"))); 29.521 + EXPECT_TRUE(cx_strsuffix(str, empty)); 29.522 + EXPECT_TRUE(cx_strsuffix(empty, empty)); 29.523 + EXPECT_TRUE(cx_strsuffix(str, cx_str("fix"))); 29.524 + EXPECT_FALSE(cx_strsuffix(str, cx_str("fox"))); 29.525 +} 29.526 + 29.527 +TEST(String, strcaseprefix) { 29.528 + cxstring str = CX_STR("test my prefix and my suffix"); 29.529 + cxstring empty = CX_STR(""); 29.530 + EXPECT_FALSE(cx_strcaseprefix(empty, cx_str("pREf"))); 29.531 + EXPECT_TRUE(cx_strcaseprefix(str, empty)); 29.532 + EXPECT_TRUE(cx_strcaseprefix(empty, empty)); 29.533 + EXPECT_TRUE(cx_strcaseprefix(str, cx_str("TEST "))); 29.534 + EXPECT_FALSE(cx_strcaseprefix(str, cx_str("8-) fsck "))); 29.535 +} 29.536 + 29.537 +TEST(String, strcasesuffix) { 29.538 + cxstring str = CX_STR("test my prefix and my suffix"); 29.539 + cxstring empty = CX_STR(""); 29.540 + EXPECT_FALSE(cx_strcasesuffix(empty, cx_str("sUf"))); 29.541 + EXPECT_TRUE(cx_strcasesuffix(str, empty)); 29.542 + EXPECT_TRUE(cx_strcasesuffix(empty, empty)); 29.543 + EXPECT_TRUE(cx_strcasesuffix(str, cx_str("FIX"))); 29.544 + EXPECT_FALSE(cx_strcasesuffix(str, cx_str("fox"))); 29.545 +} 29.546 + 29.547 +TEST(String, strreplace) { 29.548 + CxTestingAllocator alloc; 29.549 + cxstring str = CX_STR("test ababab string aba"); 29.550 + cxstring longstr = CX_STR( 29.551 + "xyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacd"); 29.552 + cxstring notrail = CX_STR("test abab"); 29.553 + cxstring empty = CX_STR(""); 29.554 + cxstring astr = CX_STR("aaaaaaaaaa"); 29.555 + cxstring csstr = CX_STR("test AB ab TEST xyz"); 29.556 + 29.557 + cxmutstr repl = cx_strreplace(str, cx_str("abab"), cx_str("muchlonger")); 29.558 + auto expected = "test muchlongerab string aba"; 29.559 + 29.560 + cxmutstr repln = cx_strreplacen(str, cx_str("ab"), cx_str("c"), 2); 29.561 + auto expectedn = "test ccab string aba"; 29.562 + 29.563 + cxmutstr longrepl = cx_strreplace(longstr, cx_str("a"), cx_str("z")); 29.564 + auto longexpect = "xyzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzcd"; 29.565 + 29.566 + cxmutstr replnotrail = cx_strreplace(notrail, cx_str("ab"), cx_str("z")); 29.567 + auto notrailexpect = "test zz"; 29.568 + 29.569 + cxmutstr repleq = cx_strreplace(str, str, cx_str("hello")); 29.570 + auto eqexpect = "hello"; 29.571 + 29.572 + cxmutstr replempty1 = cx_strreplace(empty, cx_str("ab"), cx_str("c")); // expect: empty 29.573 + cxmutstr replempty2 = cx_strreplace(str, cx_str("abab"), empty); 29.574 + auto emptyexpect2 = "test ab string aba"; 29.575 + 29.576 + cxmutstr replpre = cx_strreplace(str, cx_str("test "), cx_str("TEST ")); 29.577 + auto preexpected = "TEST ababab string aba"; 29.578 + 29.579 + cxmutstr replan1 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 1); 29.580 + auto an1expected = "xaaaaaaaaa"; 29.581 + 29.582 + cxmutstr replan4 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 4); 29.583 + auto an4expected = "xxxxaaaaaa"; 29.584 + 29.585 + cxmutstr replan9 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 9); 29.586 + auto an9expected = "xxxxxxxxxa"; 29.587 + 29.588 + cxmutstr replan10 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 10); 29.589 + auto an10expected = "xxxxxxxxxx"; 29.590 + 29.591 + cxmutstr repl1_a = cx_strreplace_a(&alloc, csstr, cx_str("AB"), cx_str("*")); 29.592 + auto expeced1_a = "test * ab TEST xyz"; 29.593 + 29.594 + cxmutstr repl2_a = cx_strreplace_a(&alloc, csstr, cx_str("test"), cx_str("TEST")); 29.595 + auto expected2_a = "TEST AB ab TEST xyz"; 29.596 + 29.597 + 29.598 + EXPECT_NE(repl.ptr, str.ptr); 29.599 + EXPECT_ZERO_TERMINATED(repl); 29.600 + EXPECT_STREQ(repl.ptr, expected); 29.601 + EXPECT_ZERO_TERMINATED(repln); 29.602 + EXPECT_STREQ(repln.ptr, expectedn); 29.603 + EXPECT_ZERO_TERMINATED(longrepl); 29.604 + EXPECT_STREQ(longrepl.ptr, longexpect); 29.605 + EXPECT_ZERO_TERMINATED(replnotrail); 29.606 + EXPECT_STREQ(replnotrail.ptr, notrailexpect); 29.607 + EXPECT_ZERO_TERMINATED(repleq); 29.608 + EXPECT_STREQ(repleq.ptr, eqexpect); 29.609 + EXPECT_ZERO_TERMINATED(replempty1); 29.610 + EXPECT_STREQ(replempty1.ptr, ""); 29.611 + EXPECT_ZERO_TERMINATED(replempty2); 29.612 + EXPECT_STREQ(replempty2.ptr, emptyexpect2); 29.613 + EXPECT_ZERO_TERMINATED(replpre); 29.614 + EXPECT_STREQ(replpre.ptr, preexpected); 29.615 + EXPECT_ZERO_TERMINATED(replan1); 29.616 + EXPECT_STREQ(replan1.ptr, an1expected); 29.617 + EXPECT_ZERO_TERMINATED(replan4); 29.618 + EXPECT_STREQ(replan4.ptr, an4expected); 29.619 + EXPECT_ZERO_TERMINATED(replan9); 29.620 + EXPECT_STREQ(replan9.ptr, an9expected); 29.621 + EXPECT_ZERO_TERMINATED(replan10); 29.622 + EXPECT_STREQ(replan10.ptr, an10expected); 29.623 + EXPECT_ZERO_TERMINATED(repl1_a); 29.624 + EXPECT_STREQ(repl1_a.ptr, expeced1_a); 29.625 + EXPECT_ZERO_TERMINATED(repl2_a); 29.626 + EXPECT_STREQ(repl2_a.ptr, expected2_a); 29.627 + 29.628 + cx_strfree(&repl); 29.629 + cx_strfree(&repln); 29.630 + cx_strfree(&longrepl); 29.631 + cx_strfree(&replnotrail); 29.632 + cx_strfree(&repleq); 29.633 + cx_strfree(&replempty1); 29.634 + cx_strfree(&replempty2); 29.635 + cx_strfree(&replpre); 29.636 + cx_strfree(&replan1); 29.637 + cx_strfree(&replan4); 29.638 + cx_strfree(&replan9); 29.639 + cx_strfree(&replan10); 29.640 + 29.641 + cx_strfree_a(&alloc, &repl1_a); 29.642 + cx_strfree_a(&alloc, &repl2_a); 29.643 + EXPECT_TRUE(alloc.verify()); 29.644 +} 29.645 + 29.646 +TEST(String, strupper) { 29.647 + cxmutstr str = cx_strdup(cx_str("thIs 1s @ Te$t")); 29.648 + cx_strupper(str); 29.649 + EXPECT_STREQ(str.ptr, "THIS 1S @ TE$T"); 29.650 + cx_strfree(&str); 29.651 +} 29.652 + 29.653 +TEST(String, strlower) { 29.654 + cxmutstr str = cx_strdup(cx_str("thIs 1s @ Te$t")); 29.655 + cx_strlower(str); 29.656 + EXPECT_STREQ(str.ptr, "this 1s @ te$t"); 29.657 + cx_strfree(&str); 29.658 +} 29.659 + 29.660 +TEST(String, strtok) { 29.661 + cxstring str = cx_str("a,comma,separated,string"); 29.662 + cxstring delim = cx_str(","); 29.663 + CxStrtokCtx ctx = cx_strtok(str, delim, 3); 29.664 + EXPECT_EQ(ctx.str.ptr, str.ptr); 29.665 + EXPECT_EQ(ctx.str.length, str.length); 29.666 + EXPECT_EQ(ctx.delim.ptr, delim.ptr); 29.667 + EXPECT_EQ(ctx.delim.length, delim.length); 29.668 + EXPECT_EQ(ctx.limit, 3); 29.669 + EXPECT_EQ(ctx.found, 0); 29.670 + EXPECT_EQ(ctx.pos, 0); 29.671 + EXPECT_EQ(ctx.next_pos, 0); 29.672 + EXPECT_EQ(ctx.delim_more, nullptr); 29.673 + EXPECT_EQ(ctx.delim_more_count, 0); 29.674 +} 29.675 + 29.676 +TEST(String, strtok_m) { 29.677 + cxmutstr str = cx_strdup(cx_str("a,comma,separated,string")); 29.678 + cxstring delim = cx_str(","); 29.679 + CxStrtokCtx ctx = cx_strtok_m(str, delim, 3); 29.680 + EXPECT_EQ(ctx.str.ptr, str.ptr); 29.681 + EXPECT_EQ(ctx.str.length, str.length); 29.682 + EXPECT_EQ(ctx.delim.ptr, delim.ptr); 29.683 + EXPECT_EQ(ctx.delim.length, delim.length); 29.684 + EXPECT_EQ(ctx.limit, 3); 29.685 + EXPECT_EQ(ctx.found, 0); 29.686 + EXPECT_EQ(ctx.pos, 0); 29.687 + EXPECT_EQ(ctx.next_pos, 0); 29.688 + EXPECT_EQ(ctx.delim_more, nullptr); 29.689 + EXPECT_EQ(ctx.delim_more_count, 0); 29.690 + cx_strfree(&str); 29.691 +} 29.692 + 29.693 +TEST(String, strtok_delim) { 29.694 + cxstring str = cx_str("an,arbitrarily|separated;string"); 29.695 + cxstring delim = cx_str(","); 29.696 + cxstring delim_more[2] = {CX_STR("|"), CX_STR(";")}; 29.697 + CxStrtokCtx ctx = cx_strtok(str, delim, 3); 29.698 + cx_strtok_delim(&ctx, delim_more, 2); 29.699 + EXPECT_EQ(ctx.str.ptr, str.ptr); 29.700 + EXPECT_EQ(ctx.str.length, str.length); 29.701 + EXPECT_EQ(ctx.delim.ptr, delim.ptr); 29.702 + EXPECT_EQ(ctx.delim.length, delim.length); 29.703 + EXPECT_EQ(ctx.limit, 3); 29.704 + EXPECT_EQ(ctx.found, 0); 29.705 + EXPECT_EQ(ctx.pos, 0); 29.706 + EXPECT_EQ(ctx.next_pos, 0); 29.707 + EXPECT_EQ(ctx.delim_more, delim_more); 29.708 + EXPECT_EQ(ctx.delim_more_count, 2); 29.709 +} 29.710 + 29.711 +TEST(String, strtok_next_easy) { 29.712 + cxstring str = cx_str("a,comma,separated,string"); 29.713 + cxstring delim = cx_str(","); 29.714 + CxStrtokCtx ctx = cx_strtok(str, delim, 3); 29.715 + bool ret; 29.716 + cxstring tok; 29.717 + 29.718 + ret = cx_strtok_next(&ctx, &tok); 29.719 + ASSERT_TRUE(ret); 29.720 + EXPECT_EQ(cx_strcmp(tok, cx_str("a")), 0); 29.721 + EXPECT_EQ(ctx.pos, 0); 29.722 + EXPECT_EQ(ctx.next_pos, 2); 29.723 + EXPECT_EQ(ctx.delim_pos, 1); 29.724 + EXPECT_EQ(ctx.found, 1); 29.725 + 29.726 + ret = cx_strtok_next(&ctx, &tok); 29.727 + ASSERT_TRUE(ret); 29.728 + EXPECT_EQ(cx_strcmp(tok, cx_str("comma")), 0); 29.729 + EXPECT_EQ(ctx.pos, 2); 29.730 + EXPECT_EQ(ctx.next_pos, 8); 29.731 + EXPECT_EQ(ctx.delim_pos, 7); 29.732 + EXPECT_EQ(ctx.found, 2); 29.733 + 29.734 + ret = cx_strtok_next(&ctx, &tok); 29.735 + ASSERT_TRUE(ret); 29.736 + EXPECT_EQ(cx_strcmp(tok, cx_str("separated")), 0); 29.737 + EXPECT_EQ(ctx.pos, 8); 29.738 + EXPECT_EQ(ctx.next_pos, 18); 29.739 + EXPECT_EQ(ctx.delim_pos, 17); 29.740 + EXPECT_EQ(ctx.found, 3); 29.741 + 29.742 + ret = cx_strtok_next(&ctx, &tok); 29.743 + ASSERT_FALSE(ret); 29.744 + EXPECT_EQ(ctx.pos, 8); 29.745 + EXPECT_EQ(ctx.next_pos, 18); 29.746 + EXPECT_EQ(ctx.delim_pos, 17); 29.747 + EXPECT_EQ(ctx.found, 3); 29.748 +} 29.749 + 29.750 +TEST(String, strtok_next_unlimited) { 29.751 + cxstring str = cx_str("some;-;otherwise;-;separated;-;string;-;"); 29.752 + cxstring delim = cx_str(";-;"); 29.753 + CxStrtokCtx ctx = cx_strtok(str, delim, SIZE_MAX); 29.754 + bool ret; 29.755 + cxstring tok; 29.756 + 29.757 + ret = cx_strtok_next(&ctx, &tok); 29.758 + ASSERT_TRUE(ret); 29.759 + EXPECT_EQ(cx_strcmp(tok, cx_str("some")), 0); 29.760 + EXPECT_EQ(ctx.pos, 0); 29.761 + EXPECT_EQ(ctx.next_pos, 7); 29.762 + EXPECT_EQ(ctx.delim_pos, 4); 29.763 + EXPECT_EQ(ctx.found, 1); 29.764 + 29.765 + ret = cx_strtok_next(&ctx, &tok); 29.766 + ASSERT_TRUE(ret); 29.767 + EXPECT_EQ(cx_strcmp(tok, cx_str("otherwise")), 0); 29.768 + EXPECT_EQ(ctx.pos, 7); 29.769 + EXPECT_EQ(ctx.next_pos, 19); 29.770 + EXPECT_EQ(ctx.delim_pos, 16); 29.771 + EXPECT_EQ(ctx.found, 2); 29.772 + 29.773 + ret = cx_strtok_next(&ctx, &tok); 29.774 + ASSERT_TRUE(ret); 29.775 + EXPECT_EQ(cx_strcmp(tok, cx_str("separated")), 0); 29.776 + EXPECT_EQ(ctx.pos, 19); 29.777 + EXPECT_EQ(ctx.next_pos, 31); 29.778 + EXPECT_EQ(ctx.delim_pos, 28); 29.779 + EXPECT_EQ(ctx.found, 3); 29.780 + 29.781 + ret = cx_strtok_next(&ctx, &tok); 29.782 + ASSERT_TRUE(ret); 29.783 + EXPECT_EQ(cx_strcmp(tok, cx_str("string")), 0); 29.784 + EXPECT_EQ(ctx.pos, 31); 29.785 + EXPECT_EQ(ctx.next_pos, 40); 29.786 + EXPECT_EQ(ctx.delim_pos, 37); 29.787 + EXPECT_EQ(ctx.found, 4); 29.788 + 29.789 + ret = cx_strtok_next(&ctx, &tok); 29.790 + ASSERT_TRUE(ret); 29.791 + EXPECT_EQ(cx_strcmp(tok, cx_str("")), 0); 29.792 + EXPECT_EQ(ctx.pos, 40); 29.793 + EXPECT_EQ(ctx.next_pos, 40); 29.794 + EXPECT_EQ(ctx.delim_pos, 40); 29.795 + EXPECT_EQ(ctx.found, 5); 29.796 + 29.797 + ret = cx_strtok_next(&ctx, &tok); 29.798 + ASSERT_FALSE(ret); 29.799 + EXPECT_EQ(ctx.pos, 40); 29.800 + EXPECT_EQ(ctx.delim_pos, 40); 29.801 + EXPECT_EQ(ctx.found, 5); 29.802 +} 29.803 + 29.804 +TEST(String, strtok_next_advanced) { 29.805 + cxmutstr str = cx_strdup(cx_str("an,arbitrarily;||separated;string")); 29.806 + cxstring delim = cx_str(","); 29.807 + cxstring delim_more[2] = {CX_STR("||"), CX_STR(";")}; 29.808 + CxStrtokCtx ctx = cx_strtok_m(str, delim, 10); 29.809 + cx_strtok_delim(&ctx, delim_more, 2); 29.810 + bool ret; 29.811 + cxmutstr tok; 29.812 + 29.813 + ret = cx_strtok_next_m(&ctx, &tok); 29.814 + ASSERT_TRUE(ret); 29.815 + EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("an")), 0); 29.816 + EXPECT_EQ(ctx.pos, 0); 29.817 + EXPECT_EQ(ctx.next_pos, 3); 29.818 + EXPECT_EQ(ctx.delim_pos, 2); 29.819 + EXPECT_EQ(ctx.found, 1); 29.820 + cx_strupper(tok); 29.821 + 29.822 + ret = cx_strtok_next_m(&ctx, &tok); 29.823 + ASSERT_TRUE(ret); 29.824 + EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("arbitrarily")), 0); 29.825 + EXPECT_EQ(ctx.pos, 3); 29.826 + EXPECT_EQ(ctx.next_pos, 15); 29.827 + EXPECT_EQ(ctx.delim_pos, 14); 29.828 + EXPECT_EQ(ctx.found, 2); 29.829 + cx_strupper(tok); 29.830 + 29.831 + ret = cx_strtok_next_m(&ctx, &tok); 29.832 + ASSERT_TRUE(ret); 29.833 + EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("")), 0); 29.834 + EXPECT_EQ(ctx.pos, 15); 29.835 + EXPECT_EQ(ctx.next_pos, 17); 29.836 + EXPECT_EQ(ctx.delim_pos, 15); 29.837 + EXPECT_EQ(ctx.found, 3); 29.838 + cx_strupper(tok); 29.839 + 29.840 + ret = cx_strtok_next_m(&ctx, &tok); 29.841 + ASSERT_TRUE(ret); 29.842 + EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("separated")), 0); 29.843 + EXPECT_EQ(ctx.pos, 17); 29.844 + EXPECT_EQ(ctx.next_pos, 27); 29.845 + EXPECT_EQ(ctx.delim_pos, 26); 29.846 + EXPECT_EQ(ctx.found, 4); 29.847 + cx_strupper(tok); 29.848 + 29.849 + ret = cx_strtok_next_m(&ctx, &tok); 29.850 + ASSERT_TRUE(ret); 29.851 + EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("string")), 0); 29.852 + EXPECT_EQ(ctx.pos, 27); 29.853 + EXPECT_EQ(ctx.next_pos, 33); 29.854 + EXPECT_EQ(ctx.delim_pos, 33); 29.855 + EXPECT_EQ(ctx.found, 5); 29.856 + cx_strupper(tok); 29.857 + 29.858 + ret = cx_strtok_next_m(&ctx, &tok); 29.859 + ASSERT_FALSE(ret); 29.860 + EXPECT_EQ(ctx.pos, 27); 29.861 + EXPECT_EQ(ctx.next_pos, 33); 29.862 + EXPECT_EQ(ctx.delim_pos, 33); 29.863 + EXPECT_EQ(ctx.found, 5); 29.864 + 29.865 + EXPECT_EQ(cx_strcmp(cx_strcast(str), cx_str("AN,ARBITRARILY;||SEPARATED;STRING")), 0); 29.866 + 29.867 + cx_strfree(&str); 29.868 +}
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/tests/test_tree.cpp Tue Feb 07 21:55:37 2023 +0100 30.3 @@ -0,0 +1,122 @@ 30.4 +/* 30.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 30.6 + * 30.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 30.8 + * 30.9 + * Redistribution and use in source and binary forms, with or without 30.10 + * modification, are permitted provided that the following conditions are met: 30.11 + * 30.12 + * 1. Redistributions of source code must retain the above copyright 30.13 + * notice, this list of conditions and the following disclaimer. 30.14 + * 30.15 + * 2. Redistributions in binary form must reproduce the above copyright 30.16 + * notice, this list of conditions and the following disclaimer in the 30.17 + * documentation and/or other materials provided with the distribution. 30.18 + * 30.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 30.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 30.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 30.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30.29 + * POSSIBILITY OF SUCH DAMAGE. 30.30 + */ 30.31 + 30.32 +#include "cx/tree.h" 30.33 +#include <gtest/gtest.h> 30.34 + 30.35 +struct TestNode { 30.36 + TestNode *parent = nullptr; 30.37 + TestNode *prev = nullptr; 30.38 + TestNode *next = nullptr; 30.39 + 30.40 + TestNode *children_begin = nullptr; 30.41 + TestNode *children_end = nullptr; 30.42 +}; 30.43 + 30.44 +TEST(Tree, cx_tree_add_sibling) { 30.45 + // prepare test tree 30.46 + TestNode root, a; 30.47 + root.children_begin = &a; 30.48 + root.children_end = &a; 30.49 + a.parent = &root; 30.50 + 30.51 + // new test nodes 30.52 + TestNode b, c; 30.53 + 30.54 + // test 30.55 + cx_tree_add_sibling(&a, offsetof(TestNode, prev), offsetof(TestNode, next), offsetof(TestNode, parent), &b); 30.56 + EXPECT_EQ(b.parent, &root); 30.57 + EXPECT_EQ(b.prev, &a); 30.58 + EXPECT_EQ(b.next, nullptr); 30.59 + EXPECT_EQ(a.next, &b); 30.60 + 30.61 + cx_tree_add_sibling(&a, -1, offsetof(TestNode, next), -1, &c); 30.62 + EXPECT_EQ(c.parent, nullptr); 30.63 + EXPECT_EQ(c.prev, nullptr); 30.64 + EXPECT_EQ(c.next, nullptr); 30.65 + EXPECT_EQ(b.next, &c); 30.66 +} 30.67 + 30.68 +TEST(Tree, cx_tree_add_child) { 30.69 + TestNode root, a, b, c, a1; 30.70 + 30.71 + cx_tree_add_child( 30.72 + (void **) &root.children_begin, 30.73 + (void **) &root.children_end, 30.74 + offsetof(TestNode, prev), 30.75 + offsetof(TestNode, next), 30.76 + &a, 30.77 + offsetof(TestNode, parent), 30.78 + &root); 30.79 + EXPECT_EQ(root.children_begin, &a); 30.80 + EXPECT_EQ(root.children_end, &a); 30.81 + EXPECT_EQ(a.parent, &root); 30.82 + EXPECT_EQ(a.prev, nullptr); 30.83 + EXPECT_EQ(a.next, nullptr); 30.84 + 30.85 + cx_tree_add_child( 30.86 + (void **) &root.children_begin, 30.87 + (void **) &root.children_end, 30.88 + offsetof(TestNode, prev), 30.89 + offsetof(TestNode, next), 30.90 + &b, 30.91 + offsetof(TestNode, parent), 30.92 + &root); 30.93 + EXPECT_EQ(root.children_begin, &a); 30.94 + EXPECT_EQ(root.children_begin->next, &b); 30.95 + EXPECT_EQ(root.children_end, &b); 30.96 + EXPECT_EQ(b.parent, &root); 30.97 + EXPECT_EQ(b.prev, &a); 30.98 + 30.99 + cx_tree_add_child( 30.100 + (void **) &root.children_begin, 30.101 + nullptr, 30.102 + -1, 30.103 + offsetof(TestNode, next), 30.104 + &c, 30.105 + -1, 30.106 + &root); 30.107 + EXPECT_EQ(root.children_end, &b); // children_end unchanged 30.108 + EXPECT_EQ(b.next, &c); 30.109 + EXPECT_EQ(c.prev, nullptr); 30.110 + EXPECT_EQ(c.next, nullptr); 30.111 + EXPECT_EQ(c.parent, nullptr); 30.112 + 30.113 + cx_tree_add_child( 30.114 + (void **) &a.children_begin, 30.115 + (void **) &a.children_end, 30.116 + offsetof(TestNode, prev), 30.117 + offsetof(TestNode, next), 30.118 + &a1, 30.119 + offsetof(TestNode, parent), 30.120 + &a); 30.121 + EXPECT_EQ(a.children_begin, &a1); 30.122 + EXPECT_EQ(a1.parent, &a); 30.123 + EXPECT_EQ(root.children_begin, &a); 30.124 + EXPECT_EQ(root.children_begin->children_begin, &a1); 30.125 +}
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 31.2 +++ b/tests/test_utils.cpp Tue Feb 07 21:55:37 2023 +0100 31.3 @@ -0,0 +1,155 @@ 31.4 +/* 31.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 31.6 + * 31.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 31.8 + * 31.9 + * Redistribution and use in source and binary forms, with or without 31.10 + * modification, are permitted provided that the following conditions are met: 31.11 + * 31.12 + * 1. Redistributions of source code must retain the above copyright 31.13 + * notice, this list of conditions and the following disclaimer. 31.14 + * 31.15 + * 2. Redistributions in binary form must reproduce the above copyright 31.16 + * notice, this list of conditions and the following disclaimer in the 31.17 + * documentation and/or other materials provided with the distribution. 31.18 + * 31.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 31.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 31.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 31.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31.29 + * POSSIBILITY OF SUCH DAMAGE. 31.30 + */ 31.31 + 31.32 +#include "cx/utils.h" 31.33 + 31.34 +#include <gtest/gtest.h> 31.35 + 31.36 +TEST(Utils, ForN) { 31.37 + unsigned j; 31.38 + j = 0; 31.39 + cx_for_n(i, 50) { 31.40 + EXPECT_EQ(i, j); 31.41 + j++; 31.42 + } 31.43 +} 31.44 + 31.45 +TEST(Utils, szmul) { 31.46 + size_t r; 31.47 + int e; 31.48 + e = cx_szmul(5, 7, &r); 31.49 + EXPECT_EQ(0, e); 31.50 + EXPECT_EQ(35, r); 31.51 + 31.52 + size_t s = SIZE_MAX & ~3; 31.53 + 31.54 + e = cx_szmul(s / 4, 2, &r); 31.55 + EXPECT_EQ(0, e); 31.56 + EXPECT_EQ(s / 2, r); 31.57 + e = cx_szmul(2, s / 4, &r); 31.58 + EXPECT_EQ(0, e); 31.59 + EXPECT_EQ(s / 2, r); 31.60 + 31.61 + e = cx_szmul(s / 4, 4, &r); 31.62 + EXPECT_EQ(0, e); 31.63 + EXPECT_EQ(s, r); 31.64 + 31.65 + e = cx_szmul(4, s / 4, &r); 31.66 + EXPECT_EQ(0, e); 31.67 + EXPECT_EQ(s, r); 31.68 + 31.69 + e = cx_szmul(s / 4, 5, &r); 31.70 + EXPECT_NE(0, e); 31.71 + 31.72 + e = cx_szmul(5, s / 4, &r); 31.73 + EXPECT_NE(0, e); 31.74 + 31.75 + e = cx_szmul(SIZE_MAX - 4, 0, &r); 31.76 + EXPECT_EQ(0, e); 31.77 + EXPECT_EQ(0, r); 31.78 + 31.79 + e = cx_szmul(0, SIZE_MAX - 1, &r); 31.80 + EXPECT_EQ(0, e); 31.81 + EXPECT_EQ(0, r); 31.82 + 31.83 + e = cx_szmul(SIZE_MAX, 0, &r); 31.84 + EXPECT_EQ(0, e); 31.85 + EXPECT_EQ(0, r); 31.86 + 31.87 + e = cx_szmul(0, SIZE_MAX, &r); 31.88 + EXPECT_EQ(0, e); 31.89 + EXPECT_EQ(0, r); 31.90 + 31.91 + e = cx_szmul(0, 0, &r); 31.92 + EXPECT_EQ(0, e); 31.93 + EXPECT_EQ(0, r); 31.94 +} 31.95 + 31.96 +#ifdef CX_SZMUL_BUILTIN 31.97 + 31.98 +// also test the custom implementation 31.99 +struct Utils_szmul_impl : ::testing::Test { 31.100 +#undef CX_SZMUL_BUILTIN 31.101 + 31.102 +#include "../src/utils.c" 31.103 + 31.104 +#define CX_SZMUL_BUILTIN 31.105 +}; 31.106 + 31.107 +TEST_F(Utils_szmul_impl, Test) { 31.108 + size_t r; 31.109 + int e; 31.110 + e = cx_szmul_impl(5, 7, &r); 31.111 + EXPECT_EQ(0, e); 31.112 + EXPECT_EQ(35, r); 31.113 + 31.114 + size_t s = SIZE_MAX & ~3; 31.115 + 31.116 + e = cx_szmul_impl(s / 4, 2, &r); 31.117 + EXPECT_EQ(0, e); 31.118 + EXPECT_EQ(s / 2, r); 31.119 + e = cx_szmul_impl(2, s / 4, &r); 31.120 + EXPECT_EQ(0, e); 31.121 + EXPECT_EQ(s / 2, r); 31.122 + 31.123 + e = cx_szmul_impl(s / 4, 4, &r); 31.124 + EXPECT_EQ(0, e); 31.125 + EXPECT_EQ(s, r); 31.126 + 31.127 + e = cx_szmul_impl(4, s / 4, &r); 31.128 + EXPECT_EQ(0, e); 31.129 + EXPECT_EQ(s, r); 31.130 + 31.131 + e = cx_szmul_impl(s / 4, 5, &r); 31.132 + EXPECT_NE(0, e); 31.133 + 31.134 + e = cx_szmul_impl(5, s / 4, &r); 31.135 + EXPECT_NE(0, e); 31.136 + 31.137 + e = cx_szmul_impl(SIZE_MAX - 4, 0, &r); 31.138 + EXPECT_EQ(0, e); 31.139 + EXPECT_EQ(0, r); 31.140 + 31.141 + e = cx_szmul_impl(0, SIZE_MAX - 1, &r); 31.142 + EXPECT_EQ(0, e); 31.143 + EXPECT_EQ(0, r); 31.144 + 31.145 + e = cx_szmul_impl(SIZE_MAX, 0, &r); 31.146 + EXPECT_EQ(0, e); 31.147 + EXPECT_EQ(0, r); 31.148 + 31.149 + e = cx_szmul_impl(0, SIZE_MAX, &r); 31.150 + EXPECT_EQ(0, e); 31.151 + EXPECT_EQ(0, r); 31.152 + 31.153 + e = cx_szmul_impl(0, 0, &r); 31.154 + EXPECT_EQ(0, e); 31.155 + EXPECT_EQ(0, r); 31.156 +} 31.157 + 31.158 +#endif // CX_SZMUL_BUILTIN
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/tests/util_allocator.cpp Tue Feb 07 21:55:37 2023 +0100 32.3 @@ -0,0 +1,167 @@ 32.4 +/* 32.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 32.6 + * 32.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 32.8 + * 32.9 + * Redistribution and use in source and binary forms, with or without 32.10 + * modification, are permitted provided that the following conditions are met: 32.11 + * 32.12 + * 1. Redistributions of source code must retain the above copyright 32.13 + * notice, this list of conditions and the following disclaimer. 32.14 + * 32.15 + * 2. Redistributions in binary form must reproduce the above copyright 32.16 + * notice, this list of conditions and the following disclaimer in the 32.17 + * documentation and/or other materials provided with the distribution. 32.18 + * 32.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 32.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 32.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32.29 + * POSSIBILITY OF SUCH DAMAGE. 32.30 + */ 32.31 + 32.32 +#include "util_allocator.h" 32.33 + 32.34 +void *cx_malloc_testing(void *d, size_t n) { 32.35 + auto data = reinterpret_cast<CxTestingAllocator *>(d); 32.36 + void *ptr = malloc(n); 32.37 + data->alloc_total++; 32.38 + if (ptr == nullptr) { 32.39 + data->alloc_failed++; 32.40 + } else { 32.41 + data->tracked.insert(ptr); 32.42 + } 32.43 + return ptr; 32.44 +} 32.45 + 32.46 +void *cx_realloc_testing(void *d, void *mem, size_t n) { 32.47 + auto data = reinterpret_cast<CxTestingAllocator *>(d); 32.48 + void *ptr = realloc(mem, n); 32.49 + if (ptr == mem) { 32.50 + return ptr; 32.51 + } else { 32.52 + data->alloc_total++; 32.53 + if (ptr == nullptr) { 32.54 + data->alloc_failed++; 32.55 + } else { 32.56 + data->free_total++; 32.57 + if (data->tracked.erase(mem) == 0) { 32.58 + data->free_failed++; 32.59 + } 32.60 + data->tracked.insert(ptr); 32.61 + } 32.62 + return ptr; 32.63 + } 32.64 +} 32.65 + 32.66 +void *cx_calloc_testing(void *d, size_t nelem, size_t n) { 32.67 + auto data = reinterpret_cast<CxTestingAllocator *>(d); 32.68 + void *ptr = calloc(nelem, n); 32.69 + data->alloc_total++; 32.70 + if (ptr == nullptr) { 32.71 + data->alloc_failed++; 32.72 + } else { 32.73 + data->tracked.insert(ptr); 32.74 + } 32.75 + return ptr; 32.76 +} 32.77 + 32.78 +void cx_free_testing(void *d, void *mem) { 32.79 + auto data = reinterpret_cast<CxTestingAllocator *>(d); 32.80 + data->free_total++; 32.81 + if (data->tracked.erase(mem) == 0) { 32.82 + data->free_failed++; 32.83 + // do not even attempt to free mem, because it is likely to segfault 32.84 + } else { 32.85 + free(mem); 32.86 + } 32.87 +} 32.88 + 32.89 +cx_allocator_class cx_testing_allocator_class = { 32.90 + cx_malloc_testing, 32.91 + cx_realloc_testing, 32.92 + cx_calloc_testing, 32.93 + cx_free_testing 32.94 +}; 32.95 + 32.96 +CxTestingAllocator::CxTestingAllocator() : CxAllocator() { 32.97 + cl = &cx_testing_allocator_class; 32.98 + data = this; 32.99 +} 32.100 + 32.101 +bool CxTestingAllocator::used() const { 32.102 + return alloc_total > 0; 32.103 +} 32.104 + 32.105 +bool CxTestingAllocator::verify() const { 32.106 + return tracked.empty() && alloc_failed == 0 && free_failed == 0 && alloc_total == free_total; 32.107 +} 32.108 + 32.109 +// SELF-TEST 32.110 + 32.111 +#include <gtest/gtest.h> 32.112 + 32.113 +TEST(TestingAllocator, ExpectFree) { 32.114 + CxTestingAllocator allocator; 32.115 + 32.116 + ASSERT_TRUE(allocator.verify()); 32.117 + EXPECT_FALSE(allocator.used()); 32.118 + auto ptr = cxMalloc(&allocator, 16); 32.119 + EXPECT_TRUE(allocator.used()); 32.120 + ASSERT_NE(ptr, nullptr); 32.121 + EXPECT_FALSE(allocator.verify()); 32.122 + 32.123 + cxFree(&allocator, ptr); 32.124 + EXPECT_TRUE(allocator.verify()); 32.125 +} 32.126 + 32.127 +TEST(TestingAllocator, DetectDoubleFree) { 32.128 + CxTestingAllocator allocator; 32.129 + 32.130 + ASSERT_TRUE(allocator.verify()); 32.131 + auto ptr = cxMalloc(&allocator, 16); 32.132 + ASSERT_NE(ptr, nullptr); 32.133 + 32.134 + cxFree(&allocator, ptr); 32.135 + EXPECT_TRUE(allocator.verify()); 32.136 + ASSERT_NO_FATAL_FAILURE(cxFree(&allocator, ptr)); 32.137 + EXPECT_FALSE(allocator.verify()); 32.138 +} 32.139 + 32.140 +TEST(TestingAllocator, FreeUntracked) { 32.141 + CxTestingAllocator allocator; 32.142 + 32.143 + auto ptr = malloc(16); 32.144 + ASSERT_TRUE(allocator.verify()); 32.145 + ASSERT_NO_FATAL_FAILURE(cxFree(&allocator, ptr)); 32.146 + EXPECT_FALSE(allocator.verify()); 32.147 + ASSERT_NO_FATAL_FAILURE(free(ptr)); 32.148 +} 32.149 + 32.150 +TEST(TestingAllocator, FullLifecycleWithRealloc) { 32.151 + CxTestingAllocator allocator; 32.152 + ASSERT_TRUE(allocator.verify()); 32.153 + auto ptr = cxMalloc(&allocator, 16); 32.154 + ASSERT_NE(ptr, nullptr); 32.155 + EXPECT_EQ(allocator.tracked.size(), 1); 32.156 + ptr = cxRealloc(&allocator, ptr, 256); 32.157 + ASSERT_NE(ptr, nullptr); 32.158 + EXPECT_EQ(allocator.tracked.size(), 1); 32.159 + cxFree(&allocator, ptr); 32.160 + EXPECT_TRUE(allocator.verify()); 32.161 +} 32.162 + 32.163 +TEST(TestingAllocator, CallocInitializes) { 32.164 + CxTestingAllocator allocator; 32.165 + const char zeros[16] = {0}; 32.166 + auto ptr = cxCalloc(&allocator, 16, 1); 32.167 + EXPECT_EQ(memcmp(ptr, zeros, 16), 0); 32.168 + cxFree(&allocator, ptr); 32.169 + EXPECT_TRUE(allocator.verify()); 32.170 +}
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/tests/util_allocator.h Tue Feb 07 21:55:37 2023 +0100 33.3 @@ -0,0 +1,81 @@ 33.4 +/* 33.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 33.6 + * 33.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 33.8 + * 33.9 + * Redistribution and use in source and binary forms, with or without 33.10 + * modification, are permitted provided that the following conditions are met: 33.11 + * 33.12 + * 1. Redistributions of source code must retain the above copyright 33.13 + * notice, this list of conditions and the following disclaimer. 33.14 + * 33.15 + * 2. Redistributions in binary form must reproduce the above copyright 33.16 + * notice, this list of conditions and the following disclaimer in the 33.17 + * documentation and/or other materials provided with the distribution. 33.18 + * 33.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 33.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 33.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 33.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 33.29 + * POSSIBILITY OF SUCH DAMAGE. 33.30 + */ 33.31 + 33.32 +#ifndef UCX_UTIL_ALLOCATOR_H 33.33 +#define UCX_UTIL_ALLOCATOR_H 33.34 + 33.35 +#include "cx/allocator.h" 33.36 + 33.37 +#include <set> 33.38 + 33.39 +struct CxTestingAllocator : public CxAllocator { 33.40 + /** 33.41 + * Total number of all allocations (malloc, calloc, realloc). 33.42 + * A realloc() does only count when the memory has to be moved. 33.43 + */ 33.44 + unsigned alloc_total = 0; 33.45 + /** 33.46 + * Number of failed allocations (malloc, calloc, realloc). 33.47 + */ 33.48 + unsigned alloc_failed = 0; 33.49 + /** 33.50 + * Total number of freed pointers. 33.51 + * A reallocation also counts as a free when the memory has to be moved. 33.52 + */ 33.53 + unsigned free_total = 0; 33.54 + /** 33.55 + * Number of failed free invocations. 33.56 + * A free() is considered failed, if it has not been performed on tracked memory. 33.57 + */ 33.58 + unsigned free_failed = 0; 33.59 + /** 33.60 + * The set of tracked memory blocks. 33.61 + */ 33.62 + std::set<void *> tracked; 33.63 + 33.64 + /** 33.65 + * Constructs a new testing allocator. 33.66 + */ 33.67 + CxTestingAllocator(); 33.68 + 33.69 + /** 33.70 + * Verifies that this allocator has been used. 33.71 + * 33.72 + * @return true if any allocation was attempted using this allocator 33.73 + */ 33.74 + [[nodiscard]] bool used() const; 33.75 + 33.76 + /** 33.77 + * Verifies that all allocated memory blocks are freed and no free occurred twice. 33.78 + * 33.79 + * @return true iff all tracked allocations / deallocations were valid 33.80 + */ 33.81 + [[nodiscard]] bool verify() const; 33.82 +}; 33.83 + 33.84 +#endif // UCX_UTIL_ALLOCATOR_H