Wed, 08 Feb 2023 20:26:26 +0100
Automated merge
src/array_list.c | file | annotate | diff | comparison | revisions | |
src/cx/utils.h | file | annotate | diff | comparison | revisions | |
src/linked_list.c | file | annotate | diff | comparison | revisions | |
test/test_list.cpp | file | annotate | diff | comparison | revisions | |
test/test_utils.cpp | file | annotate | diff | comparison | revisions | |
tests/test_list.cpp | file | annotate | diff | comparison | revisions | |
tests/test_utils.cpp | file | annotate | diff | comparison | revisions |
1.1 --- a/CMakeLists.txt Wed Feb 08 20:26:09 2023 +0100 1.2 +++ b/CMakeLists.txt Wed Feb 08 20:26:26 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/README Wed Feb 08 20:26:09 2023 +0100 2.2 +++ b/README Wed Feb 08 20:26:26 2023 +0100 2.3 @@ -38,7 +38,7 @@ 2.4 2.5 If you want to verify your build, you can run 2.6 2.7 - make check 2.8 + make test 2.9 2.10 2.11 3. Documentation
3.1 --- a/src/allocator.c Wed Feb 08 20:26:09 2023 +0100 3.2 +++ b/src/allocator.c Wed Feb 08 20:26:26 2023 +0100 3.3 @@ -28,8 +28,6 @@ 3.4 3.5 #include "cx/allocator.h" 3.6 3.7 -#include <stdlib.h> 3.8 - 3.9 __attribute__((__malloc__, __alloc_size__(2))) 3.10 static void *cx_malloc_stdlib( 3.11 __attribute__((__unused__)) void *d,
4.1 --- a/src/array_list.c Wed Feb 08 20:26:09 2023 +0100 4.2 +++ b/src/array_list.c Wed Feb 08 20:26:26 2023 +0100 4.3 @@ -29,7 +29,6 @@ 4.4 #include "cx/array_list.h" 4.5 #include <assert.h> 4.6 #include <string.h> 4.7 -#include <stdint.h> 4.8 4.9 // LOW LEVEL ARRAY LIST FUNCTIONS 4.10
5.1 --- a/src/basic_mempool.c Wed Feb 08 20:26:09 2023 +0100 5.2 +++ b/src/basic_mempool.c Wed Feb 08 20:26:26 2023 +0100 5.3 @@ -28,7 +28,6 @@ 5.4 5.5 #include "cx/basic_mempool.h" 5.6 #include "cx/utils.h" 5.7 -#include <stdint.h> 5.8 #include <string.h> 5.9 5.10 #define of_chk_(n) if (SIZE_MAX - sizeof(cx_destructor_func) < (n)) return NULL
6.1 --- a/src/buffer.c Wed Feb 08 20:26:09 2023 +0100 6.2 +++ b/src/buffer.c Wed Feb 08 20:26:26 2023 +0100 6.3 @@ -29,10 +29,8 @@ 6.4 #include "cx/buffer.h" 6.5 #include "cx/utils.h" 6.6 6.7 -#include <stdlib.h> 6.8 #include <stdio.h> 6.9 #include <string.h> 6.10 -#include <stdint.h> 6.11 6.12 int cxBufferInit( 6.13 CxBuffer *buffer,
7.1 --- a/src/compare.c Wed Feb 08 20:26:09 2023 +0100 7.2 +++ b/src/compare.c Wed Feb 08 20:26:26 2023 +0100 7.3 @@ -28,7 +28,6 @@ 7.4 7.5 #include "cx/compare.h" 7.6 7.7 -#include <stdint.h> 7.8 #include <math.h> 7.9 7.10 int cx_cmp_int(void const *i1, void const *i2) {
8.1 --- a/src/cx/common.h Wed Feb 08 20:26:09 2023 +0100 8.2 +++ b/src/cx/common.h Wed Feb 08 20:26:26 2023 +0100 8.3 @@ -92,6 +92,7 @@ 8.4 #include <stdlib.h> 8.5 #include <stddef.h> 8.6 #include <stdbool.h> 8.7 +#include <stdint.h> 8.8 8.9 /** 8.10 * Function pointer compatible with fwrite-like functions. 8.11 @@ -104,13 +105,11 @@ 8.12 ); 8.13 8.14 #ifdef _WIN32 8.15 -#ifndef __WORDSIZE 8.16 -#ifdef _WIN64 8.17 -#define __WORDSIZE 64 8.18 -#else 8.19 -#define __WORDSIZE 32 8.20 -#endif 8.21 -#endif // __WORDSIZE 8.22 + 8.23 +#ifdef __MINGW32__ 8.24 +#include <sys/types.h> 8.25 +#endif // __MINGW32__ 8.26 + 8.27 #else // !_WIN32 8.28 8.29 #include <sys/types.h>
9.1 --- a/src/cx/compare.h Wed Feb 08 20:26:09 2023 +0100 9.2 +++ b/src/cx/compare.h Wed Feb 08 20:26:26 2023 +0100 9.3 @@ -37,6 +37,8 @@ 9.4 #ifndef UCX_COMPARE_H 9.5 #define UCX_COMPARE_H 9.6 9.7 +#include "common.h" 9.8 + 9.9 #ifdef __cplusplus 9.10 extern "C" { 9.11 #endif
10.1 --- a/src/cx/utils.h Wed Feb 08 20:26:09 2023 +0100 10.2 +++ b/src/cx/utils.h Wed Feb 08 20:26:26 2023 +0100 10.3 @@ -65,9 +65,8 @@ 10.4 #if (__GNUC__ >= 5 || defined(__clang__)) && !defined(CX_NO_SZMUL_BUILTIN) 10.5 #define CX_SZMUL_BUILTIN 10.6 10.7 -#if __WORDSIZE == 32 10.8 /** 10.9 - * Alias for \c __builtin_umul_overflow. 10.10 + * Alias for \c __builtin_mul_overflow. 10.11 * 10.12 * Performs a multiplication of size_t values and checks for overflow. 10.13 * 10.14 @@ -78,22 +77,7 @@ 10.15 * @return zero, if no overflow occurred and the result is correct, non-zero 10.16 * otherwise 10.17 */ 10.18 -#define cx_szmul(a, b, result) __builtin_umul_overflow(a, b, result) 10.19 -#else // __WORDSIZE != 32 10.20 -/** 10.21 - * Alias for \c __builtin_umull_overflow. 10.22 - * 10.23 - * Performs a multiplication of size_t values and checks for overflow. 10.24 - * 10.25 - * @param a first operand 10.26 - * @param b second operand 10.27 - * @param result a pointer to a size_t, where the result should 10.28 - * be stored 10.29 - * @return zero, if no overflow occurred and the result is correct, non-zero 10.30 - * otherwise 10.31 - */ 10.32 -#define cx_szmul(a, b, result) __builtin_umull_overflow(a, b, result) 10.33 -#endif // __WORDSIZE 10.34 +#define cx_szmul(a, b, result) __builtin_mul_overflow(a, b, result) 10.35 10.36 #else // no GNUC or clang bultin 10.37
11.1 --- a/src/linked_list.c Wed Feb 08 20:26:09 2023 +0100 11.2 +++ b/src/linked_list.c Wed Feb 08 20:26:26 2023 +0100 11.3 @@ -28,7 +28,6 @@ 11.4 11.5 #include "cx/linked_list.h" 11.6 #include "cx/utils.h" 11.7 -#include <stdint.h> 11.8 #include <string.h> 11.9 #include <assert.h> 11.10
12.1 --- a/test/.clang-tidy Wed Feb 08 20:26:09 2023 +0100 12.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 12.3 @@ -1,2 +0,0 @@ 12.4 -# Disable static initialization warning for test code 12.5 -Checks: '-cert-err58-cpp'
13.1 --- a/test/CMakeLists.txt Wed Feb 08 20:26:09 2023 +0100 13.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 13.3 @@ -1,32 +0,0 @@ 13.4 -# Load Google Test Framework 13.5 -set(CMAKE_CXX_STANDARD 17) 13.6 - 13.7 -include(FetchContent) 13.8 -FetchContent_Declare( 13.9 - googletest 13.10 - GIT_REPOSITORY https://github.com/google/googletest.git 13.11 - GIT_TAG e2239ee6043f73722e7aa812a459f54a28552929 # release 1.11.0 13.12 -) 13.13 -# For Windows: Prevent overriding the parent project's compiler/linker settings 13.14 -set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 13.15 -FetchContent_MakeAvailable(googletest) 13.16 -include(GoogleTest) 13.17 -message(STATUS "Google Test made available") 13.18 - 13.19 -add_executable(ucxtest 13.20 - test_utils.cpp 13.21 - test_allocator.cpp 13.22 - test_compare.cpp 13.23 - test_string.cpp 13.24 - test_buffer.cpp 13.25 - test_list.cpp 13.26 - test_tree.cpp 13.27 - test_hash_key.cpp 13.28 - test_map.cpp 13.29 - test_basic_mempool.cpp 13.30 - test_printf.cpp 13.31 - selftest.cpp 13.32 - util_allocator.cpp 13.33 - ) 13.34 -target_link_libraries(ucxtest PRIVATE ucx_static gtest_main) 13.35 -gtest_discover_tests(ucxtest)
14.1 --- a/test/selftest.cpp Wed Feb 08 20:26:09 2023 +0100 14.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 14.3 @@ -1,43 +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 <gtest/gtest.h> 14.33 -#include <cx/common.h> 14.34 - 14.35 -TEST(SelfTest, BasicAssertion) { 14.36 - EXPECT_EQ(7 * 6, 42); 14.37 -} 14.38 - 14.39 -TEST(SelfTest, UcxVersion) { 14.40 - EXPECT_GE(UCX_VERSION_MAJOR, 3); 14.41 - EXPECT_GE(UCX_VERSION, 3 << 16); 14.42 -} 14.43 - 14.44 -TEST(SelfTest, CommonDefinitions) { 14.45 - EXPECT_EQ(__WORDSIZE, 8 * sizeof(void*)); 14.46 -}
15.1 --- a/test/test_allocator.cpp Wed Feb 08 20:26:09 2023 +0100 15.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 15.3 @@ -1,96 +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/allocator.h" 15.33 -#include <gtest/gtest.h> 15.34 - 15.35 -TEST(Allocator, DefaultAllocator) { 15.36 - cx_allocator_class *clazz = cxDefaultAllocator->cl; 15.37 - ASSERT_NE(clazz, nullptr); 15.38 -} 15.39 - 15.40 -TEST(Allocator, DefaultMalloc) { 15.41 - void *test = cxMalloc(cxDefaultAllocator, 16); 15.42 - ASSERT_NE(test, nullptr); 15.43 - free(test); 15.44 -} 15.45 - 15.46 -TEST(Allocator, DefaultRealloc) { 15.47 - void *test = calloc(8, 1); 15.48 - memcpy(test, "Test", 5); 15.49 - test = cxRealloc(cxDefaultAllocator, test, 16); 15.50 - ASSERT_NE(test, nullptr); 15.51 - EXPECT_STREQ(reinterpret_cast<char *>(test), "Test"); 15.52 - free(test); 15.53 -} 15.54 - 15.55 -TEST(Allocator, Reallocate) { 15.56 - void *test = calloc(8, 1); 15.57 - memcpy(test, "Test", 5); 15.58 - int ret = cxReallocate(cxDefaultAllocator, &test, 16); 15.59 - EXPECT_EQ(ret, 0); 15.60 - ASSERT_NE(test, nullptr); 15.61 - EXPECT_STREQ(reinterpret_cast<char *>(test), "Test"); 15.62 - free(test); 15.63 -} 15.64 - 15.65 -TEST(Allocator, DefaultCalloc) { 15.66 - char *test = reinterpret_cast<char *>(cxCalloc(cxDefaultAllocator, 8, 2)); 15.67 - ASSERT_NE(test, nullptr); 15.68 - for (int i = 0; i < 16; i++) ASSERT_EQ(test[i], 0); 15.69 - free(test); 15.70 -} 15.71 - 15.72 -TEST(Allocator, DefaultFree) { 15.73 - void *test = malloc(16); 15.74 - EXPECT_NO_FATAL_FAILURE( 15.75 - cxFree(cxDefaultAllocator, test); 15.76 - ); 15.77 -} 15.78 - 15.79 -TEST(Allocator, FailingReallocate) { 15.80 - // Mock an allocator that always returns nullptr on realloc 15.81 - cx_allocator_class mock_cl; 15.82 - mock_cl.realloc = []( 15.83 - [[maybe_unused]]void *p, 15.84 - [[maybe_unused]]void *d, 15.85 - [[maybe_unused]]size_t n 15.86 - ) -> void * { return nullptr; }; 15.87 - cx_allocator_s mock{&mock_cl, nullptr}; 15.88 - 15.89 - void *test = calloc(8, 1); 15.90 - memcpy(test, "Test", 5); 15.91 - void *original = test; 15.92 - int ret = cxReallocate(&mock, &test, 16); 15.93 - // non-zero return code because of the failure 15.94 - EXPECT_NE(ret, 0); 15.95 - // the test pointer was not changed and still points to the same memory 15.96 - EXPECT_EQ(test, original); 15.97 - EXPECT_STREQ(reinterpret_cast<char *>(test), "Test"); 15.98 - free(test); 15.99 -}
16.1 --- a/test/test_basic_mempool.cpp Wed Feb 08 20:26:09 2023 +0100 16.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 16.3 @@ -1,154 +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 "cx/basic_mempool.h" 16.33 -#include "util_allocator.h" 16.34 -#include <gtest/gtest.h> 16.35 - 16.36 -class CxBasicMempool : public ::testing::Test { 16.37 -protected: 16.38 - CxMempool *pool = nullptr; 16.39 - 16.40 - void TearDown() override { 16.41 - if (pool != nullptr) { 16.42 - cxMempoolDestroy(pool); 16.43 - } 16.44 - } 16.45 -}; 16.46 - 16.47 -TEST_F(CxBasicMempool, Create) { 16.48 - pool = cxBasicMempoolCreate(16); 16.49 - ASSERT_NE(pool->allocator, nullptr); 16.50 - ASSERT_NE(pool->cl, nullptr); 16.51 - EXPECT_NE(pool->cl->destroy, nullptr); 16.52 - ASSERT_NE(pool->allocator->cl, nullptr); 16.53 - EXPECT_EQ(pool->allocator->data, pool); 16.54 - EXPECT_NE(pool->allocator->cl->malloc, nullptr); 16.55 - EXPECT_NE(pool->allocator->cl->calloc, nullptr); 16.56 - EXPECT_NE(pool->allocator->cl->realloc, nullptr); 16.57 - EXPECT_NE(pool->allocator->cl->free, nullptr); 16.58 - 16.59 - auto basic_pool = reinterpret_cast<cx_basic_mempool_s *>(pool); 16.60 - EXPECT_EQ(basic_pool->size, 16); 16.61 - EXPECT_EQ(basic_pool->ndata, 0); 16.62 - EXPECT_NE(basic_pool->data, nullptr); 16.63 -} 16.64 - 16.65 -TEST_F(CxBasicMempool, malloc) { 16.66 - pool = cxBasicMempoolCreate(4); 16.67 - auto basic_pool = reinterpret_cast<cx_basic_mempool_s *>(pool); 16.68 - EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 16.69 - EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 16.70 - EXPECT_EQ(basic_pool->ndata, 2); 16.71 - EXPECT_EQ(basic_pool->size, 4); 16.72 - EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 16.73 - EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 16.74 - EXPECT_EQ(basic_pool->ndata, 4); 16.75 - EXPECT_EQ(basic_pool->size, 4); 16.76 - EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 16.77 - EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 16.78 - EXPECT_EQ(basic_pool->ndata, 6); 16.79 - EXPECT_GE(basic_pool->size, 6); 16.80 -} 16.81 - 16.82 -TEST_F(CxBasicMempool, calloc) { 16.83 - pool = cxBasicMempoolCreate(4); 16.84 - 16.85 - auto test = (int *) cxCalloc(pool->allocator, 2, sizeof(int)); 16.86 - ASSERT_NE(test, nullptr); 16.87 - EXPECT_EQ(test[0], 0); 16.88 - EXPECT_EQ(test[1], 0); 16.89 -} 16.90 - 16.91 -static unsigned test_destructor_called = 0; 16.92 - 16.93 -static void test_destructor([[maybe_unused]] void *mem) { 16.94 - test_destructor_called++; 16.95 -} 16.96 - 16.97 -TEST_F(CxBasicMempool, destructor) { 16.98 - pool = cxBasicMempoolCreate(4); 16.99 - auto data = cxMalloc(pool->allocator, sizeof(int)); 16.100 - *((int *) data) = 13; 16.101 - cxMempoolSetDestructor(pool, data, test_destructor); 16.102 - EXPECT_EQ(*((int *) data), 13); 16.103 - test_destructor_called = 0; 16.104 - cxFree(pool->allocator, data); 16.105 - EXPECT_EQ(test_destructor_called, 1); 16.106 - data = cxMalloc(pool->allocator, sizeof(int)); 16.107 - cxMempoolSetDestructor(pool, data, test_destructor); 16.108 - cxMempoolDestroy(pool); 16.109 - pool = nullptr; 16.110 - EXPECT_EQ(test_destructor_called, 2); 16.111 -} 16.112 - 16.113 -TEST_F(CxBasicMempool, realloc) { 16.114 - pool = cxBasicMempoolCreate(4); 16.115 - auto data = cxMalloc(pool->allocator, sizeof(int)); 16.116 - *((int *) data) = 13; 16.117 - cxMempoolSetDestructor(pool, data, test_destructor); 16.118 - 16.119 - void *rdata = data; 16.120 - unsigned n = 1; 16.121 - while (rdata == data) { 16.122 - n <<= 1; 16.123 - ASSERT_LT(n, 65536); // eventually the memory should be moved elsewhere 16.124 - rdata = cxRealloc(pool->allocator, data, n * sizeof(intptr_t)); 16.125 - } 16.126 - 16.127 - EXPECT_EQ(*((int *) rdata), 13); 16.128 - // test if destructor is still intact 16.129 - test_destructor_called = 0; 16.130 - cxFree(pool->allocator, rdata); 16.131 - EXPECT_EQ(test_destructor_called, 1); 16.132 -} 16.133 - 16.134 - 16.135 -TEST_F(CxBasicMempool, free) { 16.136 - pool = cxBasicMempoolCreate(4); 16.137 - auto basic_pool = reinterpret_cast<cx_basic_mempool_s *>(pool); 16.138 - 16.139 - void *mem1; 16.140 - void *mem2; 16.141 - 16.142 - mem1 = cxMalloc(pool->allocator, 16); 16.143 - cxFree(pool->allocator, mem1); 16.144 - EXPECT_EQ(basic_pool->ndata, 0); 16.145 - 16.146 - cxMalloc(pool->allocator, 16); 16.147 - cxMalloc(pool->allocator, 16); 16.148 - mem1 = cxMalloc(pool->allocator, 16); 16.149 - cxMalloc(pool->allocator, 16); 16.150 - mem2 = cxMalloc(pool->allocator, 16); 16.151 - 16.152 - EXPECT_EQ(basic_pool->ndata, 5); 16.153 - cxFree(pool->allocator, mem1); 16.154 - EXPECT_EQ(basic_pool->ndata, 4); 16.155 - cxFree(pool->allocator, mem2); 16.156 - EXPECT_EQ(basic_pool->ndata, 3); 16.157 -} 16.158 \ No newline at end of file
17.1 --- a/test/test_buffer.cpp Wed Feb 08 20:26:09 2023 +0100 17.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 17.3 @@ -1,815 +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 -#include "cx/buffer.h" 17.33 - 17.34 -#include <gtest/gtest.h> 17.35 -#include "util_allocator.h" 17.36 - 17.37 -class BufferFixture : public ::testing::Test { 17.38 -protected: 17.39 - void SetUp() override { 17.40 - cxBufferInit(&buf, nullptr, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT); 17.41 - buf.size = 6; 17.42 - buf.pos = 3; 17.43 - } 17.44 - 17.45 - void TearDown() override { 17.46 - cxBufferDestroy(&buf); 17.47 - } 17.48 - 17.49 - CxBuffer buf{}; 17.50 -}; 17.51 - 17.52 -static void expect_default_flush_config(CxBuffer *buf) { 17.53 - EXPECT_EQ(buf->flush_blkmax, 0); 17.54 - EXPECT_EQ(buf->flush_blksize, 4096); 17.55 - EXPECT_EQ(buf->flush_threshold, SIZE_MAX); 17.56 - EXPECT_EQ(buf->flush_func, nullptr); 17.57 - EXPECT_EQ(buf->flush_target, nullptr); 17.58 -} 17.59 - 17.60 -TEST(BufferInit, WrapSpace) { 17.61 - CxTestingAllocator alloc; 17.62 - CxBuffer buf; 17.63 - void *space = cxMalloc(&alloc, 16); 17.64 - cxBufferInit(&buf, space, 16, &alloc, CX_BUFFER_DEFAULT); 17.65 - expect_default_flush_config(&buf); 17.66 - EXPECT_EQ(buf.space, space); 17.67 - EXPECT_EQ(buf.flags & CX_BUFFER_AUTO_EXTEND, 0); 17.68 - EXPECT_EQ(buf.flags & CX_BUFFER_FREE_CONTENTS, 0); 17.69 - EXPECT_EQ(buf.pos, 0); 17.70 - EXPECT_EQ(buf.size, 0); 17.71 - EXPECT_EQ(buf.capacity, 16); 17.72 - EXPECT_EQ(buf.allocator, &alloc); 17.73 - cxBufferDestroy(&buf); 17.74 - EXPECT_FALSE(alloc.verify()); 17.75 - cxFree(&alloc, space); 17.76 - EXPECT_TRUE(alloc.verify()); 17.77 -} 17.78 - 17.79 -TEST(BufferInit, WrapSpaceAutoExtend) { 17.80 - CxTestingAllocator alloc; 17.81 - CxBuffer buf; 17.82 - void *space = cxMalloc(&alloc, 16); 17.83 - cxBufferInit(&buf, space, 16, &alloc, CX_BUFFER_AUTO_EXTEND); 17.84 - expect_default_flush_config(&buf); 17.85 - EXPECT_EQ(buf.space, space); 17.86 - EXPECT_EQ(buf.flags & CX_BUFFER_AUTO_EXTEND, CX_BUFFER_AUTO_EXTEND); 17.87 - EXPECT_EQ(buf.flags & CX_BUFFER_FREE_CONTENTS, 0); 17.88 - EXPECT_EQ(buf.pos, 0); 17.89 - EXPECT_EQ(buf.size, 0); 17.90 - EXPECT_EQ(buf.capacity, 16); 17.91 - EXPECT_EQ(buf.allocator, &alloc); 17.92 - cxBufferDestroy(&buf); 17.93 - EXPECT_FALSE(alloc.verify()); 17.94 - cxFree(&alloc, space); 17.95 - EXPECT_TRUE(alloc.verify()); 17.96 -} 17.97 - 17.98 -TEST(BufferInit, WrapSpaceAutoFree) { 17.99 - CxTestingAllocator alloc; 17.100 - CxBuffer buf; 17.101 - void *space = cxMalloc(&alloc, 16); 17.102 - cxBufferInit(&buf, space, 16, &alloc, CX_BUFFER_FREE_CONTENTS); 17.103 - expect_default_flush_config(&buf); 17.104 - EXPECT_EQ(buf.space, space); 17.105 - EXPECT_EQ(buf.flags & CX_BUFFER_AUTO_EXTEND, 0); 17.106 - EXPECT_EQ(buf.flags & CX_BUFFER_FREE_CONTENTS, CX_BUFFER_FREE_CONTENTS); 17.107 - EXPECT_EQ(buf.pos, 0); 17.108 - EXPECT_EQ(buf.size, 0); 17.109 - EXPECT_EQ(buf.capacity, 16); 17.110 - EXPECT_EQ(buf.allocator, &alloc); 17.111 - EXPECT_FALSE(alloc.verify()); 17.112 - cxBufferDestroy(&buf); 17.113 - EXPECT_TRUE(alloc.verify()); 17.114 -} 17.115 - 17.116 -TEST(BufferInit, FreshSpace) { 17.117 - CxTestingAllocator alloc; 17.118 - CxBuffer buf; 17.119 - cxBufferInit(&buf, nullptr, 8, &alloc, CX_BUFFER_DEFAULT); 17.120 - expect_default_flush_config(&buf); 17.121 - EXPECT_NE(buf.space, nullptr); 17.122 - EXPECT_EQ(buf.flags & CX_BUFFER_AUTO_EXTEND, 0); 17.123 - EXPECT_EQ(buf.flags & CX_BUFFER_FREE_CONTENTS, CX_BUFFER_FREE_CONTENTS); 17.124 - EXPECT_EQ(buf.pos, 0); 17.125 - EXPECT_EQ(buf.size, 0); 17.126 - EXPECT_EQ(buf.capacity, 8); 17.127 - EXPECT_EQ(buf.allocator, &alloc); 17.128 - EXPECT_FALSE(alloc.verify()); // space is still allocated 17.129 - cxBufferDestroy(&buf); 17.130 - EXPECT_TRUE(alloc.verify()); 17.131 -} 17.132 - 17.133 -class BufferShiftFixture : public ::testing::Test { 17.134 -protected: 17.135 - void SetUp() override { 17.136 - ASSERT_TRUE(alloc.verify()); 17.137 - cxBufferInit(&buf, nullptr, 16, &alloc, CX_BUFFER_DEFAULT); 17.138 - memcpy(buf.space, "test____________", 16); 17.139 - buf.capacity = 8; // purposely pretend that the buffer has less capacity s.t. we can test beyond the range 17.140 - buf.pos = 4; 17.141 - buf.size = 4; 17.142 - } 17.143 - 17.144 - void TearDown() override { 17.145 - cxBufferDestroy(&buf); 17.146 - EXPECT_TRUE(alloc.verify()); 17.147 - } 17.148 - 17.149 - CxTestingAllocator alloc; 17.150 - CxBuffer buf{}; 17.151 -}; 17.152 - 17.153 -class BufferShiftLeft : public BufferShiftFixture { 17.154 -}; 17.155 - 17.156 -TEST_F(BufferShiftLeft, Zero) { 17.157 - ASSERT_EQ(buf.pos, 4); 17.158 - ASSERT_EQ(buf.size, 4); 17.159 - int ret = cxBufferShiftLeft(&buf, 0); 17.160 - EXPECT_EQ(ret, 0); 17.161 - EXPECT_EQ(buf.pos, 4); 17.162 - EXPECT_EQ(buf.size, 4); 17.163 - EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 17.164 -} 17.165 - 17.166 -TEST_F(BufferShiftLeft, ZeroOffsetInterface) { 17.167 - ASSERT_EQ(buf.pos, 4); 17.168 - ASSERT_EQ(buf.size, 4); 17.169 - int ret = cxBufferShift(&buf, -0); 17.170 - EXPECT_EQ(ret, 0); 17.171 - EXPECT_EQ(buf.pos, 4); 17.172 - EXPECT_EQ(buf.size, 4); 17.173 - EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 17.174 -} 17.175 - 17.176 -TEST_F(BufferShiftLeft, Standard) { 17.177 - ASSERT_EQ(buf.pos, 4); 17.178 - ASSERT_EQ(buf.size, 4); 17.179 - int ret = cxBufferShiftLeft(&buf, 2); 17.180 - EXPECT_EQ(ret, 0); 17.181 - EXPECT_EQ(buf.pos, 2); 17.182 - EXPECT_EQ(buf.size, 2); 17.183 - EXPECT_TRUE(memcmp(buf.space, "stst________", 8) == 0); 17.184 -} 17.185 - 17.186 -TEST_F(BufferShiftLeft, Overshift) { 17.187 - ASSERT_LT(buf.pos, 6); 17.188 - ASSERT_LT(buf.size, 6); 17.189 - int ret = cxBufferShiftLeft(&buf, 6); 17.190 - EXPECT_EQ(ret, 0); 17.191 - EXPECT_EQ(buf.pos, 0); 17.192 - EXPECT_EQ(buf.size, 0); 17.193 - EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 17.194 -} 17.195 - 17.196 -TEST_F(BufferShiftLeft, OvershiftPosOnly) { 17.197 - buf.pos = 2; 17.198 - ASSERT_EQ(buf.size, 4); 17.199 - int ret = cxBufferShiftLeft(&buf, 3); 17.200 - EXPECT_EQ(ret, 0); 17.201 - EXPECT_EQ(buf.pos, 0); 17.202 - EXPECT_EQ(buf.size, 1); 17.203 - EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 17.204 -} 17.205 - 17.206 -TEST_F(BufferShiftLeft, OffsetInterface) { 17.207 - buf.pos = 3; 17.208 - ASSERT_EQ(buf.size, 4); 17.209 - int ret = cxBufferShift(&buf, -2); 17.210 - EXPECT_EQ(ret, 0); 17.211 - EXPECT_EQ(buf.pos, 1); 17.212 - EXPECT_EQ(buf.size, 2); 17.213 - EXPECT_TRUE(memcmp(buf.space, "stst________", 8) == 0); 17.214 -} 17.215 - 17.216 -class BufferShiftRight : public BufferShiftFixture { 17.217 -}; 17.218 - 17.219 -TEST_F(BufferShiftRight, Zero) { 17.220 - ASSERT_EQ(buf.pos, 4); 17.221 - ASSERT_EQ(buf.size, 4); 17.222 - int ret = cxBufferShiftRight(&buf, 0); 17.223 - EXPECT_EQ(ret, 0); 17.224 - EXPECT_EQ(buf.pos, 4); 17.225 - EXPECT_EQ(buf.size, 4); 17.226 - EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 17.227 -} 17.228 - 17.229 -TEST_F(BufferShiftRight, ZeroOffsetInterface) { 17.230 - ASSERT_EQ(buf.pos, 4); 17.231 - ASSERT_EQ(buf.size, 4); 17.232 - int ret = cxBufferShift(&buf, +0); 17.233 - EXPECT_EQ(ret, 0); 17.234 - EXPECT_EQ(buf.pos, 4); 17.235 - EXPECT_EQ(buf.size, 4); 17.236 - EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 17.237 -} 17.238 - 17.239 -TEST_F(BufferShiftRight, Standard) { 17.240 - ASSERT_EQ(buf.pos, 4); 17.241 - ASSERT_EQ(buf.size, 4); 17.242 - int ret = cxBufferShiftRight(&buf, 3); 17.243 - EXPECT_EQ(ret, 0); 17.244 - EXPECT_EQ(buf.pos, 7); 17.245 - EXPECT_EQ(buf.size, 7); 17.246 - EXPECT_TRUE(memcmp(buf.space, "testest_____", 8) == 0); 17.247 -} 17.248 - 17.249 -TEST_F(BufferShiftRight, OvershiftDiscard) { 17.250 - ASSERT_EQ(buf.pos, 4); 17.251 - ASSERT_EQ(buf.size, 4); 17.252 - ASSERT_EQ(buf.capacity, 8); 17.253 - int ret = cxBufferShiftRight(&buf, 6); 17.254 - EXPECT_EQ(ret, 0); 17.255 - EXPECT_EQ(buf.pos, 8); 17.256 - EXPECT_EQ(buf.size, 8); 17.257 - EXPECT_EQ(buf.capacity, 8); 17.258 - EXPECT_TRUE(memcmp(buf.space, "test__te____", 8) == 0); 17.259 -} 17.260 - 17.261 -TEST_F(BufferShiftRight, OvershiftExtend) { 17.262 - ASSERT_EQ(buf.pos, 4); 17.263 - ASSERT_EQ(buf.size, 4); 17.264 - ASSERT_EQ(buf.capacity, 8); 17.265 - buf.flags |= CX_BUFFER_AUTO_EXTEND; 17.266 - int ret = cxBufferShiftRight(&buf, 6); 17.267 - EXPECT_EQ(ret, 0); 17.268 - EXPECT_EQ(buf.pos, 10); 17.269 - EXPECT_EQ(buf.size, 10); 17.270 - EXPECT_GE(buf.capacity, 10); 17.271 - EXPECT_TRUE(memcmp(buf.space, "test__test__", 8) == 0); 17.272 -} 17.273 - 17.274 -TEST_F(BufferShiftRight, OffsetInterface) { 17.275 - buf.pos = 3; 17.276 - ASSERT_EQ(buf.size, 4); 17.277 - int ret = cxBufferShift(&buf, 2); 17.278 - EXPECT_EQ(ret, 0); 17.279 - EXPECT_EQ(buf.pos, 5); 17.280 - EXPECT_EQ(buf.size, 6); 17.281 - EXPECT_TRUE(memcmp(buf.space, "tetest______", 8) == 0); 17.282 -} 17.283 - 17.284 -TEST(BufferMinimumCapacity, Sufficient) { 17.285 - CxTestingAllocator alloc; 17.286 - auto space = cxMalloc(&alloc, 8); 17.287 - CxBuffer buf; 17.288 - cxBufferInit(&buf, space, 8, &alloc, CX_BUFFER_FREE_CONTENTS); 17.289 - memcpy(space, "Testing", 8); 17.290 - buf.size = 8; 17.291 - cxBufferMinimumCapacity(&buf, 6); 17.292 - EXPECT_EQ(buf.capacity, 8); 17.293 - EXPECT_EQ(buf.size, 8); 17.294 - EXPECT_TRUE(memcmp(buf.space, "Testing", 8) == 0); 17.295 - cxBufferDestroy(&buf); 17.296 - EXPECT_TRUE(alloc.verify()); 17.297 -} 17.298 - 17.299 -TEST(BufferMinimumCapacity, Extend) { 17.300 - CxTestingAllocator alloc; 17.301 - auto space = cxMalloc(&alloc, 8); 17.302 - CxBuffer buf; 17.303 - cxBufferInit(&buf, space, 8, &alloc, CX_BUFFER_FREE_CONTENTS); // NO auto extend! 17.304 - memcpy(space, "Testing", 8); 17.305 - buf.size = 8; 17.306 - cxBufferMinimumCapacity(&buf, 16); 17.307 - EXPECT_EQ(buf.capacity, 16); 17.308 - EXPECT_EQ(buf.size, 8); 17.309 - EXPECT_TRUE(memcmp(buf.space, "Testing", 8) == 0); 17.310 - cxBufferDestroy(&buf); 17.311 - EXPECT_TRUE(alloc.verify()); 17.312 -} 17.313 - 17.314 -TEST(BufferClear, Test) { 17.315 - char space[16]; 17.316 - strcpy(space, "clear test"); 17.317 - CxBuffer buf; 17.318 - cxBufferInit(&buf, space, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT); 17.319 - ASSERT_EQ(buf.size, 0); 17.320 - // only clear the used part of the buffer 17.321 - cxBufferClear(&buf); 17.322 - EXPECT_EQ(memcmp(space, "clear test", 10), 0); 17.323 - buf.size = 5; 17.324 - buf.pos = 3; 17.325 - cxBufferClear(&buf); 17.326 - EXPECT_EQ(memcmp(space, "\0\0\0\0\0 test", 10), 0); 17.327 - EXPECT_EQ(buf.size, 0); 17.328 - EXPECT_EQ(buf.pos, 0); 17.329 - cxBufferDestroy(&buf); 17.330 -} 17.331 - 17.332 -class BufferWrite : public ::testing::Test { 17.333 -protected: 17.334 - CxBuffer buf{}, target{}; 17.335 - 17.336 - void SetUp() override { 17.337 - cxBufferInit(&target, nullptr, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND); 17.338 - cxBufferInit(&buf, nullptr, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT); 17.339 - buf.capacity = 8; // artificially reduce capacity to check OOB writes 17.340 - memset(buf.space, 0, 16); 17.341 - memcpy(buf.space, "prep", 4); 17.342 - buf.size = buf.pos = 4; 17.343 - } 17.344 - 17.345 - void TearDown() override { 17.346 - cxBufferDestroy(&buf); 17.347 - cxBufferDestroy(&target); 17.348 - } 17.349 - 17.350 - void enableFlushing() { 17.351 - buf.flush_target = ⌖ 17.352 - buf.flush_func = reinterpret_cast<cx_write_func>(cxBufferWrite); 17.353 - buf.flush_blkmax = 1; 17.354 - } 17.355 -}; 17.356 - 17.357 -static size_t mock_write_limited_rate( 17.358 - void const *ptr, 17.359 - size_t size, 17.360 - __attribute__((unused)) size_t nitems, 17.361 - CxBuffer *buffer 17.362 -) { 17.363 - // simulate limited target drain capacity 17.364 - static bool full = false; 17.365 - if (full) { 17.366 - full = false; 17.367 - return 0; 17.368 - } else { 17.369 - full = true; 17.370 - return cxBufferWrite(ptr, size, nitems > 2 ? 2 : nitems, buffer); 17.371 - } 17.372 -} 17.373 - 17.374 -TEST_F(BufferWrite, SizeOneFit) { 17.375 - const char *data = "test"; 17.376 - ASSERT_EQ(buf.capacity, 8); 17.377 - ASSERT_EQ(buf.pos, 4); 17.378 - ASSERT_EQ(buf.size, 4); 17.379 - size_t written = cxBufferWrite(data, 1, 4, &buf); 17.380 - EXPECT_EQ(written, 4); 17.381 - EXPECT_EQ(buf.size, 8); 17.382 - EXPECT_EQ(buf.pos, 8); 17.383 - EXPECT_EQ(buf.capacity, 8); 17.384 - EXPECT_EQ(memcmp(buf.space, "preptest", 8), 0); 17.385 -} 17.386 - 17.387 -TEST_F(BufferWrite, SizeOneDiscard) { 17.388 - const char *data = "testing"; 17.389 - ASSERT_EQ(buf.capacity, 8); 17.390 - ASSERT_EQ(buf.pos, 4); 17.391 - ASSERT_EQ(buf.size, 4); 17.392 - size_t written = cxBufferWrite(data, 1, 7, &buf); 17.393 - EXPECT_EQ(written, 4); 17.394 - EXPECT_EQ(buf.size, 8); 17.395 - EXPECT_EQ(buf.pos, 8); 17.396 - EXPECT_EQ(buf.capacity, 8); 17.397 - EXPECT_EQ(memcmp(buf.space, "preptest\0", 9), 0); 17.398 -} 17.399 - 17.400 -TEST_F(BufferWrite, SizeOneExtend) { 17.401 - buf.flags |= CX_BUFFER_AUTO_EXTEND; 17.402 - const char *data = "testing"; 17.403 - ASSERT_EQ(buf.capacity, 8); 17.404 - ASSERT_EQ(buf.pos, 4); 17.405 - ASSERT_EQ(buf.size, 4); 17.406 - size_t written = cxBufferWrite(data, 1, 7, &buf); 17.407 - EXPECT_EQ(written, 7); 17.408 - EXPECT_EQ(buf.size, 11); 17.409 - EXPECT_EQ(buf.pos, 11); 17.410 - EXPECT_GE(buf.capacity, 11); 17.411 - EXPECT_EQ(memcmp(buf.space, "preptesting", 11), 0); 17.412 -} 17.413 - 17.414 -TEST_F(BufferWrite, MultibyteFit) { 17.415 - const char *data = "test"; 17.416 - ASSERT_EQ(buf.capacity, 8); 17.417 - ASSERT_EQ(buf.pos, 4); 17.418 - ASSERT_EQ(buf.size, 4); 17.419 - size_t written = cxBufferWrite(data, 2, 2, &buf); 17.420 - EXPECT_EQ(written, 2); 17.421 - EXPECT_EQ(buf.size, 8); 17.422 - EXPECT_EQ(buf.pos, 8); 17.423 - EXPECT_EQ(buf.capacity, 8); 17.424 - EXPECT_EQ(memcmp(buf.space, "preptest", 8), 0); 17.425 -} 17.426 - 17.427 -TEST_F(BufferWrite, MultibyteDiscard) { 17.428 - const char *data = "testing"; 17.429 - ASSERT_EQ(buf.capacity, 8); 17.430 - ASSERT_EQ(buf.size, 4); 17.431 - buf.pos = 3; 17.432 - size_t written = cxBufferWrite(data, 2, 4, &buf); 17.433 - // remember: whole elements are discarded if they do not fit 17.434 - EXPECT_EQ(written, 2); 17.435 - EXPECT_EQ(buf.size, 7); 17.436 - EXPECT_EQ(buf.pos, 7); 17.437 - EXPECT_EQ(buf.capacity, 8); 17.438 - EXPECT_EQ(memcmp(buf.space, "pretest\0", 8), 0); 17.439 -} 17.440 - 17.441 -TEST_F(BufferWrite, MultibyteExtend) { 17.442 - buf.flags |= CX_BUFFER_AUTO_EXTEND; 17.443 - const char *data = "tester"; 17.444 - ASSERT_EQ(buf.capacity, 8); 17.445 - ASSERT_EQ(buf.size, 4); 17.446 - buf.pos = 3; 17.447 - size_t written = cxBufferWrite(data, 2, 3, &buf); 17.448 - // remember: whole elements are discarded if they do not fit 17.449 - EXPECT_EQ(written, 3); 17.450 - EXPECT_EQ(buf.size, 9); 17.451 - EXPECT_EQ(buf.pos, 9); 17.452 - EXPECT_GE(buf.capacity, 9); 17.453 - EXPECT_EQ(memcmp(buf.space, "pretester", 9), 0); 17.454 -} 17.455 - 17.456 -TEST_F(BufferWrite, PutcWrapperFit) { 17.457 - ASSERT_EQ(buf.capacity, 8); 17.458 - ASSERT_EQ(buf.pos, 4); 17.459 - ASSERT_EQ(buf.size, 4); 17.460 - int c = cxBufferPut(&buf, 0x200 | 'a'); 17.461 - EXPECT_EQ(c, 'a'); 17.462 - EXPECT_EQ(buf.size, 5); 17.463 - EXPECT_EQ(buf.pos, 5); 17.464 - EXPECT_EQ(buf.capacity, 8); 17.465 - EXPECT_EQ(memcmp(buf.space, "prepa\0", 6), 0); 17.466 -} 17.467 - 17.468 -TEST_F(BufferWrite, PutcWrapperDiscard) { 17.469 - ASSERT_EQ(buf.capacity, 8); 17.470 - ASSERT_EQ(buf.size, 4); 17.471 - buf.pos = 8; 17.472 - int c = cxBufferPut(&buf, 0x200 | 'a'); 17.473 - EXPECT_EQ(c, EOF); 17.474 - EXPECT_EQ(buf.size, 4); 17.475 - EXPECT_EQ(buf.pos, 8); 17.476 - EXPECT_EQ(buf.capacity, 8); 17.477 - EXPECT_EQ(memcmp(buf.space, "prep\0\0\0\0\0", 9), 0); 17.478 -} 17.479 - 17.480 -TEST_F(BufferWrite, PutcWrapperExtend) { 17.481 - buf.flags |= CX_BUFFER_AUTO_EXTEND; 17.482 - ASSERT_EQ(buf.capacity, 8); 17.483 - ASSERT_EQ(buf.size, 4); 17.484 - buf.pos = 8; 17.485 - int c = cxBufferPut(&buf, 0x200 | 'a'); 17.486 - EXPECT_EQ(c, 'a'); 17.487 - EXPECT_EQ(buf.size, 9); 17.488 - EXPECT_EQ(buf.pos, 9); 17.489 - EXPECT_GE(buf.capacity, 9); 17.490 - EXPECT_EQ(memcmp(buf.space, "prep\0\0\0\0a", 9), 0); 17.491 -} 17.492 - 17.493 -TEST_F(BufferWrite, PutStringWrapperFit) { 17.494 - const char *data = "test"; 17.495 - ASSERT_EQ(buf.capacity, 8); 17.496 - ASSERT_EQ(buf.pos, 4); 17.497 - ASSERT_EQ(buf.size, 4); 17.498 - size_t written = cxBufferPutString(&buf, data); 17.499 - EXPECT_EQ(written, 4); 17.500 - EXPECT_EQ(buf.size, 8); 17.501 - EXPECT_EQ(buf.pos, 8); 17.502 - EXPECT_EQ(buf.capacity, 8); 17.503 - EXPECT_EQ(memcmp(buf.space, "preptest", 8), 0); 17.504 -} 17.505 - 17.506 -TEST_F(BufferWrite, PutStringWrapperDiscard) { 17.507 - const char *data = "testing"; 17.508 - ASSERT_EQ(buf.capacity, 8); 17.509 - ASSERT_EQ(buf.pos, 4); 17.510 - ASSERT_EQ(buf.size, 4); 17.511 - size_t written = cxBufferPutString(&buf, data); 17.512 - EXPECT_EQ(written, 4); 17.513 - EXPECT_EQ(buf.size, 8); 17.514 - EXPECT_EQ(buf.pos, 8); 17.515 - EXPECT_EQ(buf.capacity, 8); 17.516 - EXPECT_EQ(memcmp(buf.space, "preptest\0", 9), 0); 17.517 -} 17.518 - 17.519 -TEST_F(BufferWrite, PutStringWrapperExtend) { 17.520 - buf.flags |= CX_BUFFER_AUTO_EXTEND; 17.521 - const char *data = "testing"; 17.522 - ASSERT_EQ(buf.capacity, 8); 17.523 - ASSERT_EQ(buf.pos, 4); 17.524 - ASSERT_EQ(buf.size, 4); 17.525 - size_t written = cxBufferPutString(&buf, data); 17.526 - EXPECT_EQ(written, 7); 17.527 - EXPECT_EQ(buf.size, 11); 17.528 - EXPECT_EQ(buf.pos, 11); 17.529 - EXPECT_GE(buf.capacity, 11); 17.530 - EXPECT_EQ(memcmp(buf.space, "preptesting", 11), 0); 17.531 -} 17.532 - 17.533 -TEST_F(BufferWrite, MultOverflow) { 17.534 - const char *data = "testing"; 17.535 - ASSERT_EQ(buf.capacity, 8); 17.536 - ASSERT_EQ(buf.pos, 4); 17.537 - ASSERT_EQ(buf.size, 4); 17.538 - size_t written = cxBufferWrite(data, 8, SIZE_MAX / 4, &buf); 17.539 - EXPECT_EQ(written, 0); 17.540 - EXPECT_EQ(buf.capacity, 8); 17.541 - EXPECT_EQ(buf.pos, 4); 17.542 - EXPECT_EQ(buf.size, 4); 17.543 - EXPECT_EQ(memcmp(buf.space, "prep\0", 5), 0); 17.544 -} 17.545 - 17.546 -TEST_F(BufferWrite, MaxCapaOverflow) { 17.547 - buf.flags |= CX_BUFFER_AUTO_EXTEND; 17.548 - const char *data = "testing"; 17.549 - ASSERT_EQ(buf.capacity, 8); 17.550 - ASSERT_EQ(buf.pos, 4); 17.551 - ASSERT_EQ(buf.size, 4); 17.552 - size_t written = cxBufferWrite(data, 1, SIZE_MAX - 2, &buf); 17.553 - EXPECT_EQ(written, 0); 17.554 - EXPECT_EQ(buf.capacity, 8); 17.555 - EXPECT_EQ(buf.pos, 4); 17.556 - EXPECT_EQ(buf.size, 4); 17.557 - EXPECT_EQ(memcmp(buf.space, "prep\0", 5), 0); 17.558 -} 17.559 - 17.560 -TEST_F(BufferWrite, OnlyOverwrite) { 17.561 - buf.flags |= CX_BUFFER_AUTO_EXTEND; 17.562 - ASSERT_EQ(buf.capacity, 8); 17.563 - memcpy(buf.space, "preptest", 8); 17.564 - buf.pos = 3; 17.565 - buf.size = 8; 17.566 - size_t written = cxBufferWrite("XXX", 2, 2, &buf); 17.567 - EXPECT_EQ(written, 2); 17.568 - EXPECT_EQ(buf.capacity, 8); 17.569 - EXPECT_EQ(buf.size, 8); 17.570 - EXPECT_EQ(buf.pos, 7); 17.571 - EXPECT_EQ(memcmp(buf.space, "preXXX\0t", 8), 0); 17.572 -} 17.573 - 17.574 -TEST_F(BufferWrite, FlushAtCapacity) { 17.575 - enableFlushing(); 17.576 - ASSERT_EQ(buf.capacity, 8); 17.577 - ASSERT_EQ(buf.pos, 4); 17.578 - size_t written = cxBufferWrite("foo", 1, 3, &buf); 17.579 - EXPECT_EQ(written, 3); 17.580 - ASSERT_EQ(buf.pos, 7); 17.581 - ASSERT_EQ(buf.size, 7); 17.582 - ASSERT_EQ(target.pos, 0); 17.583 - ASSERT_EQ(target.size, 0); 17.584 - written = cxBufferWrite("hello", 1, 5, &buf); 17.585 - EXPECT_EQ(written, 5); 17.586 - EXPECT_EQ(buf.pos, 0); 17.587 - EXPECT_EQ(buf.size, 0); 17.588 - EXPECT_EQ(buf.capacity, 8); 17.589 - EXPECT_EQ(target.pos, 12); 17.590 - ASSERT_EQ(target.size, 12); 17.591 - EXPECT_EQ(memcmp(target.space, "prepfoohello", 12), 0); 17.592 -} 17.593 - 17.594 -TEST_F(BufferWrite, FlushAtThreshold) { 17.595 - enableFlushing(); 17.596 - buf.flush_threshold = 12; 17.597 - buf.flags |= CX_BUFFER_AUTO_EXTEND; 17.598 - ASSERT_EQ(buf.capacity, 8); 17.599 - ASSERT_EQ(buf.pos, 4); 17.600 - size_t written = cxBufferWrite("foobar", 1, 6, &buf); 17.601 - EXPECT_EQ(written, 6); 17.602 - ASSERT_EQ(buf.pos, 10); 17.603 - ASSERT_EQ(buf.size, 10); 17.604 - ASSERT_GE(buf.capacity, 10); 17.605 - ASSERT_LE(buf.capacity, 12); 17.606 - ASSERT_EQ(target.pos, 0); 17.607 - ASSERT_EQ(target.size, 0); 17.608 - written = cxBufferWrite("hello", 1, 5, &buf); 17.609 - EXPECT_EQ(written, 5); 17.610 - EXPECT_EQ(buf.pos, 0); 17.611 - EXPECT_EQ(buf.size, 0); 17.612 - EXPECT_LE(buf.capacity, 12); 17.613 - EXPECT_EQ(target.pos, 15); 17.614 - ASSERT_EQ(target.size, 15); 17.615 - EXPECT_EQ(memcmp(target.space, "prepfoobarhello", 15), 0); 17.616 -} 17.617 - 17.618 -TEST_F(BufferWrite, FlushRateLimited) { 17.619 - enableFlushing(); 17.620 - // limit the rate of the flush function and the capacity of the target 17.621 - target.capacity = 16; 17.622 - target.flags &= ~CX_BUFFER_AUTO_EXTEND; 17.623 - buf.flush_func = (cx_write_func) mock_write_limited_rate; 17.624 - ASSERT_EQ(buf.capacity, 8); 17.625 - ASSERT_EQ(buf.pos, 4); 17.626 - size_t written = cxBufferWrite("foo", 1, 3, &buf); 17.627 - EXPECT_EQ(written, 3); 17.628 - ASSERT_EQ(buf.pos, 7); 17.629 - ASSERT_EQ(buf.size, 7); 17.630 - ASSERT_EQ(target.pos, 0); 17.631 - ASSERT_EQ(target.size, 0); 17.632 - written = cxBufferWrite("hello, world!", 1, 13, &buf); 17.633 - // " world!" fits into this buffer, the remaining stuff is flushed out 17.634 - EXPECT_EQ(written, 13); 17.635 - EXPECT_EQ(buf.pos, 7); 17.636 - EXPECT_EQ(buf.size, 7); 17.637 - EXPECT_EQ(buf.capacity, 8); 17.638 - EXPECT_EQ(memcmp(buf.space, " world!", 7), 0); 17.639 - EXPECT_EQ(target.pos, 13); 17.640 - ASSERT_EQ(target.size, 13); 17.641 - EXPECT_EQ(target.capacity, 16); 17.642 - EXPECT_EQ(memcmp(target.space, "prepfoohello,", 13), 0); 17.643 -} 17.644 - 17.645 -class BufferSeek : public BufferFixture { 17.646 -}; 17.647 - 17.648 -TEST_F(BufferSeek, SetZero) { 17.649 - int result = cxBufferSeek(&buf, 0, SEEK_SET); 17.650 - EXPECT_EQ(result, 0); 17.651 - EXPECT_EQ(buf.pos, 0); 17.652 -} 17.653 - 17.654 -TEST_F(BufferSeek, SetValid) { 17.655 - int result = cxBufferSeek(&buf, 5, SEEK_SET); 17.656 - EXPECT_EQ(result, 0); 17.657 - EXPECT_EQ(buf.pos, 5); 17.658 -} 17.659 - 17.660 -TEST_F(BufferSeek, SetInvalid) { 17.661 - ASSERT_EQ(buf.pos, 3); 17.662 - int result = cxBufferSeek(&buf, 6, SEEK_SET); 17.663 - EXPECT_NE(result, 0); 17.664 - EXPECT_EQ(buf.pos, 3); 17.665 -} 17.666 - 17.667 -TEST_F(BufferSeek, CurZero) { 17.668 - ASSERT_EQ(buf.pos, 3); 17.669 - int result = cxBufferSeek(&buf, 0, SEEK_CUR); 17.670 - EXPECT_EQ(result, 0); 17.671 - EXPECT_EQ(buf.pos, 3); 17.672 -} 17.673 - 17.674 -TEST_F(BufferSeek, CurValidPositive) { 17.675 - ASSERT_EQ(buf.pos, 3); 17.676 - int result = cxBufferSeek(&buf, 2, SEEK_CUR); 17.677 - EXPECT_EQ(result, 0); 17.678 - EXPECT_EQ(buf.pos, 5); 17.679 -} 17.680 - 17.681 -TEST_F(BufferSeek, CurValidNegative) { 17.682 - ASSERT_EQ(buf.pos, 3); 17.683 - int result = cxBufferSeek(&buf, -3, SEEK_CUR); 17.684 - EXPECT_EQ(result, 0); 17.685 - EXPECT_EQ(buf.pos, 0); 17.686 -} 17.687 - 17.688 -TEST_F(BufferSeek, CurInvalidPositive) { 17.689 - ASSERT_EQ(buf.pos, 3); 17.690 - int result = cxBufferSeek(&buf, 3, SEEK_CUR); 17.691 - EXPECT_NE(result, 0); 17.692 - EXPECT_EQ(buf.pos, 3); 17.693 -} 17.694 - 17.695 -TEST_F(BufferSeek, CurInvalidNegative) { 17.696 - ASSERT_EQ(buf.pos, 3); 17.697 - int result = cxBufferSeek(&buf, -4, SEEK_CUR); 17.698 - EXPECT_NE(result, 0); 17.699 - EXPECT_EQ(buf.pos, 3); 17.700 -} 17.701 - 17.702 -TEST_F(BufferSeek, EndZero) { 17.703 - ASSERT_EQ(buf.size, 6); 17.704 - int result = cxBufferSeek(&buf, 0, SEEK_END); 17.705 - // the (past-the-)end position is always invalid 17.706 - EXPECT_NE(result, 0); 17.707 - EXPECT_EQ(buf.pos, 3); 17.708 -} 17.709 - 17.710 -TEST_F(BufferSeek, EndValid) { 17.711 - ASSERT_EQ(buf.size, 6); 17.712 - int result = cxBufferSeek(&buf, -6, SEEK_END); 17.713 - EXPECT_EQ(result, 0); 17.714 - EXPECT_EQ(buf.pos, 0); 17.715 -} 17.716 - 17.717 -TEST_F(BufferSeek, EndInvalid) { 17.718 - ASSERT_EQ(buf.size, 6); 17.719 - int result = cxBufferSeek(&buf, 1, SEEK_END); 17.720 - EXPECT_NE(result, 0); 17.721 - EXPECT_EQ(buf.pos, 3); 17.722 -} 17.723 - 17.724 -TEST_F(BufferSeek, WhenceInvalid) { 17.725 - ASSERT_EQ(buf.size, 6); 17.726 - ASSERT_EQ(buf.pos, 3); 17.727 - int result = cxBufferSeek(&buf, 2, 9000); 17.728 - EXPECT_NE(result, 0); 17.729 - EXPECT_EQ(buf.size, 6); 17.730 - EXPECT_EQ(buf.pos, 3); 17.731 -} 17.732 - 17.733 -class BufferEof : public BufferFixture { 17.734 -}; 17.735 - 17.736 -TEST_F(BufferEof, Reached) { 17.737 - buf.pos = buf.size; 17.738 - EXPECT_TRUE(cxBufferEof(&buf)); 17.739 - buf.pos = buf.size - 1; 17.740 - ASSERT_FALSE(cxBufferEof(&buf)); 17.741 - cxBufferPut(&buf, 'a'); 17.742 - EXPECT_TRUE(cxBufferEof(&buf)); 17.743 -} 17.744 - 17.745 -TEST_F(BufferEof, NotReached) { 17.746 - buf.pos = buf.size - 1; 17.747 - EXPECT_FALSE(cxBufferEof(&buf)); 17.748 - buf.pos = 0; 17.749 - cxBufferWrite("test", 1, 5, &buf); 17.750 - EXPECT_FALSE(cxBufferEof(&buf)); 17.751 -} 17.752 - 17.753 -class BufferRead : public ::testing::Test { 17.754 -protected: 17.755 - CxBuffer buf{}; 17.756 - 17.757 - void SetUp() override { 17.758 - cxBufferInit(&buf, nullptr, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT); 17.759 - buf.capacity = 8; // artificially reduce capacity to check OOB writes 17.760 - memset(buf.space, 0, 16); 17.761 - memcpy(buf.space, "some data", 9); 17.762 - buf.size = 9; 17.763 - } 17.764 - 17.765 - void TearDown() override { 17.766 - cxBufferDestroy(&buf); 17.767 - } 17.768 -}; 17.769 - 17.770 -TEST_F(BufferRead, GetByte) { 17.771 - buf.pos = 2; 17.772 - EXPECT_EQ(cxBufferGet(&buf), 'm'); 17.773 - EXPECT_EQ(cxBufferGet(&buf), 'e'); 17.774 - EXPECT_EQ(cxBufferGet(&buf), ' '); 17.775 - EXPECT_EQ(cxBufferGet(&buf), 'd'); 17.776 - EXPECT_EQ(buf.pos, 6); 17.777 -} 17.778 - 17.779 -TEST_F(BufferRead, GetEof) { 17.780 - buf.pos = buf.size; 17.781 - EXPECT_EQ(cxBufferGet(&buf), EOF); 17.782 -} 17.783 - 17.784 -TEST_F(BufferRead, ReadWithinBounds) { 17.785 - buf.pos = 2; 17.786 - char target[4]; 17.787 - auto read = cxBufferRead(&target, 1, 4, &buf); 17.788 - ASSERT_EQ(read, 4); 17.789 - EXPECT_EQ(memcmp(&target, "me d", 4), 0); 17.790 - EXPECT_EQ(buf.pos, 6); 17.791 -} 17.792 - 17.793 -TEST_F(BufferRead, ReadOutOfBounds) { 17.794 - buf.pos = 6; 17.795 - char target[4]; 17.796 - auto read = cxBufferRead(&target, 1, 4, &buf); 17.797 - ASSERT_EQ(read, 3); 17.798 - EXPECT_EQ(memcmp(&target, "ata", 3), 0); 17.799 - EXPECT_EQ(buf.pos, 9); 17.800 -} 17.801 - 17.802 -TEST_F(BufferRead, ReadOutOfBoundsMultibyte) { 17.803 - buf.pos = 6; 17.804 - char target[4]; 17.805 - target[2] = '\0'; 17.806 - auto read = cxBufferRead(&target, 2, 2, &buf); 17.807 - ASSERT_EQ(read, 1); 17.808 - EXPECT_EQ(memcmp(&target, "at\0", 3), 0); 17.809 - EXPECT_EQ(buf.pos, 8); 17.810 -} 17.811 - 17.812 -TEST_F(BufferRead, ReadEof) { 17.813 - buf.pos = 9; 17.814 - char target[4]; 17.815 - auto read = cxBufferRead(&target, 1, 1, &buf); 17.816 - ASSERT_EQ(read, 0); 17.817 - EXPECT_EQ(buf.pos, 9); 17.818 -}
18.1 --- a/test/test_compare.cpp Wed Feb 08 20:26:09 2023 +0100 18.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 18.3 @@ -1,127 +0,0 @@ 18.4 -/* 18.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 18.6 - * 18.7 - * Copyright 2022 Mike Becker, Olaf Wintermann All rights reserved. 18.8 - * 18.9 - * Redistribution and use in source and binary forms, with or without 18.10 - * modification, are permitted provided that the following conditions are met: 18.11 - * 18.12 - * 1. Redistributions of source code must retain the above copyright 18.13 - * notice, this list of conditions and the following disclaimer. 18.14 - * 18.15 - * 2. Redistributions in binary form must reproduce the above copyright 18.16 - * notice, this list of conditions and the following disclaimer in the 18.17 - * documentation and/or other materials provided with the distribution. 18.18 - * 18.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 18.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 18.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 18.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 18.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 18.29 - * POSSIBILITY OF SUCH DAMAGE. 18.30 - */ 18.31 - 18.32 -#include "cx/compare.h" 18.33 - 18.34 -#include <gtest/gtest.h> 18.35 - 18.36 -template<typename T> 18.37 -static void test_compare( 18.38 - int (*fnc)( 18.39 - void const *, 18.40 - void const * 18.41 - ) 18.42 -) { 18.43 - auto m = std::numeric_limits<T>::max() / 400; 18.44 - T x, y; 18.45 - 18.46 - x = (std::is_signed_v<T> ? -3 : 3) * m; 18.47 - y = 5 * m; 18.48 - EXPECT_LT(fnc(&x, &y), 0); 18.49 - EXPECT_GT(fnc(&y, &x), 0); 18.50 - 18.51 - x = 120 * m; 18.52 - y = 348 * m; 18.53 - EXPECT_LT(fnc(&x, &y), 0); 18.54 - EXPECT_GT(fnc(&y, &x), 0); 18.55 - 18.56 - if constexpr (std::is_signed_v<T>) { 18.57 - x = -120 * m; 18.58 - y = -348 * m; 18.59 - EXPECT_GT(fnc(&x, &y), 0); 18.60 - EXPECT_LT(fnc(&y, &x), 0); 18.61 - } 18.62 - 18.63 - x = y; 18.64 - EXPECT_EQ(fnc(&x, &y), 0); 18.65 - EXPECT_EQ(fnc(&y, &x), 0); 18.66 -} 18.67 - 18.68 -TEST(Compare, Int) { 18.69 - test_compare<int>(cx_cmp_int); 18.70 -} 18.71 - 18.72 -TEST(Compare, Longint) { 18.73 - test_compare<long int>(cx_cmp_longint); 18.74 -} 18.75 - 18.76 -TEST(Compare, Longlong) { 18.77 - test_compare<long long>(cx_cmp_longlong); 18.78 -} 18.79 - 18.80 -TEST(Compare, Int16) { 18.81 - test_compare<int16_t>(cx_cmp_int16); 18.82 -} 18.83 - 18.84 -TEST(Compare, Int32) { 18.85 - test_compare<int32_t>(cx_cmp_int32); 18.86 -} 18.87 - 18.88 -TEST(Compare, Int64) { 18.89 - test_compare<int64_t>(cx_cmp_int64); 18.90 -} 18.91 - 18.92 -TEST(Compare, Uint) { 18.93 - test_compare<uint>(cx_cmp_uint); 18.94 -} 18.95 - 18.96 -TEST(Compare, Ulongint) { 18.97 - test_compare<unsigned long int>(cx_cmp_ulongint); 18.98 -} 18.99 - 18.100 -TEST(Compare, Ulonglong) { 18.101 - test_compare<unsigned long long>(cx_cmp_ulonglong); 18.102 -} 18.103 - 18.104 -TEST(Compare, Uint16) { 18.105 - test_compare<uint16_t>(cx_cmp_uint16); 18.106 -} 18.107 - 18.108 -TEST(Compare, Uint32) { 18.109 - test_compare<uint32_t>(cx_cmp_uint32); 18.110 -} 18.111 - 18.112 -TEST(Compare, Uint64) { 18.113 - test_compare<uint64_t>(cx_cmp_uint64); 18.114 -} 18.115 - 18.116 -TEST(Compare, Float) { 18.117 - test_compare<float>(cx_cmp_float); 18.118 -} 18.119 - 18.120 -TEST(Compare, Double) { 18.121 - test_compare<double>(cx_cmp_double); 18.122 -} 18.123 - 18.124 -TEST(Compare, IntPtr) { 18.125 - test_compare<intptr_t>(cx_cmp_intptr); 18.126 -} 18.127 - 18.128 -TEST(Compare, UintPtr) { 18.129 - test_compare<uintptr_t>(cx_cmp_uintptr); 18.130 -}
19.1 --- a/test/test_hash_key.cpp Wed Feb 08 20:26:09 2023 +0100 19.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 19.3 @@ -1,87 +0,0 @@ 19.4 -/* 19.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 19.6 - * 19.7 - * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 19.8 - * 19.9 - * Redistribution and use in source and binary forms, with or without 19.10 - * modification, are permitted provided that the following conditions are met: 19.11 - * 19.12 - * 1. Redistributions of source code must retain the above copyright 19.13 - * notice, this list of conditions and the following disclaimer. 19.14 - * 19.15 - * 2. Redistributions in binary form must reproduce the above copyright 19.16 - * notice, this list of conditions and the following disclaimer in the 19.17 - * documentation and/or other materials provided with the distribution. 19.18 - * 19.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 19.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 19.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 19.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 19.29 - * POSSIBILITY OF SUCH DAMAGE. 19.30 - */ 19.31 - 19.32 -#include "cx/hash_key.h" 19.33 - 19.34 -#include <gtest/gtest.h> 19.35 - 19.36 -TEST(cx_hash_key, functions) { 19.37 - auto str = "my key"; 19.38 - auto len = strlen(str); 19.39 - 19.40 - auto str_key = cx_hash_key_str(str); 19.41 - auto bytes_key = cx_hash_key_bytes( 19.42 - reinterpret_cast<unsigned char const *>(str), len); 19.43 - auto obj_key = cx_hash_key( 19.44 - reinterpret_cast<void const *>(str), len); 19.45 - 19.46 - EXPECT_EQ(str_key.hash, bytes_key.hash); 19.47 - EXPECT_EQ(obj_key.hash, bytes_key.hash); 19.48 - EXPECT_EQ(str_key.len, len); 19.49 - EXPECT_EQ(bytes_key.len, len); 19.50 - EXPECT_EQ(bytes_key.len, len); 19.51 - EXPECT_EQ(str_key.data.cstr, str); 19.52 - EXPECT_EQ(bytes_key.data.cbytes, reinterpret_cast<unsigned char const *>(str)); 19.53 - EXPECT_EQ(bytes_key.data.cobj, reinterpret_cast<void const *>(str)); 19.54 -} 19.55 - 19.56 -TEST(cx_hash_key, empty_string) { 19.57 - auto str = ""; 19.58 - 19.59 - auto str_key = cx_hash_key_str(str); 19.60 - auto bytes_key = cx_hash_key_bytes( 19.61 - reinterpret_cast<unsigned char const *>(str), 0); 19.62 - auto obj_key = cx_hash_key( 19.63 - reinterpret_cast<void const *>(str), 0); 19.64 - 19.65 - EXPECT_EQ(bytes_key.hash, 4152238450u); 19.66 - EXPECT_EQ(str_key.hash, 4152238450u); 19.67 - EXPECT_EQ(obj_key.hash, 4152238450u); 19.68 - EXPECT_EQ(str_key.len, 0); 19.69 - EXPECT_EQ(bytes_key.len, 0); 19.70 - EXPECT_EQ(bytes_key.len, 0); 19.71 - EXPECT_EQ(str_key.data.cstr, str); 19.72 - EXPECT_EQ(bytes_key.data.cbytes, reinterpret_cast<unsigned char const *>(str)); 19.73 - EXPECT_EQ(bytes_key.data.cobj, reinterpret_cast<void const *>(str)); 19.74 -} 19.75 - 19.76 -TEST(cx_hash_key, null_ptr) { 19.77 - auto str_key = cx_hash_key_str(nullptr); 19.78 - auto bytes_key = cx_hash_key_bytes(nullptr, 0); 19.79 - auto obj_key = cx_hash_key(nullptr, 0); 19.80 - 19.81 - EXPECT_EQ(bytes_key.hash, 1574210520u); 19.82 - EXPECT_EQ(str_key.hash, 1574210520u); 19.83 - EXPECT_EQ(obj_key.hash, 1574210520u); 19.84 - EXPECT_EQ(str_key.len, 0); 19.85 - EXPECT_EQ(bytes_key.len, 0); 19.86 - EXPECT_EQ(bytes_key.len, 0); 19.87 - EXPECT_EQ(str_key.data.cstr, nullptr); 19.88 - EXPECT_EQ(bytes_key.data.cbytes, nullptr); 19.89 - EXPECT_EQ(bytes_key.data.cobj, nullptr); 19.90 -}
20.1 --- a/test/test_list.cpp Wed Feb 08 20:26:09 2023 +0100 20.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 20.3 @@ -1,1159 +0,0 @@ 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 "cx/linked_list.h" 20.33 -#include "cx/array_list.h" 20.34 -#include "cx/utils.h" 20.35 -#include "cx/compare.h" 20.36 -#include "util_allocator.h" 20.37 - 20.38 -#include <gtest/gtest.h> 20.39 -#include <array> 20.40 -#include <vector> 20.41 -#include <unordered_set> 20.42 -#include <algorithm> 20.43 - 20.44 -struct node { 20.45 - node *next = nullptr; 20.46 - node *prev = nullptr; 20.47 - int data = 0; 20.48 -}; 20.49 - 20.50 -const ptrdiff_t loc_prev = offsetof(struct node, prev); 20.51 -const ptrdiff_t loc_next = offsetof(struct node, next); 20.52 -const ptrdiff_t loc_data = offsetof(struct node, data); 20.53 - 20.54 -struct node_test_data { 20.55 - node *begin = nullptr; 20.56 - 20.57 - explicit node_test_data(node *begin) : begin(begin) { 20.58 - auto n = begin; 20.59 - while (n != nullptr) { 20.60 - nodes.push_back(n); 20.61 - n = n->next; 20.62 - } 20.63 - } 20.64 - 20.65 - node_test_data(node_test_data &) = delete; 20.66 - 20.67 - node_test_data(node_test_data &&) = default; 20.68 - 20.69 - ~node_test_data() { 20.70 - for (auto &&n: nodes) delete n; 20.71 - } 20.72 - 20.73 -private: 20.74 - std::vector<node *> nodes; 20.75 -}; 20.76 - 20.77 -static node_test_data create_nodes_test_data(size_t len) { 20.78 - if (len == 0) return node_test_data{nullptr}; 20.79 - auto begin = new node; 20.80 - auto prev = begin; 20.81 - for (size_t i = 1; i < len; i++) { 20.82 - auto n = new node; 20.83 - cx_linked_list_link(prev, n, loc_prev, loc_next); 20.84 - prev = n; 20.85 - } 20.86 - return node_test_data{begin}; 20.87 -} 20.88 - 20.89 -template<typename InputIter> 20.90 -static node_test_data create_nodes_test_data( 20.91 - InputIter begin, 20.92 - InputIter end 20.93 -) { 20.94 - if (begin == end) return node_test_data{nullptr}; 20.95 - node *first = new node; 20.96 - first->data = *begin; 20.97 - node *prev = first; 20.98 - begin++; 20.99 - for (; begin != end; begin++) { 20.100 - auto n = new node; 20.101 - n->data = *begin; 20.102 - cx_linked_list_link(prev, n, loc_prev, loc_next); 20.103 - prev = n; 20.104 - } 20.105 - return node_test_data{first}; 20.106 -} 20.107 - 20.108 -static node_test_data create_nodes_test_data(std::initializer_list<int> data) { 20.109 - return create_nodes_test_data(data.begin(), data.end()); 20.110 -} 20.111 - 20.112 -template<size_t N> 20.113 -struct int_test_data { 20.114 - std::array<int, N> data; 20.115 - 20.116 - int_test_data() { 20.117 - cx_for_n (i, N) data[i] = ::rand(); // NOLINT(cert-msc50-cpp) 20.118 - } 20.119 -}; 20.120 - 20.121 -TEST(LinkedList_LowLevel, link_unlink) { 20.122 - node a, b, c; 20.123 - 20.124 - cx_linked_list_link(&a, &b, loc_prev, loc_next); 20.125 - EXPECT_EQ(a.prev, nullptr); 20.126 - EXPECT_EQ(a.next, &b); 20.127 - EXPECT_EQ(b.prev, &a); 20.128 - EXPECT_EQ(b.next, nullptr); 20.129 - 20.130 - cx_linked_list_unlink(&a, &b, loc_prev, loc_next); 20.131 - EXPECT_EQ(a.prev, nullptr); 20.132 - EXPECT_EQ(a.next, nullptr); 20.133 - EXPECT_EQ(b.prev, nullptr); 20.134 - EXPECT_EQ(b.next, nullptr); 20.135 - 20.136 - cx_linked_list_link(&b, &c, loc_prev, loc_next); 20.137 - cx_linked_list_link(&a, &b, loc_prev, loc_next); 20.138 - cx_linked_list_unlink(&b, &c, loc_prev, loc_next); 20.139 - EXPECT_EQ(a.prev, nullptr); 20.140 - EXPECT_EQ(a.next, &b); 20.141 - EXPECT_EQ(b.prev, &a); 20.142 - EXPECT_EQ(b.next, nullptr); 20.143 - EXPECT_EQ(c.prev, nullptr); 20.144 - EXPECT_EQ(c.next, nullptr); 20.145 -} 20.146 - 20.147 -TEST(LinkedList_LowLevel, cx_linked_list_at) { 20.148 - node a, b, c, d; 20.149 - cx_linked_list_link(&a, &b, loc_prev, loc_next); 20.150 - cx_linked_list_link(&b, &c, loc_prev, loc_next); 20.151 - cx_linked_list_link(&c, &d, loc_prev, loc_next); 20.152 - 20.153 - EXPECT_EQ(cx_linked_list_at(&a, 0, loc_next, 0), &a); 20.154 - EXPECT_EQ(cx_linked_list_at(&a, 0, loc_next, 1), &b); 20.155 - EXPECT_EQ(cx_linked_list_at(&a, 0, loc_next, 2), &c); 20.156 - EXPECT_EQ(cx_linked_list_at(&a, 0, loc_next, 3), &d); 20.157 - EXPECT_EQ(cx_linked_list_at(&a, 0, loc_next, 4), nullptr); 20.158 - 20.159 - EXPECT_EQ(cx_linked_list_at(&b, 1, loc_prev, 0), &a); 20.160 - EXPECT_EQ(cx_linked_list_at(&b, 1, loc_next, 1), &b); 20.161 - EXPECT_EQ(cx_linked_list_at(&b, 1, loc_next, 2), &c); 20.162 - EXPECT_EQ(cx_linked_list_at(&b, 1, loc_next, 3), &d); 20.163 - EXPECT_EQ(cx_linked_list_at(&b, 1, loc_next, 4), nullptr); 20.164 - 20.165 - EXPECT_EQ(cx_linked_list_at(&d, 3, loc_prev, 0), &a); 20.166 - EXPECT_EQ(cx_linked_list_at(&d, 3, loc_prev, 1), &b); 20.167 -} 20.168 - 20.169 -TEST(LinkedList_LowLevel, cx_linked_list_find) { 20.170 - auto testdata = create_nodes_test_data({2, 4, 6, 8}); 20.171 - auto list = testdata.begin; 20.172 - int s; 20.173 - 20.174 - s = 2; 20.175 - EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 0); 20.176 - s = 4; 20.177 - EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 1); 20.178 - s = 6; 20.179 - EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 2); 20.180 - s = 8; 20.181 - EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 3); 20.182 - s = 10; 20.183 - EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 4); 20.184 - s = -2; 20.185 - EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 4); 20.186 -} 20.187 - 20.188 -TEST(LinkedList_LowLevel, cx_linked_list_compare) { 20.189 - auto ta = create_nodes_test_data({2, 4, 6, 8}); 20.190 - auto tb = create_nodes_test_data({2, 4, 6}); 20.191 - auto tc = create_nodes_test_data({2, 4, 6, 9}); 20.192 - auto la = ta.begin, lb = tb.begin, lc = tc.begin; 20.193 - 20.194 - EXPECT_GT(cx_linked_list_compare(la, lb, loc_next, loc_data, cx_cmp_int), 0); 20.195 - EXPECT_LT(cx_linked_list_compare(lb, la, loc_next, loc_data, cx_cmp_int), 0); 20.196 - EXPECT_GT(cx_linked_list_compare(lc, la, loc_next, loc_data, cx_cmp_int), 0); 20.197 - EXPECT_LT(cx_linked_list_compare(la, lc, loc_next, loc_data, cx_cmp_int), 0); 20.198 - EXPECT_EQ(cx_linked_list_compare(la, la, loc_next, loc_data, cx_cmp_int), 0); 20.199 -} 20.200 - 20.201 -TEST(LinkedList_LowLevel, cx_linked_list_add) { 20.202 - // test with begin, end / prev, next 20.203 - { 20.204 - node nodes[4]; 20.205 - void *begin = nullptr, *end = nullptr; 20.206 - 20.207 - cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[0]); 20.208 - EXPECT_EQ(begin, &nodes[0]); 20.209 - EXPECT_EQ(end, &nodes[0]); 20.210 - EXPECT_EQ(nodes[0].prev, nullptr); 20.211 - EXPECT_EQ(nodes[0].next, nullptr); 20.212 - 20.213 - cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[1]); 20.214 - EXPECT_EQ(begin, &nodes[0]); 20.215 - EXPECT_EQ(end, &nodes[1]); 20.216 - EXPECT_EQ(nodes[0].next, &nodes[1]); 20.217 - EXPECT_EQ(nodes[1].prev, &nodes[0]); 20.218 - } 20.219 - 20.220 - // test with begin only / prev, next 20.221 - { 20.222 - node nodes[4]; 20.223 - void *begin = nullptr; 20.224 - 20.225 - cx_linked_list_add(&begin, nullptr, loc_prev, loc_next, &nodes[0]); 20.226 - EXPECT_EQ(begin, &nodes[0]); 20.227 - cx_linked_list_add(&begin, nullptr, loc_prev, loc_next, &nodes[1]); 20.228 - EXPECT_EQ(begin, &nodes[0]); 20.229 - EXPECT_EQ(nodes[0].next, &nodes[1]); 20.230 - EXPECT_EQ(nodes[1].prev, &nodes[0]); 20.231 - 20.232 - cx_linked_list_add(&begin, nullptr, loc_prev, loc_next, &nodes[2]); 20.233 - EXPECT_EQ(nodes[1].next, &nodes[2]); 20.234 - EXPECT_EQ(nodes[2].prev, &nodes[1]); 20.235 - } 20.236 - 20.237 - // test with end only / prev, next 20.238 - { 20.239 - node nodes[4]; 20.240 - void *end = nullptr; 20.241 - 20.242 - cx_linked_list_add(nullptr, &end, loc_prev, loc_next, &nodes[0]); 20.243 - EXPECT_EQ(end, &nodes[0]); 20.244 - cx_linked_list_add(nullptr, &end, loc_prev, loc_next, &nodes[1]); 20.245 - EXPECT_EQ(end, &nodes[1]); 20.246 - EXPECT_EQ(nodes[0].next, &nodes[1]); 20.247 - EXPECT_EQ(nodes[1].prev, &nodes[0]); 20.248 - 20.249 - cx_linked_list_add(nullptr, &end, loc_prev, loc_next, &nodes[2]); 20.250 - EXPECT_EQ(end, &nodes[2]); 20.251 - EXPECT_EQ(nodes[1].next, &nodes[2]); 20.252 - EXPECT_EQ(nodes[2].prev, &nodes[1]); 20.253 - } 20.254 - 20.255 - // test with begin, end / next 20.256 - { 20.257 - node nodes[4]; 20.258 - void *begin = nullptr, *end = nullptr; 20.259 - 20.260 - cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[0]); 20.261 - EXPECT_EQ(begin, &nodes[0]); 20.262 - EXPECT_EQ(end, &nodes[0]); 20.263 - cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[1]); 20.264 - EXPECT_EQ(end, &nodes[1]); 20.265 - EXPECT_EQ(nodes[0].next, &nodes[1]); 20.266 - EXPECT_EQ(nodes[1].prev, nullptr); 20.267 - } 20.268 -} 20.269 - 20.270 -TEST(LinkedList_LowLevel, cx_linked_list_prepend) { 20.271 - // test with begin, end / prev, next 20.272 - { 20.273 - node nodes[4]; 20.274 - void *begin = nullptr, *end = nullptr; 20.275 - 20.276 - cx_linked_list_prepend(&begin, &end, loc_prev, loc_next, &nodes[0]); 20.277 - EXPECT_EQ(begin, &nodes[0]); 20.278 - EXPECT_EQ(end, &nodes[0]); 20.279 - EXPECT_EQ(nodes[0].prev, nullptr); 20.280 - EXPECT_EQ(nodes[0].next, nullptr); 20.281 - 20.282 - cx_linked_list_prepend(&begin, &end, loc_prev, loc_next, &nodes[1]); 20.283 - EXPECT_EQ(begin, &nodes[1]); 20.284 - EXPECT_EQ(end, &nodes[0]); 20.285 - EXPECT_EQ(nodes[1].next, &nodes[0]); 20.286 - EXPECT_EQ(nodes[0].prev, &nodes[1]); 20.287 - } 20.288 - 20.289 - // test with begin only / prev, next 20.290 - { 20.291 - node nodes[4]; 20.292 - void *begin = nullptr; 20.293 - 20.294 - cx_linked_list_prepend(&begin, nullptr, loc_prev, loc_next, &nodes[0]); 20.295 - EXPECT_EQ(begin, &nodes[0]); 20.296 - cx_linked_list_prepend(&begin, nullptr, loc_prev, loc_next, &nodes[1]); 20.297 - EXPECT_EQ(begin, &nodes[1]); 20.298 - EXPECT_EQ(nodes[1].next, &nodes[0]); 20.299 - EXPECT_EQ(nodes[0].prev, &nodes[1]); 20.300 - 20.301 - cx_linked_list_prepend(&begin, nullptr, loc_prev, loc_next, &nodes[2]); 20.302 - EXPECT_EQ(begin, &nodes[2]); 20.303 - EXPECT_EQ(nodes[2].next, &nodes[1]); 20.304 - EXPECT_EQ(nodes[1].prev, &nodes[2]); 20.305 - } 20.306 - 20.307 - // test with end only / prev, next 20.308 - { 20.309 - node nodes[4]; 20.310 - void *end = nullptr; 20.311 - 20.312 - cx_linked_list_prepend(nullptr, &end, loc_prev, loc_next, &nodes[0]); 20.313 - EXPECT_EQ(end, &nodes[0]); 20.314 - cx_linked_list_prepend(nullptr, &end, loc_prev, loc_next, &nodes[1]); 20.315 - EXPECT_EQ(end, &nodes[0]); 20.316 - EXPECT_EQ(nodes[1].next, &nodes[0]); 20.317 - EXPECT_EQ(nodes[0].prev, &nodes[1]); 20.318 - 20.319 - cx_linked_list_prepend(nullptr, &end, loc_prev, loc_next, &nodes[2]); 20.320 - EXPECT_EQ(end, &nodes[0]); 20.321 - EXPECT_EQ(nodes[2].next, &nodes[1]); 20.322 - EXPECT_EQ(nodes[1].prev, &nodes[2]); 20.323 - } 20.324 - 20.325 - // test with begin, end / next 20.326 - { 20.327 - node nodes[4]; 20.328 - void *begin = nullptr, *end = nullptr; 20.329 - 20.330 - cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[0]); 20.331 - EXPECT_EQ(begin, &nodes[0]); 20.332 - EXPECT_EQ(end, &nodes[0]); 20.333 - cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[1]); 20.334 - cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[2]); 20.335 - EXPECT_EQ(begin, &nodes[2]); 20.336 - EXPECT_EQ(end, &nodes[0]); 20.337 - EXPECT_EQ(nodes[1].next, &nodes[0]); 20.338 - EXPECT_EQ(nodes[2].next, &nodes[1]); 20.339 - EXPECT_EQ(nodes[1].prev, nullptr); 20.340 - EXPECT_EQ(nodes[0].prev, nullptr); 20.341 - } 20.342 -} 20.343 - 20.344 -TEST(LinkedList_LowLevel, cx_linked_list_insert) { 20.345 - // insert mid list 20.346 - { 20.347 - node nodes[4]; 20.348 - void *begin = &nodes[0], *end = &nodes[2]; 20.349 - 20.350 - cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 20.351 - cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 20.352 - 20.353 - cx_linked_list_insert(&begin, &end, loc_prev, loc_next, &nodes[1], &nodes[3]); 20.354 - EXPECT_EQ(begin, &nodes[0]); 20.355 - EXPECT_EQ(end, &nodes[2]); 20.356 - EXPECT_EQ(nodes[1].next, &nodes[3]); 20.357 - EXPECT_EQ(nodes[2].prev, &nodes[3]); 20.358 - EXPECT_EQ(nodes[3].prev, &nodes[1]); 20.359 - EXPECT_EQ(nodes[3].next, &nodes[2]); 20.360 - } 20.361 - 20.362 - // insert end 20.363 - { 20.364 - node nodes[4]; 20.365 - void *begin = &nodes[0], *end = &nodes[2]; 20.366 - 20.367 - cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 20.368 - cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 20.369 - 20.370 - cx_linked_list_insert(&begin, &end, loc_prev, loc_next, &nodes[2], &nodes[3]); 20.371 - EXPECT_EQ(begin, &nodes[0]); 20.372 - EXPECT_EQ(end, &nodes[3]); 20.373 - EXPECT_EQ(nodes[2].next, &nodes[3]); 20.374 - EXPECT_EQ(nodes[3].prev, &nodes[2]); 20.375 - EXPECT_EQ(nodes[3].next, nullptr); 20.376 - } 20.377 - 20.378 - // insert begin 20.379 - { 20.380 - node nodes[4]; 20.381 - void *begin = &nodes[0], *end = &nodes[2]; 20.382 - 20.383 - cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 20.384 - cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 20.385 - 20.386 - cx_linked_list_insert(&begin, &end, loc_prev, loc_next, nullptr, &nodes[3]); 20.387 - EXPECT_EQ(begin, &nodes[3]); 20.388 - EXPECT_EQ(end, &nodes[2]); 20.389 - EXPECT_EQ(nodes[0].prev, &nodes[3]); 20.390 - EXPECT_EQ(nodes[3].prev, nullptr); 20.391 - EXPECT_EQ(nodes[3].next, &nodes[0]); 20.392 - } 20.393 -} 20.394 - 20.395 -TEST(LinkedList_LowLevel, cx_linked_list_insert_chain) { 20.396 - // insert mid list 20.397 - { 20.398 - node nodes[5]; 20.399 - void *begin = &nodes[0], *end = &nodes[2]; 20.400 - 20.401 - cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 20.402 - cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 20.403 - cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); 20.404 - 20.405 - cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, &nodes[1], &nodes[3], nullptr); 20.406 - EXPECT_EQ(begin, &nodes[0]); 20.407 - EXPECT_EQ(end, &nodes[2]); 20.408 - EXPECT_EQ(nodes[1].next, &nodes[3]); 20.409 - EXPECT_EQ(nodes[2].prev, &nodes[4]); 20.410 - EXPECT_EQ(nodes[3].prev, &nodes[1]); 20.411 - EXPECT_EQ(nodes[4].next, &nodes[2]); 20.412 - } 20.413 - 20.414 - // insert end 20.415 - { 20.416 - node nodes[5]; 20.417 - void *begin = &nodes[0], *end = &nodes[2]; 20.418 - 20.419 - cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 20.420 - cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 20.421 - cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); 20.422 - 20.423 - cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, &nodes[2], &nodes[3], nullptr); 20.424 - EXPECT_EQ(begin, &nodes[0]); 20.425 - EXPECT_EQ(end, &nodes[4]); 20.426 - EXPECT_EQ(nodes[2].next, &nodes[3]); 20.427 - EXPECT_EQ(nodes[3].prev, &nodes[2]); 20.428 - EXPECT_EQ(nodes[4].next, nullptr); 20.429 - } 20.430 - 20.431 - // insert begin 20.432 - { 20.433 - node nodes[5]; 20.434 - void *begin = &nodes[0], *end = &nodes[2]; 20.435 - 20.436 - cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 20.437 - cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 20.438 - cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); 20.439 - 20.440 - cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, nullptr, &nodes[3], nullptr); 20.441 - EXPECT_EQ(begin, &nodes[3]); 20.442 - EXPECT_EQ(end, &nodes[2]); 20.443 - EXPECT_EQ(nodes[0].prev, &nodes[4]); 20.444 - EXPECT_EQ(nodes[3].prev, nullptr); 20.445 - EXPECT_EQ(nodes[4].next, &nodes[0]); 20.446 - } 20.447 -} 20.448 - 20.449 -TEST(LinkedList_LowLevel, cx_linked_list_first) { 20.450 - auto testdata = create_nodes_test_data(3); 20.451 - auto begin = testdata.begin; 20.452 - EXPECT_EQ(cx_linked_list_first(begin, loc_prev), begin); 20.453 - EXPECT_EQ(cx_linked_list_first(begin->next, loc_prev), begin); 20.454 - EXPECT_EQ(cx_linked_list_first(begin->next->next, loc_prev), begin); 20.455 -} 20.456 - 20.457 -TEST(LinkedList_LowLevel, cx_linked_list_last) { 20.458 - auto testdata = create_nodes_test_data(3); 20.459 - auto begin = testdata.begin; 20.460 - auto end = begin->next->next; 20.461 - EXPECT_EQ(cx_linked_list_last(begin, loc_next), end); 20.462 - EXPECT_EQ(cx_linked_list_last(begin->next, loc_next), end); 20.463 - EXPECT_EQ(cx_linked_list_last(begin->next->next, loc_next), end); 20.464 -} 20.465 - 20.466 -TEST(LinkedList_LowLevel, cx_linked_list_prev) { 20.467 - auto testdata = create_nodes_test_data(3); 20.468 - auto begin = testdata.begin; 20.469 - EXPECT_EQ(cx_linked_list_prev(begin, loc_next, begin), nullptr); 20.470 - EXPECT_EQ(cx_linked_list_prev(begin, loc_next, begin->next), begin); 20.471 - EXPECT_EQ(cx_linked_list_prev(begin, loc_next, begin->next->next), begin->next); 20.472 -} 20.473 - 20.474 -TEST(LinkedList_LowLevel, cx_linked_list_remove) { 20.475 - auto testdata = create_nodes_test_data({2, 4, 6}); 20.476 - auto begin = reinterpret_cast<void *>(testdata.begin); 20.477 - auto first = testdata.begin; 20.478 - auto second = first->next; 20.479 - auto third = second->next; 20.480 - auto end = reinterpret_cast<void *>(third); 20.481 - 20.482 - cx_linked_list_remove(&begin, &end, loc_prev, loc_next, second); 20.483 - EXPECT_EQ(begin, first); 20.484 - EXPECT_EQ(end, third); 20.485 - EXPECT_EQ(first->prev, nullptr); 20.486 - EXPECT_EQ(first->next, third); 20.487 - EXPECT_EQ(third->prev, first); 20.488 - EXPECT_EQ(third->next, nullptr); 20.489 - 20.490 - cx_linked_list_remove(&begin, &end, loc_prev, loc_next, third); 20.491 - EXPECT_EQ(begin, first); 20.492 - EXPECT_EQ(end, first); 20.493 - EXPECT_EQ(first->prev, nullptr); 20.494 - EXPECT_EQ(first->next, nullptr); 20.495 - 20.496 - cx_linked_list_remove(&begin, &end, loc_prev, loc_next, first); 20.497 - EXPECT_EQ(begin, nullptr); 20.498 - EXPECT_EQ(end, nullptr); 20.499 -} 20.500 - 20.501 -TEST(LinkedList_LowLevel, cx_linked_list_size) { 20.502 - EXPECT_EQ(cx_linked_list_size(nullptr, loc_next), 0); 20.503 - 20.504 - { 20.505 - auto testdata = create_nodes_test_data(5); 20.506 - EXPECT_EQ(cx_linked_list_size(testdata.begin, loc_next), 5); 20.507 - } 20.508 - 20.509 - { 20.510 - auto testdata = create_nodes_test_data(13); 20.511 - EXPECT_EQ(cx_linked_list_size(testdata.begin, loc_next), 13); 20.512 - } 20.513 -} 20.514 - 20.515 -TEST(LinkedList_LowLevel, cx_linked_list_sort) { 20.516 - int_test_data<1500> testdata; 20.517 - std::array<int, 1500> sorted{}; 20.518 - std::partial_sort_copy(testdata.data.begin(), testdata.data.end(), sorted.begin(), sorted.end()); 20.519 - 20.520 - auto scrambled = create_nodes_test_data(testdata.data.begin(), testdata.data.end()); 20.521 - void *begin = scrambled.begin; 20.522 - void *end = cx_linked_list_last(begin, loc_next); 20.523 - 20.524 - cx_linked_list_sort(&begin, &end, loc_prev, loc_next, loc_data, cx_cmp_int); 20.525 - 20.526 - node *check = reinterpret_cast<node *>(begin); 20.527 - node *check_last = nullptr; 20.528 - cx_for_n (i, sorted.size()) { 20.529 - EXPECT_EQ(check->data, sorted[i]); 20.530 - EXPECT_EQ(check->prev, check_last); 20.531 - if (i < sorted.size() - 1) { 20.532 - ASSERT_NE(check->next, nullptr); 20.533 - } 20.534 - check_last = check; 20.535 - check = check->next; 20.536 - } 20.537 - EXPECT_EQ(check, nullptr); 20.538 - EXPECT_EQ(end, check_last); 20.539 -} 20.540 - 20.541 -TEST(LinkedList_LowLevel, cx_linked_list_reverse) { 20.542 - auto testdata = create_nodes_test_data({2, 4, 6, 8}); 20.543 - auto expected = create_nodes_test_data({8, 6, 4, 2}); 20.544 - 20.545 - auto begin = reinterpret_cast<void *>(testdata.begin); 20.546 - auto end = cx_linked_list_last(begin, loc_next); 20.547 - auto orig_begin = begin, orig_end = end; 20.548 - 20.549 - cx_linked_list_reverse(&begin, &end, loc_prev, loc_next); 20.550 - EXPECT_EQ(end, orig_begin); 20.551 - EXPECT_EQ(begin, orig_end); 20.552 - EXPECT_EQ(cx_linked_list_compare(begin, expected.begin, loc_next, loc_data, cx_cmp_int), 0); 20.553 -} 20.554 - 20.555 -class HighLevelTest : public ::testing::Test { 20.556 - mutable std::unordered_set<CxList *> lists; 20.557 -protected: 20.558 - CxTestingAllocator testingAllocator; 20.559 - 20.560 - void TearDown() override { 20.561 - for (auto &&l: lists) cxListDestroy(l); 20.562 - EXPECT_TRUE(testingAllocator.verify()); 20.563 - } 20.564 - 20.565 - static constexpr size_t testdata_len = 250; 20.566 - int_test_data<testdata_len> testdata; 20.567 - 20.568 - auto autofree(CxList *list) const -> CxList * { 20.569 - if (list != nullptr) lists.insert(list); 20.570 - return list; 20.571 - } 20.572 - 20.573 - auto linkedListFromTestData() const -> CxList * { 20.574 - auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 20.575 - cxListAddArray(list, testdata.data.data(), testdata_len); 20.576 - return list; 20.577 - } 20.578 - 20.579 - auto pointerLinkedListFromTestData() const -> CxList * { 20.580 - auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 20.581 - cxListStorePointers(list); 20.582 - // note: cannot use cxListAddArray() because we don't have a list of pointers 20.583 - cx_for_n(i, testdata_len) cxListAdd(list, &testdata.data[i]); 20.584 - return list; 20.585 - } 20.586 - 20.587 - auto arrayListFromTestData() const -> CxList * { 20.588 - auto list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), testdata_len)); 20.589 - cxListAddArray(list, testdata.data.data(), testdata_len); 20.590 - return list; 20.591 - } 20.592 - 20.593 - void verifyCreate(CxList *list) const { 20.594 - EXPECT_EQ(list->content_destructor_type, CX_DESTRUCTOR_NONE); 20.595 - EXPECT_EQ(list->size, 0); 20.596 - EXPECT_EQ(list->allocator, &testingAllocator); 20.597 - EXPECT_EQ(list->cmpfunc, cx_cmp_int); 20.598 - } 20.599 - 20.600 - void verifyAdd( 20.601 - CxList *list, 20.602 - bool as_pointer 20.603 - ) { 20.604 - auto len = testdata_len; 20.605 - cx_for_n (i, len) EXPECT_EQ(cxListAdd(list, &testdata.data[i]), 0); 20.606 - EXPECT_EQ(list->size, len); 20.607 - EXPECT_GE(list->capacity, list->size); 20.608 - cx_for_n (i, len) EXPECT_EQ(*(int *) cxListAt(list, i), testdata.data[i]); 20.609 - cx_for_n (i, len) ++testdata.data[i]; 20.610 - if (as_pointer) { 20.611 - cx_for_n (i, len) EXPECT_EQ(*(int *) cxListAt(list, i), testdata.data[i]); 20.612 - } else { 20.613 - cx_for_n (i, len) EXPECT_EQ(*(int *) cxListAt(list, i), testdata.data[i] - 1); 20.614 - } 20.615 - } 20.616 - 20.617 - static void verifyInsert(CxList *list) { 20.618 - int a = 5, b = 47, c = 13, d = 42; 20.619 - 20.620 - EXPECT_NE(cxListInsert(list, 1, &a), 0); 20.621 - EXPECT_EQ(list->size, 0); 20.622 - EXPECT_EQ(cxListInsert(list, 0, &a), 0); 20.623 - EXPECT_EQ(list->size, 1); 20.624 - EXPECT_EQ(cxListInsert(list, 0, &b), 0); 20.625 - EXPECT_EQ(list->size, 2); 20.626 - EXPECT_EQ(cxListInsert(list, 1, &c), 0); 20.627 - EXPECT_EQ(list->size, 3); 20.628 - EXPECT_EQ(cxListInsert(list, 3, &d), 0); 20.629 - 20.630 - ASSERT_EQ(list->size, 4); 20.631 - EXPECT_GE(list->capacity, list->size); 20.632 - 20.633 - EXPECT_EQ(*(int *) cxListAt(list, 0), 47); 20.634 - EXPECT_EQ(*(int *) cxListAt(list, 1), 13); 20.635 - EXPECT_EQ(*(int *) cxListAt(list, 2), 5); 20.636 - EXPECT_EQ(*(int *) cxListAt(list, 3), 42); 20.637 - } 20.638 - 20.639 - static void verifyInsertArray( 20.640 - CxList *list, 20.641 - bool pointers = false 20.642 - ) { 20.643 - int a[5] = {5, 47, 11, 13, 42}; 20.644 - int b[5] = {9, 18, 72, 50, 7}; 20.645 - int *aptr[5]; 20.646 - int *bptr[5]; 20.647 - cx_for_n(i, 5) { 20.648 - aptr[i] = &a[i]; 20.649 - bptr[i] = &b[i]; 20.650 - } 20.651 - 20.652 - size_t inserted; 20.653 - 20.654 - if (pointers) { 20.655 - inserted = cxListInsertArray(list, 0, aptr, 5); 20.656 - } else { 20.657 - inserted = cxListInsertArray(list, 0, a, 5); 20.658 - } 20.659 - EXPECT_EQ(inserted, 5); 20.660 - EXPECT_EQ(*(int *) cxListAt(list, 0), 5); 20.661 - EXPECT_EQ(*(int *) cxListAt(list, 1), 47); 20.662 - EXPECT_EQ(*(int *) cxListAt(list, 2), 11); 20.663 - EXPECT_EQ(*(int *) cxListAt(list, 3), 13); 20.664 - EXPECT_EQ(*(int *) cxListAt(list, 4), 42); 20.665 - if (pointers) { 20.666 - inserted = cxListInsertArray(list, 3, bptr, 5); 20.667 - } else { 20.668 - inserted = cxListInsertArray(list, 3, b, 5); 20.669 - } 20.670 - EXPECT_EQ(inserted, 5); 20.671 - EXPECT_EQ(*(int *) cxListAt(list, 0), 5); 20.672 - EXPECT_EQ(*(int *) cxListAt(list, 1), 47); 20.673 - EXPECT_EQ(*(int *) cxListAt(list, 2), 11); 20.674 - EXPECT_EQ(*(int *) cxListAt(list, 3), 9); 20.675 - EXPECT_EQ(*(int *) cxListAt(list, 4), 18); 20.676 - EXPECT_EQ(*(int *) cxListAt(list, 5), 72); 20.677 - EXPECT_EQ(*(int *) cxListAt(list, 6), 50); 20.678 - EXPECT_EQ(*(int *) cxListAt(list, 7), 7); 20.679 - EXPECT_EQ(*(int *) cxListAt(list, 8), 13); 20.680 - EXPECT_EQ(*(int *) cxListAt(list, 9), 42); 20.681 - } 20.682 - 20.683 - void verifyRemove(CxList *list) const { 20.684 - EXPECT_EQ(cxListRemove(list, 2), 0); 20.685 - EXPECT_EQ(cxListRemove(list, 4), 0); 20.686 - EXPECT_EQ(list->size, testdata_len - 2); 20.687 - EXPECT_GE(list->capacity, list->size); 20.688 - EXPECT_EQ(*(int *) cxListAt(list, 0), testdata.data[0]); 20.689 - EXPECT_EQ(*(int *) cxListAt(list, 1), testdata.data[1]); 20.690 - EXPECT_EQ(*(int *) cxListAt(list, 2), testdata.data[3]); 20.691 - EXPECT_EQ(*(int *) cxListAt(list, 3), testdata.data[4]); 20.692 - EXPECT_EQ(*(int *) cxListAt(list, 4), testdata.data[6]); 20.693 - 20.694 - EXPECT_EQ(cxListRemove(list, 0), 0); 20.695 - EXPECT_EQ(list->size, testdata_len - 3); 20.696 - EXPECT_GE(list->capacity, list->size); 20.697 - EXPECT_EQ(*(int *) cxListAt(list, 0), testdata.data[1]); 20.698 - EXPECT_EQ(*(int *) cxListAt(list, 1), testdata.data[3]); 20.699 - 20.700 - EXPECT_NE(cxListRemove(list, testdata_len), 0); 20.701 - } 20.702 - 20.703 - static void verifySwap(CxList *list) { 20.704 - ASSERT_EQ(list->size, 0); 20.705 - 20.706 - int original[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; 20.707 - int swapped[16] = {8, 4, 14, 3, 1, 5, 9, 12, 0, 6, 11, 10, 7, 15, 2, 13}; 20.708 - 20.709 - // we have to add the items one by one, because it could be a pointer list 20.710 - cx_for_n(i, 16) { 20.711 - cxListAdd(list, &original[i]); 20.712 - } 20.713 - 20.714 - int result; 20.715 - 20.716 - // execute the test two times with different item sizes 20.717 - result = cxListSwap(list, 1, 4); 20.718 - EXPECT_EQ(0, result); 20.719 - result = cxListSwap(list, 2, 14); 20.720 - EXPECT_EQ(0, result); 20.721 - result = cxListSwap(list, 9, 6); 20.722 - EXPECT_EQ(0, result); 20.723 - result = cxListSwap(list, 3, 3); 20.724 - EXPECT_EQ(0, result); 20.725 - result = cxListSwap(list, 10, 11); 20.726 - EXPECT_EQ(0, result); 20.727 - result = cxListSwap(list, 8, 0); 20.728 - EXPECT_EQ(0, result); 20.729 - result = cxListSwap(list, 7, 12); 20.730 - EXPECT_EQ(0, result); 20.731 - result = cxListSwap(list, 13, 15); 20.732 - EXPECT_EQ(0, result); 20.733 - 20.734 - result = cxListSwap(list, 5, 16); 20.735 - EXPECT_NE(0, result); 20.736 - result = cxListSwap(list, 16, 6); 20.737 - EXPECT_NE(0, result); 20.738 - result = cxListSwap(list, 16, 17); 20.739 - EXPECT_NE(0, result); 20.740 - 20.741 - auto iter = cxListBegin(list); 20.742 - cx_foreach(int*, e, iter) { 20.743 - EXPECT_EQ(*e, swapped[iter.index]); 20.744 - } 20.745 - // TODO: replace with backward iterator 20.746 - cx_for_n(i, 16) { 20.747 - EXPECT_EQ(*((int *) cxListAt(list, i)), swapped[i]); 20.748 - } 20.749 - } 20.750 - 20.751 - void verifyAt(CxList *list) const { 20.752 - auto len = testdata_len; 20.753 - EXPECT_EQ(list->size, len); 20.754 - cx_for_n (i, len) { 20.755 - EXPECT_EQ(*(int *) cxListAt(list, i), testdata.data[i]); 20.756 - } 20.757 - EXPECT_EQ(cxListAt(list, list->size), nullptr); 20.758 - } 20.759 - 20.760 - void verifyFind(CxList *list) const { 20.761 - cx_for_n (attempt, 25) { 20.762 - size_t exp = rand() % testdata_len; // NOLINT(cert-msc50-cpp) 20.763 - int val = testdata.data[exp]; 20.764 - // randomly picked number could occur earlier in list - find first position 20.765 - cx_for_n (i, exp) { 20.766 - if (testdata.data[i] == val) { 20.767 - exp = i; 20.768 - break; 20.769 - } 20.770 - } 20.771 - EXPECT_EQ(cxListFind(list, &val), exp); 20.772 - } 20.773 - } 20.774 - 20.775 - void verifySort(CxList *list) const { 20.776 - std::array<int, testdata_len> expected{}; 20.777 - std::partial_sort_copy(testdata.data.begin(), testdata.data.end(), expected.begin(), expected.end()); 20.778 - cxListSort(list); 20.779 - cx_for_n (i, testdata_len) ASSERT_EQ(*(int *) cxListAt(list, i), expected[i]); 20.780 - } 20.781 - 20.782 - void verifyIterator(CxList *list) const { 20.783 - int i = 0; 20.784 - auto iter = cxListBeginMut(list); 20.785 - cx_foreach(int*, x, iter) { 20.786 - ASSERT_EQ(iter.index, (size_t) (i + 1) / 2); 20.787 - ASSERT_EQ(*x, testdata.data[i]); 20.788 - if (i % 2 == 1) cxIteratorFlagRemoval(iter); 20.789 - i++; 20.790 - } 20.791 - auto len = testdata_len; 20.792 - EXPECT_EQ(i, len); 20.793 - ASSERT_EQ(list->size, len / 2); 20.794 - cx_for_n(j, len / 2) ASSERT_EQ(*(int *) cxListAt(list, j), testdata.data[j * 2]); 20.795 - } 20.796 - 20.797 - static void verifyInsertViaIterator(CxList *list) { 20.798 - int newdata[] = {10, 20, 30, 40, 50}; 20.799 - 20.800 - auto iter = cxListMutIterator(list, 2); 20.801 - EXPECT_TRUE(cxIteratorValid(iter)); 20.802 - EXPECT_EQ(iter.index, 2); 20.803 - EXPECT_EQ(*(int *) cxIteratorCurrent(iter), 2); 20.804 - cxListInsertAfter(&iter, &newdata[0]); 20.805 - EXPECT_TRUE(cxIteratorValid(iter)); 20.806 - EXPECT_EQ(iter.index, 2); 20.807 - EXPECT_EQ(*(int *) cxIteratorCurrent(iter), 2); 20.808 - cxListInsertBefore(&iter, &newdata[1]); 20.809 - EXPECT_TRUE(cxIteratorValid(iter)); 20.810 - EXPECT_EQ(iter.index, 3); 20.811 - EXPECT_EQ(*(int *) cxIteratorCurrent(iter), 2); 20.812 - 20.813 - iter = cxListBeginMut(list); 20.814 - cxListInsertBefore(&iter, &newdata[2]); 20.815 - EXPECT_TRUE(cxIteratorValid(iter)); 20.816 - EXPECT_EQ(iter.index, 1); 20.817 - EXPECT_EQ(*(int *) cxIteratorCurrent(iter), 0); 20.818 - iter = cxListMutIterator(list, list->size); 20.819 - cxListInsertBefore(&iter, &newdata[3]); 20.820 - EXPECT_FALSE(cxIteratorValid(iter)); 20.821 - EXPECT_EQ(iter.index, 9); 20.822 - iter = cxListMutIterator(list, list->size); 20.823 - cxListInsertAfter(&iter, &newdata[4]); 20.824 - EXPECT_FALSE(cxIteratorValid(iter)); 20.825 - EXPECT_EQ(iter.index, 10); 20.826 - 20.827 - int expdata[] = {30, 0, 1, 20, 2, 10, 3, 4, 40, 50}; 20.828 - cx_for_n (j, 10) EXPECT_EQ(*(int *) cxListAt(list, j), expdata[j]); 20.829 - } 20.830 - 20.831 - void verifyReverse(CxList *list) const { 20.832 - cxListReverse(list); 20.833 - cx_for_n(i, testdata_len) { 20.834 - ASSERT_EQ(*(int *) cxListAt(list, i), testdata.data[testdata_len - 1 - i]); 20.835 - } 20.836 - } 20.837 - 20.838 - static void verifyCompare( 20.839 - CxList *left, 20.840 - CxList *right 20.841 - ) { 20.842 - EXPECT_EQ(cxListCompare(left, right), 0); 20.843 - int x = 42; 20.844 - cxListAdd(left, &x); 20.845 - ASSERT_GT(left->size, right->size); 20.846 - EXPECT_GT(cxListCompare(left, right), 0); 20.847 - EXPECT_LT(cxListCompare(right, left), 0); 20.848 - cxListAdd(right, &x); 20.849 - ASSERT_EQ(left->size, right->size); 20.850 - EXPECT_EQ(cxListCompare(left, right), 0); 20.851 - int a = 5, b = 10; 20.852 - cxListInsert(left, 15, &a); 20.853 - cxListInsert(right, 15, &b); 20.854 - ASSERT_EQ(left->size, right->size); 20.855 - EXPECT_LT(cxListCompare(left, right), 0); 20.856 - EXPECT_GT(cxListCompare(right, left), 0); 20.857 - *(int *) cxListAt(left, 15) = 10; 20.858 - EXPECT_EQ(cxListCompare(left, right), 0); 20.859 - } 20.860 -}; 20.861 - 20.862 -class LinkedList : public HighLevelTest { 20.863 -}; 20.864 - 20.865 -class PointerLinkedList : public HighLevelTest { 20.866 -}; 20.867 - 20.868 -class ArrayList : public HighLevelTest { 20.869 -}; 20.870 - 20.871 -TEST_F(PointerLinkedList, cxListStorePointers) { 20.872 - auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, 47)); 20.873 - EXPECT_FALSE(cxListIsStoringPointers(list)); 20.874 - cxListStorePointers(list); 20.875 - EXPECT_EQ(list->itemsize, sizeof(void *)); 20.876 - EXPECT_NE(list->cl, nullptr); 20.877 - EXPECT_NE(list->climpl, nullptr); 20.878 - EXPECT_TRUE(cxListIsStoringPointers(list)); 20.879 - cxListStoreObjects(list); 20.880 - EXPECT_NE(list->cl, nullptr); 20.881 - EXPECT_EQ(list->climpl, nullptr); 20.882 - EXPECT_FALSE(cxListIsStoringPointers(list)); 20.883 -} 20.884 - 20.885 -TEST_F(LinkedList, cxLinkedListCreate) { 20.886 - CxList *list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 20.887 - ASSERT_NE(list, nullptr); 20.888 - EXPECT_EQ(list->itemsize, sizeof(int)); 20.889 - EXPECT_EQ(list->capacity, (size_t) -1); 20.890 - verifyCreate(list); 20.891 -} 20.892 - 20.893 -TEST_F(ArrayList, cxArrayListCreate) { 20.894 - CxList *list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 8)); 20.895 - ASSERT_NE(list, nullptr); 20.896 - EXPECT_EQ(list->itemsize, sizeof(int)); 20.897 - EXPECT_EQ(list->capacity, 8); 20.898 - verifyCreate(list); 20.899 -} 20.900 - 20.901 -TEST_F(LinkedList, cxListAdd) { 20.902 - auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 20.903 - verifyAdd(list, false); 20.904 -} 20.905 - 20.906 -TEST_F(PointerLinkedList, cxListAdd) { 20.907 - auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 20.908 - cxListStorePointers(list); 20.909 - verifyAdd(list, true); 20.910 -} 20.911 - 20.912 -TEST_F(ArrayList, cxListAdd) { 20.913 - auto list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 8)); 20.914 - verifyAdd(list, false); 20.915 -} 20.916 - 20.917 -TEST_F(LinkedList, cxListInsert) { 20.918 - verifyInsert(autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)))); 20.919 -} 20.920 - 20.921 -TEST_F(PointerLinkedList, cxListInsert) { 20.922 - auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 20.923 - cxListStorePointers(list); 20.924 - verifyInsert(list); 20.925 -} 20.926 - 20.927 -TEST_F(ArrayList, cxListInsert) { 20.928 - verifyInsert(autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 2))); 20.929 -} 20.930 - 20.931 -TEST_F(LinkedList, cxListInsertArray) { 20.932 - verifyInsertArray(autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)))); 20.933 -} 20.934 - 20.935 -TEST_F(PointerLinkedList, cxListInsertArray) { 20.936 - auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 20.937 - cxListStorePointers(list); 20.938 - verifyInsertArray(list, true); 20.939 -} 20.940 - 20.941 -TEST_F(ArrayList, cxListInsertArray) { 20.942 - verifyInsertArray(autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 4))); 20.943 -} 20.944 - 20.945 -TEST_F(LinkedList, cxListRemove) { 20.946 - verifyRemove(linkedListFromTestData()); 20.947 -} 20.948 - 20.949 -TEST_F(PointerLinkedList, cxListRemove) { 20.950 - verifyRemove(pointerLinkedListFromTestData()); 20.951 -} 20.952 - 20.953 -TEST_F(ArrayList, cxListRemove) { 20.954 - verifyRemove(arrayListFromTestData()); 20.955 -} 20.956 - 20.957 -TEST_F(LinkedList, cxListSwap) { 20.958 - verifySwap(autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)))); 20.959 -} 20.960 - 20.961 -TEST_F(PointerLinkedList, cxListSwap) { 20.962 - auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 20.963 - cxListStorePointers(list); 20.964 - verifySwap(list); 20.965 -} 20.966 - 20.967 -TEST_F(ArrayList, cxListSwap) { 20.968 - verifySwap(autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 16))); 20.969 -} 20.970 - 20.971 -TEST_F(LinkedList, cxListSwapNoSBO) { 20.972 - CX_DISABLE_LINKED_LIST_SWAP_SBO = true; 20.973 - verifySwap(autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)))); 20.974 - CX_DISABLE_LINKED_LIST_SWAP_SBO = false; 20.975 -} 20.976 - 20.977 -TEST_F(PointerLinkedList, cxListSwapNoSBO) { 20.978 - auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 20.979 - cxListStorePointers(list); 20.980 - CX_DISABLE_LINKED_LIST_SWAP_SBO = true; 20.981 - verifySwap(list); 20.982 - CX_DISABLE_LINKED_LIST_SWAP_SBO = false; 20.983 -} 20.984 - 20.985 -TEST_F(ArrayList, cxListSwapNoSBO) { 20.986 - CX_DISABLE_LINKED_LIST_SWAP_SBO = true; 20.987 - verifySwap(autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 16))); 20.988 - CX_DISABLE_LINKED_LIST_SWAP_SBO = false; 20.989 -} 20.990 - 20.991 -TEST_F(LinkedList, cxListAt) { 20.992 - verifyAt(linkedListFromTestData()); 20.993 -} 20.994 - 20.995 -TEST_F(PointerLinkedList, cxListAt) { 20.996 - verifyAt(pointerLinkedListFromTestData()); 20.997 -} 20.998 - 20.999 -TEST_F(ArrayList, cxListAt) { 20.1000 - verifyAt(arrayListFromTestData()); 20.1001 -} 20.1002 - 20.1003 -TEST_F(LinkedList, cxListFind) { 20.1004 - verifyFind(linkedListFromTestData()); 20.1005 -} 20.1006 - 20.1007 -TEST_F(PointerLinkedList, cxListFind) { 20.1008 - verifyFind(pointerLinkedListFromTestData()); 20.1009 -} 20.1010 - 20.1011 -TEST_F(ArrayList, cxListFind) { 20.1012 - verifyFind(arrayListFromTestData()); 20.1013 -} 20.1014 - 20.1015 -TEST_F(LinkedList, cxListSort) { 20.1016 - verifySort(linkedListFromTestData()); 20.1017 -} 20.1018 - 20.1019 -TEST_F(PointerLinkedList, cxListSort) { 20.1020 - verifySort(pointerLinkedListFromTestData()); 20.1021 -} 20.1022 - 20.1023 -TEST_F(ArrayList, cxListSort) { 20.1024 - verifySort(arrayListFromTestData()); 20.1025 -} 20.1026 - 20.1027 -TEST_F(LinkedList, Iterator) { 20.1028 - verifyIterator(linkedListFromTestData()); 20.1029 -} 20.1030 - 20.1031 -TEST_F(PointerLinkedList, Iterator) { 20.1032 - verifyIterator(pointerLinkedListFromTestData()); 20.1033 -} 20.1034 - 20.1035 -TEST_F(ArrayList, Iterator) { 20.1036 - verifyIterator(arrayListFromTestData()); 20.1037 -} 20.1038 - 20.1039 -TEST_F(LinkedList, InsertViaIterator) { 20.1040 - int fivenums[] = {0, 1, 2, 3, 4, 5}; 20.1041 - CxList *list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 20.1042 - cxListAddArray(list, fivenums, 5); 20.1043 - verifyInsertViaIterator(list); 20.1044 -} 20.1045 - 20.1046 -TEST_F(PointerLinkedList, InsertViaIterator) { 20.1047 - int fivenums[] = {0, 1, 2, 3, 4, 5}; 20.1048 - auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 20.1049 - cxListStorePointers(list); 20.1050 - // note: cannot use cxListAddArray() because we don't have a list of pointers 20.1051 - cx_for_n(i, 5) cxListAdd(list, &fivenums[i]); 20.1052 - verifyInsertViaIterator(list); 20.1053 -} 20.1054 - 20.1055 -TEST_F(ArrayList, InsertViaIterator) { 20.1056 - int fivenums[] = {0, 1, 2, 3, 4, 5}; 20.1057 - CxList *list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 4)); 20.1058 - cxListAddArray(list, fivenums, 5); 20.1059 - verifyInsertViaIterator(list); 20.1060 -} 20.1061 - 20.1062 -TEST_F(LinkedList, cxListReverse) { 20.1063 - verifyReverse(linkedListFromTestData()); 20.1064 -} 20.1065 - 20.1066 -TEST_F(PointerLinkedList, cxListReverse) { 20.1067 - verifyReverse(pointerLinkedListFromTestData()); 20.1068 -} 20.1069 - 20.1070 -TEST_F(ArrayList, cxListReverse) { 20.1071 - verifyReverse(arrayListFromTestData()); 20.1072 -} 20.1073 - 20.1074 -TEST_F(LinkedList, cxListCompare) { 20.1075 - auto left = linkedListFromTestData(); 20.1076 - auto right = linkedListFromTestData(); 20.1077 - verifyCompare(left, right); 20.1078 -} 20.1079 - 20.1080 -TEST_F(LinkedList, cxListCompareWithPtrList) { 20.1081 - auto left = linkedListFromTestData(); 20.1082 - auto right = pointerLinkedListFromTestData(); 20.1083 - verifyCompare(left, right); 20.1084 -} 20.1085 - 20.1086 -TEST_F(LinkedList, cxListCompareWithArrayList) { 20.1087 - auto left = linkedListFromTestData(); 20.1088 - auto right = arrayListFromTestData(); 20.1089 - verifyCompare(left, right); 20.1090 -} 20.1091 - 20.1092 -TEST_F(PointerLinkedList, cxListCompare) { 20.1093 - auto left = pointerLinkedListFromTestData(); 20.1094 - auto right = pointerLinkedListFromTestData(); 20.1095 - verifyCompare(left, right); 20.1096 -} 20.1097 - 20.1098 -TEST_F(PointerLinkedList, cxListCompareWithNormalList) { 20.1099 - auto left = pointerLinkedListFromTestData(); 20.1100 - auto right = linkedListFromTestData(); 20.1101 - verifyCompare(left, right); 20.1102 -} 20.1103 - 20.1104 -TEST_F(PointerLinkedList, cxListCompareWithArrayList) { 20.1105 - auto left = pointerLinkedListFromTestData(); 20.1106 - auto right = arrayListFromTestData(); 20.1107 - verifyCompare(left, right); 20.1108 -} 20.1109 - 20.1110 -TEST_F(ArrayList, cxListCompare) { 20.1111 - auto left = arrayListFromTestData(); 20.1112 - auto right = arrayListFromTestData(); 20.1113 - verifyCompare(left, right); 20.1114 -} 20.1115 - 20.1116 -TEST_F(ArrayList, cxListCompareWithPtrList) { 20.1117 - auto left = arrayListFromTestData(); 20.1118 - auto right = pointerLinkedListFromTestData(); 20.1119 - verifyCompare(left, right); 20.1120 -} 20.1121 - 20.1122 -TEST_F(ArrayList, cxListCompareWithNormalList) { 20.1123 - auto left = arrayListFromTestData(); 20.1124 - auto right = linkedListFromTestData(); 20.1125 - verifyCompare(left, right); 20.1126 -} 20.1127 - 20.1128 -TEST_F(PointerLinkedList, NoDestructor) { 20.1129 - void *item = cxMalloc(&testingAllocator, sizeof(int)); 20.1130 - auto list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int *)); 20.1131 - cxListStorePointers(list); 20.1132 - cxListAdd(list, item); 20.1133 - ASSERT_FALSE(testingAllocator.verify()); 20.1134 - cxListDestroy(list); 20.1135 - EXPECT_FALSE(testingAllocator.verify()); 20.1136 - cxFree(&testingAllocator, item); 20.1137 - EXPECT_TRUE(testingAllocator.verify()); 20.1138 -} 20.1139 - 20.1140 -TEST_F(PointerLinkedList, SimpleDestructor) { 20.1141 - int item = 0; 20.1142 - auto list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int *)); 20.1143 - cxListStorePointers(list); 20.1144 - list->content_destructor_type = CX_DESTRUCTOR_SIMPLE; 20.1145 - list->simple_destructor = [](void *elem) { *(int *) elem = 42; }; 20.1146 - cxListAdd(list, &item); 20.1147 - cxListDestroy(list); 20.1148 - EXPECT_EQ(item, 42); 20.1149 -} 20.1150 - 20.1151 -TEST_F(PointerLinkedList, AdvancedDestructor) { 20.1152 - void *item = cxMalloc(&testingAllocator, sizeof(int)); 20.1153 - auto list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int *)); 20.1154 - cxListStorePointers(list); 20.1155 - list->content_destructor_type = CX_DESTRUCTOR_ADVANCED; 20.1156 - list->advanced_destructor.data = &testingAllocator; 20.1157 - list->advanced_destructor.func = (cx_destructor_func2) cxFree; 20.1158 - cxListAdd(list, item); 20.1159 - ASSERT_FALSE(testingAllocator.verify()); 20.1160 - cxListDestroy(list); 20.1161 - EXPECT_TRUE(testingAllocator.verify()); 20.1162 -}
21.1 --- a/test/test_map.cpp Wed Feb 08 20:26:09 2023 +0100 21.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 21.3 @@ -1,272 +0,0 @@ 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/hash_map.h" 21.33 -#include "cx/utils.h" 21.34 -#include "util_allocator.h" 21.35 - 21.36 -#include <gtest/gtest.h> 21.37 -#include <unordered_map> 21.38 -#include <unordered_set> 21.39 - 21.40 -struct map_operation { 21.41 - enum { 21.42 - put, rm 21.43 - } op; 21.44 - char const *key; 21.45 - char const *value; 21.46 -}; 21.47 - 21.48 -auto generate_map_operations() -> std::vector<map_operation> { 21.49 - return { 21.50 - {map_operation::put, "key 1", "test"}, 21.51 - {map_operation::put, "key 2", "blub"}, 21.52 - {map_operation::put, "key 3", "hallo"}, 21.53 - {map_operation::put, "key 2", "foobar"}, 21.54 - {map_operation::put, "key 4", "value 4"}, 21.55 - {map_operation::put, "key 5", "value 5"}, 21.56 - {map_operation::put, "key 6", "value 6"}, 21.57 - {map_operation::rm, "key 4", nullptr}, 21.58 - {map_operation::put, "key 7", "value 7"}, 21.59 - {map_operation::put, "key 8", "value 8"}, 21.60 - {map_operation::rm, "does not exist", nullptr}, 21.61 - {map_operation::put, "key 9", "value 9"}, 21.62 - {map_operation::put, "key 6", "other value"}, 21.63 - {map_operation::put, "key 7", "something else"}, 21.64 - {map_operation::rm, "key 8", nullptr}, 21.65 - {map_operation::rm, "key 2", nullptr}, 21.66 - {map_operation::put, "key 8", "new value"}, 21.67 - }; 21.68 -} 21.69 - 21.70 -static void verify_map_contents( 21.71 - CxMap *map, 21.72 - std::unordered_map<std::string, std::string> const &refmap 21.73 -) { 21.74 - // verify key iterator 21.75 - { 21.76 - auto keyiter = cxMapIteratorKeys(map); 21.77 - std::unordered_set<std::string> keys; 21.78 - cx_foreach(CxHashKey*, elem, keyiter) { 21.79 - keys.insert(std::string(elem->data.cstr, elem->len)); 21.80 - } 21.81 - EXPECT_EQ(keyiter.index, map->size); 21.82 - ASSERT_EQ(keys.size(), map->size); 21.83 - for (auto &&k: keys) { 21.84 - EXPECT_NE(refmap.find(k), refmap.end()); 21.85 - } 21.86 - } 21.87 - 21.88 - // verify value iterator 21.89 - { 21.90 - auto valiter = cxMapIteratorValues(map); 21.91 - std::unordered_set<std::string> values; // we use that the values in our test data are unique strings 21.92 - cx_foreach(char const*, elem, valiter) { 21.93 - values.insert(std::string(elem)); 21.94 - } 21.95 - EXPECT_EQ(valiter.index, map->size); 21.96 - ASSERT_EQ(values.size(), map->size); 21.97 - for (auto &&v: values) { 21.98 - EXPECT_NE(std::find_if(refmap.begin(), refmap.end(), 21.99 - [v](auto const &e) { return e.second == v; }), refmap.end()); 21.100 - } 21.101 - } 21.102 - 21.103 - // verify pair iterator 21.104 - { 21.105 - auto pairiter = cxMapIterator(map); 21.106 - std::unordered_map<std::string, std::string> pairs; 21.107 - cx_foreach(CxMapEntry*, entry, pairiter) { 21.108 - pairs[std::string(entry->key->data.cstr, entry->key->len)] = std::string((char *) entry->value); 21.109 - } 21.110 - EXPECT_EQ(pairiter.index, map->size); 21.111 - ASSERT_EQ(pairs.size(), refmap.size()); 21.112 - for (auto &&p: pairs) { 21.113 - ASSERT_EQ(p.second, refmap.at(p.first)); 21.114 - } 21.115 - } 21.116 -} 21.117 - 21.118 -TEST(CxHashMap, Create) { 21.119 - CxTestingAllocator allocator; 21.120 - auto map = cxHashMapCreate(&allocator, 0); 21.121 - auto hmap = reinterpret_cast<struct cx_hash_map_s *>(map); 21.122 - EXPECT_GT(hmap->bucket_count, 0); 21.123 - cx_for_n(i, hmap->bucket_count) { 21.124 - EXPECT_EQ(hmap->buckets[i], nullptr); 21.125 - } 21.126 - EXPECT_EQ(map->size, 0); 21.127 - EXPECT_EQ(map->allocator, &allocator); 21.128 - 21.129 - cxMapDestroy(map); 21.130 - EXPECT_TRUE(allocator.verify()); 21.131 -} 21.132 - 21.133 -TEST(CxHashMap, BasicOperations) { 21.134 - // create the map 21.135 - CxTestingAllocator allocator; 21.136 - auto map = cxHashMapCreate(&allocator, 8); 21.137 - 21.138 - // create a reference map 21.139 - std::unordered_map<std::string, std::string> refmap; 21.140 - 21.141 - // generate operations 21.142 - auto ops = generate_map_operations(); 21.143 - 21.144 - // verify iterators for empty map 21.145 - verify_map_contents(map, refmap); 21.146 - 21.147 - // execute operations and verify results 21.148 - for (auto &&op: ops) { 21.149 - CxHashKey key = cx_hash_key_str(op.key); 21.150 - key.hash = 0; // force the hash map to compute the hash 21.151 - if (op.op == map_operation::put) { 21.152 - // execute a put operation and verify that the exact value can be read back 21.153 - refmap[std::string(op.key)] = std::string(op.value); 21.154 - int result = cxMapPut(map, key, (void *) op.value); 21.155 - EXPECT_EQ(result, 0); 21.156 - auto added = cxMapGet(map, key); 21.157 - EXPECT_EQ(memcmp(op.value, added, strlen(op.value)), 0); 21.158 - } else { 21.159 - // execute a remove and verify that the removed element was returned (or nullptr) 21.160 - auto found = refmap.find(op.key); 21.161 - auto removed = cxMapRemove(map, key); 21.162 - if (found == refmap.end()) { 21.163 - EXPECT_EQ(removed, nullptr); 21.164 - } else { 21.165 - EXPECT_EQ(std::string((char *) removed), found->second); 21.166 - refmap.erase(found); 21.167 - } 21.168 - } 21.169 - // compare the current map state with the reference map 21.170 - verify_map_contents(map, refmap); 21.171 - } 21.172 - 21.173 - // destroy the map and verify the memory (de)allocations 21.174 - cxMapDestroy(map); 21.175 - EXPECT_TRUE(allocator.verify()); 21.176 -} 21.177 - 21.178 -TEST(CxHashMap, RemoveViaIterator) { 21.179 - CxTestingAllocator allocator; 21.180 - auto map = cxHashMapCreate(&allocator, 4); 21.181 - 21.182 - cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); 21.183 - cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); 21.184 - cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); 21.185 - cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); 21.186 - cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5"); 21.187 - cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6"); 21.188 - 21.189 - auto iter = cxMapMutIterator(map); 21.190 - cx_foreach(CxMapEntry*, entry, iter) { 21.191 - if (entry->key->data.cstr[4] % 2 == 1) cxIteratorFlagRemoval(iter); 21.192 - } 21.193 - EXPECT_EQ(map->size, 3); 21.194 - EXPECT_EQ(iter.index, map->size); 21.195 - 21.196 - EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 1")), nullptr); 21.197 - EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 2")), nullptr); 21.198 - EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 3")), nullptr); 21.199 - EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 4")), nullptr); 21.200 - EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 5")), nullptr); 21.201 - EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 6")), nullptr); 21.202 - 21.203 - cxMapDestroy(map); 21.204 - EXPECT_TRUE(allocator.verify()); 21.205 -} 21.206 - 21.207 -TEST(CxHashMap, RehashNotRequired) { 21.208 - CxTestingAllocator allocator; 21.209 - auto map = cxHashMapCreate(&allocator, 8); 21.210 - 21.211 - cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); 21.212 - cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); 21.213 - cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); 21.214 - cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); 21.215 - cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5"); 21.216 - cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6"); 21.217 - 21.218 - // 6/8 does not exceed 0.75, therefore the function should not rehash 21.219 - int result = cxMapRehash(map); 21.220 - EXPECT_EQ(result, 0); 21.221 - EXPECT_EQ(reinterpret_cast<struct cx_hash_map_s *>(map)->bucket_count, 8); 21.222 - 21.223 - cxMapDestroy(map); 21.224 - EXPECT_TRUE(allocator.verify()); 21.225 -} 21.226 - 21.227 -TEST(CxHashMap, Rehash) { 21.228 - CxTestingAllocator allocator; 21.229 - auto map = cxHashMapCreate(&allocator, 8); 21.230 - 21.231 - cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); 21.232 - cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); 21.233 - cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); 21.234 - cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); 21.235 - cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5"); 21.236 - cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6"); 21.237 - cxMapPut(map, cx_hash_key_str("key 7"), (void *) "val 7"); 21.238 - 21.239 - int result = cxMapRehash(map); 21.240 - EXPECT_EQ(result, 0); 21.241 - EXPECT_EQ(reinterpret_cast<struct cx_hash_map_s *>(map)->bucket_count, 17); 21.242 - EXPECT_EQ(map->size, 7); 21.243 - 21.244 - EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 1")), "val 1"), 0); 21.245 - EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 2")), "val 2"), 0); 21.246 - EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 3")), "val 3"), 0); 21.247 - EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 4")), "val 4"), 0); 21.248 - EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 5")), "val 5"), 0); 21.249 - EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 6")), "val 6"), 0); 21.250 - EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 7")), "val 7"), 0); 21.251 - 21.252 - cxMapDestroy(map); 21.253 - EXPECT_TRUE(allocator.verify()); 21.254 -} 21.255 - 21.256 -TEST(CxHashMap, Clear) { 21.257 - CxTestingAllocator allocator; 21.258 - auto map = cxHashMapCreate(&allocator, 0); 21.259 - 21.260 - cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); 21.261 - cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); 21.262 - cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); 21.263 - 21.264 - EXPECT_EQ(map->size, 3); 21.265 - 21.266 - cxMapClear(map); 21.267 - 21.268 - EXPECT_EQ(map->size, 0); 21.269 - EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 1")), nullptr); 21.270 - EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 2")), nullptr); 21.271 - EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 3")), nullptr); 21.272 - 21.273 - cxMapDestroy(map); 21.274 - EXPECT_TRUE(allocator.verify()); 21.275 -} 21.276 \ No newline at end of file
22.1 --- a/test/test_printf.cpp Wed Feb 08 20:26:09 2023 +0100 22.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 22.3 @@ -1,284 +0,0 @@ 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/printf.h" 22.33 -#include "cx/buffer.h" 22.34 - 22.35 -#include <gtest/gtest.h> 22.36 -#include "util_allocator.h" 22.37 - 22.38 -class PrintfFixture : public ::testing::Test { 22.39 -protected: 22.40 - std::string buf; 22.41 - CxTestingAllocator alloc; 22.42 - 22.43 - void TearDown() override { 22.44 - buf.clear(); 22.45 - ASSERT_TRUE(alloc.verify()); 22.46 - } 22.47 - 22.48 - static size_t write_func( 22.49 - void const *src, 22.50 - size_t esize, 22.51 - size_t ecount, 22.52 - void *target 22.53 - ) { 22.54 - auto str = reinterpret_cast<char const *>(src); 22.55 - auto buf = reinterpret_cast<std::string *>(target); 22.56 - EXPECT_EQ(esize, 1); 22.57 - EXPECT_EQ(strlen(str), ecount); 22.58 - *buf = str; 22.59 - return ecount; 22.60 - } 22.61 -}; 22.62 - 22.63 - 22.64 -TEST_F(PrintfFixture, BPrintf) { 22.65 - CxBuffer buf; 22.66 - cxBufferInit(&buf, nullptr, 64, &alloc, 0); 22.67 - 22.68 - auto r = cx_bprintf(&buf, "This %s aged %u years in a %2XSK.", "Test", 10, 0xca); 22.69 - EXPECT_EQ(r, 34); 22.70 - EXPECT_EQ(buf.size, 34); 22.71 - buf.space[r] = '\0'; 22.72 - EXPECT_STREQ(buf.space, "This Test aged 10 years in a CASK."); 22.73 - 22.74 - cxBufferDestroy(&buf); 22.75 -} 22.76 - 22.77 -TEST_F(PrintfFixture, FPrintf) { 22.78 - auto h = "Hello"; 22.79 - size_t r; 22.80 - 22.81 - r = cx_fprintf(&buf, PrintfFixture::write_func, "teststring"); 22.82 - EXPECT_EQ(r, 10); 22.83 - EXPECT_EQ(buf, "teststring"); 22.84 - 22.85 - r = cx_fprintf(&buf, PrintfFixture::write_func, "[%10s]", h); 22.86 - EXPECT_EQ(r, 12); 22.87 - EXPECT_EQ(buf, "[ Hello]"); 22.88 - 22.89 - r = cx_fprintf(&buf, PrintfFixture::write_func, "[%-10s]", h); 22.90 - EXPECT_EQ(r, 12); 22.91 - EXPECT_EQ(buf, "[Hello ]"); 22.92 - 22.93 - r = cx_fprintf(&buf, PrintfFixture::write_func, "[%*s]", 10, h); 22.94 - EXPECT_EQ(r, 12); 22.95 - EXPECT_EQ(buf, "[ Hello]"); 22.96 - 22.97 - r = cx_fprintf(&buf, PrintfFixture::write_func, "[%-10.*s]", 4, h); 22.98 - EXPECT_EQ(r, 12); 22.99 - EXPECT_EQ(buf, "[Hell ]"); 22.100 - 22.101 - r = cx_fprintf(&buf, PrintfFixture::write_func, "[%-*.*s]", 10, 4, h); 22.102 - EXPECT_EQ(r, 12); 22.103 - EXPECT_EQ(buf, "[Hell ]"); 22.104 - 22.105 - r = cx_fprintf(&buf, PrintfFixture::write_func, "%c", 'A'); 22.106 - EXPECT_EQ(r, 1); 22.107 - EXPECT_EQ(buf, "A"); 22.108 - 22.109 - r = cx_fprintf(&buf, PrintfFixture::write_func, "%i %d %.6i %i %.0i %+i %i", 1, 2, 3, 0, 0, 4, -4); 22.110 - EXPECT_EQ(r, 19); 22.111 - EXPECT_EQ(buf, "1 2 000003 0 +4 -4"); 22.112 - 22.113 - r = cx_fprintf(&buf, PrintfFixture::write_func, "%x %x %X %#x", 5, 10, 10, 6); 22.114 - EXPECT_EQ(r, 9); 22.115 - EXPECT_EQ(buf, "5 a A 0x6"); 22.116 - 22.117 - r = cx_fprintf(&buf, PrintfFixture::write_func, "%o %#o %#o", 10, 10, 4); 22.118 - EXPECT_EQ(r, 9); 22.119 - EXPECT_EQ(buf, "12 012 04"); 22.120 - 22.121 - r = cx_fprintf(&buf, PrintfFixture::write_func, "%f %.0f %.32f", 1.5, 1.5, 1.3); 22.122 - EXPECT_EQ(r, 45); 22.123 - EXPECT_EQ(buf, "1.500000 2 1.30000000000000004440892098500626"); 22.124 - 22.125 - r = cx_fprintf(&buf, PrintfFixture::write_func, "%05.2f %.2f %5.2f", 1.5, 1.5, 1.5); 22.126 - EXPECT_EQ(r, 16); 22.127 - EXPECT_EQ(buf, "01.50 1.50 1.50"); 22.128 - 22.129 - r = cx_fprintf(&buf, PrintfFixture::write_func, "%E %e", 1.5, 1.5); 22.130 - EXPECT_EQ(r, 25); 22.131 - EXPECT_EQ(buf, "1.500000E+00 1.500000e+00"); 22.132 - 22.133 - r = cx_fprintf(&buf, PrintfFixture::write_func, "%a %A", 1.5, 1.5); 22.134 - EXPECT_EQ(r, 17); 22.135 - EXPECT_EQ(buf, "0x1.8p+0 0X1.8P+0"); 22.136 - 22.137 - r = cx_fprintf(&buf, PrintfFixture::write_func, "0/0=%g 1/0=%g", 0.0 / 0.0, 1.0 / 0.0); 22.138 - EXPECT_EQ(r, 16); 22.139 - EXPECT_EQ(buf, "0/0=-nan 1/0=inf"); 22.140 - 22.141 - r = cx_fprintf(&buf, PrintfFixture::write_func, "'%*c'", 5, 'x'); 22.142 - EXPECT_EQ(r, 7); 22.143 - EXPECT_EQ(buf, "' x'"); 22.144 - 22.145 - r = cx_fprintf(&buf, PrintfFixture::write_func, "'%*c'", -5, 'x'); 22.146 - EXPECT_EQ(r, 7); 22.147 - EXPECT_EQ(buf, "'x '"); 22.148 -} 22.149 - 22.150 -TEST_F(PrintfFixture, BPrintfLargeString) { 22.151 - CxBuffer buf; 22.152 - cxBufferInit(&buf, nullptr, 64, &alloc, CX_BUFFER_AUTO_EXTEND); 22.153 - 22.154 - auto aaa = std::string(512, 'a'); 22.155 - auto bbb = std::string(512, 'b'); 22.156 - 22.157 - auto r = cx_bprintf(&buf, "After %s comes %s.", aaa.data(), bbb.data()); 22.158 - EXPECT_EQ(r, 1038); 22.159 - EXPECT_EQ(buf.size, 1038); 22.160 - cxBufferPut(&buf, 0); 22.161 - EXPECT_EQ(buf.space, std::string("After ") + aaa + " comes " + bbb + "."); 22.162 - 22.163 - cxBufferDestroy(&buf); 22.164 -} 22.165 - 22.166 -TEST_F(PrintfFixture, BPrintfNoCap) { 22.167 - CxBuffer buf; 22.168 - char space[20]; 22.169 - memset(space, 'a', 20); 22.170 - cxBufferInit(&buf, space, 16, &alloc, 0); 22.171 - 22.172 - auto r = cx_bprintf(&buf, "Hello %s with more than %d chars.", "string", 16); 22.173 - EXPECT_EQ(r, 16); 22.174 - EXPECT_EQ(buf.size, 16); 22.175 - EXPECT_EQ(0, memcmp(space, "Hello string witaaaa", 20)); 22.176 - 22.177 - cxBufferDestroy(&buf); 22.178 -} 22.179 - 22.180 -TEST_F(PrintfFixture, SPrintf) { 22.181 - auto h = "Hello"; 22.182 - 22.183 - std::vector<char *> fl; 22.184 - cxmutstr r; 22.185 - 22.186 - r = cx_asprintf_a(&alloc, "teststring"); 22.187 - EXPECT_EQ(r.length, 10); 22.188 - EXPECT_STREQ(r.ptr, "teststring"); 22.189 - fl.push_back(r.ptr); 22.190 - 22.191 - r = cx_asprintf_a(&alloc, "[%10s]", h); 22.192 - EXPECT_EQ(r.length, 12); 22.193 - EXPECT_STREQ(r.ptr, "[ Hello]"); 22.194 - fl.push_back(r.ptr); 22.195 - 22.196 - r = cx_asprintf_a(&alloc, "[%-10s]", h); 22.197 - EXPECT_EQ(r.length, 12); 22.198 - EXPECT_STREQ(r.ptr, "[Hello ]"); 22.199 - fl.push_back(r.ptr); 22.200 - 22.201 - r = cx_asprintf_a(&alloc, "[%*s]", 10, h); 22.202 - EXPECT_EQ(r.length, 12); 22.203 - EXPECT_STREQ(r.ptr, "[ Hello]"); 22.204 - fl.push_back(r.ptr); 22.205 - 22.206 - r = cx_asprintf_a(&alloc, "[%-10.*s]", 4, h); 22.207 - EXPECT_EQ(r.length, 12); 22.208 - EXPECT_STREQ(r.ptr, "[Hell ]"); 22.209 - fl.push_back(r.ptr); 22.210 - 22.211 - r = cx_asprintf_a(&alloc, "[%-*.*s]", 10, 4, h); 22.212 - EXPECT_EQ(r.length, 12); 22.213 - EXPECT_STREQ(r.ptr, "[Hell ]"); 22.214 - fl.push_back(r.ptr); 22.215 - 22.216 - r = cx_asprintf_a(&alloc, "%c", 'A'); 22.217 - EXPECT_EQ(r.length, 1); 22.218 - EXPECT_STREQ(r.ptr, "A"); 22.219 - fl.push_back(r.ptr); 22.220 - 22.221 - r = cx_asprintf_a(&alloc, "%i %d %.6i %i %.0i %+i %i", 1, 2, 3, 0, 0, 4, -4); 22.222 - EXPECT_EQ(r.length, 19); 22.223 - EXPECT_STREQ(r.ptr, "1 2 000003 0 +4 -4"); 22.224 - fl.push_back(r.ptr); 22.225 - 22.226 - r = cx_asprintf_a(&alloc, "%x %x %X %#x", 5, 10, 10, 6); 22.227 - EXPECT_EQ(r.length, 9); 22.228 - EXPECT_STREQ(r.ptr, "5 a A 0x6"); 22.229 - fl.push_back(r.ptr); 22.230 - 22.231 - r = cx_asprintf_a(&alloc, "%o %#o %#o", 10, 10, 4); 22.232 - EXPECT_EQ(r.length, 9); 22.233 - EXPECT_STREQ(r.ptr, "12 012 04"); 22.234 - fl.push_back(r.ptr); 22.235 - 22.236 - r = cx_asprintf_a(&alloc, "%f %.0f %.32f", 1.5, 1.5, 1.3); 22.237 - EXPECT_EQ(r.length, 45); 22.238 - EXPECT_STREQ(r.ptr, "1.500000 2 1.30000000000000004440892098500626"); 22.239 - fl.push_back(r.ptr); 22.240 - 22.241 - r = cx_asprintf_a(&alloc, "%05.2f %.2f %5.2f", 1.5, 1.5, 1.5); 22.242 - EXPECT_EQ(r.length, 16); 22.243 - EXPECT_STREQ(r.ptr, "01.50 1.50 1.50"); 22.244 - fl.push_back(r.ptr); 22.245 - 22.246 - r = cx_asprintf_a(&alloc, "%E %e", 1.5, 1.5); 22.247 - EXPECT_EQ(r.length, 25); 22.248 - EXPECT_STREQ(r.ptr, "1.500000E+00 1.500000e+00"); 22.249 - fl.push_back(r.ptr); 22.250 - 22.251 - r = cx_asprintf_a(&alloc, "%a %A", 1.5, 1.5); 22.252 - EXPECT_EQ(r.length, 17); 22.253 - EXPECT_STREQ(r.ptr, "0x1.8p+0 0X1.8P+0"); 22.254 - fl.push_back(r.ptr); 22.255 - 22.256 - r = cx_asprintf_a(&alloc, "0/0=%g 1/0=%g", 0.0 / 0.0, 1.0 / 0.0); 22.257 - EXPECT_EQ(r.length, 16); 22.258 - EXPECT_STREQ(r.ptr, "0/0=-nan 1/0=inf"); 22.259 - fl.push_back(r.ptr); 22.260 - 22.261 - r = cx_asprintf_a(&alloc, "'%*c'", 5, 'x'); 22.262 - EXPECT_EQ(r.length, 7); 22.263 - EXPECT_STREQ(r.ptr, "' x'"); 22.264 - fl.push_back(r.ptr); 22.265 - 22.266 - r = cx_asprintf_a(&alloc, "'%*c'", -5, 'x'); 22.267 - EXPECT_EQ(r.length, 7); 22.268 - EXPECT_STREQ(r.ptr, "'x '"); 22.269 - fl.push_back(r.ptr); 22.270 - 22.271 - for (auto c: fl) { 22.272 - auto s = cx_mutstrn(c, 0); 22.273 - cx_strfree_a(&alloc, &s); 22.274 - } 22.275 -} 22.276 - 22.277 -TEST_F(PrintfFixture, SPrintfLargeString) { 22.278 - auto aaa = std::string(512, 'a'); 22.279 - auto bbb = std::string(512, 'b'); 22.280 - 22.281 - auto r = cx_asprintf_a(&alloc, "After %s comes %s.", aaa.data(), bbb.data()); 22.282 - EXPECT_EQ(r.length, 1038); 22.283 - EXPECT_EQ(r.ptr, std::string("After ") + aaa + " comes " + bbb + "."); 22.284 - EXPECT_EQ(r.ptr[1038], '\0'); 22.285 - 22.286 - cx_strfree_a(&alloc, &r); 22.287 -} 22.288 \ No newline at end of file
23.1 --- a/test/test_string.cpp Wed Feb 08 20:26:09 2023 +0100 23.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 23.3 @@ -1,865 +0,0 @@ 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/string.h" 23.33 -#include "util_allocator.h" 23.34 - 23.35 -#include <gtest/gtest.h> 23.36 - 23.37 -#define EXPECT_ZERO_TERMINATED(str) EXPECT_EQ((str).ptr[(str).length], '\0') 23.38 - 23.39 -TEST(String, construct) { 23.40 - cxstring s1 = cx_str("1234"); 23.41 - cxstring s2 = cx_strn("abcd", 2); 23.42 - cxmutstr s3 = cx_mutstr((char *) "1234"); 23.43 - cxmutstr s4 = cx_mutstrn((char *) "abcd", 2); 23.44 - 23.45 - EXPECT_EQ(s1.length, 4); 23.46 - EXPECT_EQ(s2.length, 2); 23.47 - EXPECT_EQ(s3.length, 4); 23.48 - EXPECT_EQ(s4.length, 2); 23.49 -} 23.50 - 23.51 -TEST(String, strfree) { 23.52 - CxTestingAllocator alloc; 23.53 - auto test = (char *) cxMalloc(&alloc, 16); 23.54 - cxmutstr str = cx_mutstrn(test, 16); 23.55 - ASSERT_EQ(str.ptr, test); 23.56 - EXPECT_EQ(str.length, 16); 23.57 - cx_strfree_a(&alloc, &str); 23.58 - EXPECT_EQ(str.ptr, nullptr); 23.59 - EXPECT_EQ(str.length, 0); 23.60 - EXPECT_TRUE(alloc.verify()); 23.61 -} 23.62 - 23.63 -TEST(String, strdup) { 23.64 - cxstring str = CX_STR("test"); 23.65 - cxmutstr dup = cx_strdup(str); 23.66 - ASSERT_EQ(dup.length, str.length); 23.67 - EXPECT_STREQ(dup.ptr, str.ptr); 23.68 - EXPECT_ZERO_TERMINATED(dup); 23.69 - cx_strfree(&dup); 23.70 - 23.71 - str.length = 2; 23.72 - dup = cx_strdup(str); 23.73 - ASSERT_EQ(dup.length, str.length); 23.74 - EXPECT_STREQ(dup.ptr, "te"); 23.75 - EXPECT_ZERO_TERMINATED(dup); 23.76 - cx_strfree(&dup); 23.77 -} 23.78 - 23.79 -TEST(String, strlen) { 23.80 - cxstring s1 = CX_STR("1234"); 23.81 - cxstring s2 = CX_STR(".:.:."); 23.82 - cxstring s3 = CX_STR("X"); 23.83 - 23.84 - size_t len0 = cx_strlen(0); 23.85 - size_t len1 = cx_strlen(1, s1); 23.86 - size_t len2 = cx_strlen(2, s1, s2); 23.87 - size_t len3 = cx_strlen(3, s1, s2, s3); 23.88 - 23.89 - EXPECT_EQ(len0, 0); 23.90 - EXPECT_EQ(len1, 4); 23.91 - EXPECT_EQ(len2, 9); 23.92 - EXPECT_EQ(len3, 10); 23.93 -} 23.94 - 23.95 -TEST(String, strsubs) { 23.96 - cxstring str = CX_STR("A test string"); 23.97 - 23.98 - cxstring sub = cx_strsubs(str, 0); 23.99 - EXPECT_EQ(cx_strcmp(sub, str), 0); 23.100 - 23.101 - sub = cx_strsubs(str, 2); 23.102 - EXPECT_EQ(cx_strcmp(sub, cx_str("test string")), 0); 23.103 - 23.104 - sub = cx_strsubs(str, 7); 23.105 - EXPECT_EQ(cx_strcmp(sub, cx_str("string")), 0); 23.106 - 23.107 - sub = cx_strsubs(str, 15); 23.108 - EXPECT_EQ(cx_strcmp(sub, cx_str("")), 0); 23.109 - 23.110 - sub = cx_strsubsl(str, 2, 4); 23.111 - EXPECT_EQ(cx_strcmp(sub, cx_str("test")), 0); 23.112 - 23.113 - sub = cx_strsubsl(str, 7, 3); 23.114 - EXPECT_EQ(cx_strcmp(sub, cx_str("str")), 0); 23.115 - 23.116 - sub = cx_strsubsl(str, 7, 20); 23.117 - EXPECT_EQ(cx_strcmp(sub, cx_str("string")), 0); 23.118 - 23.119 - // just for coverage, call the _m variant 23.120 - auto m = cx_strsubs_m(cx_mutstrn(nullptr, 0), 0); 23.121 - EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0); 23.122 -} 23.123 - 23.124 -TEST(String, strchr) { 23.125 - cxstring str = CX_STR("I will find you - and I will kill you"); 23.126 - 23.127 - cxstring notfound = cx_strchr(str, 'x'); 23.128 - EXPECT_EQ(notfound.length, 0); 23.129 - 23.130 - cxstring result = cx_strchr(str, 'w'); 23.131 - EXPECT_EQ(result.length, 35); 23.132 - EXPECT_STREQ(result.ptr, "will find you - and I will kill you"); 23.133 - 23.134 - // just for coverage, call the _m variant 23.135 - auto m = cx_strchr_m(cx_mutstrn(nullptr, 0), 'a'); 23.136 - EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0); 23.137 -} 23.138 - 23.139 -TEST(String, strrchr) { 23.140 - cxstring str = CX_STR("I will find you - and I will kill you"); 23.141 - 23.142 - cxstring notfound = cx_strrchr(str, 'x'); 23.143 - EXPECT_EQ(notfound.length, 0); 23.144 - 23.145 - cxstring result = cx_strrchr(str, 'w'); 23.146 - EXPECT_EQ(result.length, 13); 23.147 - EXPECT_STREQ(result.ptr, "will kill you"); 23.148 - 23.149 - // just for coverage, call the _m variant 23.150 - auto m = cx_strrchr_m(cx_mutstrn(nullptr, 0), 'a'); 23.151 - EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0); 23.152 -} 23.153 - 23.154 -TEST(String, strstr) { 23.155 - cxstring str = CX_STR("find the match in this string"); 23.156 - cxstring longstr = CX_STR( 23.157 - "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl" 23.158 - "mnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx" 23.159 - "yzabcdeababababnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij" 23.160 - "klmnopqrstuvwxyzaababababababababrstuvwxyzabcdefghijklmnopqrstuv" 23.161 - "abababababababababababababababababababababababababababababababab" 23.162 - "abababababababababababababababababababababababababababababababab" 23.163 - "abababababababababababababababababababababababababababababababab" 23.164 - "abababababababababababababababababababababababababababababababab" 23.165 - "abababababababababababababababababababababababababababababababab" 23.166 - "abababababababababababababababababababababababababababababababab" 23.167 - "wxyz1234567890"); 23.168 - cxstring longstrpattern = CX_STR( 23.169 - "abababababababababababababababababababababababababababababababab" 23.170 - "abababababababababababababababababababababababababababababababab" 23.171 - "abababababababababababababababababababababababababababababababab" 23.172 - "abababababababababababababababababababababababababababababababab" 23.173 - "abababababababababababababababababababababababababababababababab" 23.174 - ); 23.175 - cxstring longstrresult = CX_STR( 23.176 - "abababababababababababababababababababababababababababababababab" 23.177 - "abababababababababababababababababababababababababababababababab" 23.178 - "abababababababababababababababababababababababababababababababab" 23.179 - "abababababababababababababababababababababababababababababababab" 23.180 - "abababababababababababababababababababababababababababababababab" 23.181 - "abababababababababababababababababababababababababababababababab" 23.182 - "wxyz1234567890" 23.183 - ); 23.184 - 23.185 - cxstring notfound = cx_strstr(str, cx_str("no match")); 23.186 - EXPECT_EQ(notfound.length, 0); 23.187 - 23.188 - cxstring result = cx_strstr(str, cx_str("match")); 23.189 - EXPECT_EQ(result.length, 20); 23.190 - EXPECT_STREQ(result.ptr, "match in this string"); 23.191 - 23.192 - result = cx_strstr(str, cx_str("")); 23.193 - EXPECT_EQ(result.length, str.length); 23.194 - EXPECT_STREQ(result.ptr, str.ptr); 23.195 - 23.196 - result = cx_strstr(longstr, longstrpattern); 23.197 - EXPECT_EQ(result.length, longstrresult.length); 23.198 - EXPECT_STREQ(result.ptr, longstrresult.ptr); 23.199 - 23.200 - // just for coverage, call the _m variant 23.201 - auto mstr = cx_strdup(longstr); 23.202 - auto m = cx_strstr_m(mstr, longstrpattern); 23.203 - EXPECT_EQ(m.length, longstrresult.length); 23.204 - EXPECT_STREQ(m.ptr, longstrresult.ptr); 23.205 - cx_strfree(&mstr); 23.206 -} 23.207 - 23.208 -TEST(String, strcmp) { 23.209 - cxstring str = CX_STR("compare this"); 23.210 - 23.211 - EXPECT_EQ(cx_strcmp(cx_str(""), cx_str("")), 0); 23.212 - EXPECT_GT(cx_strcmp(str, cx_str("")), 0); 23.213 - EXPECT_EQ(cx_strcmp(str, cx_str("compare this")), 0); 23.214 - EXPECT_NE(cx_strcmp(str, cx_str("Compare This")), 0); 23.215 - EXPECT_LT(cx_strcmp(str, cx_str("compare tool")), 0); 23.216 - EXPECT_GT(cx_strcmp(str, cx_str("compare shit")), 0); 23.217 - EXPECT_LT(cx_strcmp(str, cx_str("compare this not")), 0); 23.218 - EXPECT_GT(cx_strcmp(str, cx_str("compare")), 0); 23.219 -} 23.220 - 23.221 -TEST(String, strcasecmp) { 23.222 - cxstring str = CX_STR("compare this"); 23.223 - 23.224 - EXPECT_EQ(cx_strcasecmp(cx_str(""), cx_str("")), 0); 23.225 - EXPECT_GT(cx_strcasecmp(str, cx_str("")), 0); 23.226 - EXPECT_EQ(cx_strcasecmp(str, cx_str("compare this")), 0); 23.227 - EXPECT_EQ(cx_strcasecmp(str, cx_str("Compare This")), 0); 23.228 - EXPECT_LT(cx_strcasecmp(str, cx_str("compare tool")), 0); 23.229 - EXPECT_GT(cx_strcasecmp(str, cx_str("compare shit")), 0); 23.230 - EXPECT_LT(cx_strcasecmp(str, cx_str("compare this not")), 0); 23.231 - EXPECT_GT(cx_strcasecmp(str, cx_str("compare")), 0); 23.232 -} 23.233 - 23.234 -TEST(String, strcat) { 23.235 - cxstring s1 = CX_STR("12"); 23.236 - cxstring s2 = CX_STR("34"); 23.237 - cxstring s3 = CX_STR("56"); 23.238 - cxstring sn = {nullptr, 0}; 23.239 - 23.240 - CxTestingAllocator alloc; 23.241 - 23.242 - cxmutstr t1 = cx_strcat_a(&alloc, 2, s1, s2); 23.243 - EXPECT_EQ(cx_strcmp(cx_strcast(t1), cx_str("1234")), 0); 23.244 - EXPECT_ZERO_TERMINATED(t1); 23.245 - cx_strfree_a(&alloc, &t1); 23.246 - 23.247 - cxmutstr t2 = cx_strcat_a(&alloc, 3, s1, s2, s3); 23.248 - EXPECT_EQ(cx_strcmp(cx_strcast(t2), cx_str("123456")), 0); 23.249 - EXPECT_ZERO_TERMINATED(t2); 23.250 - cx_strfree_a(&alloc, &t2); 23.251 - 23.252 - cxmutstr t3 = cx_strcat_a(&alloc, 6, s1, sn, s2, sn, s3, sn); 23.253 - EXPECT_EQ(cx_strcmp(cx_strcast(t3), cx_str("123456")), 0); 23.254 - EXPECT_ZERO_TERMINATED(t3); 23.255 - cx_strfree_a(&alloc, &t3); 23.256 - 23.257 - cxmutstr t4 = cx_strcat_a(&alloc, 2, sn, sn); 23.258 - EXPECT_EQ(cx_strcmp(cx_strcast(t4), cx_str("")), 0); 23.259 - EXPECT_ZERO_TERMINATED(t4); 23.260 - cx_strfree_a(&alloc, &t4); 23.261 - 23.262 - EXPECT_TRUE(alloc.verify()); 23.263 - 23.264 - // use the macro 23.265 - cxmutstr t5 = cx_strcat(3, s3, s1, s2); 23.266 - EXPECT_EQ(cx_strcmp(cx_strcast(t5), cx_str("561234")), 0); 23.267 - EXPECT_ZERO_TERMINATED(t5); 23.268 - cx_strfree(&t5); 23.269 -} 23.270 - 23.271 -TEST(String, strsplit) { 23.272 - 23.273 - cxstring test = cx_str("this,is,a,csv,string"); 23.274 - size_t capa = 8; 23.275 - cxstring list[8]; 23.276 - size_t n; 23.277 - 23.278 - // special case: empty string 23.279 - n = cx_strsplit(test, cx_str(""), capa, list); 23.280 - ASSERT_EQ(n, 1); 23.281 - EXPECT_EQ(cx_strcmp(list[0], test), 0); 23.282 - 23.283 - // no delimiter occurrence 23.284 - n = cx_strsplit(test, cx_str("z"), capa, list); 23.285 - ASSERT_EQ(n, 1); 23.286 - EXPECT_EQ(cx_strcmp(list[0], test), 0); 23.287 - 23.288 - // partially matching delimiter 23.289 - n = cx_strsplit(test, cx_str("is,not"), capa, list); 23.290 - ASSERT_EQ(n, 1); 23.291 - EXPECT_EQ(cx_strcmp(list[0], test), 0); 23.292 - 23.293 - // matching single-char delimiter 23.294 - n = cx_strsplit(test, cx_str(","), capa, list); 23.295 - ASSERT_EQ(n, 5); 23.296 - EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0); 23.297 - EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0); 23.298 - EXPECT_EQ(cx_strcmp(list[2], cx_str("a")), 0); 23.299 - EXPECT_EQ(cx_strcmp(list[3], cx_str("csv")), 0); 23.300 - EXPECT_EQ(cx_strcmp(list[4], cx_str("string")), 0); 23.301 - 23.302 - // matching multi-char delimiter 23.303 - n = cx_strsplit(test, cx_str("is"), capa, list); 23.304 - ASSERT_EQ(n, 3); 23.305 - EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 23.306 - EXPECT_EQ(cx_strcmp(list[1], cx_str(",")), 0); 23.307 - EXPECT_EQ(cx_strcmp(list[2], cx_str(",a,csv,string")), 0); 23.308 - 23.309 - // bounded list using single-char delimiter 23.310 - n = cx_strsplit(test, cx_str(","), 3, list); 23.311 - ASSERT_EQ(n, 3); 23.312 - EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0); 23.313 - EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0); 23.314 - EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0); 23.315 - 23.316 - // bounded list using multi-char delimiter 23.317 - n = cx_strsplit(test, cx_str("is"), 2, list); 23.318 - ASSERT_EQ(n, 2); 23.319 - EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 23.320 - EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0); 23.321 - 23.322 - // start with delimiter 23.323 - n = cx_strsplit(test, cx_str("this"), capa, list); 23.324 - ASSERT_EQ(n, 2); 23.325 - EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0); 23.326 - EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0); 23.327 - 23.328 - // end with delimiter 23.329 - n = cx_strsplit(test, cx_str("string"), capa, list); 23.330 - ASSERT_EQ(n, 2); 23.331 - EXPECT_EQ(cx_strcmp(list[0], cx_str("this,is,a,csv,")), 0); 23.332 - EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 23.333 - 23.334 - 23.335 - // end with delimiter exceed bound 23.336 - n = cx_strsplit(cx_str("a,b,c,"), cx_str(","), 3, list); 23.337 - ASSERT_EQ(n, 3); 23.338 - EXPECT_EQ(cx_strcmp(list[0], cx_str("a")), 0); 23.339 - EXPECT_EQ(cx_strcmp(list[1], cx_str("b")), 0); 23.340 - EXPECT_EQ(cx_strcmp(list[2], cx_str("c,")), 0); 23.341 - 23.342 - // exact match 23.343 - n = cx_strsplit(test, cx_str("this,is,a,csv,string"), capa, list); 23.344 - ASSERT_EQ(n, 2); 23.345 - EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0); 23.346 - EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 23.347 - 23.348 - // string to be split is only substring 23.349 - n = cx_strsplit(test, cx_str("this,is,a,csv,string,with,extension"), capa, list); 23.350 - ASSERT_EQ(n, 1); 23.351 - EXPECT_EQ(cx_strcmp(list[0], test), 0); 23.352 - 23.353 - // subsequent encounter of delimiter (the string between is empty) 23.354 - n = cx_strsplit(test, cx_str("is,"), capa, list); 23.355 - ASSERT_EQ(n, 3); 23.356 - EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 23.357 - EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 23.358 - EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0); 23.359 - 23.360 - // call the _m variant just for coverage 23.361 - auto mtest = cx_strdup(test); 23.362 - cxmutstr mlist[4]; 23.363 - n = cx_strsplit_m(mtest, cx_str("is,"), 4, mlist); 23.364 - ASSERT_EQ(n, 3); 23.365 - EXPECT_EQ(cx_strcmp(cx_strcast(mlist[0]), cx_str("th")), 0); 23.366 - EXPECT_EQ(cx_strcmp(cx_strcast(mlist[1]), cx_str("")), 0); 23.367 - EXPECT_EQ(cx_strcmp(cx_strcast(mlist[2]), cx_str("a,csv,string")), 0); 23.368 - cx_strfree(&mtest); 23.369 -} 23.370 - 23.371 -TEST(String, strsplit_a) { 23.372 - CxTestingAllocator alloc; 23.373 - 23.374 - cxstring test = cx_str("this,is,a,csv,string"); 23.375 - size_t capa = 8; 23.376 - cxstring *list; 23.377 - size_t n; 23.378 - 23.379 - // special case: empty string 23.380 - n = cx_strsplit_a(&alloc, test, cx_str(""), capa, &list); 23.381 - ASSERT_EQ(n, 1); 23.382 - EXPECT_EQ(cx_strcmp(list[0], test), 0); 23.383 - cxFree(&alloc, list); 23.384 - 23.385 - // no delimiter occurrence 23.386 - n = cx_strsplit_a(&alloc, test, cx_str("z"), capa, &list); 23.387 - ASSERT_EQ(n, 1); 23.388 - EXPECT_EQ(cx_strcmp(list[0], test), 0); 23.389 - cxFree(&alloc, list); 23.390 - 23.391 - // partially matching delimiter 23.392 - n = cx_strsplit_a(&alloc, test, cx_str("is,not"), capa, &list); 23.393 - ASSERT_EQ(n, 1); 23.394 - EXPECT_EQ(cx_strcmp(list[0], test), 0); 23.395 - cxFree(&alloc, list); 23.396 - 23.397 - // matching single-char delimiter 23.398 - n = cx_strsplit_a(&alloc, test, cx_str(","), capa, &list); 23.399 - ASSERT_EQ(n, 5); 23.400 - EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0); 23.401 - EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0); 23.402 - EXPECT_EQ(cx_strcmp(list[2], cx_str("a")), 0); 23.403 - EXPECT_EQ(cx_strcmp(list[3], cx_str("csv")), 0); 23.404 - EXPECT_EQ(cx_strcmp(list[4], cx_str("string")), 0); 23.405 - cxFree(&alloc, list); 23.406 - 23.407 - // matching multi-char delimiter 23.408 - n = cx_strsplit_a(&alloc, test, cx_str("is"), capa, &list); 23.409 - ASSERT_EQ(n, 3); 23.410 - EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 23.411 - EXPECT_EQ(cx_strcmp(list[1], cx_str(",")), 0); 23.412 - EXPECT_EQ(cx_strcmp(list[2], cx_str(",a,csv,string")), 0); 23.413 - cxFree(&alloc, list); 23.414 - 23.415 - // bounded list using single-char delimiter 23.416 - n = cx_strsplit_a(&alloc, test, cx_str(","), 3, &list); 23.417 - ASSERT_EQ(n, 3); 23.418 - EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0); 23.419 - EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0); 23.420 - EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0); 23.421 - cxFree(&alloc, list); 23.422 - 23.423 - // bounded list using multi-char delimiter 23.424 - n = cx_strsplit_a(&alloc, test, cx_str("is"), 2, &list); 23.425 - ASSERT_EQ(n, 2); 23.426 - EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 23.427 - EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0); 23.428 - cxFree(&alloc, list); 23.429 - 23.430 - // start with delimiter 23.431 - n = cx_strsplit_a(&alloc, test, cx_str("this"), capa, &list); 23.432 - ASSERT_EQ(n, 2); 23.433 - EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0); 23.434 - EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0); 23.435 - cxFree(&alloc, list); 23.436 - 23.437 - // end with delimiter 23.438 - n = cx_strsplit_a(&alloc, test, cx_str("string"), capa, &list); 23.439 - ASSERT_EQ(n, 2); 23.440 - EXPECT_EQ(cx_strcmp(list[0], cx_str("this,is,a,csv,")), 0); 23.441 - EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 23.442 - cxFree(&alloc, list); 23.443 - 23.444 - // end with delimiter exceed bound 23.445 - n = cx_strsplit_a(&alloc, cx_str("a,b,c,"), cx_str(","), 3, &list); 23.446 - ASSERT_EQ(n, 3); 23.447 - EXPECT_EQ(cx_strcmp(list[0], cx_str("a")), 0); 23.448 - EXPECT_EQ(cx_strcmp(list[1], cx_str("b")), 0); 23.449 - EXPECT_EQ(cx_strcmp(list[2], cx_str("c,")), 0); 23.450 - cxFree(&alloc, list); 23.451 - 23.452 - // exact match 23.453 - n = cx_strsplit_a(&alloc, test, cx_str("this,is,a,csv,string"), capa, &list); 23.454 - ASSERT_EQ(n, 2); 23.455 - EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0); 23.456 - EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 23.457 - cxFree(&alloc, list); 23.458 - 23.459 - // string to be split is only substring 23.460 - n = cx_strsplit_a(&alloc, test, cx_str("this,is,a,csv,string,with,extension"), capa, &list); 23.461 - ASSERT_EQ(n, 1); 23.462 - EXPECT_EQ(cx_strcmp(list[0], test), 0); 23.463 - cxFree(&alloc, list); 23.464 - 23.465 - // subsequent encounter of delimiter (the string between is empty) 23.466 - n = cx_strsplit_a(&alloc, test, cx_str("is,"), capa, &list); 23.467 - ASSERT_EQ(n, 3); 23.468 - EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 23.469 - EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 23.470 - EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0); 23.471 - cxFree(&alloc, list); 23.472 - 23.473 - // call the _m variant just for coverage 23.474 - auto mtest = cx_strdup(test); 23.475 - cxmutstr *mlist; 23.476 - n = cx_strsplit_ma(&alloc, mtest, cx_str("is,"), 4, &mlist); 23.477 - ASSERT_EQ(n, 3); 23.478 - EXPECT_EQ(cx_strcmp(cx_strcast(mlist[0]), cx_str("th")), 0); 23.479 - EXPECT_EQ(cx_strcmp(cx_strcast(mlist[1]), cx_str("")), 0); 23.480 - EXPECT_EQ(cx_strcmp(cx_strcast(mlist[2]), cx_str("a,csv,string")), 0); 23.481 - cxFree(&alloc, mlist); 23.482 - cx_strfree(&mtest); 23.483 - 23.484 - EXPECT_TRUE(alloc.verify()); 23.485 -} 23.486 - 23.487 -TEST(String, strtrim) { 23.488 - cxstring t1 = cx_strtrim(cx_str(" ein test \t ")); 23.489 - cxstring t2 = cx_strtrim(cx_str("abc")); 23.490 - cxstring t3 = cx_strtrim(cx_str(" 123")); 23.491 - cxstring t4 = cx_strtrim(cx_str("xyz ")); 23.492 - cxstring t5 = cx_strtrim(cx_str(" ")); 23.493 - cxstring empty = cx_strtrim(cx_str("")); 23.494 - 23.495 - EXPECT_EQ(cx_strcmp(t1, cx_str("ein test")), 0); 23.496 - EXPECT_EQ(cx_strcmp(t2, cx_str("abc")), 0); 23.497 - EXPECT_EQ(cx_strcmp(t3, cx_str("123")), 0); 23.498 - EXPECT_EQ(cx_strcmp(t4, cx_str("xyz")), 0); 23.499 - EXPECT_EQ(cx_strcmp(t5, cx_str("")), 0); 23.500 - EXPECT_EQ(cx_strcmp(empty, cx_str("")), 0); 23.501 - 23.502 - // call the _m variant just for coverage 23.503 - cxmutstr m1 = cx_strtrim_m(cx_mutstr((char *) " ein test \t ")); 23.504 - EXPECT_EQ(cx_strcmp(cx_strcast(m1), cx_str("ein test")), 0); 23.505 -} 23.506 - 23.507 -TEST(String, strprefix) { 23.508 - cxstring str = CX_STR("test my prefix and my suffix"); 23.509 - cxstring empty = CX_STR(""); 23.510 - EXPECT_FALSE(cx_strprefix(empty, cx_str("pref"))); 23.511 - EXPECT_TRUE(cx_strprefix(str, empty)); 23.512 - EXPECT_TRUE(cx_strprefix(empty, empty)); 23.513 - EXPECT_TRUE(cx_strprefix(str, cx_str("test "))); 23.514 - EXPECT_FALSE(cx_strprefix(str, cx_str("8-) fsck "))); 23.515 -} 23.516 - 23.517 -TEST(String, strsuffix) { 23.518 - cxstring str = CX_STR("test my prefix and my suffix"); 23.519 - cxstring empty = CX_STR(""); 23.520 - EXPECT_FALSE(cx_strsuffix(empty, cx_str("suf"))); 23.521 - EXPECT_TRUE(cx_strsuffix(str, empty)); 23.522 - EXPECT_TRUE(cx_strsuffix(empty, empty)); 23.523 - EXPECT_TRUE(cx_strsuffix(str, cx_str("fix"))); 23.524 - EXPECT_FALSE(cx_strsuffix(str, cx_str("fox"))); 23.525 -} 23.526 - 23.527 -TEST(String, strcaseprefix) { 23.528 - cxstring str = CX_STR("test my prefix and my suffix"); 23.529 - cxstring empty = CX_STR(""); 23.530 - EXPECT_FALSE(cx_strcaseprefix(empty, cx_str("pREf"))); 23.531 - EXPECT_TRUE(cx_strcaseprefix(str, empty)); 23.532 - EXPECT_TRUE(cx_strcaseprefix(empty, empty)); 23.533 - EXPECT_TRUE(cx_strcaseprefix(str, cx_str("TEST "))); 23.534 - EXPECT_FALSE(cx_strcaseprefix(str, cx_str("8-) fsck "))); 23.535 -} 23.536 - 23.537 -TEST(String, strcasesuffix) { 23.538 - cxstring str = CX_STR("test my prefix and my suffix"); 23.539 - cxstring empty = CX_STR(""); 23.540 - EXPECT_FALSE(cx_strcasesuffix(empty, cx_str("sUf"))); 23.541 - EXPECT_TRUE(cx_strcasesuffix(str, empty)); 23.542 - EXPECT_TRUE(cx_strcasesuffix(empty, empty)); 23.543 - EXPECT_TRUE(cx_strcasesuffix(str, cx_str("FIX"))); 23.544 - EXPECT_FALSE(cx_strcasesuffix(str, cx_str("fox"))); 23.545 -} 23.546 - 23.547 -TEST(String, strreplace) { 23.548 - CxTestingAllocator alloc; 23.549 - cxstring str = CX_STR("test ababab string aba"); 23.550 - cxstring longstr = CX_STR( 23.551 - "xyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacd"); 23.552 - cxstring notrail = CX_STR("test abab"); 23.553 - cxstring empty = CX_STR(""); 23.554 - cxstring astr = CX_STR("aaaaaaaaaa"); 23.555 - cxstring csstr = CX_STR("test AB ab TEST xyz"); 23.556 - 23.557 - cxmutstr repl = cx_strreplace(str, cx_str("abab"), cx_str("muchlonger")); 23.558 - auto expected = "test muchlongerab string aba"; 23.559 - 23.560 - cxmutstr repln = cx_strreplacen(str, cx_str("ab"), cx_str("c"), 2); 23.561 - auto expectedn = "test ccab string aba"; 23.562 - 23.563 - cxmutstr longrepl = cx_strreplace(longstr, cx_str("a"), cx_str("z")); 23.564 - auto longexpect = "xyzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzcd"; 23.565 - 23.566 - cxmutstr replnotrail = cx_strreplace(notrail, cx_str("ab"), cx_str("z")); 23.567 - auto notrailexpect = "test zz"; 23.568 - 23.569 - cxmutstr repleq = cx_strreplace(str, str, cx_str("hello")); 23.570 - auto eqexpect = "hello"; 23.571 - 23.572 - cxmutstr replempty1 = cx_strreplace(empty, cx_str("ab"), cx_str("c")); // expect: empty 23.573 - cxmutstr replempty2 = cx_strreplace(str, cx_str("abab"), empty); 23.574 - auto emptyexpect2 = "test ab string aba"; 23.575 - 23.576 - cxmutstr replpre = cx_strreplace(str, cx_str("test "), cx_str("TEST ")); 23.577 - auto preexpected = "TEST ababab string aba"; 23.578 - 23.579 - cxmutstr replan1 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 1); 23.580 - auto an1expected = "xaaaaaaaaa"; 23.581 - 23.582 - cxmutstr replan4 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 4); 23.583 - auto an4expected = "xxxxaaaaaa"; 23.584 - 23.585 - cxmutstr replan9 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 9); 23.586 - auto an9expected = "xxxxxxxxxa"; 23.587 - 23.588 - cxmutstr replan10 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 10); 23.589 - auto an10expected = "xxxxxxxxxx"; 23.590 - 23.591 - cxmutstr repl1_a = cx_strreplace_a(&alloc, csstr, cx_str("AB"), cx_str("*")); 23.592 - auto expeced1_a = "test * ab TEST xyz"; 23.593 - 23.594 - cxmutstr repl2_a = cx_strreplace_a(&alloc, csstr, cx_str("test"), cx_str("TEST")); 23.595 - auto expected2_a = "TEST AB ab TEST xyz"; 23.596 - 23.597 - 23.598 - EXPECT_NE(repl.ptr, str.ptr); 23.599 - EXPECT_ZERO_TERMINATED(repl); 23.600 - EXPECT_STREQ(repl.ptr, expected); 23.601 - EXPECT_ZERO_TERMINATED(repln); 23.602 - EXPECT_STREQ(repln.ptr, expectedn); 23.603 - EXPECT_ZERO_TERMINATED(longrepl); 23.604 - EXPECT_STREQ(longrepl.ptr, longexpect); 23.605 - EXPECT_ZERO_TERMINATED(replnotrail); 23.606 - EXPECT_STREQ(replnotrail.ptr, notrailexpect); 23.607 - EXPECT_ZERO_TERMINATED(repleq); 23.608 - EXPECT_STREQ(repleq.ptr, eqexpect); 23.609 - EXPECT_ZERO_TERMINATED(replempty1); 23.610 - EXPECT_STREQ(replempty1.ptr, ""); 23.611 - EXPECT_ZERO_TERMINATED(replempty2); 23.612 - EXPECT_STREQ(replempty2.ptr, emptyexpect2); 23.613 - EXPECT_ZERO_TERMINATED(replpre); 23.614 - EXPECT_STREQ(replpre.ptr, preexpected); 23.615 - EXPECT_ZERO_TERMINATED(replan1); 23.616 - EXPECT_STREQ(replan1.ptr, an1expected); 23.617 - EXPECT_ZERO_TERMINATED(replan4); 23.618 - EXPECT_STREQ(replan4.ptr, an4expected); 23.619 - EXPECT_ZERO_TERMINATED(replan9); 23.620 - EXPECT_STREQ(replan9.ptr, an9expected); 23.621 - EXPECT_ZERO_TERMINATED(replan10); 23.622 - EXPECT_STREQ(replan10.ptr, an10expected); 23.623 - EXPECT_ZERO_TERMINATED(repl1_a); 23.624 - EXPECT_STREQ(repl1_a.ptr, expeced1_a); 23.625 - EXPECT_ZERO_TERMINATED(repl2_a); 23.626 - EXPECT_STREQ(repl2_a.ptr, expected2_a); 23.627 - 23.628 - cx_strfree(&repl); 23.629 - cx_strfree(&repln); 23.630 - cx_strfree(&longrepl); 23.631 - cx_strfree(&replnotrail); 23.632 - cx_strfree(&repleq); 23.633 - cx_strfree(&replempty1); 23.634 - cx_strfree(&replempty2); 23.635 - cx_strfree(&replpre); 23.636 - cx_strfree(&replan1); 23.637 - cx_strfree(&replan4); 23.638 - cx_strfree(&replan9); 23.639 - cx_strfree(&replan10); 23.640 - 23.641 - cx_strfree_a(&alloc, &repl1_a); 23.642 - cx_strfree_a(&alloc, &repl2_a); 23.643 - EXPECT_TRUE(alloc.verify()); 23.644 -} 23.645 - 23.646 -TEST(String, strupper) { 23.647 - cxmutstr str = cx_strdup(cx_str("thIs 1s @ Te$t")); 23.648 - cx_strupper(str); 23.649 - EXPECT_STREQ(str.ptr, "THIS 1S @ TE$T"); 23.650 - cx_strfree(&str); 23.651 -} 23.652 - 23.653 -TEST(String, strlower) { 23.654 - cxmutstr str = cx_strdup(cx_str("thIs 1s @ Te$t")); 23.655 - cx_strlower(str); 23.656 - EXPECT_STREQ(str.ptr, "this 1s @ te$t"); 23.657 - cx_strfree(&str); 23.658 -} 23.659 - 23.660 -TEST(String, strtok) { 23.661 - cxstring str = cx_str("a,comma,separated,string"); 23.662 - cxstring delim = cx_str(","); 23.663 - CxStrtokCtx ctx = cx_strtok(str, delim, 3); 23.664 - EXPECT_EQ(ctx.str.ptr, str.ptr); 23.665 - EXPECT_EQ(ctx.str.length, str.length); 23.666 - EXPECT_EQ(ctx.delim.ptr, delim.ptr); 23.667 - EXPECT_EQ(ctx.delim.length, delim.length); 23.668 - EXPECT_EQ(ctx.limit, 3); 23.669 - EXPECT_EQ(ctx.found, 0); 23.670 - EXPECT_EQ(ctx.pos, 0); 23.671 - EXPECT_EQ(ctx.next_pos, 0); 23.672 - EXPECT_EQ(ctx.delim_more, nullptr); 23.673 - EXPECT_EQ(ctx.delim_more_count, 0); 23.674 -} 23.675 - 23.676 -TEST(String, strtok_m) { 23.677 - cxmutstr str = cx_strdup(cx_str("a,comma,separated,string")); 23.678 - cxstring delim = cx_str(","); 23.679 - CxStrtokCtx ctx = cx_strtok_m(str, delim, 3); 23.680 - EXPECT_EQ(ctx.str.ptr, str.ptr); 23.681 - EXPECT_EQ(ctx.str.length, str.length); 23.682 - EXPECT_EQ(ctx.delim.ptr, delim.ptr); 23.683 - EXPECT_EQ(ctx.delim.length, delim.length); 23.684 - EXPECT_EQ(ctx.limit, 3); 23.685 - EXPECT_EQ(ctx.found, 0); 23.686 - EXPECT_EQ(ctx.pos, 0); 23.687 - EXPECT_EQ(ctx.next_pos, 0); 23.688 - EXPECT_EQ(ctx.delim_more, nullptr); 23.689 - EXPECT_EQ(ctx.delim_more_count, 0); 23.690 - cx_strfree(&str); 23.691 -} 23.692 - 23.693 -TEST(String, strtok_delim) { 23.694 - cxstring str = cx_str("an,arbitrarily|separated;string"); 23.695 - cxstring delim = cx_str(","); 23.696 - cxstring delim_more[2] = {CX_STR("|"), CX_STR(";")}; 23.697 - CxStrtokCtx ctx = cx_strtok(str, delim, 3); 23.698 - cx_strtok_delim(&ctx, delim_more, 2); 23.699 - EXPECT_EQ(ctx.str.ptr, str.ptr); 23.700 - EXPECT_EQ(ctx.str.length, str.length); 23.701 - EXPECT_EQ(ctx.delim.ptr, delim.ptr); 23.702 - EXPECT_EQ(ctx.delim.length, delim.length); 23.703 - EXPECT_EQ(ctx.limit, 3); 23.704 - EXPECT_EQ(ctx.found, 0); 23.705 - EXPECT_EQ(ctx.pos, 0); 23.706 - EXPECT_EQ(ctx.next_pos, 0); 23.707 - EXPECT_EQ(ctx.delim_more, delim_more); 23.708 - EXPECT_EQ(ctx.delim_more_count, 2); 23.709 -} 23.710 - 23.711 -TEST(String, strtok_next_easy) { 23.712 - cxstring str = cx_str("a,comma,separated,string"); 23.713 - cxstring delim = cx_str(","); 23.714 - CxStrtokCtx ctx = cx_strtok(str, delim, 3); 23.715 - bool ret; 23.716 - cxstring tok; 23.717 - 23.718 - ret = cx_strtok_next(&ctx, &tok); 23.719 - ASSERT_TRUE(ret); 23.720 - EXPECT_EQ(cx_strcmp(tok, cx_str("a")), 0); 23.721 - EXPECT_EQ(ctx.pos, 0); 23.722 - EXPECT_EQ(ctx.next_pos, 2); 23.723 - EXPECT_EQ(ctx.delim_pos, 1); 23.724 - EXPECT_EQ(ctx.found, 1); 23.725 - 23.726 - ret = cx_strtok_next(&ctx, &tok); 23.727 - ASSERT_TRUE(ret); 23.728 - EXPECT_EQ(cx_strcmp(tok, cx_str("comma")), 0); 23.729 - EXPECT_EQ(ctx.pos, 2); 23.730 - EXPECT_EQ(ctx.next_pos, 8); 23.731 - EXPECT_EQ(ctx.delim_pos, 7); 23.732 - EXPECT_EQ(ctx.found, 2); 23.733 - 23.734 - ret = cx_strtok_next(&ctx, &tok); 23.735 - ASSERT_TRUE(ret); 23.736 - EXPECT_EQ(cx_strcmp(tok, cx_str("separated")), 0); 23.737 - EXPECT_EQ(ctx.pos, 8); 23.738 - EXPECT_EQ(ctx.next_pos, 18); 23.739 - EXPECT_EQ(ctx.delim_pos, 17); 23.740 - EXPECT_EQ(ctx.found, 3); 23.741 - 23.742 - ret = cx_strtok_next(&ctx, &tok); 23.743 - ASSERT_FALSE(ret); 23.744 - EXPECT_EQ(ctx.pos, 8); 23.745 - EXPECT_EQ(ctx.next_pos, 18); 23.746 - EXPECT_EQ(ctx.delim_pos, 17); 23.747 - EXPECT_EQ(ctx.found, 3); 23.748 -} 23.749 - 23.750 -TEST(String, strtok_next_unlimited) { 23.751 - cxstring str = cx_str("some;-;otherwise;-;separated;-;string;-;"); 23.752 - cxstring delim = cx_str(";-;"); 23.753 - CxStrtokCtx ctx = cx_strtok(str, delim, SIZE_MAX); 23.754 - bool ret; 23.755 - cxstring tok; 23.756 - 23.757 - ret = cx_strtok_next(&ctx, &tok); 23.758 - ASSERT_TRUE(ret); 23.759 - EXPECT_EQ(cx_strcmp(tok, cx_str("some")), 0); 23.760 - EXPECT_EQ(ctx.pos, 0); 23.761 - EXPECT_EQ(ctx.next_pos, 7); 23.762 - EXPECT_EQ(ctx.delim_pos, 4); 23.763 - EXPECT_EQ(ctx.found, 1); 23.764 - 23.765 - ret = cx_strtok_next(&ctx, &tok); 23.766 - ASSERT_TRUE(ret); 23.767 - EXPECT_EQ(cx_strcmp(tok, cx_str("otherwise")), 0); 23.768 - EXPECT_EQ(ctx.pos, 7); 23.769 - EXPECT_EQ(ctx.next_pos, 19); 23.770 - EXPECT_EQ(ctx.delim_pos, 16); 23.771 - EXPECT_EQ(ctx.found, 2); 23.772 - 23.773 - ret = cx_strtok_next(&ctx, &tok); 23.774 - ASSERT_TRUE(ret); 23.775 - EXPECT_EQ(cx_strcmp(tok, cx_str("separated")), 0); 23.776 - EXPECT_EQ(ctx.pos, 19); 23.777 - EXPECT_EQ(ctx.next_pos, 31); 23.778 - EXPECT_EQ(ctx.delim_pos, 28); 23.779 - EXPECT_EQ(ctx.found, 3); 23.780 - 23.781 - ret = cx_strtok_next(&ctx, &tok); 23.782 - ASSERT_TRUE(ret); 23.783 - EXPECT_EQ(cx_strcmp(tok, cx_str("string")), 0); 23.784 - EXPECT_EQ(ctx.pos, 31); 23.785 - EXPECT_EQ(ctx.next_pos, 40); 23.786 - EXPECT_EQ(ctx.delim_pos, 37); 23.787 - EXPECT_EQ(ctx.found, 4); 23.788 - 23.789 - ret = cx_strtok_next(&ctx, &tok); 23.790 - ASSERT_TRUE(ret); 23.791 - EXPECT_EQ(cx_strcmp(tok, cx_str("")), 0); 23.792 - EXPECT_EQ(ctx.pos, 40); 23.793 - EXPECT_EQ(ctx.next_pos, 40); 23.794 - EXPECT_EQ(ctx.delim_pos, 40); 23.795 - EXPECT_EQ(ctx.found, 5); 23.796 - 23.797 - ret = cx_strtok_next(&ctx, &tok); 23.798 - ASSERT_FALSE(ret); 23.799 - EXPECT_EQ(ctx.pos, 40); 23.800 - EXPECT_EQ(ctx.delim_pos, 40); 23.801 - EXPECT_EQ(ctx.found, 5); 23.802 -} 23.803 - 23.804 -TEST(String, strtok_next_advanced) { 23.805 - cxmutstr str = cx_strdup(cx_str("an,arbitrarily;||separated;string")); 23.806 - cxstring delim = cx_str(","); 23.807 - cxstring delim_more[2] = {CX_STR("||"), CX_STR(";")}; 23.808 - CxStrtokCtx ctx = cx_strtok_m(str, delim, 10); 23.809 - cx_strtok_delim(&ctx, delim_more, 2); 23.810 - bool ret; 23.811 - cxmutstr tok; 23.812 - 23.813 - ret = cx_strtok_next_m(&ctx, &tok); 23.814 - ASSERT_TRUE(ret); 23.815 - EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("an")), 0); 23.816 - EXPECT_EQ(ctx.pos, 0); 23.817 - EXPECT_EQ(ctx.next_pos, 3); 23.818 - EXPECT_EQ(ctx.delim_pos, 2); 23.819 - EXPECT_EQ(ctx.found, 1); 23.820 - cx_strupper(tok); 23.821 - 23.822 - ret = cx_strtok_next_m(&ctx, &tok); 23.823 - ASSERT_TRUE(ret); 23.824 - EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("arbitrarily")), 0); 23.825 - EXPECT_EQ(ctx.pos, 3); 23.826 - EXPECT_EQ(ctx.next_pos, 15); 23.827 - EXPECT_EQ(ctx.delim_pos, 14); 23.828 - EXPECT_EQ(ctx.found, 2); 23.829 - cx_strupper(tok); 23.830 - 23.831 - ret = cx_strtok_next_m(&ctx, &tok); 23.832 - ASSERT_TRUE(ret); 23.833 - EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("")), 0); 23.834 - EXPECT_EQ(ctx.pos, 15); 23.835 - EXPECT_EQ(ctx.next_pos, 17); 23.836 - EXPECT_EQ(ctx.delim_pos, 15); 23.837 - EXPECT_EQ(ctx.found, 3); 23.838 - cx_strupper(tok); 23.839 - 23.840 - ret = cx_strtok_next_m(&ctx, &tok); 23.841 - ASSERT_TRUE(ret); 23.842 - EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("separated")), 0); 23.843 - EXPECT_EQ(ctx.pos, 17); 23.844 - EXPECT_EQ(ctx.next_pos, 27); 23.845 - EXPECT_EQ(ctx.delim_pos, 26); 23.846 - EXPECT_EQ(ctx.found, 4); 23.847 - cx_strupper(tok); 23.848 - 23.849 - ret = cx_strtok_next_m(&ctx, &tok); 23.850 - ASSERT_TRUE(ret); 23.851 - EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("string")), 0); 23.852 - EXPECT_EQ(ctx.pos, 27); 23.853 - EXPECT_EQ(ctx.next_pos, 33); 23.854 - EXPECT_EQ(ctx.delim_pos, 33); 23.855 - EXPECT_EQ(ctx.found, 5); 23.856 - cx_strupper(tok); 23.857 - 23.858 - ret = cx_strtok_next_m(&ctx, &tok); 23.859 - ASSERT_FALSE(ret); 23.860 - EXPECT_EQ(ctx.pos, 27); 23.861 - EXPECT_EQ(ctx.next_pos, 33); 23.862 - EXPECT_EQ(ctx.delim_pos, 33); 23.863 - EXPECT_EQ(ctx.found, 5); 23.864 - 23.865 - EXPECT_EQ(cx_strcmp(cx_strcast(str), cx_str("AN,ARBITRARILY;||SEPARATED;STRING")), 0); 23.866 - 23.867 - cx_strfree(&str); 23.868 -}
24.1 --- a/test/test_tree.cpp Wed Feb 08 20:26:09 2023 +0100 24.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 24.3 @@ -1,122 +0,0 @@ 24.4 -/* 24.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 24.6 - * 24.7 - * Copyright 2021 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/tree.h" 24.33 -#include <gtest/gtest.h> 24.34 - 24.35 -struct TestNode { 24.36 - TestNode *parent = nullptr; 24.37 - TestNode *prev = nullptr; 24.38 - TestNode *next = nullptr; 24.39 - 24.40 - TestNode *children_begin = nullptr; 24.41 - TestNode *children_end = nullptr; 24.42 -}; 24.43 - 24.44 -TEST(Tree, cx_tree_add_sibling) { 24.45 - // prepare test tree 24.46 - TestNode root, a; 24.47 - root.children_begin = &a; 24.48 - root.children_end = &a; 24.49 - a.parent = &root; 24.50 - 24.51 - // new test nodes 24.52 - TestNode b, c; 24.53 - 24.54 - // test 24.55 - cx_tree_add_sibling(&a, offsetof(TestNode, prev), offsetof(TestNode, next), offsetof(TestNode, parent), &b); 24.56 - EXPECT_EQ(b.parent, &root); 24.57 - EXPECT_EQ(b.prev, &a); 24.58 - EXPECT_EQ(b.next, nullptr); 24.59 - EXPECT_EQ(a.next, &b); 24.60 - 24.61 - cx_tree_add_sibling(&a, -1, offsetof(TestNode, next), -1, &c); 24.62 - EXPECT_EQ(c.parent, nullptr); 24.63 - EXPECT_EQ(c.prev, nullptr); 24.64 - EXPECT_EQ(c.next, nullptr); 24.65 - EXPECT_EQ(b.next, &c); 24.66 -} 24.67 - 24.68 -TEST(Tree, cx_tree_add_child) { 24.69 - TestNode root, a, b, c, a1; 24.70 - 24.71 - cx_tree_add_child( 24.72 - (void **) &root.children_begin, 24.73 - (void **) &root.children_end, 24.74 - offsetof(TestNode, prev), 24.75 - offsetof(TestNode, next), 24.76 - &a, 24.77 - offsetof(TestNode, parent), 24.78 - &root); 24.79 - EXPECT_EQ(root.children_begin, &a); 24.80 - EXPECT_EQ(root.children_end, &a); 24.81 - EXPECT_EQ(a.parent, &root); 24.82 - EXPECT_EQ(a.prev, nullptr); 24.83 - EXPECT_EQ(a.next, nullptr); 24.84 - 24.85 - cx_tree_add_child( 24.86 - (void **) &root.children_begin, 24.87 - (void **) &root.children_end, 24.88 - offsetof(TestNode, prev), 24.89 - offsetof(TestNode, next), 24.90 - &b, 24.91 - offsetof(TestNode, parent), 24.92 - &root); 24.93 - EXPECT_EQ(root.children_begin, &a); 24.94 - EXPECT_EQ(root.children_begin->next, &b); 24.95 - EXPECT_EQ(root.children_end, &b); 24.96 - EXPECT_EQ(b.parent, &root); 24.97 - EXPECT_EQ(b.prev, &a); 24.98 - 24.99 - cx_tree_add_child( 24.100 - (void **) &root.children_begin, 24.101 - nullptr, 24.102 - -1, 24.103 - offsetof(TestNode, next), 24.104 - &c, 24.105 - -1, 24.106 - &root); 24.107 - EXPECT_EQ(root.children_end, &b); // children_end unchanged 24.108 - EXPECT_EQ(b.next, &c); 24.109 - EXPECT_EQ(c.prev, nullptr); 24.110 - EXPECT_EQ(c.next, nullptr); 24.111 - EXPECT_EQ(c.parent, nullptr); 24.112 - 24.113 - cx_tree_add_child( 24.114 - (void **) &a.children_begin, 24.115 - (void **) &a.children_end, 24.116 - offsetof(TestNode, prev), 24.117 - offsetof(TestNode, next), 24.118 - &a1, 24.119 - offsetof(TestNode, parent), 24.120 - &a); 24.121 - EXPECT_EQ(a.children_begin, &a1); 24.122 - EXPECT_EQ(a1.parent, &a); 24.123 - EXPECT_EQ(root.children_begin, &a); 24.124 - EXPECT_EQ(root.children_begin->children_begin, &a1); 24.125 -}
25.1 --- a/test/test_utils.cpp Wed Feb 08 20:26:09 2023 +0100 25.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 25.3 @@ -1,165 +0,0 @@ 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/utils.h" 25.33 - 25.34 -#include <gtest/gtest.h> 25.35 - 25.36 -TEST(Utils, ForN) { 25.37 - unsigned j; 25.38 - j = 0; 25.39 - cx_for_n(i, 50) { 25.40 - EXPECT_EQ(i, j); 25.41 - j++; 25.42 - } 25.43 -} 25.44 - 25.45 -TEST(Utils, swap_ptr) { 25.46 - int i = 5; 25.47 - int j = 8; 25.48 - int *ip = &i; 25.49 - int *jp = &j; 25.50 - cx_swap_ptr(ip, jp); 25.51 - EXPECT_EQ(ip, &j); 25.52 - EXPECT_EQ(jp, &i); 25.53 -} 25.54 - 25.55 -TEST(Utils, szmul) { 25.56 - size_t r; 25.57 - int e; 25.58 - e = cx_szmul(5, 7, &r); 25.59 - EXPECT_EQ(0, e); 25.60 - EXPECT_EQ(35, r); 25.61 - 25.62 - size_t s = SIZE_MAX & ~3; 25.63 - 25.64 - e = cx_szmul(s / 4, 2, &r); 25.65 - EXPECT_EQ(0, e); 25.66 - EXPECT_EQ(s / 2, r); 25.67 - e = cx_szmul(2, s / 4, &r); 25.68 - EXPECT_EQ(0, e); 25.69 - EXPECT_EQ(s / 2, r); 25.70 - 25.71 - e = cx_szmul(s / 4, 4, &r); 25.72 - EXPECT_EQ(0, e); 25.73 - EXPECT_EQ(s, r); 25.74 - 25.75 - e = cx_szmul(4, s / 4, &r); 25.76 - EXPECT_EQ(0, e); 25.77 - EXPECT_EQ(s, r); 25.78 - 25.79 - e = cx_szmul(s / 4, 5, &r); 25.80 - EXPECT_NE(0, e); 25.81 - 25.82 - e = cx_szmul(5, s / 4, &r); 25.83 - EXPECT_NE(0, e); 25.84 - 25.85 - e = cx_szmul(SIZE_MAX - 4, 0, &r); 25.86 - EXPECT_EQ(0, e); 25.87 - EXPECT_EQ(0, r); 25.88 - 25.89 - e = cx_szmul(0, SIZE_MAX - 1, &r); 25.90 - EXPECT_EQ(0, e); 25.91 - EXPECT_EQ(0, r); 25.92 - 25.93 - e = cx_szmul(SIZE_MAX, 0, &r); 25.94 - EXPECT_EQ(0, e); 25.95 - EXPECT_EQ(0, r); 25.96 - 25.97 - e = cx_szmul(0, SIZE_MAX, &r); 25.98 - EXPECT_EQ(0, e); 25.99 - EXPECT_EQ(0, r); 25.100 - 25.101 - e = cx_szmul(0, 0, &r); 25.102 - EXPECT_EQ(0, e); 25.103 - EXPECT_EQ(0, r); 25.104 -} 25.105 - 25.106 -#ifdef CX_SZMUL_BUILTIN 25.107 - 25.108 -// also test the custom implementation 25.109 -struct Utils_szmul_impl : ::testing::Test { 25.110 -#undef CX_SZMUL_BUILTIN 25.111 - 25.112 -#include "../src/utils.c" 25.113 - 25.114 -#define CX_SZMUL_BUILTIN 25.115 -}; 25.116 - 25.117 -TEST_F(Utils_szmul_impl, Test) { 25.118 - size_t r; 25.119 - int e; 25.120 - e = cx_szmul_impl(5, 7, &r); 25.121 - EXPECT_EQ(0, e); 25.122 - EXPECT_EQ(35, r); 25.123 - 25.124 - size_t s = SIZE_MAX & ~3; 25.125 - 25.126 - e = cx_szmul_impl(s / 4, 2, &r); 25.127 - EXPECT_EQ(0, e); 25.128 - EXPECT_EQ(s / 2, r); 25.129 - e = cx_szmul_impl(2, s / 4, &r); 25.130 - EXPECT_EQ(0, e); 25.131 - EXPECT_EQ(s / 2, r); 25.132 - 25.133 - e = cx_szmul_impl(s / 4, 4, &r); 25.134 - EXPECT_EQ(0, e); 25.135 - EXPECT_EQ(s, r); 25.136 - 25.137 - e = cx_szmul_impl(4, s / 4, &r); 25.138 - EXPECT_EQ(0, e); 25.139 - EXPECT_EQ(s, r); 25.140 - 25.141 - e = cx_szmul_impl(s / 4, 5, &r); 25.142 - EXPECT_NE(0, e); 25.143 - 25.144 - e = cx_szmul_impl(5, s / 4, &r); 25.145 - EXPECT_NE(0, e); 25.146 - 25.147 - e = cx_szmul_impl(SIZE_MAX - 4, 0, &r); 25.148 - EXPECT_EQ(0, e); 25.149 - EXPECT_EQ(0, r); 25.150 - 25.151 - e = cx_szmul_impl(0, SIZE_MAX - 1, &r); 25.152 - EXPECT_EQ(0, e); 25.153 - EXPECT_EQ(0, r); 25.154 - 25.155 - e = cx_szmul_impl(SIZE_MAX, 0, &r); 25.156 - EXPECT_EQ(0, e); 25.157 - EXPECT_EQ(0, r); 25.158 - 25.159 - e = cx_szmul_impl(0, SIZE_MAX, &r); 25.160 - EXPECT_EQ(0, e); 25.161 - EXPECT_EQ(0, r); 25.162 - 25.163 - e = cx_szmul_impl(0, 0, &r); 25.164 - EXPECT_EQ(0, e); 25.165 - EXPECT_EQ(0, r); 25.166 -} 25.167 - 25.168 -#endif // CX_SZMUL_BUILTIN
26.1 --- a/test/util_allocator.cpp Wed Feb 08 20:26:09 2023 +0100 26.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 26.3 @@ -1,167 +0,0 @@ 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 "util_allocator.h" 26.33 - 26.34 -void *cx_malloc_testing(void *d, size_t n) { 26.35 - auto data = reinterpret_cast<CxTestingAllocator *>(d); 26.36 - void *ptr = malloc(n); 26.37 - data->alloc_total++; 26.38 - if (ptr == nullptr) { 26.39 - data->alloc_failed++; 26.40 - } else { 26.41 - data->tracked.insert(ptr); 26.42 - } 26.43 - return ptr; 26.44 -} 26.45 - 26.46 -void *cx_realloc_testing(void *d, void *mem, size_t n) { 26.47 - auto data = reinterpret_cast<CxTestingAllocator *>(d); 26.48 - void *ptr = realloc(mem, n); 26.49 - if (ptr == mem) { 26.50 - return ptr; 26.51 - } else { 26.52 - data->alloc_total++; 26.53 - if (ptr == nullptr) { 26.54 - data->alloc_failed++; 26.55 - } else { 26.56 - data->free_total++; 26.57 - if (data->tracked.erase(mem) == 0) { 26.58 - data->free_failed++; 26.59 - } 26.60 - data->tracked.insert(ptr); 26.61 - } 26.62 - return ptr; 26.63 - } 26.64 -} 26.65 - 26.66 -void *cx_calloc_testing(void *d, size_t nelem, size_t n) { 26.67 - auto data = reinterpret_cast<CxTestingAllocator *>(d); 26.68 - void *ptr = calloc(nelem, n); 26.69 - data->alloc_total++; 26.70 - if (ptr == nullptr) { 26.71 - data->alloc_failed++; 26.72 - } else { 26.73 - data->tracked.insert(ptr); 26.74 - } 26.75 - return ptr; 26.76 -} 26.77 - 26.78 -void cx_free_testing(void *d, void *mem) { 26.79 - auto data = reinterpret_cast<CxTestingAllocator *>(d); 26.80 - data->free_total++; 26.81 - if (data->tracked.erase(mem) == 0) { 26.82 - data->free_failed++; 26.83 - // do not even attempt to free mem, because it is likely to segfault 26.84 - } else { 26.85 - free(mem); 26.86 - } 26.87 -} 26.88 - 26.89 -cx_allocator_class cx_testing_allocator_class = { 26.90 - cx_malloc_testing, 26.91 - cx_realloc_testing, 26.92 - cx_calloc_testing, 26.93 - cx_free_testing 26.94 -}; 26.95 - 26.96 -CxTestingAllocator::CxTestingAllocator() : CxAllocator() { 26.97 - cl = &cx_testing_allocator_class; 26.98 - data = this; 26.99 -} 26.100 - 26.101 -bool CxTestingAllocator::used() const { 26.102 - return alloc_total > 0; 26.103 -} 26.104 - 26.105 -bool CxTestingAllocator::verify() const { 26.106 - return tracked.empty() && alloc_failed == 0 && free_failed == 0 && alloc_total == free_total; 26.107 -} 26.108 - 26.109 -// SELF-TEST 26.110 - 26.111 -#include <gtest/gtest.h> 26.112 - 26.113 -TEST(TestingAllocator, ExpectFree) { 26.114 - CxTestingAllocator allocator; 26.115 - 26.116 - ASSERT_TRUE(allocator.verify()); 26.117 - EXPECT_FALSE(allocator.used()); 26.118 - auto ptr = cxMalloc(&allocator, 16); 26.119 - EXPECT_TRUE(allocator.used()); 26.120 - ASSERT_NE(ptr, nullptr); 26.121 - EXPECT_FALSE(allocator.verify()); 26.122 - 26.123 - cxFree(&allocator, ptr); 26.124 - EXPECT_TRUE(allocator.verify()); 26.125 -} 26.126 - 26.127 -TEST(TestingAllocator, DetectDoubleFree) { 26.128 - CxTestingAllocator allocator; 26.129 - 26.130 - ASSERT_TRUE(allocator.verify()); 26.131 - auto ptr = cxMalloc(&allocator, 16); 26.132 - ASSERT_NE(ptr, nullptr); 26.133 - 26.134 - cxFree(&allocator, ptr); 26.135 - EXPECT_TRUE(allocator.verify()); 26.136 - ASSERT_NO_FATAL_FAILURE(cxFree(&allocator, ptr)); 26.137 - EXPECT_FALSE(allocator.verify()); 26.138 -} 26.139 - 26.140 -TEST(TestingAllocator, FreeUntracked) { 26.141 - CxTestingAllocator allocator; 26.142 - 26.143 - auto ptr = malloc(16); 26.144 - ASSERT_TRUE(allocator.verify()); 26.145 - ASSERT_NO_FATAL_FAILURE(cxFree(&allocator, ptr)); 26.146 - EXPECT_FALSE(allocator.verify()); 26.147 - ASSERT_NO_FATAL_FAILURE(free(ptr)); 26.148 -} 26.149 - 26.150 -TEST(TestingAllocator, FullLifecycleWithRealloc) { 26.151 - CxTestingAllocator allocator; 26.152 - ASSERT_TRUE(allocator.verify()); 26.153 - auto ptr = cxMalloc(&allocator, 16); 26.154 - ASSERT_NE(ptr, nullptr); 26.155 - EXPECT_EQ(allocator.tracked.size(), 1); 26.156 - ptr = cxRealloc(&allocator, ptr, 256); 26.157 - ASSERT_NE(ptr, nullptr); 26.158 - EXPECT_EQ(allocator.tracked.size(), 1); 26.159 - cxFree(&allocator, ptr); 26.160 - EXPECT_TRUE(allocator.verify()); 26.161 -} 26.162 - 26.163 -TEST(TestingAllocator, CallocInitializes) { 26.164 - CxTestingAllocator allocator; 26.165 - const char zeros[16] = {0}; 26.166 - auto ptr = cxCalloc(&allocator, 16, 1); 26.167 - EXPECT_EQ(memcmp(ptr, zeros, 16), 0); 26.168 - cxFree(&allocator, ptr); 26.169 - EXPECT_TRUE(allocator.verify()); 26.170 -}
27.1 --- a/test/util_allocator.h Wed Feb 08 20:26:09 2023 +0100 27.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 27.3 @@ -1,81 +0,0 @@ 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 -#ifndef UCX_UTIL_ALLOCATOR_H 27.33 -#define UCX_UTIL_ALLOCATOR_H 27.34 - 27.35 -#include "cx/allocator.h" 27.36 - 27.37 -#include <set> 27.38 - 27.39 -struct CxTestingAllocator : public CxAllocator { 27.40 - /** 27.41 - * Total number of all allocations (malloc, calloc, realloc). 27.42 - * A realloc() does only count when the memory has to be moved. 27.43 - */ 27.44 - unsigned alloc_total = 0; 27.45 - /** 27.46 - * Number of failed allocations (malloc, calloc, realloc). 27.47 - */ 27.48 - unsigned alloc_failed = 0; 27.49 - /** 27.50 - * Total number of freed pointers. 27.51 - * A reallocation also counts as a free when the memory has to be moved. 27.52 - */ 27.53 - unsigned free_total = 0; 27.54 - /** 27.55 - * Number of failed free invocations. 27.56 - * A free() is considered failed, if it has not been performed on tracked memory. 27.57 - */ 27.58 - unsigned free_failed = 0; 27.59 - /** 27.60 - * The set of tracked memory blocks. 27.61 - */ 27.62 - std::set<void *> tracked; 27.63 - 27.64 - /** 27.65 - * Constructs a new testing allocator. 27.66 - */ 27.67 - CxTestingAllocator(); 27.68 - 27.69 - /** 27.70 - * Verifies that this allocator has been used. 27.71 - * 27.72 - * @return true if any allocation was attempted using this allocator 27.73 - */ 27.74 - [[nodiscard]] bool used() const; 27.75 - 27.76 - /** 27.77 - * Verifies that all allocated memory blocks are freed and no free occurred twice. 27.78 - * 27.79 - * @return true iff all tracked allocations / deallocations were valid 27.80 - */ 27.81 - [[nodiscard]] bool verify() const; 27.82 -}; 27.83 - 27.84 -#endif // UCX_UTIL_ALLOCATOR_H
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/tests/.clang-tidy Wed Feb 08 20:26:26 2023 +0100 28.3 @@ -0,0 +1,2 @@ 28.4 +# Disable static initialization warning for test code 28.5 +Checks: '-cert-err58-cpp'
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 29.2 +++ b/tests/CMakeLists.txt Wed Feb 08 20:26:26 2023 +0100 29.3 @@ -0,0 +1,32 @@ 29.4 +# Load Google Test Framework 29.5 +set(CMAKE_CXX_STANDARD 17) 29.6 + 29.7 +include(FetchContent) 29.8 +FetchContent_Declare( 29.9 + googletest 29.10 + GIT_REPOSITORY https://github.com/google/googletest.git 29.11 + GIT_TAG e2239ee6043f73722e7aa812a459f54a28552929 # release 1.11.0 29.12 +) 29.13 +# For Windows: Prevent overriding the parent project's compiler/linker settings 29.14 +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 29.15 +FetchContent_MakeAvailable(googletest) 29.16 +include(GoogleTest) 29.17 +message(STATUS "Google Test made available") 29.18 + 29.19 +add_executable(ucxtest 29.20 + test_utils.cpp 29.21 + test_allocator.cpp 29.22 + test_compare.cpp 29.23 + test_string.cpp 29.24 + test_buffer.cpp 29.25 + test_list.cpp 29.26 + test_tree.cpp 29.27 + test_hash_key.cpp 29.28 + test_map.cpp 29.29 + test_basic_mempool.cpp 29.30 + test_printf.cpp 29.31 + selftest.cpp 29.32 + util_allocator.cpp 29.33 + ) 29.34 +target_link_libraries(ucxtest PRIVATE ucx_static gtest_main) 29.35 +gtest_discover_tests(ucxtest)
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/tests/selftest.cpp Wed Feb 08 20:26:26 2023 +0100 30.3 @@ -0,0 +1,39 @@ 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 <gtest/gtest.h> 30.33 +#include <cx/common.h> 30.34 + 30.35 +TEST(SelfTest, BasicAssertion) { 30.36 + EXPECT_EQ(7 * 6, 42); 30.37 +} 30.38 + 30.39 +TEST(SelfTest, UcxVersion) { 30.40 + EXPECT_GE(UCX_VERSION_MAJOR, 3); 30.41 + EXPECT_GE(UCX_VERSION, 3 << 16); 30.42 +}
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 31.2 +++ b/tests/test_allocator.cpp Wed Feb 08 20:26:26 2023 +0100 31.3 @@ -0,0 +1,96 @@ 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/allocator.h" 31.33 +#include <gtest/gtest.h> 31.34 + 31.35 +TEST(Allocator, DefaultAllocator) { 31.36 + cx_allocator_class *clazz = cxDefaultAllocator->cl; 31.37 + ASSERT_NE(clazz, nullptr); 31.38 +} 31.39 + 31.40 +TEST(Allocator, DefaultMalloc) { 31.41 + void *test = cxMalloc(cxDefaultAllocator, 16); 31.42 + ASSERT_NE(test, nullptr); 31.43 + free(test); 31.44 +} 31.45 + 31.46 +TEST(Allocator, DefaultRealloc) { 31.47 + void *test = calloc(8, 1); 31.48 + memcpy(test, "Test", 5); 31.49 + test = cxRealloc(cxDefaultAllocator, test, 16); 31.50 + ASSERT_NE(test, nullptr); 31.51 + EXPECT_STREQ(reinterpret_cast<char *>(test), "Test"); 31.52 + free(test); 31.53 +} 31.54 + 31.55 +TEST(Allocator, Reallocate) { 31.56 + void *test = calloc(8, 1); 31.57 + memcpy(test, "Test", 5); 31.58 + int ret = cxReallocate(cxDefaultAllocator, &test, 16); 31.59 + EXPECT_EQ(ret, 0); 31.60 + ASSERT_NE(test, nullptr); 31.61 + EXPECT_STREQ(reinterpret_cast<char *>(test), "Test"); 31.62 + free(test); 31.63 +} 31.64 + 31.65 +TEST(Allocator, DefaultCalloc) { 31.66 + char *test = reinterpret_cast<char *>(cxCalloc(cxDefaultAllocator, 8, 2)); 31.67 + ASSERT_NE(test, nullptr); 31.68 + for (int i = 0; i < 16; i++) ASSERT_EQ(test[i], 0); 31.69 + free(test); 31.70 +} 31.71 + 31.72 +TEST(Allocator, DefaultFree) { 31.73 + void *test = malloc(16); 31.74 + EXPECT_NO_FATAL_FAILURE( 31.75 + cxFree(cxDefaultAllocator, test); 31.76 + ); 31.77 +} 31.78 + 31.79 +TEST(Allocator, FailingReallocate) { 31.80 + // Mock an allocator that always returns nullptr on realloc 31.81 + cx_allocator_class mock_cl; 31.82 + mock_cl.realloc = []( 31.83 + [[maybe_unused]]void *p, 31.84 + [[maybe_unused]]void *d, 31.85 + [[maybe_unused]]size_t n 31.86 + ) -> void * { return nullptr; }; 31.87 + cx_allocator_s mock{&mock_cl, nullptr}; 31.88 + 31.89 + void *test = calloc(8, 1); 31.90 + memcpy(test, "Test", 5); 31.91 + void *original = test; 31.92 + int ret = cxReallocate(&mock, &test, 16); 31.93 + // non-zero return code because of the failure 31.94 + EXPECT_NE(ret, 0); 31.95 + // the test pointer was not changed and still points to the same memory 31.96 + EXPECT_EQ(test, original); 31.97 + EXPECT_STREQ(reinterpret_cast<char *>(test), "Test"); 31.98 + free(test); 31.99 +}
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/tests/test_basic_mempool.cpp Wed Feb 08 20:26:26 2023 +0100 32.3 @@ -0,0 +1,154 @@ 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 "cx/basic_mempool.h" 32.33 +#include "util_allocator.h" 32.34 +#include <gtest/gtest.h> 32.35 + 32.36 +class CxBasicMempool : public ::testing::Test { 32.37 +protected: 32.38 + CxMempool *pool = nullptr; 32.39 + 32.40 + void TearDown() override { 32.41 + if (pool != nullptr) { 32.42 + cxMempoolDestroy(pool); 32.43 + } 32.44 + } 32.45 +}; 32.46 + 32.47 +TEST_F(CxBasicMempool, Create) { 32.48 + pool = cxBasicMempoolCreate(16); 32.49 + ASSERT_NE(pool->allocator, nullptr); 32.50 + ASSERT_NE(pool->cl, nullptr); 32.51 + EXPECT_NE(pool->cl->destroy, nullptr); 32.52 + ASSERT_NE(pool->allocator->cl, nullptr); 32.53 + EXPECT_EQ(pool->allocator->data, pool); 32.54 + EXPECT_NE(pool->allocator->cl->malloc, nullptr); 32.55 + EXPECT_NE(pool->allocator->cl->calloc, nullptr); 32.56 + EXPECT_NE(pool->allocator->cl->realloc, nullptr); 32.57 + EXPECT_NE(pool->allocator->cl->free, nullptr); 32.58 + 32.59 + auto basic_pool = reinterpret_cast<cx_basic_mempool_s *>(pool); 32.60 + EXPECT_EQ(basic_pool->size, 16); 32.61 + EXPECT_EQ(basic_pool->ndata, 0); 32.62 + EXPECT_NE(basic_pool->data, nullptr); 32.63 +} 32.64 + 32.65 +TEST_F(CxBasicMempool, malloc) { 32.66 + pool = cxBasicMempoolCreate(4); 32.67 + auto basic_pool = reinterpret_cast<cx_basic_mempool_s *>(pool); 32.68 + EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 32.69 + EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 32.70 + EXPECT_EQ(basic_pool->ndata, 2); 32.71 + EXPECT_EQ(basic_pool->size, 4); 32.72 + EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 32.73 + EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 32.74 + EXPECT_EQ(basic_pool->ndata, 4); 32.75 + EXPECT_EQ(basic_pool->size, 4); 32.76 + EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 32.77 + EXPECT_NE(cxMalloc(pool->allocator, sizeof(int)), nullptr); 32.78 + EXPECT_EQ(basic_pool->ndata, 6); 32.79 + EXPECT_GE(basic_pool->size, 6); 32.80 +} 32.81 + 32.82 +TEST_F(CxBasicMempool, calloc) { 32.83 + pool = cxBasicMempoolCreate(4); 32.84 + 32.85 + auto test = (int *) cxCalloc(pool->allocator, 2, sizeof(int)); 32.86 + ASSERT_NE(test, nullptr); 32.87 + EXPECT_EQ(test[0], 0); 32.88 + EXPECT_EQ(test[1], 0); 32.89 +} 32.90 + 32.91 +static unsigned test_destructor_called = 0; 32.92 + 32.93 +static void test_destructor([[maybe_unused]] void *mem) { 32.94 + test_destructor_called++; 32.95 +} 32.96 + 32.97 +TEST_F(CxBasicMempool, destructor) { 32.98 + pool = cxBasicMempoolCreate(4); 32.99 + auto data = cxMalloc(pool->allocator, sizeof(int)); 32.100 + *((int *) data) = 13; 32.101 + cxMempoolSetDestructor(pool, data, test_destructor); 32.102 + EXPECT_EQ(*((int *) data), 13); 32.103 + test_destructor_called = 0; 32.104 + cxFree(pool->allocator, data); 32.105 + EXPECT_EQ(test_destructor_called, 1); 32.106 + data = cxMalloc(pool->allocator, sizeof(int)); 32.107 + cxMempoolSetDestructor(pool, data, test_destructor); 32.108 + cxMempoolDestroy(pool); 32.109 + pool = nullptr; 32.110 + EXPECT_EQ(test_destructor_called, 2); 32.111 +} 32.112 + 32.113 +TEST_F(CxBasicMempool, realloc) { 32.114 + pool = cxBasicMempoolCreate(4); 32.115 + auto data = cxMalloc(pool->allocator, sizeof(int)); 32.116 + *((int *) data) = 13; 32.117 + cxMempoolSetDestructor(pool, data, test_destructor); 32.118 + 32.119 + void *rdata = data; 32.120 + unsigned n = 1; 32.121 + while (rdata == data) { 32.122 + n <<= 1; 32.123 + ASSERT_LT(n, 65536); // eventually the memory should be moved elsewhere 32.124 + rdata = cxRealloc(pool->allocator, data, n * sizeof(intptr_t)); 32.125 + } 32.126 + 32.127 + EXPECT_EQ(*((int *) rdata), 13); 32.128 + // test if destructor is still intact 32.129 + test_destructor_called = 0; 32.130 + cxFree(pool->allocator, rdata); 32.131 + EXPECT_EQ(test_destructor_called, 1); 32.132 +} 32.133 + 32.134 + 32.135 +TEST_F(CxBasicMempool, free) { 32.136 + pool = cxBasicMempoolCreate(4); 32.137 + auto basic_pool = reinterpret_cast<cx_basic_mempool_s *>(pool); 32.138 + 32.139 + void *mem1; 32.140 + void *mem2; 32.141 + 32.142 + mem1 = cxMalloc(pool->allocator, 16); 32.143 + cxFree(pool->allocator, mem1); 32.144 + EXPECT_EQ(basic_pool->ndata, 0); 32.145 + 32.146 + cxMalloc(pool->allocator, 16); 32.147 + cxMalloc(pool->allocator, 16); 32.148 + mem1 = cxMalloc(pool->allocator, 16); 32.149 + cxMalloc(pool->allocator, 16); 32.150 + mem2 = cxMalloc(pool->allocator, 16); 32.151 + 32.152 + EXPECT_EQ(basic_pool->ndata, 5); 32.153 + cxFree(pool->allocator, mem1); 32.154 + EXPECT_EQ(basic_pool->ndata, 4); 32.155 + cxFree(pool->allocator, mem2); 32.156 + EXPECT_EQ(basic_pool->ndata, 3); 32.157 +} 32.158 \ No newline at end of file
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/tests/test_buffer.cpp Wed Feb 08 20:26:26 2023 +0100 33.3 @@ -0,0 +1,815 @@ 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 +#include "cx/buffer.h" 33.33 + 33.34 +#include <gtest/gtest.h> 33.35 +#include "util_allocator.h" 33.36 + 33.37 +class BufferFixture : public ::testing::Test { 33.38 +protected: 33.39 + void SetUp() override { 33.40 + cxBufferInit(&buf, nullptr, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT); 33.41 + buf.size = 6; 33.42 + buf.pos = 3; 33.43 + } 33.44 + 33.45 + void TearDown() override { 33.46 + cxBufferDestroy(&buf); 33.47 + } 33.48 + 33.49 + CxBuffer buf{}; 33.50 +}; 33.51 + 33.52 +static void expect_default_flush_config(CxBuffer *buf) { 33.53 + EXPECT_EQ(buf->flush_blkmax, 0); 33.54 + EXPECT_EQ(buf->flush_blksize, 4096); 33.55 + EXPECT_EQ(buf->flush_threshold, SIZE_MAX); 33.56 + EXPECT_EQ(buf->flush_func, nullptr); 33.57 + EXPECT_EQ(buf->flush_target, nullptr); 33.58 +} 33.59 + 33.60 +TEST(BufferInit, WrapSpace) { 33.61 + CxTestingAllocator alloc; 33.62 + CxBuffer buf; 33.63 + void *space = cxMalloc(&alloc, 16); 33.64 + cxBufferInit(&buf, space, 16, &alloc, CX_BUFFER_DEFAULT); 33.65 + expect_default_flush_config(&buf); 33.66 + EXPECT_EQ(buf.space, space); 33.67 + EXPECT_EQ(buf.flags & CX_BUFFER_AUTO_EXTEND, 0); 33.68 + EXPECT_EQ(buf.flags & CX_BUFFER_FREE_CONTENTS, 0); 33.69 + EXPECT_EQ(buf.pos, 0); 33.70 + EXPECT_EQ(buf.size, 0); 33.71 + EXPECT_EQ(buf.capacity, 16); 33.72 + EXPECT_EQ(buf.allocator, &alloc); 33.73 + cxBufferDestroy(&buf); 33.74 + EXPECT_FALSE(alloc.verify()); 33.75 + cxFree(&alloc, space); 33.76 + EXPECT_TRUE(alloc.verify()); 33.77 +} 33.78 + 33.79 +TEST(BufferInit, WrapSpaceAutoExtend) { 33.80 + CxTestingAllocator alloc; 33.81 + CxBuffer buf; 33.82 + void *space = cxMalloc(&alloc, 16); 33.83 + cxBufferInit(&buf, space, 16, &alloc, CX_BUFFER_AUTO_EXTEND); 33.84 + expect_default_flush_config(&buf); 33.85 + EXPECT_EQ(buf.space, space); 33.86 + EXPECT_EQ(buf.flags & CX_BUFFER_AUTO_EXTEND, CX_BUFFER_AUTO_EXTEND); 33.87 + EXPECT_EQ(buf.flags & CX_BUFFER_FREE_CONTENTS, 0); 33.88 + EXPECT_EQ(buf.pos, 0); 33.89 + EXPECT_EQ(buf.size, 0); 33.90 + EXPECT_EQ(buf.capacity, 16); 33.91 + EXPECT_EQ(buf.allocator, &alloc); 33.92 + cxBufferDestroy(&buf); 33.93 + EXPECT_FALSE(alloc.verify()); 33.94 + cxFree(&alloc, space); 33.95 + EXPECT_TRUE(alloc.verify()); 33.96 +} 33.97 + 33.98 +TEST(BufferInit, WrapSpaceAutoFree) { 33.99 + CxTestingAllocator alloc; 33.100 + CxBuffer buf; 33.101 + void *space = cxMalloc(&alloc, 16); 33.102 + cxBufferInit(&buf, space, 16, &alloc, CX_BUFFER_FREE_CONTENTS); 33.103 + expect_default_flush_config(&buf); 33.104 + EXPECT_EQ(buf.space, space); 33.105 + EXPECT_EQ(buf.flags & CX_BUFFER_AUTO_EXTEND, 0); 33.106 + EXPECT_EQ(buf.flags & CX_BUFFER_FREE_CONTENTS, CX_BUFFER_FREE_CONTENTS); 33.107 + EXPECT_EQ(buf.pos, 0); 33.108 + EXPECT_EQ(buf.size, 0); 33.109 + EXPECT_EQ(buf.capacity, 16); 33.110 + EXPECT_EQ(buf.allocator, &alloc); 33.111 + EXPECT_FALSE(alloc.verify()); 33.112 + cxBufferDestroy(&buf); 33.113 + EXPECT_TRUE(alloc.verify()); 33.114 +} 33.115 + 33.116 +TEST(BufferInit, FreshSpace) { 33.117 + CxTestingAllocator alloc; 33.118 + CxBuffer buf; 33.119 + cxBufferInit(&buf, nullptr, 8, &alloc, CX_BUFFER_DEFAULT); 33.120 + expect_default_flush_config(&buf); 33.121 + EXPECT_NE(buf.space, nullptr); 33.122 + EXPECT_EQ(buf.flags & CX_BUFFER_AUTO_EXTEND, 0); 33.123 + EXPECT_EQ(buf.flags & CX_BUFFER_FREE_CONTENTS, CX_BUFFER_FREE_CONTENTS); 33.124 + EXPECT_EQ(buf.pos, 0); 33.125 + EXPECT_EQ(buf.size, 0); 33.126 + EXPECT_EQ(buf.capacity, 8); 33.127 + EXPECT_EQ(buf.allocator, &alloc); 33.128 + EXPECT_FALSE(alloc.verify()); // space is still allocated 33.129 + cxBufferDestroy(&buf); 33.130 + EXPECT_TRUE(alloc.verify()); 33.131 +} 33.132 + 33.133 +class BufferShiftFixture : public ::testing::Test { 33.134 +protected: 33.135 + void SetUp() override { 33.136 + ASSERT_TRUE(alloc.verify()); 33.137 + cxBufferInit(&buf, nullptr, 16, &alloc, CX_BUFFER_DEFAULT); 33.138 + memcpy(buf.space, "test____________", 16); 33.139 + buf.capacity = 8; // purposely pretend that the buffer has less capacity s.t. we can test beyond the range 33.140 + buf.pos = 4; 33.141 + buf.size = 4; 33.142 + } 33.143 + 33.144 + void TearDown() override { 33.145 + cxBufferDestroy(&buf); 33.146 + EXPECT_TRUE(alloc.verify()); 33.147 + } 33.148 + 33.149 + CxTestingAllocator alloc; 33.150 + CxBuffer buf{}; 33.151 +}; 33.152 + 33.153 +class BufferShiftLeft : public BufferShiftFixture { 33.154 +}; 33.155 + 33.156 +TEST_F(BufferShiftLeft, Zero) { 33.157 + ASSERT_EQ(buf.pos, 4); 33.158 + ASSERT_EQ(buf.size, 4); 33.159 + int ret = cxBufferShiftLeft(&buf, 0); 33.160 + EXPECT_EQ(ret, 0); 33.161 + EXPECT_EQ(buf.pos, 4); 33.162 + EXPECT_EQ(buf.size, 4); 33.163 + EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 33.164 +} 33.165 + 33.166 +TEST_F(BufferShiftLeft, ZeroOffsetInterface) { 33.167 + ASSERT_EQ(buf.pos, 4); 33.168 + ASSERT_EQ(buf.size, 4); 33.169 + int ret = cxBufferShift(&buf, -0); 33.170 + EXPECT_EQ(ret, 0); 33.171 + EXPECT_EQ(buf.pos, 4); 33.172 + EXPECT_EQ(buf.size, 4); 33.173 + EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 33.174 +} 33.175 + 33.176 +TEST_F(BufferShiftLeft, Standard) { 33.177 + ASSERT_EQ(buf.pos, 4); 33.178 + ASSERT_EQ(buf.size, 4); 33.179 + int ret = cxBufferShiftLeft(&buf, 2); 33.180 + EXPECT_EQ(ret, 0); 33.181 + EXPECT_EQ(buf.pos, 2); 33.182 + EXPECT_EQ(buf.size, 2); 33.183 + EXPECT_TRUE(memcmp(buf.space, "stst________", 8) == 0); 33.184 +} 33.185 + 33.186 +TEST_F(BufferShiftLeft, Overshift) { 33.187 + ASSERT_LT(buf.pos, 6); 33.188 + ASSERT_LT(buf.size, 6); 33.189 + int ret = cxBufferShiftLeft(&buf, 6); 33.190 + EXPECT_EQ(ret, 0); 33.191 + EXPECT_EQ(buf.pos, 0); 33.192 + EXPECT_EQ(buf.size, 0); 33.193 + EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 33.194 +} 33.195 + 33.196 +TEST_F(BufferShiftLeft, OvershiftPosOnly) { 33.197 + buf.pos = 2; 33.198 + ASSERT_EQ(buf.size, 4); 33.199 + int ret = cxBufferShiftLeft(&buf, 3); 33.200 + EXPECT_EQ(ret, 0); 33.201 + EXPECT_EQ(buf.pos, 0); 33.202 + EXPECT_EQ(buf.size, 1); 33.203 + EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 33.204 +} 33.205 + 33.206 +TEST_F(BufferShiftLeft, OffsetInterface) { 33.207 + buf.pos = 3; 33.208 + ASSERT_EQ(buf.size, 4); 33.209 + int ret = cxBufferShift(&buf, -2); 33.210 + EXPECT_EQ(ret, 0); 33.211 + EXPECT_EQ(buf.pos, 1); 33.212 + EXPECT_EQ(buf.size, 2); 33.213 + EXPECT_TRUE(memcmp(buf.space, "stst________", 8) == 0); 33.214 +} 33.215 + 33.216 +class BufferShiftRight : public BufferShiftFixture { 33.217 +}; 33.218 + 33.219 +TEST_F(BufferShiftRight, Zero) { 33.220 + ASSERT_EQ(buf.pos, 4); 33.221 + ASSERT_EQ(buf.size, 4); 33.222 + int ret = cxBufferShiftRight(&buf, 0); 33.223 + EXPECT_EQ(ret, 0); 33.224 + EXPECT_EQ(buf.pos, 4); 33.225 + EXPECT_EQ(buf.size, 4); 33.226 + EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 33.227 +} 33.228 + 33.229 +TEST_F(BufferShiftRight, ZeroOffsetInterface) { 33.230 + ASSERT_EQ(buf.pos, 4); 33.231 + ASSERT_EQ(buf.size, 4); 33.232 + int ret = cxBufferShift(&buf, +0); 33.233 + EXPECT_EQ(ret, 0); 33.234 + EXPECT_EQ(buf.pos, 4); 33.235 + EXPECT_EQ(buf.size, 4); 33.236 + EXPECT_TRUE(memcmp(buf.space, "test________", 8) == 0); 33.237 +} 33.238 + 33.239 +TEST_F(BufferShiftRight, Standard) { 33.240 + ASSERT_EQ(buf.pos, 4); 33.241 + ASSERT_EQ(buf.size, 4); 33.242 + int ret = cxBufferShiftRight(&buf, 3); 33.243 + EXPECT_EQ(ret, 0); 33.244 + EXPECT_EQ(buf.pos, 7); 33.245 + EXPECT_EQ(buf.size, 7); 33.246 + EXPECT_TRUE(memcmp(buf.space, "testest_____", 8) == 0); 33.247 +} 33.248 + 33.249 +TEST_F(BufferShiftRight, OvershiftDiscard) { 33.250 + ASSERT_EQ(buf.pos, 4); 33.251 + ASSERT_EQ(buf.size, 4); 33.252 + ASSERT_EQ(buf.capacity, 8); 33.253 + int ret = cxBufferShiftRight(&buf, 6); 33.254 + EXPECT_EQ(ret, 0); 33.255 + EXPECT_EQ(buf.pos, 8); 33.256 + EXPECT_EQ(buf.size, 8); 33.257 + EXPECT_EQ(buf.capacity, 8); 33.258 + EXPECT_TRUE(memcmp(buf.space, "test__te____", 8) == 0); 33.259 +} 33.260 + 33.261 +TEST_F(BufferShiftRight, OvershiftExtend) { 33.262 + ASSERT_EQ(buf.pos, 4); 33.263 + ASSERT_EQ(buf.size, 4); 33.264 + ASSERT_EQ(buf.capacity, 8); 33.265 + buf.flags |= CX_BUFFER_AUTO_EXTEND; 33.266 + int ret = cxBufferShiftRight(&buf, 6); 33.267 + EXPECT_EQ(ret, 0); 33.268 + EXPECT_EQ(buf.pos, 10); 33.269 + EXPECT_EQ(buf.size, 10); 33.270 + EXPECT_GE(buf.capacity, 10); 33.271 + EXPECT_TRUE(memcmp(buf.space, "test__test__", 8) == 0); 33.272 +} 33.273 + 33.274 +TEST_F(BufferShiftRight, OffsetInterface) { 33.275 + buf.pos = 3; 33.276 + ASSERT_EQ(buf.size, 4); 33.277 + int ret = cxBufferShift(&buf, 2); 33.278 + EXPECT_EQ(ret, 0); 33.279 + EXPECT_EQ(buf.pos, 5); 33.280 + EXPECT_EQ(buf.size, 6); 33.281 + EXPECT_TRUE(memcmp(buf.space, "tetest______", 8) == 0); 33.282 +} 33.283 + 33.284 +TEST(BufferMinimumCapacity, Sufficient) { 33.285 + CxTestingAllocator alloc; 33.286 + auto space = cxMalloc(&alloc, 8); 33.287 + CxBuffer buf; 33.288 + cxBufferInit(&buf, space, 8, &alloc, CX_BUFFER_FREE_CONTENTS); 33.289 + memcpy(space, "Testing", 8); 33.290 + buf.size = 8; 33.291 + cxBufferMinimumCapacity(&buf, 6); 33.292 + EXPECT_EQ(buf.capacity, 8); 33.293 + EXPECT_EQ(buf.size, 8); 33.294 + EXPECT_TRUE(memcmp(buf.space, "Testing", 8) == 0); 33.295 + cxBufferDestroy(&buf); 33.296 + EXPECT_TRUE(alloc.verify()); 33.297 +} 33.298 + 33.299 +TEST(BufferMinimumCapacity, Extend) { 33.300 + CxTestingAllocator alloc; 33.301 + auto space = cxMalloc(&alloc, 8); 33.302 + CxBuffer buf; 33.303 + cxBufferInit(&buf, space, 8, &alloc, CX_BUFFER_FREE_CONTENTS); // NO auto extend! 33.304 + memcpy(space, "Testing", 8); 33.305 + buf.size = 8; 33.306 + cxBufferMinimumCapacity(&buf, 16); 33.307 + EXPECT_EQ(buf.capacity, 16); 33.308 + EXPECT_EQ(buf.size, 8); 33.309 + EXPECT_TRUE(memcmp(buf.space, "Testing", 8) == 0); 33.310 + cxBufferDestroy(&buf); 33.311 + EXPECT_TRUE(alloc.verify()); 33.312 +} 33.313 + 33.314 +TEST(BufferClear, Test) { 33.315 + char space[16]; 33.316 + strcpy(space, "clear test"); 33.317 + CxBuffer buf; 33.318 + cxBufferInit(&buf, space, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT); 33.319 + ASSERT_EQ(buf.size, 0); 33.320 + // only clear the used part of the buffer 33.321 + cxBufferClear(&buf); 33.322 + EXPECT_EQ(memcmp(space, "clear test", 10), 0); 33.323 + buf.size = 5; 33.324 + buf.pos = 3; 33.325 + cxBufferClear(&buf); 33.326 + EXPECT_EQ(memcmp(space, "\0\0\0\0\0 test", 10), 0); 33.327 + EXPECT_EQ(buf.size, 0); 33.328 + EXPECT_EQ(buf.pos, 0); 33.329 + cxBufferDestroy(&buf); 33.330 +} 33.331 + 33.332 +class BufferWrite : public ::testing::Test { 33.333 +protected: 33.334 + CxBuffer buf{}, target{}; 33.335 + 33.336 + void SetUp() override { 33.337 + cxBufferInit(&target, nullptr, 16, cxDefaultAllocator, CX_BUFFER_AUTO_EXTEND); 33.338 + cxBufferInit(&buf, nullptr, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT); 33.339 + buf.capacity = 8; // artificially reduce capacity to check OOB writes 33.340 + memset(buf.space, 0, 16); 33.341 + memcpy(buf.space, "prep", 4); 33.342 + buf.size = buf.pos = 4; 33.343 + } 33.344 + 33.345 + void TearDown() override { 33.346 + cxBufferDestroy(&buf); 33.347 + cxBufferDestroy(&target); 33.348 + } 33.349 + 33.350 + void enableFlushing() { 33.351 + buf.flush_target = ⌖ 33.352 + buf.flush_func = reinterpret_cast<cx_write_func>(cxBufferWrite); 33.353 + buf.flush_blkmax = 1; 33.354 + } 33.355 +}; 33.356 + 33.357 +static size_t mock_write_limited_rate( 33.358 + void const *ptr, 33.359 + size_t size, 33.360 + __attribute__((unused)) size_t nitems, 33.361 + CxBuffer *buffer 33.362 +) { 33.363 + // simulate limited target drain capacity 33.364 + static bool full = false; 33.365 + if (full) { 33.366 + full = false; 33.367 + return 0; 33.368 + } else { 33.369 + full = true; 33.370 + return cxBufferWrite(ptr, size, nitems > 2 ? 2 : nitems, buffer); 33.371 + } 33.372 +} 33.373 + 33.374 +TEST_F(BufferWrite, SizeOneFit) { 33.375 + const char *data = "test"; 33.376 + ASSERT_EQ(buf.capacity, 8); 33.377 + ASSERT_EQ(buf.pos, 4); 33.378 + ASSERT_EQ(buf.size, 4); 33.379 + size_t written = cxBufferWrite(data, 1, 4, &buf); 33.380 + EXPECT_EQ(written, 4); 33.381 + EXPECT_EQ(buf.size, 8); 33.382 + EXPECT_EQ(buf.pos, 8); 33.383 + EXPECT_EQ(buf.capacity, 8); 33.384 + EXPECT_EQ(memcmp(buf.space, "preptest", 8), 0); 33.385 +} 33.386 + 33.387 +TEST_F(BufferWrite, SizeOneDiscard) { 33.388 + const char *data = "testing"; 33.389 + ASSERT_EQ(buf.capacity, 8); 33.390 + ASSERT_EQ(buf.pos, 4); 33.391 + ASSERT_EQ(buf.size, 4); 33.392 + size_t written = cxBufferWrite(data, 1, 7, &buf); 33.393 + EXPECT_EQ(written, 4); 33.394 + EXPECT_EQ(buf.size, 8); 33.395 + EXPECT_EQ(buf.pos, 8); 33.396 + EXPECT_EQ(buf.capacity, 8); 33.397 + EXPECT_EQ(memcmp(buf.space, "preptest\0", 9), 0); 33.398 +} 33.399 + 33.400 +TEST_F(BufferWrite, SizeOneExtend) { 33.401 + buf.flags |= CX_BUFFER_AUTO_EXTEND; 33.402 + const char *data = "testing"; 33.403 + ASSERT_EQ(buf.capacity, 8); 33.404 + ASSERT_EQ(buf.pos, 4); 33.405 + ASSERT_EQ(buf.size, 4); 33.406 + size_t written = cxBufferWrite(data, 1, 7, &buf); 33.407 + EXPECT_EQ(written, 7); 33.408 + EXPECT_EQ(buf.size, 11); 33.409 + EXPECT_EQ(buf.pos, 11); 33.410 + EXPECT_GE(buf.capacity, 11); 33.411 + EXPECT_EQ(memcmp(buf.space, "preptesting", 11), 0); 33.412 +} 33.413 + 33.414 +TEST_F(BufferWrite, MultibyteFit) { 33.415 + const char *data = "test"; 33.416 + ASSERT_EQ(buf.capacity, 8); 33.417 + ASSERT_EQ(buf.pos, 4); 33.418 + ASSERT_EQ(buf.size, 4); 33.419 + size_t written = cxBufferWrite(data, 2, 2, &buf); 33.420 + EXPECT_EQ(written, 2); 33.421 + EXPECT_EQ(buf.size, 8); 33.422 + EXPECT_EQ(buf.pos, 8); 33.423 + EXPECT_EQ(buf.capacity, 8); 33.424 + EXPECT_EQ(memcmp(buf.space, "preptest", 8), 0); 33.425 +} 33.426 + 33.427 +TEST_F(BufferWrite, MultibyteDiscard) { 33.428 + const char *data = "testing"; 33.429 + ASSERT_EQ(buf.capacity, 8); 33.430 + ASSERT_EQ(buf.size, 4); 33.431 + buf.pos = 3; 33.432 + size_t written = cxBufferWrite(data, 2, 4, &buf); 33.433 + // remember: whole elements are discarded if they do not fit 33.434 + EXPECT_EQ(written, 2); 33.435 + EXPECT_EQ(buf.size, 7); 33.436 + EXPECT_EQ(buf.pos, 7); 33.437 + EXPECT_EQ(buf.capacity, 8); 33.438 + EXPECT_EQ(memcmp(buf.space, "pretest\0", 8), 0); 33.439 +} 33.440 + 33.441 +TEST_F(BufferWrite, MultibyteExtend) { 33.442 + buf.flags |= CX_BUFFER_AUTO_EXTEND; 33.443 + const char *data = "tester"; 33.444 + ASSERT_EQ(buf.capacity, 8); 33.445 + ASSERT_EQ(buf.size, 4); 33.446 + buf.pos = 3; 33.447 + size_t written = cxBufferWrite(data, 2, 3, &buf); 33.448 + // remember: whole elements are discarded if they do not fit 33.449 + EXPECT_EQ(written, 3); 33.450 + EXPECT_EQ(buf.size, 9); 33.451 + EXPECT_EQ(buf.pos, 9); 33.452 + EXPECT_GE(buf.capacity, 9); 33.453 + EXPECT_EQ(memcmp(buf.space, "pretester", 9), 0); 33.454 +} 33.455 + 33.456 +TEST_F(BufferWrite, PutcWrapperFit) { 33.457 + ASSERT_EQ(buf.capacity, 8); 33.458 + ASSERT_EQ(buf.pos, 4); 33.459 + ASSERT_EQ(buf.size, 4); 33.460 + int c = cxBufferPut(&buf, 0x200 | 'a'); 33.461 + EXPECT_EQ(c, 'a'); 33.462 + EXPECT_EQ(buf.size, 5); 33.463 + EXPECT_EQ(buf.pos, 5); 33.464 + EXPECT_EQ(buf.capacity, 8); 33.465 + EXPECT_EQ(memcmp(buf.space, "prepa\0", 6), 0); 33.466 +} 33.467 + 33.468 +TEST_F(BufferWrite, PutcWrapperDiscard) { 33.469 + ASSERT_EQ(buf.capacity, 8); 33.470 + ASSERT_EQ(buf.size, 4); 33.471 + buf.pos = 8; 33.472 + int c = cxBufferPut(&buf, 0x200 | 'a'); 33.473 + EXPECT_EQ(c, EOF); 33.474 + EXPECT_EQ(buf.size, 4); 33.475 + EXPECT_EQ(buf.pos, 8); 33.476 + EXPECT_EQ(buf.capacity, 8); 33.477 + EXPECT_EQ(memcmp(buf.space, "prep\0\0\0\0\0", 9), 0); 33.478 +} 33.479 + 33.480 +TEST_F(BufferWrite, PutcWrapperExtend) { 33.481 + buf.flags |= CX_BUFFER_AUTO_EXTEND; 33.482 + ASSERT_EQ(buf.capacity, 8); 33.483 + ASSERT_EQ(buf.size, 4); 33.484 + buf.pos = 8; 33.485 + int c = cxBufferPut(&buf, 0x200 | 'a'); 33.486 + EXPECT_EQ(c, 'a'); 33.487 + EXPECT_EQ(buf.size, 9); 33.488 + EXPECT_EQ(buf.pos, 9); 33.489 + EXPECT_GE(buf.capacity, 9); 33.490 + EXPECT_EQ(memcmp(buf.space, "prep\0\0\0\0a", 9), 0); 33.491 +} 33.492 + 33.493 +TEST_F(BufferWrite, PutStringWrapperFit) { 33.494 + const char *data = "test"; 33.495 + ASSERT_EQ(buf.capacity, 8); 33.496 + ASSERT_EQ(buf.pos, 4); 33.497 + ASSERT_EQ(buf.size, 4); 33.498 + size_t written = cxBufferPutString(&buf, data); 33.499 + EXPECT_EQ(written, 4); 33.500 + EXPECT_EQ(buf.size, 8); 33.501 + EXPECT_EQ(buf.pos, 8); 33.502 + EXPECT_EQ(buf.capacity, 8); 33.503 + EXPECT_EQ(memcmp(buf.space, "preptest", 8), 0); 33.504 +} 33.505 + 33.506 +TEST_F(BufferWrite, PutStringWrapperDiscard) { 33.507 + const char *data = "testing"; 33.508 + ASSERT_EQ(buf.capacity, 8); 33.509 + ASSERT_EQ(buf.pos, 4); 33.510 + ASSERT_EQ(buf.size, 4); 33.511 + size_t written = cxBufferPutString(&buf, data); 33.512 + EXPECT_EQ(written, 4); 33.513 + EXPECT_EQ(buf.size, 8); 33.514 + EXPECT_EQ(buf.pos, 8); 33.515 + EXPECT_EQ(buf.capacity, 8); 33.516 + EXPECT_EQ(memcmp(buf.space, "preptest\0", 9), 0); 33.517 +} 33.518 + 33.519 +TEST_F(BufferWrite, PutStringWrapperExtend) { 33.520 + buf.flags |= CX_BUFFER_AUTO_EXTEND; 33.521 + const char *data = "testing"; 33.522 + ASSERT_EQ(buf.capacity, 8); 33.523 + ASSERT_EQ(buf.pos, 4); 33.524 + ASSERT_EQ(buf.size, 4); 33.525 + size_t written = cxBufferPutString(&buf, data); 33.526 + EXPECT_EQ(written, 7); 33.527 + EXPECT_EQ(buf.size, 11); 33.528 + EXPECT_EQ(buf.pos, 11); 33.529 + EXPECT_GE(buf.capacity, 11); 33.530 + EXPECT_EQ(memcmp(buf.space, "preptesting", 11), 0); 33.531 +} 33.532 + 33.533 +TEST_F(BufferWrite, MultOverflow) { 33.534 + const char *data = "testing"; 33.535 + ASSERT_EQ(buf.capacity, 8); 33.536 + ASSERT_EQ(buf.pos, 4); 33.537 + ASSERT_EQ(buf.size, 4); 33.538 + size_t written = cxBufferWrite(data, 8, SIZE_MAX / 4, &buf); 33.539 + EXPECT_EQ(written, 0); 33.540 + EXPECT_EQ(buf.capacity, 8); 33.541 + EXPECT_EQ(buf.pos, 4); 33.542 + EXPECT_EQ(buf.size, 4); 33.543 + EXPECT_EQ(memcmp(buf.space, "prep\0", 5), 0); 33.544 +} 33.545 + 33.546 +TEST_F(BufferWrite, MaxCapaOverflow) { 33.547 + buf.flags |= CX_BUFFER_AUTO_EXTEND; 33.548 + const char *data = "testing"; 33.549 + ASSERT_EQ(buf.capacity, 8); 33.550 + ASSERT_EQ(buf.pos, 4); 33.551 + ASSERT_EQ(buf.size, 4); 33.552 + size_t written = cxBufferWrite(data, 1, SIZE_MAX - 2, &buf); 33.553 + EXPECT_EQ(written, 0); 33.554 + EXPECT_EQ(buf.capacity, 8); 33.555 + EXPECT_EQ(buf.pos, 4); 33.556 + EXPECT_EQ(buf.size, 4); 33.557 + EXPECT_EQ(memcmp(buf.space, "prep\0", 5), 0); 33.558 +} 33.559 + 33.560 +TEST_F(BufferWrite, OnlyOverwrite) { 33.561 + buf.flags |= CX_BUFFER_AUTO_EXTEND; 33.562 + ASSERT_EQ(buf.capacity, 8); 33.563 + memcpy(buf.space, "preptest", 8); 33.564 + buf.pos = 3; 33.565 + buf.size = 8; 33.566 + size_t written = cxBufferWrite("XXX", 2, 2, &buf); 33.567 + EXPECT_EQ(written, 2); 33.568 + EXPECT_EQ(buf.capacity, 8); 33.569 + EXPECT_EQ(buf.size, 8); 33.570 + EXPECT_EQ(buf.pos, 7); 33.571 + EXPECT_EQ(memcmp(buf.space, "preXXX\0t", 8), 0); 33.572 +} 33.573 + 33.574 +TEST_F(BufferWrite, FlushAtCapacity) { 33.575 + enableFlushing(); 33.576 + ASSERT_EQ(buf.capacity, 8); 33.577 + ASSERT_EQ(buf.pos, 4); 33.578 + size_t written = cxBufferWrite("foo", 1, 3, &buf); 33.579 + EXPECT_EQ(written, 3); 33.580 + ASSERT_EQ(buf.pos, 7); 33.581 + ASSERT_EQ(buf.size, 7); 33.582 + ASSERT_EQ(target.pos, 0); 33.583 + ASSERT_EQ(target.size, 0); 33.584 + written = cxBufferWrite("hello", 1, 5, &buf); 33.585 + EXPECT_EQ(written, 5); 33.586 + EXPECT_EQ(buf.pos, 0); 33.587 + EXPECT_EQ(buf.size, 0); 33.588 + EXPECT_EQ(buf.capacity, 8); 33.589 + EXPECT_EQ(target.pos, 12); 33.590 + ASSERT_EQ(target.size, 12); 33.591 + EXPECT_EQ(memcmp(target.space, "prepfoohello", 12), 0); 33.592 +} 33.593 + 33.594 +TEST_F(BufferWrite, FlushAtThreshold) { 33.595 + enableFlushing(); 33.596 + buf.flush_threshold = 12; 33.597 + buf.flags |= CX_BUFFER_AUTO_EXTEND; 33.598 + ASSERT_EQ(buf.capacity, 8); 33.599 + ASSERT_EQ(buf.pos, 4); 33.600 + size_t written = cxBufferWrite("foobar", 1, 6, &buf); 33.601 + EXPECT_EQ(written, 6); 33.602 + ASSERT_EQ(buf.pos, 10); 33.603 + ASSERT_EQ(buf.size, 10); 33.604 + ASSERT_GE(buf.capacity, 10); 33.605 + ASSERT_LE(buf.capacity, 12); 33.606 + ASSERT_EQ(target.pos, 0); 33.607 + ASSERT_EQ(target.size, 0); 33.608 + written = cxBufferWrite("hello", 1, 5, &buf); 33.609 + EXPECT_EQ(written, 5); 33.610 + EXPECT_EQ(buf.pos, 0); 33.611 + EXPECT_EQ(buf.size, 0); 33.612 + EXPECT_LE(buf.capacity, 12); 33.613 + EXPECT_EQ(target.pos, 15); 33.614 + ASSERT_EQ(target.size, 15); 33.615 + EXPECT_EQ(memcmp(target.space, "prepfoobarhello", 15), 0); 33.616 +} 33.617 + 33.618 +TEST_F(BufferWrite, FlushRateLimited) { 33.619 + enableFlushing(); 33.620 + // limit the rate of the flush function and the capacity of the target 33.621 + target.capacity = 16; 33.622 + target.flags &= ~CX_BUFFER_AUTO_EXTEND; 33.623 + buf.flush_func = (cx_write_func) mock_write_limited_rate; 33.624 + ASSERT_EQ(buf.capacity, 8); 33.625 + ASSERT_EQ(buf.pos, 4); 33.626 + size_t written = cxBufferWrite("foo", 1, 3, &buf); 33.627 + EXPECT_EQ(written, 3); 33.628 + ASSERT_EQ(buf.pos, 7); 33.629 + ASSERT_EQ(buf.size, 7); 33.630 + ASSERT_EQ(target.pos, 0); 33.631 + ASSERT_EQ(target.size, 0); 33.632 + written = cxBufferWrite("hello, world!", 1, 13, &buf); 33.633 + // " world!" fits into this buffer, the remaining stuff is flushed out 33.634 + EXPECT_EQ(written, 13); 33.635 + EXPECT_EQ(buf.pos, 7); 33.636 + EXPECT_EQ(buf.size, 7); 33.637 + EXPECT_EQ(buf.capacity, 8); 33.638 + EXPECT_EQ(memcmp(buf.space, " world!", 7), 0); 33.639 + EXPECT_EQ(target.pos, 13); 33.640 + ASSERT_EQ(target.size, 13); 33.641 + EXPECT_EQ(target.capacity, 16); 33.642 + EXPECT_EQ(memcmp(target.space, "prepfoohello,", 13), 0); 33.643 +} 33.644 + 33.645 +class BufferSeek : public BufferFixture { 33.646 +}; 33.647 + 33.648 +TEST_F(BufferSeek, SetZero) { 33.649 + int result = cxBufferSeek(&buf, 0, SEEK_SET); 33.650 + EXPECT_EQ(result, 0); 33.651 + EXPECT_EQ(buf.pos, 0); 33.652 +} 33.653 + 33.654 +TEST_F(BufferSeek, SetValid) { 33.655 + int result = cxBufferSeek(&buf, 5, SEEK_SET); 33.656 + EXPECT_EQ(result, 0); 33.657 + EXPECT_EQ(buf.pos, 5); 33.658 +} 33.659 + 33.660 +TEST_F(BufferSeek, SetInvalid) { 33.661 + ASSERT_EQ(buf.pos, 3); 33.662 + int result = cxBufferSeek(&buf, 6, SEEK_SET); 33.663 + EXPECT_NE(result, 0); 33.664 + EXPECT_EQ(buf.pos, 3); 33.665 +} 33.666 + 33.667 +TEST_F(BufferSeek, CurZero) { 33.668 + ASSERT_EQ(buf.pos, 3); 33.669 + int result = cxBufferSeek(&buf, 0, SEEK_CUR); 33.670 + EXPECT_EQ(result, 0); 33.671 + EXPECT_EQ(buf.pos, 3); 33.672 +} 33.673 + 33.674 +TEST_F(BufferSeek, CurValidPositive) { 33.675 + ASSERT_EQ(buf.pos, 3); 33.676 + int result = cxBufferSeek(&buf, 2, SEEK_CUR); 33.677 + EXPECT_EQ(result, 0); 33.678 + EXPECT_EQ(buf.pos, 5); 33.679 +} 33.680 + 33.681 +TEST_F(BufferSeek, CurValidNegative) { 33.682 + ASSERT_EQ(buf.pos, 3); 33.683 + int result = cxBufferSeek(&buf, -3, SEEK_CUR); 33.684 + EXPECT_EQ(result, 0); 33.685 + EXPECT_EQ(buf.pos, 0); 33.686 +} 33.687 + 33.688 +TEST_F(BufferSeek, CurInvalidPositive) { 33.689 + ASSERT_EQ(buf.pos, 3); 33.690 + int result = cxBufferSeek(&buf, 3, SEEK_CUR); 33.691 + EXPECT_NE(result, 0); 33.692 + EXPECT_EQ(buf.pos, 3); 33.693 +} 33.694 + 33.695 +TEST_F(BufferSeek, CurInvalidNegative) { 33.696 + ASSERT_EQ(buf.pos, 3); 33.697 + int result = cxBufferSeek(&buf, -4, SEEK_CUR); 33.698 + EXPECT_NE(result, 0); 33.699 + EXPECT_EQ(buf.pos, 3); 33.700 +} 33.701 + 33.702 +TEST_F(BufferSeek, EndZero) { 33.703 + ASSERT_EQ(buf.size, 6); 33.704 + int result = cxBufferSeek(&buf, 0, SEEK_END); 33.705 + // the (past-the-)end position is always invalid 33.706 + EXPECT_NE(result, 0); 33.707 + EXPECT_EQ(buf.pos, 3); 33.708 +} 33.709 + 33.710 +TEST_F(BufferSeek, EndValid) { 33.711 + ASSERT_EQ(buf.size, 6); 33.712 + int result = cxBufferSeek(&buf, -6, SEEK_END); 33.713 + EXPECT_EQ(result, 0); 33.714 + EXPECT_EQ(buf.pos, 0); 33.715 +} 33.716 + 33.717 +TEST_F(BufferSeek, EndInvalid) { 33.718 + ASSERT_EQ(buf.size, 6); 33.719 + int result = cxBufferSeek(&buf, 1, SEEK_END); 33.720 + EXPECT_NE(result, 0); 33.721 + EXPECT_EQ(buf.pos, 3); 33.722 +} 33.723 + 33.724 +TEST_F(BufferSeek, WhenceInvalid) { 33.725 + ASSERT_EQ(buf.size, 6); 33.726 + ASSERT_EQ(buf.pos, 3); 33.727 + int result = cxBufferSeek(&buf, 2, 9000); 33.728 + EXPECT_NE(result, 0); 33.729 + EXPECT_EQ(buf.size, 6); 33.730 + EXPECT_EQ(buf.pos, 3); 33.731 +} 33.732 + 33.733 +class BufferEof : public BufferFixture { 33.734 +}; 33.735 + 33.736 +TEST_F(BufferEof, Reached) { 33.737 + buf.pos = buf.size; 33.738 + EXPECT_TRUE(cxBufferEof(&buf)); 33.739 + buf.pos = buf.size - 1; 33.740 + ASSERT_FALSE(cxBufferEof(&buf)); 33.741 + cxBufferPut(&buf, 'a'); 33.742 + EXPECT_TRUE(cxBufferEof(&buf)); 33.743 +} 33.744 + 33.745 +TEST_F(BufferEof, NotReached) { 33.746 + buf.pos = buf.size - 1; 33.747 + EXPECT_FALSE(cxBufferEof(&buf)); 33.748 + buf.pos = 0; 33.749 + cxBufferWrite("test", 1, 5, &buf); 33.750 + EXPECT_FALSE(cxBufferEof(&buf)); 33.751 +} 33.752 + 33.753 +class BufferRead : public ::testing::Test { 33.754 +protected: 33.755 + CxBuffer buf{}; 33.756 + 33.757 + void SetUp() override { 33.758 + cxBufferInit(&buf, nullptr, 16, cxDefaultAllocator, CX_BUFFER_DEFAULT); 33.759 + buf.capacity = 8; // artificially reduce capacity to check OOB writes 33.760 + memset(buf.space, 0, 16); 33.761 + memcpy(buf.space, "some data", 9); 33.762 + buf.size = 9; 33.763 + } 33.764 + 33.765 + void TearDown() override { 33.766 + cxBufferDestroy(&buf); 33.767 + } 33.768 +}; 33.769 + 33.770 +TEST_F(BufferRead, GetByte) { 33.771 + buf.pos = 2; 33.772 + EXPECT_EQ(cxBufferGet(&buf), 'm'); 33.773 + EXPECT_EQ(cxBufferGet(&buf), 'e'); 33.774 + EXPECT_EQ(cxBufferGet(&buf), ' '); 33.775 + EXPECT_EQ(cxBufferGet(&buf), 'd'); 33.776 + EXPECT_EQ(buf.pos, 6); 33.777 +} 33.778 + 33.779 +TEST_F(BufferRead, GetEof) { 33.780 + buf.pos = buf.size; 33.781 + EXPECT_EQ(cxBufferGet(&buf), EOF); 33.782 +} 33.783 + 33.784 +TEST_F(BufferRead, ReadWithinBounds) { 33.785 + buf.pos = 2; 33.786 + char target[4]; 33.787 + auto read = cxBufferRead(&target, 1, 4, &buf); 33.788 + ASSERT_EQ(read, 4); 33.789 + EXPECT_EQ(memcmp(&target, "me d", 4), 0); 33.790 + EXPECT_EQ(buf.pos, 6); 33.791 +} 33.792 + 33.793 +TEST_F(BufferRead, ReadOutOfBounds) { 33.794 + buf.pos = 6; 33.795 + char target[4]; 33.796 + auto read = cxBufferRead(&target, 1, 4, &buf); 33.797 + ASSERT_EQ(read, 3); 33.798 + EXPECT_EQ(memcmp(&target, "ata", 3), 0); 33.799 + EXPECT_EQ(buf.pos, 9); 33.800 +} 33.801 + 33.802 +TEST_F(BufferRead, ReadOutOfBoundsMultibyte) { 33.803 + buf.pos = 6; 33.804 + char target[4]; 33.805 + target[2] = '\0'; 33.806 + auto read = cxBufferRead(&target, 2, 2, &buf); 33.807 + ASSERT_EQ(read, 1); 33.808 + EXPECT_EQ(memcmp(&target, "at\0", 3), 0); 33.809 + EXPECT_EQ(buf.pos, 8); 33.810 +} 33.811 + 33.812 +TEST_F(BufferRead, ReadEof) { 33.813 + buf.pos = 9; 33.814 + char target[4]; 33.815 + auto read = cxBufferRead(&target, 1, 1, &buf); 33.816 + ASSERT_EQ(read, 0); 33.817 + EXPECT_EQ(buf.pos, 9); 33.818 +}
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/tests/test_compare.cpp Wed Feb 08 20:26:26 2023 +0100 34.3 @@ -0,0 +1,127 @@ 34.4 +/* 34.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 34.6 + * 34.7 + * Copyright 2022 Mike Becker, Olaf Wintermann All rights reserved. 34.8 + * 34.9 + * Redistribution and use in source and binary forms, with or without 34.10 + * modification, are permitted provided that the following conditions are met: 34.11 + * 34.12 + * 1. Redistributions of source code must retain the above copyright 34.13 + * notice, this list of conditions and the following disclaimer. 34.14 + * 34.15 + * 2. Redistributions in binary form must reproduce the above copyright 34.16 + * notice, this list of conditions and the following disclaimer in the 34.17 + * documentation and/or other materials provided with the distribution. 34.18 + * 34.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 34.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 34.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 34.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34.29 + * POSSIBILITY OF SUCH DAMAGE. 34.30 + */ 34.31 + 34.32 +#include "cx/compare.h" 34.33 + 34.34 +#include <gtest/gtest.h> 34.35 + 34.36 +template<typename T> 34.37 +static void test_compare( 34.38 + int (*fnc)( 34.39 + void const *, 34.40 + void const * 34.41 + ) 34.42 +) { 34.43 + auto m = std::numeric_limits<T>::max() / 400; 34.44 + T x, y; 34.45 + 34.46 + x = (std::is_signed_v<T> ? -3 : 3) * m; 34.47 + y = 5 * m; 34.48 + EXPECT_LT(fnc(&x, &y), 0); 34.49 + EXPECT_GT(fnc(&y, &x), 0); 34.50 + 34.51 + x = 120 * m; 34.52 + y = 348 * m; 34.53 + EXPECT_LT(fnc(&x, &y), 0); 34.54 + EXPECT_GT(fnc(&y, &x), 0); 34.55 + 34.56 + if constexpr (std::is_signed_v<T>) { 34.57 + x = -120 * m; 34.58 + y = -348 * m; 34.59 + EXPECT_GT(fnc(&x, &y), 0); 34.60 + EXPECT_LT(fnc(&y, &x), 0); 34.61 + } 34.62 + 34.63 + x = y; 34.64 + EXPECT_EQ(fnc(&x, &y), 0); 34.65 + EXPECT_EQ(fnc(&y, &x), 0); 34.66 +} 34.67 + 34.68 +TEST(Compare, Int) { 34.69 + test_compare<int>(cx_cmp_int); 34.70 +} 34.71 + 34.72 +TEST(Compare, Longint) { 34.73 + test_compare<long int>(cx_cmp_longint); 34.74 +} 34.75 + 34.76 +TEST(Compare, Longlong) { 34.77 + test_compare<long long>(cx_cmp_longlong); 34.78 +} 34.79 + 34.80 +TEST(Compare, Int16) { 34.81 + test_compare<int16_t>(cx_cmp_int16); 34.82 +} 34.83 + 34.84 +TEST(Compare, Int32) { 34.85 + test_compare<int32_t>(cx_cmp_int32); 34.86 +} 34.87 + 34.88 +TEST(Compare, Int64) { 34.89 + test_compare<int64_t>(cx_cmp_int64); 34.90 +} 34.91 + 34.92 +TEST(Compare, Uint) { 34.93 + test_compare<unsigned int>(cx_cmp_uint); 34.94 +} 34.95 + 34.96 +TEST(Compare, Ulongint) { 34.97 + test_compare<unsigned long int>(cx_cmp_ulongint); 34.98 +} 34.99 + 34.100 +TEST(Compare, Ulonglong) { 34.101 + test_compare<unsigned long long>(cx_cmp_ulonglong); 34.102 +} 34.103 + 34.104 +TEST(Compare, Uint16) { 34.105 + test_compare<uint16_t>(cx_cmp_uint16); 34.106 +} 34.107 + 34.108 +TEST(Compare, Uint32) { 34.109 + test_compare<uint32_t>(cx_cmp_uint32); 34.110 +} 34.111 + 34.112 +TEST(Compare, Uint64) { 34.113 + test_compare<uint64_t>(cx_cmp_uint64); 34.114 +} 34.115 + 34.116 +TEST(Compare, Float) { 34.117 + test_compare<float>(cx_cmp_float); 34.118 +} 34.119 + 34.120 +TEST(Compare, Double) { 34.121 + test_compare<double>(cx_cmp_double); 34.122 +} 34.123 + 34.124 +TEST(Compare, IntPtr) { 34.125 + test_compare<intptr_t>(cx_cmp_intptr); 34.126 +} 34.127 + 34.128 +TEST(Compare, UintPtr) { 34.129 + test_compare<uintptr_t>(cx_cmp_uintptr); 34.130 +}
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 35.2 +++ b/tests/test_hash_key.cpp Wed Feb 08 20:26:26 2023 +0100 35.3 @@ -0,0 +1,87 @@ 35.4 +/* 35.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 35.6 + * 35.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 35.8 + * 35.9 + * Redistribution and use in source and binary forms, with or without 35.10 + * modification, are permitted provided that the following conditions are met: 35.11 + * 35.12 + * 1. Redistributions of source code must retain the above copyright 35.13 + * notice, this list of conditions and the following disclaimer. 35.14 + * 35.15 + * 2. Redistributions in binary form must reproduce the above copyright 35.16 + * notice, this list of conditions and the following disclaimer in the 35.17 + * documentation and/or other materials provided with the distribution. 35.18 + * 35.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 35.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 35.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 35.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 35.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 35.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 35.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35.29 + * POSSIBILITY OF SUCH DAMAGE. 35.30 + */ 35.31 + 35.32 +#include "cx/hash_key.h" 35.33 + 35.34 +#include <gtest/gtest.h> 35.35 + 35.36 +TEST(cx_hash_key, functions) { 35.37 + auto str = "my key"; 35.38 + auto len = strlen(str); 35.39 + 35.40 + auto str_key = cx_hash_key_str(str); 35.41 + auto bytes_key = cx_hash_key_bytes( 35.42 + reinterpret_cast<unsigned char const *>(str), len); 35.43 + auto obj_key = cx_hash_key( 35.44 + reinterpret_cast<void const *>(str), len); 35.45 + 35.46 + EXPECT_EQ(str_key.hash, bytes_key.hash); 35.47 + EXPECT_EQ(obj_key.hash, bytes_key.hash); 35.48 + EXPECT_EQ(str_key.len, len); 35.49 + EXPECT_EQ(bytes_key.len, len); 35.50 + EXPECT_EQ(bytes_key.len, len); 35.51 + EXPECT_EQ(str_key.data.cstr, str); 35.52 + EXPECT_EQ(bytes_key.data.cbytes, reinterpret_cast<unsigned char const *>(str)); 35.53 + EXPECT_EQ(bytes_key.data.cobj, reinterpret_cast<void const *>(str)); 35.54 +} 35.55 + 35.56 +TEST(cx_hash_key, empty_string) { 35.57 + auto str = ""; 35.58 + 35.59 + auto str_key = cx_hash_key_str(str); 35.60 + auto bytes_key = cx_hash_key_bytes( 35.61 + reinterpret_cast<unsigned char const *>(str), 0); 35.62 + auto obj_key = cx_hash_key( 35.63 + reinterpret_cast<void const *>(str), 0); 35.64 + 35.65 + EXPECT_EQ(bytes_key.hash, 4152238450u); 35.66 + EXPECT_EQ(str_key.hash, 4152238450u); 35.67 + EXPECT_EQ(obj_key.hash, 4152238450u); 35.68 + EXPECT_EQ(str_key.len, 0); 35.69 + EXPECT_EQ(bytes_key.len, 0); 35.70 + EXPECT_EQ(bytes_key.len, 0); 35.71 + EXPECT_EQ(str_key.data.cstr, str); 35.72 + EXPECT_EQ(bytes_key.data.cbytes, reinterpret_cast<unsigned char const *>(str)); 35.73 + EXPECT_EQ(bytes_key.data.cobj, reinterpret_cast<void const *>(str)); 35.74 +} 35.75 + 35.76 +TEST(cx_hash_key, null_ptr) { 35.77 + auto str_key = cx_hash_key_str(nullptr); 35.78 + auto bytes_key = cx_hash_key_bytes(nullptr, 0); 35.79 + auto obj_key = cx_hash_key(nullptr, 0); 35.80 + 35.81 + EXPECT_EQ(bytes_key.hash, 1574210520u); 35.82 + EXPECT_EQ(str_key.hash, 1574210520u); 35.83 + EXPECT_EQ(obj_key.hash, 1574210520u); 35.84 + EXPECT_EQ(str_key.len, 0); 35.85 + EXPECT_EQ(bytes_key.len, 0); 35.86 + EXPECT_EQ(bytes_key.len, 0); 35.87 + EXPECT_EQ(str_key.data.cstr, nullptr); 35.88 + EXPECT_EQ(bytes_key.data.cbytes, nullptr); 35.89 + EXPECT_EQ(bytes_key.data.cobj, nullptr); 35.90 +}
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 36.2 +++ b/tests/test_list.cpp Wed Feb 08 20:26:26 2023 +0100 36.3 @@ -0,0 +1,1159 @@ 36.4 +/* 36.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 36.6 + * 36.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 36.8 + * 36.9 + * Redistribution and use in source and binary forms, with or without 36.10 + * modification, are permitted provided that the following conditions are met: 36.11 + * 36.12 + * 1. Redistributions of source code must retain the above copyright 36.13 + * notice, this list of conditions and the following disclaimer. 36.14 + * 36.15 + * 2. Redistributions in binary form must reproduce the above copyright 36.16 + * notice, this list of conditions and the following disclaimer in the 36.17 + * documentation and/or other materials provided with the distribution. 36.18 + * 36.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 36.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 36.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 36.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 36.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 36.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 36.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 36.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 36.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36.29 + * POSSIBILITY OF SUCH DAMAGE. 36.30 + */ 36.31 + 36.32 +#include "cx/linked_list.h" 36.33 +#include "cx/array_list.h" 36.34 +#include "cx/utils.h" 36.35 +#include "cx/compare.h" 36.36 +#include "util_allocator.h" 36.37 + 36.38 +#include <gtest/gtest.h> 36.39 +#include <array> 36.40 +#include <vector> 36.41 +#include <unordered_set> 36.42 +#include <algorithm> 36.43 + 36.44 +struct node { 36.45 + node *next = nullptr; 36.46 + node *prev = nullptr; 36.47 + int data = 0; 36.48 +}; 36.49 + 36.50 +const ptrdiff_t loc_prev = offsetof(struct node, prev); 36.51 +const ptrdiff_t loc_next = offsetof(struct node, next); 36.52 +const ptrdiff_t loc_data = offsetof(struct node, data); 36.53 + 36.54 +struct node_test_data { 36.55 + node *begin = nullptr; 36.56 + 36.57 + explicit node_test_data(node *begin) : begin(begin) { 36.58 + auto n = begin; 36.59 + while (n != nullptr) { 36.60 + nodes.push_back(n); 36.61 + n = n->next; 36.62 + } 36.63 + } 36.64 + 36.65 + node_test_data(node_test_data &) = delete; 36.66 + 36.67 + node_test_data(node_test_data &&) = default; 36.68 + 36.69 + ~node_test_data() { 36.70 + for (auto &&n: nodes) delete n; 36.71 + } 36.72 + 36.73 +private: 36.74 + std::vector<node *> nodes; 36.75 +}; 36.76 + 36.77 +static node_test_data create_nodes_test_data(size_t len) { 36.78 + if (len == 0) return node_test_data{nullptr}; 36.79 + auto begin = new node; 36.80 + auto prev = begin; 36.81 + for (size_t i = 1; i < len; i++) { 36.82 + auto n = new node; 36.83 + cx_linked_list_link(prev, n, loc_prev, loc_next); 36.84 + prev = n; 36.85 + } 36.86 + return node_test_data{begin}; 36.87 +} 36.88 + 36.89 +template<typename InputIter> 36.90 +static node_test_data create_nodes_test_data( 36.91 + InputIter begin, 36.92 + InputIter end 36.93 +) { 36.94 + if (begin == end) return node_test_data{nullptr}; 36.95 + node *first = new node; 36.96 + first->data = *begin; 36.97 + node *prev = first; 36.98 + begin++; 36.99 + for (; begin != end; begin++) { 36.100 + auto n = new node; 36.101 + n->data = *begin; 36.102 + cx_linked_list_link(prev, n, loc_prev, loc_next); 36.103 + prev = n; 36.104 + } 36.105 + return node_test_data{first}; 36.106 +} 36.107 + 36.108 +static node_test_data create_nodes_test_data(std::initializer_list<int> data) { 36.109 + return create_nodes_test_data(data.begin(), data.end()); 36.110 +} 36.111 + 36.112 +template<size_t N> 36.113 +struct int_test_data { 36.114 + std::array<int, N> data; 36.115 + 36.116 + int_test_data() { 36.117 + cx_for_n (i, N) data[i] = ::rand(); // NOLINT(cert-msc50-cpp) 36.118 + } 36.119 +}; 36.120 + 36.121 +TEST(LinkedList_LowLevel, link_unlink) { 36.122 + node a, b, c; 36.123 + 36.124 + cx_linked_list_link(&a, &b, loc_prev, loc_next); 36.125 + EXPECT_EQ(a.prev, nullptr); 36.126 + EXPECT_EQ(a.next, &b); 36.127 + EXPECT_EQ(b.prev, &a); 36.128 + EXPECT_EQ(b.next, nullptr); 36.129 + 36.130 + cx_linked_list_unlink(&a, &b, loc_prev, loc_next); 36.131 + EXPECT_EQ(a.prev, nullptr); 36.132 + EXPECT_EQ(a.next, nullptr); 36.133 + EXPECT_EQ(b.prev, nullptr); 36.134 + EXPECT_EQ(b.next, nullptr); 36.135 + 36.136 + cx_linked_list_link(&b, &c, loc_prev, loc_next); 36.137 + cx_linked_list_link(&a, &b, loc_prev, loc_next); 36.138 + cx_linked_list_unlink(&b, &c, loc_prev, loc_next); 36.139 + EXPECT_EQ(a.prev, nullptr); 36.140 + EXPECT_EQ(a.next, &b); 36.141 + EXPECT_EQ(b.prev, &a); 36.142 + EXPECT_EQ(b.next, nullptr); 36.143 + EXPECT_EQ(c.prev, nullptr); 36.144 + EXPECT_EQ(c.next, nullptr); 36.145 +} 36.146 + 36.147 +TEST(LinkedList_LowLevel, cx_linked_list_at) { 36.148 + node a, b, c, d; 36.149 + cx_linked_list_link(&a, &b, loc_prev, loc_next); 36.150 + cx_linked_list_link(&b, &c, loc_prev, loc_next); 36.151 + cx_linked_list_link(&c, &d, loc_prev, loc_next); 36.152 + 36.153 + EXPECT_EQ(cx_linked_list_at(&a, 0, loc_next, 0), &a); 36.154 + EXPECT_EQ(cx_linked_list_at(&a, 0, loc_next, 1), &b); 36.155 + EXPECT_EQ(cx_linked_list_at(&a, 0, loc_next, 2), &c); 36.156 + EXPECT_EQ(cx_linked_list_at(&a, 0, loc_next, 3), &d); 36.157 + EXPECT_EQ(cx_linked_list_at(&a, 0, loc_next, 4), nullptr); 36.158 + 36.159 + EXPECT_EQ(cx_linked_list_at(&b, 1, loc_prev, 0), &a); 36.160 + EXPECT_EQ(cx_linked_list_at(&b, 1, loc_next, 1), &b); 36.161 + EXPECT_EQ(cx_linked_list_at(&b, 1, loc_next, 2), &c); 36.162 + EXPECT_EQ(cx_linked_list_at(&b, 1, loc_next, 3), &d); 36.163 + EXPECT_EQ(cx_linked_list_at(&b, 1, loc_next, 4), nullptr); 36.164 + 36.165 + EXPECT_EQ(cx_linked_list_at(&d, 3, loc_prev, 0), &a); 36.166 + EXPECT_EQ(cx_linked_list_at(&d, 3, loc_prev, 1), &b); 36.167 +} 36.168 + 36.169 +TEST(LinkedList_LowLevel, cx_linked_list_find) { 36.170 + auto testdata = create_nodes_test_data({2, 4, 6, 8}); 36.171 + auto list = testdata.begin; 36.172 + int s; 36.173 + 36.174 + s = 2; 36.175 + EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 0); 36.176 + s = 4; 36.177 + EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 1); 36.178 + s = 6; 36.179 + EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 2); 36.180 + s = 8; 36.181 + EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 3); 36.182 + s = 10; 36.183 + EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 4); 36.184 + s = -2; 36.185 + EXPECT_EQ(cx_linked_list_find(list, loc_next, loc_data, cx_cmp_int, &s), 4); 36.186 +} 36.187 + 36.188 +TEST(LinkedList_LowLevel, cx_linked_list_compare) { 36.189 + auto ta = create_nodes_test_data({2, 4, 6, 8}); 36.190 + auto tb = create_nodes_test_data({2, 4, 6}); 36.191 + auto tc = create_nodes_test_data({2, 4, 6, 9}); 36.192 + auto la = ta.begin, lb = tb.begin, lc = tc.begin; 36.193 + 36.194 + EXPECT_GT(cx_linked_list_compare(la, lb, loc_next, loc_data, cx_cmp_int), 0); 36.195 + EXPECT_LT(cx_linked_list_compare(lb, la, loc_next, loc_data, cx_cmp_int), 0); 36.196 + EXPECT_GT(cx_linked_list_compare(lc, la, loc_next, loc_data, cx_cmp_int), 0); 36.197 + EXPECT_LT(cx_linked_list_compare(la, lc, loc_next, loc_data, cx_cmp_int), 0); 36.198 + EXPECT_EQ(cx_linked_list_compare(la, la, loc_next, loc_data, cx_cmp_int), 0); 36.199 +} 36.200 + 36.201 +TEST(LinkedList_LowLevel, cx_linked_list_add) { 36.202 + // test with begin, end / prev, next 36.203 + { 36.204 + node nodes[4]; 36.205 + void *begin = nullptr, *end = nullptr; 36.206 + 36.207 + cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[0]); 36.208 + EXPECT_EQ(begin, &nodes[0]); 36.209 + EXPECT_EQ(end, &nodes[0]); 36.210 + EXPECT_EQ(nodes[0].prev, nullptr); 36.211 + EXPECT_EQ(nodes[0].next, nullptr); 36.212 + 36.213 + cx_linked_list_add(&begin, &end, loc_prev, loc_next, &nodes[1]); 36.214 + EXPECT_EQ(begin, &nodes[0]); 36.215 + EXPECT_EQ(end, &nodes[1]); 36.216 + EXPECT_EQ(nodes[0].next, &nodes[1]); 36.217 + EXPECT_EQ(nodes[1].prev, &nodes[0]); 36.218 + } 36.219 + 36.220 + // test with begin only / prev, next 36.221 + { 36.222 + node nodes[4]; 36.223 + void *begin = nullptr; 36.224 + 36.225 + cx_linked_list_add(&begin, nullptr, loc_prev, loc_next, &nodes[0]); 36.226 + EXPECT_EQ(begin, &nodes[0]); 36.227 + cx_linked_list_add(&begin, nullptr, loc_prev, loc_next, &nodes[1]); 36.228 + EXPECT_EQ(begin, &nodes[0]); 36.229 + EXPECT_EQ(nodes[0].next, &nodes[1]); 36.230 + EXPECT_EQ(nodes[1].prev, &nodes[0]); 36.231 + 36.232 + cx_linked_list_add(&begin, nullptr, loc_prev, loc_next, &nodes[2]); 36.233 + EXPECT_EQ(nodes[1].next, &nodes[2]); 36.234 + EXPECT_EQ(nodes[2].prev, &nodes[1]); 36.235 + } 36.236 + 36.237 + // test with end only / prev, next 36.238 + { 36.239 + node nodes[4]; 36.240 + void *end = nullptr; 36.241 + 36.242 + cx_linked_list_add(nullptr, &end, loc_prev, loc_next, &nodes[0]); 36.243 + EXPECT_EQ(end, &nodes[0]); 36.244 + cx_linked_list_add(nullptr, &end, loc_prev, loc_next, &nodes[1]); 36.245 + EXPECT_EQ(end, &nodes[1]); 36.246 + EXPECT_EQ(nodes[0].next, &nodes[1]); 36.247 + EXPECT_EQ(nodes[1].prev, &nodes[0]); 36.248 + 36.249 + cx_linked_list_add(nullptr, &end, loc_prev, loc_next, &nodes[2]); 36.250 + EXPECT_EQ(end, &nodes[2]); 36.251 + EXPECT_EQ(nodes[1].next, &nodes[2]); 36.252 + EXPECT_EQ(nodes[2].prev, &nodes[1]); 36.253 + } 36.254 + 36.255 + // test with begin, end / next 36.256 + { 36.257 + node nodes[4]; 36.258 + void *begin = nullptr, *end = nullptr; 36.259 + 36.260 + cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[0]); 36.261 + EXPECT_EQ(begin, &nodes[0]); 36.262 + EXPECT_EQ(end, &nodes[0]); 36.263 + cx_linked_list_add(&begin, &end, -1, loc_next, &nodes[1]); 36.264 + EXPECT_EQ(end, &nodes[1]); 36.265 + EXPECT_EQ(nodes[0].next, &nodes[1]); 36.266 + EXPECT_EQ(nodes[1].prev, nullptr); 36.267 + } 36.268 +} 36.269 + 36.270 +TEST(LinkedList_LowLevel, cx_linked_list_prepend) { 36.271 + // test with begin, end / prev, next 36.272 + { 36.273 + node nodes[4]; 36.274 + void *begin = nullptr, *end = nullptr; 36.275 + 36.276 + cx_linked_list_prepend(&begin, &end, loc_prev, loc_next, &nodes[0]); 36.277 + EXPECT_EQ(begin, &nodes[0]); 36.278 + EXPECT_EQ(end, &nodes[0]); 36.279 + EXPECT_EQ(nodes[0].prev, nullptr); 36.280 + EXPECT_EQ(nodes[0].next, nullptr); 36.281 + 36.282 + cx_linked_list_prepend(&begin, &end, loc_prev, loc_next, &nodes[1]); 36.283 + EXPECT_EQ(begin, &nodes[1]); 36.284 + EXPECT_EQ(end, &nodes[0]); 36.285 + EXPECT_EQ(nodes[1].next, &nodes[0]); 36.286 + EXPECT_EQ(nodes[0].prev, &nodes[1]); 36.287 + } 36.288 + 36.289 + // test with begin only / prev, next 36.290 + { 36.291 + node nodes[4]; 36.292 + void *begin = nullptr; 36.293 + 36.294 + cx_linked_list_prepend(&begin, nullptr, loc_prev, loc_next, &nodes[0]); 36.295 + EXPECT_EQ(begin, &nodes[0]); 36.296 + cx_linked_list_prepend(&begin, nullptr, loc_prev, loc_next, &nodes[1]); 36.297 + EXPECT_EQ(begin, &nodes[1]); 36.298 + EXPECT_EQ(nodes[1].next, &nodes[0]); 36.299 + EXPECT_EQ(nodes[0].prev, &nodes[1]); 36.300 + 36.301 + cx_linked_list_prepend(&begin, nullptr, loc_prev, loc_next, &nodes[2]); 36.302 + EXPECT_EQ(begin, &nodes[2]); 36.303 + EXPECT_EQ(nodes[2].next, &nodes[1]); 36.304 + EXPECT_EQ(nodes[1].prev, &nodes[2]); 36.305 + } 36.306 + 36.307 + // test with end only / prev, next 36.308 + { 36.309 + node nodes[4]; 36.310 + void *end = nullptr; 36.311 + 36.312 + cx_linked_list_prepend(nullptr, &end, loc_prev, loc_next, &nodes[0]); 36.313 + EXPECT_EQ(end, &nodes[0]); 36.314 + cx_linked_list_prepend(nullptr, &end, loc_prev, loc_next, &nodes[1]); 36.315 + EXPECT_EQ(end, &nodes[0]); 36.316 + EXPECT_EQ(nodes[1].next, &nodes[0]); 36.317 + EXPECT_EQ(nodes[0].prev, &nodes[1]); 36.318 + 36.319 + cx_linked_list_prepend(nullptr, &end, loc_prev, loc_next, &nodes[2]); 36.320 + EXPECT_EQ(end, &nodes[0]); 36.321 + EXPECT_EQ(nodes[2].next, &nodes[1]); 36.322 + EXPECT_EQ(nodes[1].prev, &nodes[2]); 36.323 + } 36.324 + 36.325 + // test with begin, end / next 36.326 + { 36.327 + node nodes[4]; 36.328 + void *begin = nullptr, *end = nullptr; 36.329 + 36.330 + cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[0]); 36.331 + EXPECT_EQ(begin, &nodes[0]); 36.332 + EXPECT_EQ(end, &nodes[0]); 36.333 + cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[1]); 36.334 + cx_linked_list_prepend(&begin, &end, -1, loc_next, &nodes[2]); 36.335 + EXPECT_EQ(begin, &nodes[2]); 36.336 + EXPECT_EQ(end, &nodes[0]); 36.337 + EXPECT_EQ(nodes[1].next, &nodes[0]); 36.338 + EXPECT_EQ(nodes[2].next, &nodes[1]); 36.339 + EXPECT_EQ(nodes[1].prev, nullptr); 36.340 + EXPECT_EQ(nodes[0].prev, nullptr); 36.341 + } 36.342 +} 36.343 + 36.344 +TEST(LinkedList_LowLevel, cx_linked_list_insert) { 36.345 + // insert mid list 36.346 + { 36.347 + node nodes[4]; 36.348 + void *begin = &nodes[0], *end = &nodes[2]; 36.349 + 36.350 + cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 36.351 + cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 36.352 + 36.353 + cx_linked_list_insert(&begin, &end, loc_prev, loc_next, &nodes[1], &nodes[3]); 36.354 + EXPECT_EQ(begin, &nodes[0]); 36.355 + EXPECT_EQ(end, &nodes[2]); 36.356 + EXPECT_EQ(nodes[1].next, &nodes[3]); 36.357 + EXPECT_EQ(nodes[2].prev, &nodes[3]); 36.358 + EXPECT_EQ(nodes[3].prev, &nodes[1]); 36.359 + EXPECT_EQ(nodes[3].next, &nodes[2]); 36.360 + } 36.361 + 36.362 + // insert end 36.363 + { 36.364 + node nodes[4]; 36.365 + void *begin = &nodes[0], *end = &nodes[2]; 36.366 + 36.367 + cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 36.368 + cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 36.369 + 36.370 + cx_linked_list_insert(&begin, &end, loc_prev, loc_next, &nodes[2], &nodes[3]); 36.371 + EXPECT_EQ(begin, &nodes[0]); 36.372 + EXPECT_EQ(end, &nodes[3]); 36.373 + EXPECT_EQ(nodes[2].next, &nodes[3]); 36.374 + EXPECT_EQ(nodes[3].prev, &nodes[2]); 36.375 + EXPECT_EQ(nodes[3].next, nullptr); 36.376 + } 36.377 + 36.378 + // insert begin 36.379 + { 36.380 + node nodes[4]; 36.381 + void *begin = &nodes[0], *end = &nodes[2]; 36.382 + 36.383 + cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 36.384 + cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 36.385 + 36.386 + cx_linked_list_insert(&begin, &end, loc_prev, loc_next, nullptr, &nodes[3]); 36.387 + EXPECT_EQ(begin, &nodes[3]); 36.388 + EXPECT_EQ(end, &nodes[2]); 36.389 + EXPECT_EQ(nodes[0].prev, &nodes[3]); 36.390 + EXPECT_EQ(nodes[3].prev, nullptr); 36.391 + EXPECT_EQ(nodes[3].next, &nodes[0]); 36.392 + } 36.393 +} 36.394 + 36.395 +TEST(LinkedList_LowLevel, cx_linked_list_insert_chain) { 36.396 + // insert mid list 36.397 + { 36.398 + node nodes[5]; 36.399 + void *begin = &nodes[0], *end = &nodes[2]; 36.400 + 36.401 + cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 36.402 + cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 36.403 + cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); 36.404 + 36.405 + cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, &nodes[1], &nodes[3], nullptr); 36.406 + EXPECT_EQ(begin, &nodes[0]); 36.407 + EXPECT_EQ(end, &nodes[2]); 36.408 + EXPECT_EQ(nodes[1].next, &nodes[3]); 36.409 + EXPECT_EQ(nodes[2].prev, &nodes[4]); 36.410 + EXPECT_EQ(nodes[3].prev, &nodes[1]); 36.411 + EXPECT_EQ(nodes[4].next, &nodes[2]); 36.412 + } 36.413 + 36.414 + // insert end 36.415 + { 36.416 + node nodes[5]; 36.417 + void *begin = &nodes[0], *end = &nodes[2]; 36.418 + 36.419 + cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 36.420 + cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 36.421 + cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); 36.422 + 36.423 + cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, &nodes[2], &nodes[3], nullptr); 36.424 + EXPECT_EQ(begin, &nodes[0]); 36.425 + EXPECT_EQ(end, &nodes[4]); 36.426 + EXPECT_EQ(nodes[2].next, &nodes[3]); 36.427 + EXPECT_EQ(nodes[3].prev, &nodes[2]); 36.428 + EXPECT_EQ(nodes[4].next, nullptr); 36.429 + } 36.430 + 36.431 + // insert begin 36.432 + { 36.433 + node nodes[5]; 36.434 + void *begin = &nodes[0], *end = &nodes[2]; 36.435 + 36.436 + cx_linked_list_link(&nodes[0], &nodes[1], loc_prev, loc_next); 36.437 + cx_linked_list_link(&nodes[1], &nodes[2], loc_prev, loc_next); 36.438 + cx_linked_list_link(&nodes[3], &nodes[4], loc_prev, loc_next); 36.439 + 36.440 + cx_linked_list_insert_chain(&begin, &end, loc_prev, loc_next, nullptr, &nodes[3], nullptr); 36.441 + EXPECT_EQ(begin, &nodes[3]); 36.442 + EXPECT_EQ(end, &nodes[2]); 36.443 + EXPECT_EQ(nodes[0].prev, &nodes[4]); 36.444 + EXPECT_EQ(nodes[3].prev, nullptr); 36.445 + EXPECT_EQ(nodes[4].next, &nodes[0]); 36.446 + } 36.447 +} 36.448 + 36.449 +TEST(LinkedList_LowLevel, cx_linked_list_first) { 36.450 + auto testdata = create_nodes_test_data(3); 36.451 + auto begin = testdata.begin; 36.452 + EXPECT_EQ(cx_linked_list_first(begin, loc_prev), begin); 36.453 + EXPECT_EQ(cx_linked_list_first(begin->next, loc_prev), begin); 36.454 + EXPECT_EQ(cx_linked_list_first(begin->next->next, loc_prev), begin); 36.455 +} 36.456 + 36.457 +TEST(LinkedList_LowLevel, cx_linked_list_last) { 36.458 + auto testdata = create_nodes_test_data(3); 36.459 + auto begin = testdata.begin; 36.460 + auto end = begin->next->next; 36.461 + EXPECT_EQ(cx_linked_list_last(begin, loc_next), end); 36.462 + EXPECT_EQ(cx_linked_list_last(begin->next, loc_next), end); 36.463 + EXPECT_EQ(cx_linked_list_last(begin->next->next, loc_next), end); 36.464 +} 36.465 + 36.466 +TEST(LinkedList_LowLevel, cx_linked_list_prev) { 36.467 + auto testdata = create_nodes_test_data(3); 36.468 + auto begin = testdata.begin; 36.469 + EXPECT_EQ(cx_linked_list_prev(begin, loc_next, begin), nullptr); 36.470 + EXPECT_EQ(cx_linked_list_prev(begin, loc_next, begin->next), begin); 36.471 + EXPECT_EQ(cx_linked_list_prev(begin, loc_next, begin->next->next), begin->next); 36.472 +} 36.473 + 36.474 +TEST(LinkedList_LowLevel, cx_linked_list_remove) { 36.475 + auto testdata = create_nodes_test_data({2, 4, 6}); 36.476 + auto begin = reinterpret_cast<void *>(testdata.begin); 36.477 + auto first = testdata.begin; 36.478 + auto second = first->next; 36.479 + auto third = second->next; 36.480 + auto end = reinterpret_cast<void *>(third); 36.481 + 36.482 + cx_linked_list_remove(&begin, &end, loc_prev, loc_next, second); 36.483 + EXPECT_EQ(begin, first); 36.484 + EXPECT_EQ(end, third); 36.485 + EXPECT_EQ(first->prev, nullptr); 36.486 + EXPECT_EQ(first->next, third); 36.487 + EXPECT_EQ(third->prev, first); 36.488 + EXPECT_EQ(third->next, nullptr); 36.489 + 36.490 + cx_linked_list_remove(&begin, &end, loc_prev, loc_next, third); 36.491 + EXPECT_EQ(begin, first); 36.492 + EXPECT_EQ(end, first); 36.493 + EXPECT_EQ(first->prev, nullptr); 36.494 + EXPECT_EQ(first->next, nullptr); 36.495 + 36.496 + cx_linked_list_remove(&begin, &end, loc_prev, loc_next, first); 36.497 + EXPECT_EQ(begin, nullptr); 36.498 + EXPECT_EQ(end, nullptr); 36.499 +} 36.500 + 36.501 +TEST(LinkedList_LowLevel, cx_linked_list_size) { 36.502 + EXPECT_EQ(cx_linked_list_size(nullptr, loc_next), 0); 36.503 + 36.504 + { 36.505 + auto testdata = create_nodes_test_data(5); 36.506 + EXPECT_EQ(cx_linked_list_size(testdata.begin, loc_next), 5); 36.507 + } 36.508 + 36.509 + { 36.510 + auto testdata = create_nodes_test_data(13); 36.511 + EXPECT_EQ(cx_linked_list_size(testdata.begin, loc_next), 13); 36.512 + } 36.513 +} 36.514 + 36.515 +TEST(LinkedList_LowLevel, cx_linked_list_sort) { 36.516 + int_test_data<1500> testdata; 36.517 + std::array<int, 1500> sorted{}; 36.518 + std::partial_sort_copy(testdata.data.begin(), testdata.data.end(), sorted.begin(), sorted.end()); 36.519 + 36.520 + auto scrambled = create_nodes_test_data(testdata.data.begin(), testdata.data.end()); 36.521 + void *begin = scrambled.begin; 36.522 + void *end = cx_linked_list_last(begin, loc_next); 36.523 + 36.524 + cx_linked_list_sort(&begin, &end, loc_prev, loc_next, loc_data, cx_cmp_int); 36.525 + 36.526 + node *check = reinterpret_cast<node *>(begin); 36.527 + node *check_last = nullptr; 36.528 + cx_for_n (i, sorted.size()) { 36.529 + EXPECT_EQ(check->data, sorted[i]); 36.530 + EXPECT_EQ(check->prev, check_last); 36.531 + if (i < sorted.size() - 1) { 36.532 + ASSERT_NE(check->next, nullptr); 36.533 + } 36.534 + check_last = check; 36.535 + check = check->next; 36.536 + } 36.537 + EXPECT_EQ(check, nullptr); 36.538 + EXPECT_EQ(end, check_last); 36.539 +} 36.540 + 36.541 +TEST(LinkedList_LowLevel, cx_linked_list_reverse) { 36.542 + auto testdata = create_nodes_test_data({2, 4, 6, 8}); 36.543 + auto expected = create_nodes_test_data({8, 6, 4, 2}); 36.544 + 36.545 + auto begin = reinterpret_cast<void *>(testdata.begin); 36.546 + auto end = cx_linked_list_last(begin, loc_next); 36.547 + auto orig_begin = begin, orig_end = end; 36.548 + 36.549 + cx_linked_list_reverse(&begin, &end, loc_prev, loc_next); 36.550 + EXPECT_EQ(end, orig_begin); 36.551 + EXPECT_EQ(begin, orig_end); 36.552 + EXPECT_EQ(cx_linked_list_compare(begin, expected.begin, loc_next, loc_data, cx_cmp_int), 0); 36.553 +} 36.554 + 36.555 +class HighLevelTest : public ::testing::Test { 36.556 + mutable std::unordered_set<CxList *> lists; 36.557 +protected: 36.558 + CxTestingAllocator testingAllocator; 36.559 + 36.560 + void TearDown() override { 36.561 + for (auto &&l: lists) cxListDestroy(l); 36.562 + EXPECT_TRUE(testingAllocator.verify()); 36.563 + } 36.564 + 36.565 + static constexpr size_t testdata_len = 250; 36.566 + int_test_data<testdata_len> testdata; 36.567 + 36.568 + auto autofree(CxList *list) const -> CxList * { 36.569 + if (list != nullptr) lists.insert(list); 36.570 + return list; 36.571 + } 36.572 + 36.573 + auto linkedListFromTestData() const -> CxList * { 36.574 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 36.575 + cxListAddArray(list, testdata.data.data(), testdata_len); 36.576 + return list; 36.577 + } 36.578 + 36.579 + auto pointerLinkedListFromTestData() const -> CxList * { 36.580 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 36.581 + cxListStorePointers(list); 36.582 + // note: cannot use cxListAddArray() because we don't have a list of pointers 36.583 + cx_for_n(i, testdata_len) cxListAdd(list, &testdata.data[i]); 36.584 + return list; 36.585 + } 36.586 + 36.587 + auto arrayListFromTestData() const -> CxList * { 36.588 + auto list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), testdata_len)); 36.589 + cxListAddArray(list, testdata.data.data(), testdata_len); 36.590 + return list; 36.591 + } 36.592 + 36.593 + void verifyCreate(CxList *list) const { 36.594 + EXPECT_EQ(list->content_destructor_type, CX_DESTRUCTOR_NONE); 36.595 + EXPECT_EQ(list->size, 0); 36.596 + EXPECT_EQ(list->allocator, &testingAllocator); 36.597 + EXPECT_EQ(list->cmpfunc, cx_cmp_int); 36.598 + } 36.599 + 36.600 + void verifyAdd( 36.601 + CxList *list, 36.602 + bool as_pointer 36.603 + ) { 36.604 + auto len = testdata_len; 36.605 + cx_for_n (i, len) EXPECT_EQ(cxListAdd(list, &testdata.data[i]), 0); 36.606 + EXPECT_EQ(list->size, len); 36.607 + EXPECT_GE(list->capacity, list->size); 36.608 + cx_for_n (i, len) EXPECT_EQ(*(int *) cxListAt(list, i), testdata.data[i]); 36.609 + cx_for_n (i, len) ++testdata.data[i]; 36.610 + if (as_pointer) { 36.611 + cx_for_n (i, len) EXPECT_EQ(*(int *) cxListAt(list, i), testdata.data[i]); 36.612 + } else { 36.613 + cx_for_n (i, len) EXPECT_EQ(*(int *) cxListAt(list, i), testdata.data[i] - 1); 36.614 + } 36.615 + } 36.616 + 36.617 + static void verifyInsert(CxList *list) { 36.618 + int a = 5, b = 47, c = 13, d = 42; 36.619 + 36.620 + EXPECT_NE(cxListInsert(list, 1, &a), 0); 36.621 + EXPECT_EQ(list->size, 0); 36.622 + EXPECT_EQ(cxListInsert(list, 0, &a), 0); 36.623 + EXPECT_EQ(list->size, 1); 36.624 + EXPECT_EQ(cxListInsert(list, 0, &b), 0); 36.625 + EXPECT_EQ(list->size, 2); 36.626 + EXPECT_EQ(cxListInsert(list, 1, &c), 0); 36.627 + EXPECT_EQ(list->size, 3); 36.628 + EXPECT_EQ(cxListInsert(list, 3, &d), 0); 36.629 + 36.630 + ASSERT_EQ(list->size, 4); 36.631 + EXPECT_GE(list->capacity, list->size); 36.632 + 36.633 + EXPECT_EQ(*(int *) cxListAt(list, 0), 47); 36.634 + EXPECT_EQ(*(int *) cxListAt(list, 1), 13); 36.635 + EXPECT_EQ(*(int *) cxListAt(list, 2), 5); 36.636 + EXPECT_EQ(*(int *) cxListAt(list, 3), 42); 36.637 + } 36.638 + 36.639 + static void verifyInsertArray( 36.640 + CxList *list, 36.641 + bool pointers = false 36.642 + ) { 36.643 + int a[5] = {5, 47, 11, 13, 42}; 36.644 + int b[5] = {9, 18, 72, 50, 7}; 36.645 + int *aptr[5]; 36.646 + int *bptr[5]; 36.647 + cx_for_n(i, 5) { 36.648 + aptr[i] = &a[i]; 36.649 + bptr[i] = &b[i]; 36.650 + } 36.651 + 36.652 + size_t inserted; 36.653 + 36.654 + if (pointers) { 36.655 + inserted = cxListInsertArray(list, 0, aptr, 5); 36.656 + } else { 36.657 + inserted = cxListInsertArray(list, 0, a, 5); 36.658 + } 36.659 + EXPECT_EQ(inserted, 5); 36.660 + EXPECT_EQ(*(int *) cxListAt(list, 0), 5); 36.661 + EXPECT_EQ(*(int *) cxListAt(list, 1), 47); 36.662 + EXPECT_EQ(*(int *) cxListAt(list, 2), 11); 36.663 + EXPECT_EQ(*(int *) cxListAt(list, 3), 13); 36.664 + EXPECT_EQ(*(int *) cxListAt(list, 4), 42); 36.665 + if (pointers) { 36.666 + inserted = cxListInsertArray(list, 3, bptr, 5); 36.667 + } else { 36.668 + inserted = cxListInsertArray(list, 3, b, 5); 36.669 + } 36.670 + EXPECT_EQ(inserted, 5); 36.671 + EXPECT_EQ(*(int *) cxListAt(list, 0), 5); 36.672 + EXPECT_EQ(*(int *) cxListAt(list, 1), 47); 36.673 + EXPECT_EQ(*(int *) cxListAt(list, 2), 11); 36.674 + EXPECT_EQ(*(int *) cxListAt(list, 3), 9); 36.675 + EXPECT_EQ(*(int *) cxListAt(list, 4), 18); 36.676 + EXPECT_EQ(*(int *) cxListAt(list, 5), 72); 36.677 + EXPECT_EQ(*(int *) cxListAt(list, 6), 50); 36.678 + EXPECT_EQ(*(int *) cxListAt(list, 7), 7); 36.679 + EXPECT_EQ(*(int *) cxListAt(list, 8), 13); 36.680 + EXPECT_EQ(*(int *) cxListAt(list, 9), 42); 36.681 + } 36.682 + 36.683 + void verifyRemove(CxList *list) const { 36.684 + EXPECT_EQ(cxListRemove(list, 2), 0); 36.685 + EXPECT_EQ(cxListRemove(list, 4), 0); 36.686 + EXPECT_EQ(list->size, testdata_len - 2); 36.687 + EXPECT_GE(list->capacity, list->size); 36.688 + EXPECT_EQ(*(int *) cxListAt(list, 0), testdata.data[0]); 36.689 + EXPECT_EQ(*(int *) cxListAt(list, 1), testdata.data[1]); 36.690 + EXPECT_EQ(*(int *) cxListAt(list, 2), testdata.data[3]); 36.691 + EXPECT_EQ(*(int *) cxListAt(list, 3), testdata.data[4]); 36.692 + EXPECT_EQ(*(int *) cxListAt(list, 4), testdata.data[6]); 36.693 + 36.694 + EXPECT_EQ(cxListRemove(list, 0), 0); 36.695 + EXPECT_EQ(list->size, testdata_len - 3); 36.696 + EXPECT_GE(list->capacity, list->size); 36.697 + EXPECT_EQ(*(int *) cxListAt(list, 0), testdata.data[1]); 36.698 + EXPECT_EQ(*(int *) cxListAt(list, 1), testdata.data[3]); 36.699 + 36.700 + EXPECT_NE(cxListRemove(list, testdata_len), 0); 36.701 + } 36.702 + 36.703 + static void verifySwap(CxList *list) { 36.704 + ASSERT_EQ(list->size, 0); 36.705 + 36.706 + int original[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; 36.707 + int swapped[16] = {8, 4, 14, 3, 1, 5, 9, 12, 0, 6, 11, 10, 7, 15, 2, 13}; 36.708 + 36.709 + // we have to add the items one by one, because it could be a pointer list 36.710 + cx_for_n(i, 16) { 36.711 + cxListAdd(list, &original[i]); 36.712 + } 36.713 + 36.714 + int result; 36.715 + 36.716 + // execute the test two times with different item sizes 36.717 + result = cxListSwap(list, 1, 4); 36.718 + EXPECT_EQ(0, result); 36.719 + result = cxListSwap(list, 2, 14); 36.720 + EXPECT_EQ(0, result); 36.721 + result = cxListSwap(list, 9, 6); 36.722 + EXPECT_EQ(0, result); 36.723 + result = cxListSwap(list, 3, 3); 36.724 + EXPECT_EQ(0, result); 36.725 + result = cxListSwap(list, 10, 11); 36.726 + EXPECT_EQ(0, result); 36.727 + result = cxListSwap(list, 8, 0); 36.728 + EXPECT_EQ(0, result); 36.729 + result = cxListSwap(list, 7, 12); 36.730 + EXPECT_EQ(0, result); 36.731 + result = cxListSwap(list, 13, 15); 36.732 + EXPECT_EQ(0, result); 36.733 + 36.734 + result = cxListSwap(list, 5, 16); 36.735 + EXPECT_NE(0, result); 36.736 + result = cxListSwap(list, 16, 6); 36.737 + EXPECT_NE(0, result); 36.738 + result = cxListSwap(list, 16, 17); 36.739 + EXPECT_NE(0, result); 36.740 + 36.741 + auto iter = cxListBegin(list); 36.742 + cx_foreach(int*, e, iter) { 36.743 + EXPECT_EQ(*e, swapped[iter.index]); 36.744 + } 36.745 + // TODO: replace with backward iterator 36.746 + cx_for_n(i, 16) { 36.747 + EXPECT_EQ(*((int *) cxListAt(list, i)), swapped[i]); 36.748 + } 36.749 + } 36.750 + 36.751 + void verifyAt(CxList *list) const { 36.752 + auto len = testdata_len; 36.753 + EXPECT_EQ(list->size, len); 36.754 + cx_for_n (i, len) { 36.755 + EXPECT_EQ(*(int *) cxListAt(list, i), testdata.data[i]); 36.756 + } 36.757 + EXPECT_EQ(cxListAt(list, list->size), nullptr); 36.758 + } 36.759 + 36.760 + void verifyFind(CxList *list) const { 36.761 + cx_for_n (attempt, 25) { 36.762 + size_t exp = rand() % testdata_len; // NOLINT(cert-msc50-cpp) 36.763 + int val = testdata.data[exp]; 36.764 + // randomly picked number could occur earlier in list - find first position 36.765 + cx_for_n (i, exp) { 36.766 + if (testdata.data[i] == val) { 36.767 + exp = i; 36.768 + break; 36.769 + } 36.770 + } 36.771 + EXPECT_EQ(cxListFind(list, &val), exp); 36.772 + } 36.773 + } 36.774 + 36.775 + void verifySort(CxList *list) const { 36.776 + std::array<int, testdata_len> expected{}; 36.777 + std::partial_sort_copy(testdata.data.begin(), testdata.data.end(), expected.begin(), expected.end()); 36.778 + cxListSort(list); 36.779 + cx_for_n (i, testdata_len) ASSERT_EQ(*(int *) cxListAt(list, i), expected[i]); 36.780 + } 36.781 + 36.782 + void verifyIterator(CxList *list) const { 36.783 + int i = 0; 36.784 + auto iter = cxListBeginMut(list); 36.785 + cx_foreach(int*, x, iter) { 36.786 + ASSERT_EQ(iter.index, (size_t) (i + 1) / 2); 36.787 + ASSERT_EQ(*x, testdata.data[i]); 36.788 + if (i % 2 == 1) cxIteratorFlagRemoval(iter); 36.789 + i++; 36.790 + } 36.791 + auto len = testdata_len; 36.792 + EXPECT_EQ(i, len); 36.793 + ASSERT_EQ(list->size, len / 2); 36.794 + cx_for_n(j, len / 2) ASSERT_EQ(*(int *) cxListAt(list, j), testdata.data[j * 2]); 36.795 + } 36.796 + 36.797 + static void verifyInsertViaIterator(CxList *list) { 36.798 + int newdata[] = {10, 20, 30, 40, 50}; 36.799 + 36.800 + auto iter = cxListMutIterator(list, 2); 36.801 + EXPECT_TRUE(cxIteratorValid(iter)); 36.802 + EXPECT_EQ(iter.index, 2); 36.803 + EXPECT_EQ(*(int *) cxIteratorCurrent(iter), 2); 36.804 + cxListInsertAfter(&iter, &newdata[0]); 36.805 + EXPECT_TRUE(cxIteratorValid(iter)); 36.806 + EXPECT_EQ(iter.index, 2); 36.807 + EXPECT_EQ(*(int *) cxIteratorCurrent(iter), 2); 36.808 + cxListInsertBefore(&iter, &newdata[1]); 36.809 + EXPECT_TRUE(cxIteratorValid(iter)); 36.810 + EXPECT_EQ(iter.index, 3); 36.811 + EXPECT_EQ(*(int *) cxIteratorCurrent(iter), 2); 36.812 + 36.813 + iter = cxListBeginMut(list); 36.814 + cxListInsertBefore(&iter, &newdata[2]); 36.815 + EXPECT_TRUE(cxIteratorValid(iter)); 36.816 + EXPECT_EQ(iter.index, 1); 36.817 + EXPECT_EQ(*(int *) cxIteratorCurrent(iter), 0); 36.818 + iter = cxListMutIterator(list, list->size); 36.819 + cxListInsertBefore(&iter, &newdata[3]); 36.820 + EXPECT_FALSE(cxIteratorValid(iter)); 36.821 + EXPECT_EQ(iter.index, 9); 36.822 + iter = cxListMutIterator(list, list->size); 36.823 + cxListInsertAfter(&iter, &newdata[4]); 36.824 + EXPECT_FALSE(cxIteratorValid(iter)); 36.825 + EXPECT_EQ(iter.index, 10); 36.826 + 36.827 + int expdata[] = {30, 0, 1, 20, 2, 10, 3, 4, 40, 50}; 36.828 + cx_for_n (j, 10) EXPECT_EQ(*(int *) cxListAt(list, j), expdata[j]); 36.829 + } 36.830 + 36.831 + void verifyReverse(CxList *list) const { 36.832 + cxListReverse(list); 36.833 + cx_for_n(i, testdata_len) { 36.834 + ASSERT_EQ(*(int *) cxListAt(list, i), testdata.data[testdata_len - 1 - i]); 36.835 + } 36.836 + } 36.837 + 36.838 + static void verifyCompare( 36.839 + CxList *left, 36.840 + CxList *right 36.841 + ) { 36.842 + EXPECT_EQ(cxListCompare(left, right), 0); 36.843 + int x = 42; 36.844 + cxListAdd(left, &x); 36.845 + ASSERT_GT(left->size, right->size); 36.846 + EXPECT_GT(cxListCompare(left, right), 0); 36.847 + EXPECT_LT(cxListCompare(right, left), 0); 36.848 + cxListAdd(right, &x); 36.849 + ASSERT_EQ(left->size, right->size); 36.850 + EXPECT_EQ(cxListCompare(left, right), 0); 36.851 + int a = 5, b = 10; 36.852 + cxListInsert(left, 15, &a); 36.853 + cxListInsert(right, 15, &b); 36.854 + ASSERT_EQ(left->size, right->size); 36.855 + EXPECT_LT(cxListCompare(left, right), 0); 36.856 + EXPECT_GT(cxListCompare(right, left), 0); 36.857 + *(int *) cxListAt(left, 15) = 10; 36.858 + EXPECT_EQ(cxListCompare(left, right), 0); 36.859 + } 36.860 +}; 36.861 + 36.862 +class LinkedList : public HighLevelTest { 36.863 +}; 36.864 + 36.865 +class PointerLinkedList : public HighLevelTest { 36.866 +}; 36.867 + 36.868 +class ArrayList : public HighLevelTest { 36.869 +}; 36.870 + 36.871 +TEST_F(PointerLinkedList, cxListStorePointers) { 36.872 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, 47)); 36.873 + EXPECT_FALSE(cxListIsStoringPointers(list)); 36.874 + cxListStorePointers(list); 36.875 + EXPECT_EQ(list->itemsize, sizeof(void *)); 36.876 + EXPECT_NE(list->cl, nullptr); 36.877 + EXPECT_NE(list->climpl, nullptr); 36.878 + EXPECT_TRUE(cxListIsStoringPointers(list)); 36.879 + cxListStoreObjects(list); 36.880 + EXPECT_NE(list->cl, nullptr); 36.881 + EXPECT_EQ(list->climpl, nullptr); 36.882 + EXPECT_FALSE(cxListIsStoringPointers(list)); 36.883 +} 36.884 + 36.885 +TEST_F(LinkedList, cxLinkedListCreate) { 36.886 + CxList *list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 36.887 + ASSERT_NE(list, nullptr); 36.888 + EXPECT_EQ(list->itemsize, sizeof(int)); 36.889 + EXPECT_EQ(list->capacity, (size_t) -1); 36.890 + verifyCreate(list); 36.891 +} 36.892 + 36.893 +TEST_F(ArrayList, cxArrayListCreate) { 36.894 + CxList *list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 8)); 36.895 + ASSERT_NE(list, nullptr); 36.896 + EXPECT_EQ(list->itemsize, sizeof(int)); 36.897 + EXPECT_EQ(list->capacity, 8); 36.898 + verifyCreate(list); 36.899 +} 36.900 + 36.901 +TEST_F(LinkedList, cxListAdd) { 36.902 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 36.903 + verifyAdd(list, false); 36.904 +} 36.905 + 36.906 +TEST_F(PointerLinkedList, cxListAdd) { 36.907 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 36.908 + cxListStorePointers(list); 36.909 + verifyAdd(list, true); 36.910 +} 36.911 + 36.912 +TEST_F(ArrayList, cxListAdd) { 36.913 + auto list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 8)); 36.914 + verifyAdd(list, false); 36.915 +} 36.916 + 36.917 +TEST_F(LinkedList, cxListInsert) { 36.918 + verifyInsert(autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)))); 36.919 +} 36.920 + 36.921 +TEST_F(PointerLinkedList, cxListInsert) { 36.922 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 36.923 + cxListStorePointers(list); 36.924 + verifyInsert(list); 36.925 +} 36.926 + 36.927 +TEST_F(ArrayList, cxListInsert) { 36.928 + verifyInsert(autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 2))); 36.929 +} 36.930 + 36.931 +TEST_F(LinkedList, cxListInsertArray) { 36.932 + verifyInsertArray(autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)))); 36.933 +} 36.934 + 36.935 +TEST_F(PointerLinkedList, cxListInsertArray) { 36.936 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 36.937 + cxListStorePointers(list); 36.938 + verifyInsertArray(list, true); 36.939 +} 36.940 + 36.941 +TEST_F(ArrayList, cxListInsertArray) { 36.942 + verifyInsertArray(autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 4))); 36.943 +} 36.944 + 36.945 +TEST_F(LinkedList, cxListRemove) { 36.946 + verifyRemove(linkedListFromTestData()); 36.947 +} 36.948 + 36.949 +TEST_F(PointerLinkedList, cxListRemove) { 36.950 + verifyRemove(pointerLinkedListFromTestData()); 36.951 +} 36.952 + 36.953 +TEST_F(ArrayList, cxListRemove) { 36.954 + verifyRemove(arrayListFromTestData()); 36.955 +} 36.956 + 36.957 +TEST_F(LinkedList, cxListSwap) { 36.958 + verifySwap(autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)))); 36.959 +} 36.960 + 36.961 +TEST_F(PointerLinkedList, cxListSwap) { 36.962 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 36.963 + cxListStorePointers(list); 36.964 + verifySwap(list); 36.965 +} 36.966 + 36.967 +TEST_F(ArrayList, cxListSwap) { 36.968 + verifySwap(autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 16))); 36.969 +} 36.970 + 36.971 +TEST_F(LinkedList, cxListSwapNoSBO) { 36.972 + CX_DISABLE_LINKED_LIST_SWAP_SBO = true; 36.973 + verifySwap(autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int)))); 36.974 + CX_DISABLE_LINKED_LIST_SWAP_SBO = false; 36.975 +} 36.976 + 36.977 +TEST_F(PointerLinkedList, cxListSwapNoSBO) { 36.978 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 36.979 + cxListStorePointers(list); 36.980 + CX_DISABLE_LINKED_LIST_SWAP_SBO = true; 36.981 + verifySwap(list); 36.982 + CX_DISABLE_LINKED_LIST_SWAP_SBO = false; 36.983 +} 36.984 + 36.985 +TEST_F(ArrayList, cxListSwapNoSBO) { 36.986 + CX_DISABLE_LINKED_LIST_SWAP_SBO = true; 36.987 + verifySwap(autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 16))); 36.988 + CX_DISABLE_LINKED_LIST_SWAP_SBO = false; 36.989 +} 36.990 + 36.991 +TEST_F(LinkedList, cxListAt) { 36.992 + verifyAt(linkedListFromTestData()); 36.993 +} 36.994 + 36.995 +TEST_F(PointerLinkedList, cxListAt) { 36.996 + verifyAt(pointerLinkedListFromTestData()); 36.997 +} 36.998 + 36.999 +TEST_F(ArrayList, cxListAt) { 36.1000 + verifyAt(arrayListFromTestData()); 36.1001 +} 36.1002 + 36.1003 +TEST_F(LinkedList, cxListFind) { 36.1004 + verifyFind(linkedListFromTestData()); 36.1005 +} 36.1006 + 36.1007 +TEST_F(PointerLinkedList, cxListFind) { 36.1008 + verifyFind(pointerLinkedListFromTestData()); 36.1009 +} 36.1010 + 36.1011 +TEST_F(ArrayList, cxListFind) { 36.1012 + verifyFind(arrayListFromTestData()); 36.1013 +} 36.1014 + 36.1015 +TEST_F(LinkedList, cxListSort) { 36.1016 + verifySort(linkedListFromTestData()); 36.1017 +} 36.1018 + 36.1019 +TEST_F(PointerLinkedList, cxListSort) { 36.1020 + verifySort(pointerLinkedListFromTestData()); 36.1021 +} 36.1022 + 36.1023 +TEST_F(ArrayList, cxListSort) { 36.1024 + verifySort(arrayListFromTestData()); 36.1025 +} 36.1026 + 36.1027 +TEST_F(LinkedList, Iterator) { 36.1028 + verifyIterator(linkedListFromTestData()); 36.1029 +} 36.1030 + 36.1031 +TEST_F(PointerLinkedList, Iterator) { 36.1032 + verifyIterator(pointerLinkedListFromTestData()); 36.1033 +} 36.1034 + 36.1035 +TEST_F(ArrayList, Iterator) { 36.1036 + verifyIterator(arrayListFromTestData()); 36.1037 +} 36.1038 + 36.1039 +TEST_F(LinkedList, InsertViaIterator) { 36.1040 + int fivenums[] = {0, 1, 2, 3, 4, 5}; 36.1041 + CxList *list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int))); 36.1042 + cxListAddArray(list, fivenums, 5); 36.1043 + verifyInsertViaIterator(list); 36.1044 +} 36.1045 + 36.1046 +TEST_F(PointerLinkedList, InsertViaIterator) { 36.1047 + int fivenums[] = {0, 1, 2, 3, 4, 5}; 36.1048 + auto list = autofree(cxLinkedListCreate(&testingAllocator, cx_cmp_int, sizeof(int *))); 36.1049 + cxListStorePointers(list); 36.1050 + // note: cannot use cxListAddArray() because we don't have a list of pointers 36.1051 + cx_for_n(i, 5) cxListAdd(list, &fivenums[i]); 36.1052 + verifyInsertViaIterator(list); 36.1053 +} 36.1054 + 36.1055 +TEST_F(ArrayList, InsertViaIterator) { 36.1056 + int fivenums[] = {0, 1, 2, 3, 4, 5}; 36.1057 + CxList *list = autofree(cxArrayListCreate(&testingAllocator, cx_cmp_int, sizeof(int), 4)); 36.1058 + cxListAddArray(list, fivenums, 5); 36.1059 + verifyInsertViaIterator(list); 36.1060 +} 36.1061 + 36.1062 +TEST_F(LinkedList, cxListReverse) { 36.1063 + verifyReverse(linkedListFromTestData()); 36.1064 +} 36.1065 + 36.1066 +TEST_F(PointerLinkedList, cxListReverse) { 36.1067 + verifyReverse(pointerLinkedListFromTestData()); 36.1068 +} 36.1069 + 36.1070 +TEST_F(ArrayList, cxListReverse) { 36.1071 + verifyReverse(arrayListFromTestData()); 36.1072 +} 36.1073 + 36.1074 +TEST_F(LinkedList, cxListCompare) { 36.1075 + auto left = linkedListFromTestData(); 36.1076 + auto right = linkedListFromTestData(); 36.1077 + verifyCompare(left, right); 36.1078 +} 36.1079 + 36.1080 +TEST_F(LinkedList, cxListCompareWithPtrList) { 36.1081 + auto left = linkedListFromTestData(); 36.1082 + auto right = pointerLinkedListFromTestData(); 36.1083 + verifyCompare(left, right); 36.1084 +} 36.1085 + 36.1086 +TEST_F(LinkedList, cxListCompareWithArrayList) { 36.1087 + auto left = linkedListFromTestData(); 36.1088 + auto right = arrayListFromTestData(); 36.1089 + verifyCompare(left, right); 36.1090 +} 36.1091 + 36.1092 +TEST_F(PointerLinkedList, cxListCompare) { 36.1093 + auto left = pointerLinkedListFromTestData(); 36.1094 + auto right = pointerLinkedListFromTestData(); 36.1095 + verifyCompare(left, right); 36.1096 +} 36.1097 + 36.1098 +TEST_F(PointerLinkedList, cxListCompareWithNormalList) { 36.1099 + auto left = pointerLinkedListFromTestData(); 36.1100 + auto right = linkedListFromTestData(); 36.1101 + verifyCompare(left, right); 36.1102 +} 36.1103 + 36.1104 +TEST_F(PointerLinkedList, cxListCompareWithArrayList) { 36.1105 + auto left = pointerLinkedListFromTestData(); 36.1106 + auto right = arrayListFromTestData(); 36.1107 + verifyCompare(left, right); 36.1108 +} 36.1109 + 36.1110 +TEST_F(ArrayList, cxListCompare) { 36.1111 + auto left = arrayListFromTestData(); 36.1112 + auto right = arrayListFromTestData(); 36.1113 + verifyCompare(left, right); 36.1114 +} 36.1115 + 36.1116 +TEST_F(ArrayList, cxListCompareWithPtrList) { 36.1117 + auto left = arrayListFromTestData(); 36.1118 + auto right = pointerLinkedListFromTestData(); 36.1119 + verifyCompare(left, right); 36.1120 +} 36.1121 + 36.1122 +TEST_F(ArrayList, cxListCompareWithNormalList) { 36.1123 + auto left = arrayListFromTestData(); 36.1124 + auto right = linkedListFromTestData(); 36.1125 + verifyCompare(left, right); 36.1126 +} 36.1127 + 36.1128 +TEST_F(PointerLinkedList, NoDestructor) { 36.1129 + void *item = cxMalloc(&testingAllocator, sizeof(int)); 36.1130 + auto list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int *)); 36.1131 + cxListStorePointers(list); 36.1132 + cxListAdd(list, item); 36.1133 + ASSERT_FALSE(testingAllocator.verify()); 36.1134 + cxListDestroy(list); 36.1135 + EXPECT_FALSE(testingAllocator.verify()); 36.1136 + cxFree(&testingAllocator, item); 36.1137 + EXPECT_TRUE(testingAllocator.verify()); 36.1138 +} 36.1139 + 36.1140 +TEST_F(PointerLinkedList, SimpleDestructor) { 36.1141 + int item = 0; 36.1142 + auto list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int *)); 36.1143 + cxListStorePointers(list); 36.1144 + list->content_destructor_type = CX_DESTRUCTOR_SIMPLE; 36.1145 + list->simple_destructor = [](void *elem) { *(int *) elem = 42; }; 36.1146 + cxListAdd(list, &item); 36.1147 + cxListDestroy(list); 36.1148 + EXPECT_EQ(item, 42); 36.1149 +} 36.1150 + 36.1151 +TEST_F(PointerLinkedList, AdvancedDestructor) { 36.1152 + void *item = cxMalloc(&testingAllocator, sizeof(int)); 36.1153 + auto list = cxLinkedListCreate(cxDefaultAllocator, cx_cmp_int, sizeof(int *)); 36.1154 + cxListStorePointers(list); 36.1155 + list->content_destructor_type = CX_DESTRUCTOR_ADVANCED; 36.1156 + list->advanced_destructor.data = &testingAllocator; 36.1157 + list->advanced_destructor.func = (cx_destructor_func2) cxFree; 36.1158 + cxListAdd(list, item); 36.1159 + ASSERT_FALSE(testingAllocator.verify()); 36.1160 + cxListDestroy(list); 36.1161 + EXPECT_TRUE(testingAllocator.verify()); 36.1162 +}
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 37.2 +++ b/tests/test_map.cpp Wed Feb 08 20:26:26 2023 +0100 37.3 @@ -0,0 +1,272 @@ 37.4 +/* 37.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 37.6 + * 37.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 37.8 + * 37.9 + * Redistribution and use in source and binary forms, with or without 37.10 + * modification, are permitted provided that the following conditions are met: 37.11 + * 37.12 + * 1. Redistributions of source code must retain the above copyright 37.13 + * notice, this list of conditions and the following disclaimer. 37.14 + * 37.15 + * 2. Redistributions in binary form must reproduce the above copyright 37.16 + * notice, this list of conditions and the following disclaimer in the 37.17 + * documentation and/or other materials provided with the distribution. 37.18 + * 37.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 37.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 37.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 37.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 37.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 37.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 37.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 37.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 37.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37.29 + * POSSIBILITY OF SUCH DAMAGE. 37.30 + */ 37.31 + 37.32 +#include "cx/hash_map.h" 37.33 +#include "cx/utils.h" 37.34 +#include "util_allocator.h" 37.35 + 37.36 +#include <gtest/gtest.h> 37.37 +#include <unordered_map> 37.38 +#include <unordered_set> 37.39 + 37.40 +struct map_operation { 37.41 + enum { 37.42 + put, rm 37.43 + } op; 37.44 + char const *key; 37.45 + char const *value; 37.46 +}; 37.47 + 37.48 +auto generate_map_operations() -> std::vector<map_operation> { 37.49 + return { 37.50 + {map_operation::put, "key 1", "test"}, 37.51 + {map_operation::put, "key 2", "blub"}, 37.52 + {map_operation::put, "key 3", "hallo"}, 37.53 + {map_operation::put, "key 2", "foobar"}, 37.54 + {map_operation::put, "key 4", "value 4"}, 37.55 + {map_operation::put, "key 5", "value 5"}, 37.56 + {map_operation::put, "key 6", "value 6"}, 37.57 + {map_operation::rm, "key 4", nullptr}, 37.58 + {map_operation::put, "key 7", "value 7"}, 37.59 + {map_operation::put, "key 8", "value 8"}, 37.60 + {map_operation::rm, "does not exist", nullptr}, 37.61 + {map_operation::put, "key 9", "value 9"}, 37.62 + {map_operation::put, "key 6", "other value"}, 37.63 + {map_operation::put, "key 7", "something else"}, 37.64 + {map_operation::rm, "key 8", nullptr}, 37.65 + {map_operation::rm, "key 2", nullptr}, 37.66 + {map_operation::put, "key 8", "new value"}, 37.67 + }; 37.68 +} 37.69 + 37.70 +static void verify_map_contents( 37.71 + CxMap *map, 37.72 + std::unordered_map<std::string, std::string> const &refmap 37.73 +) { 37.74 + // verify key iterator 37.75 + { 37.76 + auto keyiter = cxMapIteratorKeys(map); 37.77 + std::unordered_set<std::string> keys; 37.78 + cx_foreach(CxHashKey*, elem, keyiter) { 37.79 + keys.insert(std::string(elem->data.cstr, elem->len)); 37.80 + } 37.81 + EXPECT_EQ(keyiter.index, map->size); 37.82 + ASSERT_EQ(keys.size(), map->size); 37.83 + for (auto &&k: keys) { 37.84 + EXPECT_NE(refmap.find(k), refmap.end()); 37.85 + } 37.86 + } 37.87 + 37.88 + // verify value iterator 37.89 + { 37.90 + auto valiter = cxMapIteratorValues(map); 37.91 + std::unordered_set<std::string> values; // we use that the values in our test data are unique strings 37.92 + cx_foreach(char const*, elem, valiter) { 37.93 + values.insert(std::string(elem)); 37.94 + } 37.95 + EXPECT_EQ(valiter.index, map->size); 37.96 + ASSERT_EQ(values.size(), map->size); 37.97 + for (auto &&v: values) { 37.98 + EXPECT_NE(std::find_if(refmap.begin(), refmap.end(), 37.99 + [v](auto const &e) { return e.second == v; }), refmap.end()); 37.100 + } 37.101 + } 37.102 + 37.103 + // verify pair iterator 37.104 + { 37.105 + auto pairiter = cxMapIterator(map); 37.106 + std::unordered_map<std::string, std::string> pairs; 37.107 + cx_foreach(CxMapEntry*, entry, pairiter) { 37.108 + pairs[std::string(entry->key->data.cstr, entry->key->len)] = std::string((char *) entry->value); 37.109 + } 37.110 + EXPECT_EQ(pairiter.index, map->size); 37.111 + ASSERT_EQ(pairs.size(), refmap.size()); 37.112 + for (auto &&p: pairs) { 37.113 + ASSERT_EQ(p.second, refmap.at(p.first)); 37.114 + } 37.115 + } 37.116 +} 37.117 + 37.118 +TEST(CxHashMap, Create) { 37.119 + CxTestingAllocator allocator; 37.120 + auto map = cxHashMapCreate(&allocator, 0); 37.121 + auto hmap = reinterpret_cast<struct cx_hash_map_s *>(map); 37.122 + EXPECT_GT(hmap->bucket_count, 0); 37.123 + cx_for_n(i, hmap->bucket_count) { 37.124 + EXPECT_EQ(hmap->buckets[i], nullptr); 37.125 + } 37.126 + EXPECT_EQ(map->size, 0); 37.127 + EXPECT_EQ(map->allocator, &allocator); 37.128 + 37.129 + cxMapDestroy(map); 37.130 + EXPECT_TRUE(allocator.verify()); 37.131 +} 37.132 + 37.133 +TEST(CxHashMap, BasicOperations) { 37.134 + // create the map 37.135 + CxTestingAllocator allocator; 37.136 + auto map = cxHashMapCreate(&allocator, 8); 37.137 + 37.138 + // create a reference map 37.139 + std::unordered_map<std::string, std::string> refmap; 37.140 + 37.141 + // generate operations 37.142 + auto ops = generate_map_operations(); 37.143 + 37.144 + // verify iterators for empty map 37.145 + verify_map_contents(map, refmap); 37.146 + 37.147 + // execute operations and verify results 37.148 + for (auto &&op: ops) { 37.149 + CxHashKey key = cx_hash_key_str(op.key); 37.150 + key.hash = 0; // force the hash map to compute the hash 37.151 + if (op.op == map_operation::put) { 37.152 + // execute a put operation and verify that the exact value can be read back 37.153 + refmap[std::string(op.key)] = std::string(op.value); 37.154 + int result = cxMapPut(map, key, (void *) op.value); 37.155 + EXPECT_EQ(result, 0); 37.156 + auto added = cxMapGet(map, key); 37.157 + EXPECT_EQ(memcmp(op.value, added, strlen(op.value)), 0); 37.158 + } else { 37.159 + // execute a remove and verify that the removed element was returned (or nullptr) 37.160 + auto found = refmap.find(op.key); 37.161 + auto removed = cxMapRemove(map, key); 37.162 + if (found == refmap.end()) { 37.163 + EXPECT_EQ(removed, nullptr); 37.164 + } else { 37.165 + EXPECT_EQ(std::string((char *) removed), found->second); 37.166 + refmap.erase(found); 37.167 + } 37.168 + } 37.169 + // compare the current map state with the reference map 37.170 + verify_map_contents(map, refmap); 37.171 + } 37.172 + 37.173 + // destroy the map and verify the memory (de)allocations 37.174 + cxMapDestroy(map); 37.175 + EXPECT_TRUE(allocator.verify()); 37.176 +} 37.177 + 37.178 +TEST(CxHashMap, RemoveViaIterator) { 37.179 + CxTestingAllocator allocator; 37.180 + auto map = cxHashMapCreate(&allocator, 4); 37.181 + 37.182 + cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); 37.183 + cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); 37.184 + cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); 37.185 + cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); 37.186 + cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5"); 37.187 + cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6"); 37.188 + 37.189 + auto iter = cxMapMutIterator(map); 37.190 + cx_foreach(CxMapEntry*, entry, iter) { 37.191 + if (entry->key->data.cstr[4] % 2 == 1) cxIteratorFlagRemoval(iter); 37.192 + } 37.193 + EXPECT_EQ(map->size, 3); 37.194 + EXPECT_EQ(iter.index, map->size); 37.195 + 37.196 + EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 1")), nullptr); 37.197 + EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 2")), nullptr); 37.198 + EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 3")), nullptr); 37.199 + EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 4")), nullptr); 37.200 + EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 5")), nullptr); 37.201 + EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 6")), nullptr); 37.202 + 37.203 + cxMapDestroy(map); 37.204 + EXPECT_TRUE(allocator.verify()); 37.205 +} 37.206 + 37.207 +TEST(CxHashMap, RehashNotRequired) { 37.208 + CxTestingAllocator allocator; 37.209 + auto map = cxHashMapCreate(&allocator, 8); 37.210 + 37.211 + cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); 37.212 + cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); 37.213 + cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); 37.214 + cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); 37.215 + cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5"); 37.216 + cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6"); 37.217 + 37.218 + // 6/8 does not exceed 0.75, therefore the function should not rehash 37.219 + int result = cxMapRehash(map); 37.220 + EXPECT_EQ(result, 0); 37.221 + EXPECT_EQ(reinterpret_cast<struct cx_hash_map_s *>(map)->bucket_count, 8); 37.222 + 37.223 + cxMapDestroy(map); 37.224 + EXPECT_TRUE(allocator.verify()); 37.225 +} 37.226 + 37.227 +TEST(CxHashMap, Rehash) { 37.228 + CxTestingAllocator allocator; 37.229 + auto map = cxHashMapCreate(&allocator, 8); 37.230 + 37.231 + cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); 37.232 + cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); 37.233 + cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); 37.234 + cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); 37.235 + cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5"); 37.236 + cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6"); 37.237 + cxMapPut(map, cx_hash_key_str("key 7"), (void *) "val 7"); 37.238 + 37.239 + int result = cxMapRehash(map); 37.240 + EXPECT_EQ(result, 0); 37.241 + EXPECT_EQ(reinterpret_cast<struct cx_hash_map_s *>(map)->bucket_count, 17); 37.242 + EXPECT_EQ(map->size, 7); 37.243 + 37.244 + EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 1")), "val 1"), 0); 37.245 + EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 2")), "val 2"), 0); 37.246 + EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 3")), "val 3"), 0); 37.247 + EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 4")), "val 4"), 0); 37.248 + EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 5")), "val 5"), 0); 37.249 + EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 6")), "val 6"), 0); 37.250 + EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 7")), "val 7"), 0); 37.251 + 37.252 + cxMapDestroy(map); 37.253 + EXPECT_TRUE(allocator.verify()); 37.254 +} 37.255 + 37.256 +TEST(CxHashMap, Clear) { 37.257 + CxTestingAllocator allocator; 37.258 + auto map = cxHashMapCreate(&allocator, 0); 37.259 + 37.260 + cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); 37.261 + cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); 37.262 + cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); 37.263 + 37.264 + EXPECT_EQ(map->size, 3); 37.265 + 37.266 + cxMapClear(map); 37.267 + 37.268 + EXPECT_EQ(map->size, 0); 37.269 + EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 1")), nullptr); 37.270 + EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 2")), nullptr); 37.271 + EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 3")), nullptr); 37.272 + 37.273 + cxMapDestroy(map); 37.274 + EXPECT_TRUE(allocator.verify()); 37.275 +} 37.276 \ No newline at end of file
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 38.2 +++ b/tests/test_printf.cpp Wed Feb 08 20:26:26 2023 +0100 38.3 @@ -0,0 +1,248 @@ 38.4 +/* 38.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 38.6 + * 38.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 38.8 + * 38.9 + * Redistribution and use in source and binary forms, with or without 38.10 + * modification, are permitted provided that the following conditions are met: 38.11 + * 38.12 + * 1. Redistributions of source code must retain the above copyright 38.13 + * notice, this list of conditions and the following disclaimer. 38.14 + * 38.15 + * 2. Redistributions in binary form must reproduce the above copyright 38.16 + * notice, this list of conditions and the following disclaimer in the 38.17 + * documentation and/or other materials provided with the distribution. 38.18 + * 38.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 38.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 38.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 38.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 38.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 38.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 38.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 38.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38.29 + * POSSIBILITY OF SUCH DAMAGE. 38.30 + */ 38.31 + 38.32 +#include "cx/printf.h" 38.33 +#include "cx/buffer.h" 38.34 + 38.35 +#include <gtest/gtest.h> 38.36 +#include "util_allocator.h" 38.37 + 38.38 +class PrintfFixture : public ::testing::Test { 38.39 +protected: 38.40 + std::string buf; 38.41 + CxTestingAllocator alloc; 38.42 + 38.43 + void TearDown() override { 38.44 + buf.clear(); 38.45 + ASSERT_TRUE(alloc.verify()); 38.46 + } 38.47 + 38.48 + static size_t write_func( 38.49 + void const *src, 38.50 + size_t esize, 38.51 + size_t ecount, 38.52 + void *target 38.53 + ) { 38.54 + auto str = reinterpret_cast<char const *>(src); 38.55 + auto buf = reinterpret_cast<std::string *>(target); 38.56 + EXPECT_EQ(esize, 1); 38.57 + EXPECT_EQ(strlen(str), ecount); 38.58 + *buf = str; 38.59 + return ecount; 38.60 + } 38.61 +}; 38.62 + 38.63 + 38.64 +TEST_F(PrintfFixture, BPrintf) { 38.65 + CxBuffer buf; 38.66 + cxBufferInit(&buf, nullptr, 64, &alloc, 0); 38.67 + 38.68 + auto r = cx_bprintf(&buf, "This %s aged %u years in a %2XSK.", "Test", 10, 0xca); 38.69 + EXPECT_EQ(r, 34); 38.70 + EXPECT_EQ(buf.size, 34); 38.71 + buf.space[r] = '\0'; 38.72 + EXPECT_STREQ(buf.space, "This Test aged 10 years in a CASK."); 38.73 + 38.74 + cxBufferDestroy(&buf); 38.75 +} 38.76 + 38.77 +TEST_F(PrintfFixture, FPrintf) { 38.78 + auto h = "Hello"; 38.79 + size_t r; 38.80 + 38.81 + r = cx_fprintf(&buf, PrintfFixture::write_func, "teststring"); 38.82 + EXPECT_EQ(r, 10); 38.83 + EXPECT_EQ(buf, "teststring"); 38.84 + 38.85 + r = cx_fprintf(&buf, PrintfFixture::write_func, "[%10s]", h); 38.86 + EXPECT_EQ(r, 12); 38.87 + EXPECT_EQ(buf, "[ Hello]"); 38.88 + 38.89 + r = cx_fprintf(&buf, PrintfFixture::write_func, "[%-10s]", h); 38.90 + EXPECT_EQ(r, 12); 38.91 + EXPECT_EQ(buf, "[Hello ]"); 38.92 + 38.93 + r = cx_fprintf(&buf, PrintfFixture::write_func, "[%*s]", 10, h); 38.94 + EXPECT_EQ(r, 12); 38.95 + EXPECT_EQ(buf, "[ Hello]"); 38.96 + 38.97 + r = cx_fprintf(&buf, PrintfFixture::write_func, "[%-10.*s]", 4, h); 38.98 + EXPECT_EQ(r, 12); 38.99 + EXPECT_EQ(buf, "[Hell ]"); 38.100 + 38.101 + r = cx_fprintf(&buf, PrintfFixture::write_func, "[%-*.*s]", 10, 4, h); 38.102 + EXPECT_EQ(r, 12); 38.103 + EXPECT_EQ(buf, "[Hell ]"); 38.104 + 38.105 + r = cx_fprintf(&buf, PrintfFixture::write_func, "%c", 'A'); 38.106 + EXPECT_EQ(r, 1); 38.107 + EXPECT_EQ(buf, "A"); 38.108 + 38.109 + r = cx_fprintf(&buf, PrintfFixture::write_func, "%i %d %.6i %i %.0i %+i %i", 1, 2, 3, 0, 0, 4, -4); 38.110 + EXPECT_EQ(r, 19); 38.111 + EXPECT_EQ(buf, "1 2 000003 0 +4 -4"); 38.112 + 38.113 + r = cx_fprintf(&buf, PrintfFixture::write_func, "%x %x %X %#x", 5, 10, 10, 6); 38.114 + EXPECT_EQ(r, 9); 38.115 + EXPECT_EQ(buf, "5 a A 0x6"); 38.116 + 38.117 + r = cx_fprintf(&buf, PrintfFixture::write_func, "%o %#o %#o", 10, 10, 4); 38.118 + EXPECT_EQ(r, 9); 38.119 + EXPECT_EQ(buf, "12 012 04"); 38.120 + 38.121 + r = cx_fprintf(&buf, PrintfFixture::write_func, "%05.2f %.2f %5.2f", 1.5, 1.5, 1.5); 38.122 + EXPECT_EQ(r, 16); 38.123 + EXPECT_EQ(buf, "01.50 1.50 1.50"); 38.124 + 38.125 + r = cx_fprintf(&buf, PrintfFixture::write_func, "'%*c'", 5, 'x'); 38.126 + EXPECT_EQ(r, 7); 38.127 + EXPECT_EQ(buf, "' x'"); 38.128 + 38.129 + r = cx_fprintf(&buf, PrintfFixture::write_func, "'%*c'", -5, 'x'); 38.130 + EXPECT_EQ(r, 7); 38.131 + EXPECT_EQ(buf, "'x '"); 38.132 +} 38.133 + 38.134 +TEST_F(PrintfFixture, BPrintfLargeString) { 38.135 + CxBuffer buf; 38.136 + cxBufferInit(&buf, nullptr, 64, &alloc, CX_BUFFER_AUTO_EXTEND); 38.137 + 38.138 + auto aaa = std::string(512, 'a'); 38.139 + auto bbb = std::string(512, 'b'); 38.140 + 38.141 + auto r = cx_bprintf(&buf, "After %s comes %s.", aaa.data(), bbb.data()); 38.142 + EXPECT_EQ(r, 1038); 38.143 + EXPECT_EQ(buf.size, 1038); 38.144 + cxBufferPut(&buf, 0); 38.145 + EXPECT_EQ(buf.space, std::string("After ") + aaa + " comes " + bbb + "."); 38.146 + 38.147 + cxBufferDestroy(&buf); 38.148 +} 38.149 + 38.150 +TEST_F(PrintfFixture, BPrintfNoCap) { 38.151 + CxBuffer buf; 38.152 + char space[20]; 38.153 + memset(space, 'a', 20); 38.154 + cxBufferInit(&buf, space, 16, &alloc, 0); 38.155 + 38.156 + auto r = cx_bprintf(&buf, "Hello %s with more than %d chars.", "string", 16); 38.157 + EXPECT_EQ(r, 16); 38.158 + EXPECT_EQ(buf.size, 16); 38.159 + EXPECT_EQ(0, memcmp(space, "Hello string witaaaa", 20)); 38.160 + 38.161 + cxBufferDestroy(&buf); 38.162 +} 38.163 + 38.164 +TEST_F(PrintfFixture, SPrintf) { 38.165 + auto h = "Hello"; 38.166 + 38.167 + std::vector<char *> fl; 38.168 + cxmutstr r; 38.169 + 38.170 + r = cx_asprintf_a(&alloc, "teststring"); 38.171 + EXPECT_EQ(r.length, 10); 38.172 + EXPECT_STREQ(r.ptr, "teststring"); 38.173 + fl.push_back(r.ptr); 38.174 + 38.175 + r = cx_asprintf_a(&alloc, "[%10s]", h); 38.176 + EXPECT_EQ(r.length, 12); 38.177 + EXPECT_STREQ(r.ptr, "[ Hello]"); 38.178 + fl.push_back(r.ptr); 38.179 + 38.180 + r = cx_asprintf_a(&alloc, "[%-10s]", h); 38.181 + EXPECT_EQ(r.length, 12); 38.182 + EXPECT_STREQ(r.ptr, "[Hello ]"); 38.183 + fl.push_back(r.ptr); 38.184 + 38.185 + r = cx_asprintf_a(&alloc, "[%*s]", 10, h); 38.186 + EXPECT_EQ(r.length, 12); 38.187 + EXPECT_STREQ(r.ptr, "[ Hello]"); 38.188 + fl.push_back(r.ptr); 38.189 + 38.190 + r = cx_asprintf_a(&alloc, "[%-10.*s]", 4, h); 38.191 + EXPECT_EQ(r.length, 12); 38.192 + EXPECT_STREQ(r.ptr, "[Hell ]"); 38.193 + fl.push_back(r.ptr); 38.194 + 38.195 + r = cx_asprintf_a(&alloc, "[%-*.*s]", 10, 4, h); 38.196 + EXPECT_EQ(r.length, 12); 38.197 + EXPECT_STREQ(r.ptr, "[Hell ]"); 38.198 + fl.push_back(r.ptr); 38.199 + 38.200 + r = cx_asprintf_a(&alloc, "%c", 'A'); 38.201 + EXPECT_EQ(r.length, 1); 38.202 + EXPECT_STREQ(r.ptr, "A"); 38.203 + fl.push_back(r.ptr); 38.204 + 38.205 + r = cx_asprintf_a(&alloc, "%i %d %.6i %i %.0i %+i %i", 1, 2, 3, 0, 0, 4, -4); 38.206 + EXPECT_EQ(r.length, 19); 38.207 + EXPECT_STREQ(r.ptr, "1 2 000003 0 +4 -4"); 38.208 + fl.push_back(r.ptr); 38.209 + 38.210 + r = cx_asprintf_a(&alloc, "%x %x %X %#x", 5, 10, 10, 6); 38.211 + EXPECT_EQ(r.length, 9); 38.212 + EXPECT_STREQ(r.ptr, "5 a A 0x6"); 38.213 + fl.push_back(r.ptr); 38.214 + 38.215 + r = cx_asprintf_a(&alloc, "%o %#o %#o", 10, 10, 4); 38.216 + EXPECT_EQ(r.length, 9); 38.217 + EXPECT_STREQ(r.ptr, "12 012 04"); 38.218 + fl.push_back(r.ptr); 38.219 + 38.220 + r = cx_asprintf_a(&alloc, "%05.2f %.2f %5.2f", 1.5, 1.5, 1.5); 38.221 + EXPECT_EQ(r.length, 16); 38.222 + EXPECT_STREQ(r.ptr, "01.50 1.50 1.50"); 38.223 + fl.push_back(r.ptr); 38.224 + 38.225 + r = cx_asprintf_a(&alloc, "'%*c'", 5, 'x'); 38.226 + EXPECT_EQ(r.length, 7); 38.227 + EXPECT_STREQ(r.ptr, "' x'"); 38.228 + fl.push_back(r.ptr); 38.229 + 38.230 + r = cx_asprintf_a(&alloc, "'%*c'", -5, 'x'); 38.231 + EXPECT_EQ(r.length, 7); 38.232 + EXPECT_STREQ(r.ptr, "'x '"); 38.233 + fl.push_back(r.ptr); 38.234 + 38.235 + for (auto c: fl) { 38.236 + auto s = cx_mutstrn(c, 0); 38.237 + cx_strfree_a(&alloc, &s); 38.238 + } 38.239 +} 38.240 + 38.241 +TEST_F(PrintfFixture, SPrintfLargeString) { 38.242 + auto aaa = std::string(512, 'a'); 38.243 + auto bbb = std::string(512, 'b'); 38.244 + 38.245 + auto r = cx_asprintf_a(&alloc, "After %s comes %s.", aaa.data(), bbb.data()); 38.246 + EXPECT_EQ(r.length, 1038); 38.247 + EXPECT_EQ(r.ptr, std::string("After ") + aaa + " comes " + bbb + "."); 38.248 + EXPECT_EQ(r.ptr[1038], '\0'); 38.249 + 38.250 + cx_strfree_a(&alloc, &r); 38.251 +} 38.252 \ No newline at end of file
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 39.2 +++ b/tests/test_string.cpp Wed Feb 08 20:26:26 2023 +0100 39.3 @@ -0,0 +1,865 @@ 39.4 +/* 39.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 39.6 + * 39.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 39.8 + * 39.9 + * Redistribution and use in source and binary forms, with or without 39.10 + * modification, are permitted provided that the following conditions are met: 39.11 + * 39.12 + * 1. Redistributions of source code must retain the above copyright 39.13 + * notice, this list of conditions and the following disclaimer. 39.14 + * 39.15 + * 2. Redistributions in binary form must reproduce the above copyright 39.16 + * notice, this list of conditions and the following disclaimer in the 39.17 + * documentation and/or other materials provided with the distribution. 39.18 + * 39.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 39.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 39.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 39.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 39.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 39.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 39.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 39.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 39.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 39.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39.29 + * POSSIBILITY OF SUCH DAMAGE. 39.30 + */ 39.31 + 39.32 +#include "cx/string.h" 39.33 +#include "util_allocator.h" 39.34 + 39.35 +#include <gtest/gtest.h> 39.36 + 39.37 +#define EXPECT_ZERO_TERMINATED(str) EXPECT_EQ((str).ptr[(str).length], '\0') 39.38 + 39.39 +TEST(String, construct) { 39.40 + cxstring s1 = cx_str("1234"); 39.41 + cxstring s2 = cx_strn("abcd", 2); 39.42 + cxmutstr s3 = cx_mutstr((char *) "1234"); 39.43 + cxmutstr s4 = cx_mutstrn((char *) "abcd", 2); 39.44 + 39.45 + EXPECT_EQ(s1.length, 4); 39.46 + EXPECT_EQ(s2.length, 2); 39.47 + EXPECT_EQ(s3.length, 4); 39.48 + EXPECT_EQ(s4.length, 2); 39.49 +} 39.50 + 39.51 +TEST(String, strfree) { 39.52 + CxTestingAllocator alloc; 39.53 + auto test = (char *) cxMalloc(&alloc, 16); 39.54 + cxmutstr str = cx_mutstrn(test, 16); 39.55 + ASSERT_EQ(str.ptr, test); 39.56 + EXPECT_EQ(str.length, 16); 39.57 + cx_strfree_a(&alloc, &str); 39.58 + EXPECT_EQ(str.ptr, nullptr); 39.59 + EXPECT_EQ(str.length, 0); 39.60 + EXPECT_TRUE(alloc.verify()); 39.61 +} 39.62 + 39.63 +TEST(String, strdup) { 39.64 + cxstring str = CX_STR("test"); 39.65 + cxmutstr dup = cx_strdup(str); 39.66 + ASSERT_EQ(dup.length, str.length); 39.67 + EXPECT_STREQ(dup.ptr, str.ptr); 39.68 + EXPECT_ZERO_TERMINATED(dup); 39.69 + cx_strfree(&dup); 39.70 + 39.71 + str.length = 2; 39.72 + dup = cx_strdup(str); 39.73 + ASSERT_EQ(dup.length, str.length); 39.74 + EXPECT_STREQ(dup.ptr, "te"); 39.75 + EXPECT_ZERO_TERMINATED(dup); 39.76 + cx_strfree(&dup); 39.77 +} 39.78 + 39.79 +TEST(String, strlen) { 39.80 + cxstring s1 = CX_STR("1234"); 39.81 + cxstring s2 = CX_STR(".:.:."); 39.82 + cxstring s3 = CX_STR("X"); 39.83 + 39.84 + size_t len0 = cx_strlen(0); 39.85 + size_t len1 = cx_strlen(1, s1); 39.86 + size_t len2 = cx_strlen(2, s1, s2); 39.87 + size_t len3 = cx_strlen(3, s1, s2, s3); 39.88 + 39.89 + EXPECT_EQ(len0, 0); 39.90 + EXPECT_EQ(len1, 4); 39.91 + EXPECT_EQ(len2, 9); 39.92 + EXPECT_EQ(len3, 10); 39.93 +} 39.94 + 39.95 +TEST(String, strsubs) { 39.96 + cxstring str = CX_STR("A test string"); 39.97 + 39.98 + cxstring sub = cx_strsubs(str, 0); 39.99 + EXPECT_EQ(cx_strcmp(sub, str), 0); 39.100 + 39.101 + sub = cx_strsubs(str, 2); 39.102 + EXPECT_EQ(cx_strcmp(sub, cx_str("test string")), 0); 39.103 + 39.104 + sub = cx_strsubs(str, 7); 39.105 + EXPECT_EQ(cx_strcmp(sub, cx_str("string")), 0); 39.106 + 39.107 + sub = cx_strsubs(str, 15); 39.108 + EXPECT_EQ(cx_strcmp(sub, cx_str("")), 0); 39.109 + 39.110 + sub = cx_strsubsl(str, 2, 4); 39.111 + EXPECT_EQ(cx_strcmp(sub, cx_str("test")), 0); 39.112 + 39.113 + sub = cx_strsubsl(str, 7, 3); 39.114 + EXPECT_EQ(cx_strcmp(sub, cx_str("str")), 0); 39.115 + 39.116 + sub = cx_strsubsl(str, 7, 20); 39.117 + EXPECT_EQ(cx_strcmp(sub, cx_str("string")), 0); 39.118 + 39.119 + // just for coverage, call the _m variant 39.120 + auto m = cx_strsubs_m(cx_mutstrn(nullptr, 0), 0); 39.121 + EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0); 39.122 +} 39.123 + 39.124 +TEST(String, strchr) { 39.125 + cxstring str = CX_STR("I will find you - and I will kill you"); 39.126 + 39.127 + cxstring notfound = cx_strchr(str, 'x'); 39.128 + EXPECT_EQ(notfound.length, 0); 39.129 + 39.130 + cxstring result = cx_strchr(str, 'w'); 39.131 + EXPECT_EQ(result.length, 35); 39.132 + EXPECT_STREQ(result.ptr, "will find you - and I will kill you"); 39.133 + 39.134 + // just for coverage, call the _m variant 39.135 + auto m = cx_strchr_m(cx_mutstrn(nullptr, 0), 'a'); 39.136 + EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0); 39.137 +} 39.138 + 39.139 +TEST(String, strrchr) { 39.140 + cxstring str = CX_STR("I will find you - and I will kill you"); 39.141 + 39.142 + cxstring notfound = cx_strrchr(str, 'x'); 39.143 + EXPECT_EQ(notfound.length, 0); 39.144 + 39.145 + cxstring result = cx_strrchr(str, 'w'); 39.146 + EXPECT_EQ(result.length, 13); 39.147 + EXPECT_STREQ(result.ptr, "will kill you"); 39.148 + 39.149 + // just for coverage, call the _m variant 39.150 + auto m = cx_strrchr_m(cx_mutstrn(nullptr, 0), 'a'); 39.151 + EXPECT_EQ(cx_strcmp(cx_strcast(m), cx_str("")), 0); 39.152 +} 39.153 + 39.154 +TEST(String, strstr) { 39.155 + cxstring str = CX_STR("find the match in this string"); 39.156 + cxstring longstr = CX_STR( 39.157 + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl" 39.158 + "mnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx" 39.159 + "yzabcdeababababnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghij" 39.160 + "klmnopqrstuvwxyzaababababababababrstuvwxyzabcdefghijklmnopqrstuv" 39.161 + "abababababababababababababababababababababababababababababababab" 39.162 + "abababababababababababababababababababababababababababababababab" 39.163 + "abababababababababababababababababababababababababababababababab" 39.164 + "abababababababababababababababababababababababababababababababab" 39.165 + "abababababababababababababababababababababababababababababababab" 39.166 + "abababababababababababababababababababababababababababababababab" 39.167 + "wxyz1234567890"); 39.168 + cxstring longstrpattern = CX_STR( 39.169 + "abababababababababababababababababababababababababababababababab" 39.170 + "abababababababababababababababababababababababababababababababab" 39.171 + "abababababababababababababababababababababababababababababababab" 39.172 + "abababababababababababababababababababababababababababababababab" 39.173 + "abababababababababababababababababababababababababababababababab" 39.174 + ); 39.175 + cxstring longstrresult = CX_STR( 39.176 + "abababababababababababababababababababababababababababababababab" 39.177 + "abababababababababababababababababababababababababababababababab" 39.178 + "abababababababababababababababababababababababababababababababab" 39.179 + "abababababababababababababababababababababababababababababababab" 39.180 + "abababababababababababababababababababababababababababababababab" 39.181 + "abababababababababababababababababababababababababababababababab" 39.182 + "wxyz1234567890" 39.183 + ); 39.184 + 39.185 + cxstring notfound = cx_strstr(str, cx_str("no match")); 39.186 + EXPECT_EQ(notfound.length, 0); 39.187 + 39.188 + cxstring result = cx_strstr(str, cx_str("match")); 39.189 + EXPECT_EQ(result.length, 20); 39.190 + EXPECT_STREQ(result.ptr, "match in this string"); 39.191 + 39.192 + result = cx_strstr(str, cx_str("")); 39.193 + EXPECT_EQ(result.length, str.length); 39.194 + EXPECT_STREQ(result.ptr, str.ptr); 39.195 + 39.196 + result = cx_strstr(longstr, longstrpattern); 39.197 + EXPECT_EQ(result.length, longstrresult.length); 39.198 + EXPECT_STREQ(result.ptr, longstrresult.ptr); 39.199 + 39.200 + // just for coverage, call the _m variant 39.201 + auto mstr = cx_strdup(longstr); 39.202 + auto m = cx_strstr_m(mstr, longstrpattern); 39.203 + EXPECT_EQ(m.length, longstrresult.length); 39.204 + EXPECT_STREQ(m.ptr, longstrresult.ptr); 39.205 + cx_strfree(&mstr); 39.206 +} 39.207 + 39.208 +TEST(String, strcmp) { 39.209 + cxstring str = CX_STR("compare this"); 39.210 + 39.211 + EXPECT_EQ(cx_strcmp(cx_str(""), cx_str("")), 0); 39.212 + EXPECT_GT(cx_strcmp(str, cx_str("")), 0); 39.213 + EXPECT_EQ(cx_strcmp(str, cx_str("compare this")), 0); 39.214 + EXPECT_NE(cx_strcmp(str, cx_str("Compare This")), 0); 39.215 + EXPECT_LT(cx_strcmp(str, cx_str("compare tool")), 0); 39.216 + EXPECT_GT(cx_strcmp(str, cx_str("compare shit")), 0); 39.217 + EXPECT_LT(cx_strcmp(str, cx_str("compare this not")), 0); 39.218 + EXPECT_GT(cx_strcmp(str, cx_str("compare")), 0); 39.219 +} 39.220 + 39.221 +TEST(String, strcasecmp) { 39.222 + cxstring str = CX_STR("compare this"); 39.223 + 39.224 + EXPECT_EQ(cx_strcasecmp(cx_str(""), cx_str("")), 0); 39.225 + EXPECT_GT(cx_strcasecmp(str, cx_str("")), 0); 39.226 + EXPECT_EQ(cx_strcasecmp(str, cx_str("compare this")), 0); 39.227 + EXPECT_EQ(cx_strcasecmp(str, cx_str("Compare This")), 0); 39.228 + EXPECT_LT(cx_strcasecmp(str, cx_str("compare tool")), 0); 39.229 + EXPECT_GT(cx_strcasecmp(str, cx_str("compare shit")), 0); 39.230 + EXPECT_LT(cx_strcasecmp(str, cx_str("compare this not")), 0); 39.231 + EXPECT_GT(cx_strcasecmp(str, cx_str("compare")), 0); 39.232 +} 39.233 + 39.234 +TEST(String, strcat) { 39.235 + cxstring s1 = CX_STR("12"); 39.236 + cxstring s2 = CX_STR("34"); 39.237 + cxstring s3 = CX_STR("56"); 39.238 + cxstring sn = {nullptr, 0}; 39.239 + 39.240 + CxTestingAllocator alloc; 39.241 + 39.242 + cxmutstr t1 = cx_strcat_a(&alloc, 2, s1, s2); 39.243 + EXPECT_EQ(cx_strcmp(cx_strcast(t1), cx_str("1234")), 0); 39.244 + EXPECT_ZERO_TERMINATED(t1); 39.245 + cx_strfree_a(&alloc, &t1); 39.246 + 39.247 + cxmutstr t2 = cx_strcat_a(&alloc, 3, s1, s2, s3); 39.248 + EXPECT_EQ(cx_strcmp(cx_strcast(t2), cx_str("123456")), 0); 39.249 + EXPECT_ZERO_TERMINATED(t2); 39.250 + cx_strfree_a(&alloc, &t2); 39.251 + 39.252 + cxmutstr t3 = cx_strcat_a(&alloc, 6, s1, sn, s2, sn, s3, sn); 39.253 + EXPECT_EQ(cx_strcmp(cx_strcast(t3), cx_str("123456")), 0); 39.254 + EXPECT_ZERO_TERMINATED(t3); 39.255 + cx_strfree_a(&alloc, &t3); 39.256 + 39.257 + cxmutstr t4 = cx_strcat_a(&alloc, 2, sn, sn); 39.258 + EXPECT_EQ(cx_strcmp(cx_strcast(t4), cx_str("")), 0); 39.259 + EXPECT_ZERO_TERMINATED(t4); 39.260 + cx_strfree_a(&alloc, &t4); 39.261 + 39.262 + EXPECT_TRUE(alloc.verify()); 39.263 + 39.264 + // use the macro 39.265 + cxmutstr t5 = cx_strcat(3, s3, s1, s2); 39.266 + EXPECT_EQ(cx_strcmp(cx_strcast(t5), cx_str("561234")), 0); 39.267 + EXPECT_ZERO_TERMINATED(t5); 39.268 + cx_strfree(&t5); 39.269 +} 39.270 + 39.271 +TEST(String, strsplit) { 39.272 + 39.273 + cxstring test = cx_str("this,is,a,csv,string"); 39.274 + size_t capa = 8; 39.275 + cxstring list[8]; 39.276 + size_t n; 39.277 + 39.278 + // special case: empty string 39.279 + n = cx_strsplit(test, cx_str(""), capa, list); 39.280 + ASSERT_EQ(n, 1); 39.281 + EXPECT_EQ(cx_strcmp(list[0], test), 0); 39.282 + 39.283 + // no delimiter occurrence 39.284 + n = cx_strsplit(test, cx_str("z"), capa, list); 39.285 + ASSERT_EQ(n, 1); 39.286 + EXPECT_EQ(cx_strcmp(list[0], test), 0); 39.287 + 39.288 + // partially matching delimiter 39.289 + n = cx_strsplit(test, cx_str("is,not"), capa, list); 39.290 + ASSERT_EQ(n, 1); 39.291 + EXPECT_EQ(cx_strcmp(list[0], test), 0); 39.292 + 39.293 + // matching single-char delimiter 39.294 + n = cx_strsplit(test, cx_str(","), capa, list); 39.295 + ASSERT_EQ(n, 5); 39.296 + EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0); 39.297 + EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0); 39.298 + EXPECT_EQ(cx_strcmp(list[2], cx_str("a")), 0); 39.299 + EXPECT_EQ(cx_strcmp(list[3], cx_str("csv")), 0); 39.300 + EXPECT_EQ(cx_strcmp(list[4], cx_str("string")), 0); 39.301 + 39.302 + // matching multi-char delimiter 39.303 + n = cx_strsplit(test, cx_str("is"), capa, list); 39.304 + ASSERT_EQ(n, 3); 39.305 + EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 39.306 + EXPECT_EQ(cx_strcmp(list[1], cx_str(",")), 0); 39.307 + EXPECT_EQ(cx_strcmp(list[2], cx_str(",a,csv,string")), 0); 39.308 + 39.309 + // bounded list using single-char delimiter 39.310 + n = cx_strsplit(test, cx_str(","), 3, list); 39.311 + ASSERT_EQ(n, 3); 39.312 + EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0); 39.313 + EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0); 39.314 + EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0); 39.315 + 39.316 + // bounded list using multi-char delimiter 39.317 + n = cx_strsplit(test, cx_str("is"), 2, list); 39.318 + ASSERT_EQ(n, 2); 39.319 + EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 39.320 + EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0); 39.321 + 39.322 + // start with delimiter 39.323 + n = cx_strsplit(test, cx_str("this"), capa, list); 39.324 + ASSERT_EQ(n, 2); 39.325 + EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0); 39.326 + EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0); 39.327 + 39.328 + // end with delimiter 39.329 + n = cx_strsplit(test, cx_str("string"), capa, list); 39.330 + ASSERT_EQ(n, 2); 39.331 + EXPECT_EQ(cx_strcmp(list[0], cx_str("this,is,a,csv,")), 0); 39.332 + EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 39.333 + 39.334 + 39.335 + // end with delimiter exceed bound 39.336 + n = cx_strsplit(cx_str("a,b,c,"), cx_str(","), 3, list); 39.337 + ASSERT_EQ(n, 3); 39.338 + EXPECT_EQ(cx_strcmp(list[0], cx_str("a")), 0); 39.339 + EXPECT_EQ(cx_strcmp(list[1], cx_str("b")), 0); 39.340 + EXPECT_EQ(cx_strcmp(list[2], cx_str("c,")), 0); 39.341 + 39.342 + // exact match 39.343 + n = cx_strsplit(test, cx_str("this,is,a,csv,string"), capa, list); 39.344 + ASSERT_EQ(n, 2); 39.345 + EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0); 39.346 + EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 39.347 + 39.348 + // string to be split is only substring 39.349 + n = cx_strsplit(test, cx_str("this,is,a,csv,string,with,extension"), capa, list); 39.350 + ASSERT_EQ(n, 1); 39.351 + EXPECT_EQ(cx_strcmp(list[0], test), 0); 39.352 + 39.353 + // subsequent encounter of delimiter (the string between is empty) 39.354 + n = cx_strsplit(test, cx_str("is,"), capa, list); 39.355 + ASSERT_EQ(n, 3); 39.356 + EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 39.357 + EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 39.358 + EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0); 39.359 + 39.360 + // call the _m variant just for coverage 39.361 + auto mtest = cx_strdup(test); 39.362 + cxmutstr mlist[4]; 39.363 + n = cx_strsplit_m(mtest, cx_str("is,"), 4, mlist); 39.364 + ASSERT_EQ(n, 3); 39.365 + EXPECT_EQ(cx_strcmp(cx_strcast(mlist[0]), cx_str("th")), 0); 39.366 + EXPECT_EQ(cx_strcmp(cx_strcast(mlist[1]), cx_str("")), 0); 39.367 + EXPECT_EQ(cx_strcmp(cx_strcast(mlist[2]), cx_str("a,csv,string")), 0); 39.368 + cx_strfree(&mtest); 39.369 +} 39.370 + 39.371 +TEST(String, strsplit_a) { 39.372 + CxTestingAllocator alloc; 39.373 + 39.374 + cxstring test = cx_str("this,is,a,csv,string"); 39.375 + size_t capa = 8; 39.376 + cxstring *list; 39.377 + size_t n; 39.378 + 39.379 + // special case: empty string 39.380 + n = cx_strsplit_a(&alloc, test, cx_str(""), capa, &list); 39.381 + ASSERT_EQ(n, 1); 39.382 + EXPECT_EQ(cx_strcmp(list[0], test), 0); 39.383 + cxFree(&alloc, list); 39.384 + 39.385 + // no delimiter occurrence 39.386 + n = cx_strsplit_a(&alloc, test, cx_str("z"), capa, &list); 39.387 + ASSERT_EQ(n, 1); 39.388 + EXPECT_EQ(cx_strcmp(list[0], test), 0); 39.389 + cxFree(&alloc, list); 39.390 + 39.391 + // partially matching delimiter 39.392 + n = cx_strsplit_a(&alloc, test, cx_str("is,not"), capa, &list); 39.393 + ASSERT_EQ(n, 1); 39.394 + EXPECT_EQ(cx_strcmp(list[0], test), 0); 39.395 + cxFree(&alloc, list); 39.396 + 39.397 + // matching single-char delimiter 39.398 + n = cx_strsplit_a(&alloc, test, cx_str(","), capa, &list); 39.399 + ASSERT_EQ(n, 5); 39.400 + EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0); 39.401 + EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0); 39.402 + EXPECT_EQ(cx_strcmp(list[2], cx_str("a")), 0); 39.403 + EXPECT_EQ(cx_strcmp(list[3], cx_str("csv")), 0); 39.404 + EXPECT_EQ(cx_strcmp(list[4], cx_str("string")), 0); 39.405 + cxFree(&alloc, list); 39.406 + 39.407 + // matching multi-char delimiter 39.408 + n = cx_strsplit_a(&alloc, test, cx_str("is"), capa, &list); 39.409 + ASSERT_EQ(n, 3); 39.410 + EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 39.411 + EXPECT_EQ(cx_strcmp(list[1], cx_str(",")), 0); 39.412 + EXPECT_EQ(cx_strcmp(list[2], cx_str(",a,csv,string")), 0); 39.413 + cxFree(&alloc, list); 39.414 + 39.415 + // bounded list using single-char delimiter 39.416 + n = cx_strsplit_a(&alloc, test, cx_str(","), 3, &list); 39.417 + ASSERT_EQ(n, 3); 39.418 + EXPECT_EQ(cx_strcmp(list[0], cx_str("this")), 0); 39.419 + EXPECT_EQ(cx_strcmp(list[1], cx_str("is")), 0); 39.420 + EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0); 39.421 + cxFree(&alloc, list); 39.422 + 39.423 + // bounded list using multi-char delimiter 39.424 + n = cx_strsplit_a(&alloc, test, cx_str("is"), 2, &list); 39.425 + ASSERT_EQ(n, 2); 39.426 + EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 39.427 + EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0); 39.428 + cxFree(&alloc, list); 39.429 + 39.430 + // start with delimiter 39.431 + n = cx_strsplit_a(&alloc, test, cx_str("this"), capa, &list); 39.432 + ASSERT_EQ(n, 2); 39.433 + EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0); 39.434 + EXPECT_EQ(cx_strcmp(list[1], cx_str(",is,a,csv,string")), 0); 39.435 + cxFree(&alloc, list); 39.436 + 39.437 + // end with delimiter 39.438 + n = cx_strsplit_a(&alloc, test, cx_str("string"), capa, &list); 39.439 + ASSERT_EQ(n, 2); 39.440 + EXPECT_EQ(cx_strcmp(list[0], cx_str("this,is,a,csv,")), 0); 39.441 + EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 39.442 + cxFree(&alloc, list); 39.443 + 39.444 + // end with delimiter exceed bound 39.445 + n = cx_strsplit_a(&alloc, cx_str("a,b,c,"), cx_str(","), 3, &list); 39.446 + ASSERT_EQ(n, 3); 39.447 + EXPECT_EQ(cx_strcmp(list[0], cx_str("a")), 0); 39.448 + EXPECT_EQ(cx_strcmp(list[1], cx_str("b")), 0); 39.449 + EXPECT_EQ(cx_strcmp(list[2], cx_str("c,")), 0); 39.450 + cxFree(&alloc, list); 39.451 + 39.452 + // exact match 39.453 + n = cx_strsplit_a(&alloc, test, cx_str("this,is,a,csv,string"), capa, &list); 39.454 + ASSERT_EQ(n, 2); 39.455 + EXPECT_EQ(cx_strcmp(list[0], cx_str("")), 0); 39.456 + EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 39.457 + cxFree(&alloc, list); 39.458 + 39.459 + // string to be split is only substring 39.460 + n = cx_strsplit_a(&alloc, test, cx_str("this,is,a,csv,string,with,extension"), capa, &list); 39.461 + ASSERT_EQ(n, 1); 39.462 + EXPECT_EQ(cx_strcmp(list[0], test), 0); 39.463 + cxFree(&alloc, list); 39.464 + 39.465 + // subsequent encounter of delimiter (the string between is empty) 39.466 + n = cx_strsplit_a(&alloc, test, cx_str("is,"), capa, &list); 39.467 + ASSERT_EQ(n, 3); 39.468 + EXPECT_EQ(cx_strcmp(list[0], cx_str("th")), 0); 39.469 + EXPECT_EQ(cx_strcmp(list[1], cx_str("")), 0); 39.470 + EXPECT_EQ(cx_strcmp(list[2], cx_str("a,csv,string")), 0); 39.471 + cxFree(&alloc, list); 39.472 + 39.473 + // call the _m variant just for coverage 39.474 + auto mtest = cx_strdup(test); 39.475 + cxmutstr *mlist; 39.476 + n = cx_strsplit_ma(&alloc, mtest, cx_str("is,"), 4, &mlist); 39.477 + ASSERT_EQ(n, 3); 39.478 + EXPECT_EQ(cx_strcmp(cx_strcast(mlist[0]), cx_str("th")), 0); 39.479 + EXPECT_EQ(cx_strcmp(cx_strcast(mlist[1]), cx_str("")), 0); 39.480 + EXPECT_EQ(cx_strcmp(cx_strcast(mlist[2]), cx_str("a,csv,string")), 0); 39.481 + cxFree(&alloc, mlist); 39.482 + cx_strfree(&mtest); 39.483 + 39.484 + EXPECT_TRUE(alloc.verify()); 39.485 +} 39.486 + 39.487 +TEST(String, strtrim) { 39.488 + cxstring t1 = cx_strtrim(cx_str(" ein test \t ")); 39.489 + cxstring t2 = cx_strtrim(cx_str("abc")); 39.490 + cxstring t3 = cx_strtrim(cx_str(" 123")); 39.491 + cxstring t4 = cx_strtrim(cx_str("xyz ")); 39.492 + cxstring t5 = cx_strtrim(cx_str(" ")); 39.493 + cxstring empty = cx_strtrim(cx_str("")); 39.494 + 39.495 + EXPECT_EQ(cx_strcmp(t1, cx_str("ein test")), 0); 39.496 + EXPECT_EQ(cx_strcmp(t2, cx_str("abc")), 0); 39.497 + EXPECT_EQ(cx_strcmp(t3, cx_str("123")), 0); 39.498 + EXPECT_EQ(cx_strcmp(t4, cx_str("xyz")), 0); 39.499 + EXPECT_EQ(cx_strcmp(t5, cx_str("")), 0); 39.500 + EXPECT_EQ(cx_strcmp(empty, cx_str("")), 0); 39.501 + 39.502 + // call the _m variant just for coverage 39.503 + cxmutstr m1 = cx_strtrim_m(cx_mutstr((char *) " ein test \t ")); 39.504 + EXPECT_EQ(cx_strcmp(cx_strcast(m1), cx_str("ein test")), 0); 39.505 +} 39.506 + 39.507 +TEST(String, strprefix) { 39.508 + cxstring str = CX_STR("test my prefix and my suffix"); 39.509 + cxstring empty = CX_STR(""); 39.510 + EXPECT_FALSE(cx_strprefix(empty, cx_str("pref"))); 39.511 + EXPECT_TRUE(cx_strprefix(str, empty)); 39.512 + EXPECT_TRUE(cx_strprefix(empty, empty)); 39.513 + EXPECT_TRUE(cx_strprefix(str, cx_str("test "))); 39.514 + EXPECT_FALSE(cx_strprefix(str, cx_str("8-) fsck "))); 39.515 +} 39.516 + 39.517 +TEST(String, strsuffix) { 39.518 + cxstring str = CX_STR("test my prefix and my suffix"); 39.519 + cxstring empty = CX_STR(""); 39.520 + EXPECT_FALSE(cx_strsuffix(empty, cx_str("suf"))); 39.521 + EXPECT_TRUE(cx_strsuffix(str, empty)); 39.522 + EXPECT_TRUE(cx_strsuffix(empty, empty)); 39.523 + EXPECT_TRUE(cx_strsuffix(str, cx_str("fix"))); 39.524 + EXPECT_FALSE(cx_strsuffix(str, cx_str("fox"))); 39.525 +} 39.526 + 39.527 +TEST(String, strcaseprefix) { 39.528 + cxstring str = CX_STR("test my prefix and my suffix"); 39.529 + cxstring empty = CX_STR(""); 39.530 + EXPECT_FALSE(cx_strcaseprefix(empty, cx_str("pREf"))); 39.531 + EXPECT_TRUE(cx_strcaseprefix(str, empty)); 39.532 + EXPECT_TRUE(cx_strcaseprefix(empty, empty)); 39.533 + EXPECT_TRUE(cx_strcaseprefix(str, cx_str("TEST "))); 39.534 + EXPECT_FALSE(cx_strcaseprefix(str, cx_str("8-) fsck "))); 39.535 +} 39.536 + 39.537 +TEST(String, strcasesuffix) { 39.538 + cxstring str = CX_STR("test my prefix and my suffix"); 39.539 + cxstring empty = CX_STR(""); 39.540 + EXPECT_FALSE(cx_strcasesuffix(empty, cx_str("sUf"))); 39.541 + EXPECT_TRUE(cx_strcasesuffix(str, empty)); 39.542 + EXPECT_TRUE(cx_strcasesuffix(empty, empty)); 39.543 + EXPECT_TRUE(cx_strcasesuffix(str, cx_str("FIX"))); 39.544 + EXPECT_FALSE(cx_strcasesuffix(str, cx_str("fox"))); 39.545 +} 39.546 + 39.547 +TEST(String, strreplace) { 39.548 + CxTestingAllocator alloc; 39.549 + cxstring str = CX_STR("test ababab string aba"); 39.550 + cxstring longstr = CX_STR( 39.551 + "xyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacd"); 39.552 + cxstring notrail = CX_STR("test abab"); 39.553 + cxstring empty = CX_STR(""); 39.554 + cxstring astr = CX_STR("aaaaaaaaaa"); 39.555 + cxstring csstr = CX_STR("test AB ab TEST xyz"); 39.556 + 39.557 + cxmutstr repl = cx_strreplace(str, cx_str("abab"), cx_str("muchlonger")); 39.558 + auto expected = "test muchlongerab string aba"; 39.559 + 39.560 + cxmutstr repln = cx_strreplacen(str, cx_str("ab"), cx_str("c"), 2); 39.561 + auto expectedn = "test ccab string aba"; 39.562 + 39.563 + cxmutstr longrepl = cx_strreplace(longstr, cx_str("a"), cx_str("z")); 39.564 + auto longexpect = "xyzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzcd"; 39.565 + 39.566 + cxmutstr replnotrail = cx_strreplace(notrail, cx_str("ab"), cx_str("z")); 39.567 + auto notrailexpect = "test zz"; 39.568 + 39.569 + cxmutstr repleq = cx_strreplace(str, str, cx_str("hello")); 39.570 + auto eqexpect = "hello"; 39.571 + 39.572 + cxmutstr replempty1 = cx_strreplace(empty, cx_str("ab"), cx_str("c")); // expect: empty 39.573 + cxmutstr replempty2 = cx_strreplace(str, cx_str("abab"), empty); 39.574 + auto emptyexpect2 = "test ab string aba"; 39.575 + 39.576 + cxmutstr replpre = cx_strreplace(str, cx_str("test "), cx_str("TEST ")); 39.577 + auto preexpected = "TEST ababab string aba"; 39.578 + 39.579 + cxmutstr replan1 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 1); 39.580 + auto an1expected = "xaaaaaaaaa"; 39.581 + 39.582 + cxmutstr replan4 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 4); 39.583 + auto an4expected = "xxxxaaaaaa"; 39.584 + 39.585 + cxmutstr replan9 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 9); 39.586 + auto an9expected = "xxxxxxxxxa"; 39.587 + 39.588 + cxmutstr replan10 = cx_strreplacen(astr, cx_str("a"), cx_str("x"), 10); 39.589 + auto an10expected = "xxxxxxxxxx"; 39.590 + 39.591 + cxmutstr repl1_a = cx_strreplace_a(&alloc, csstr, cx_str("AB"), cx_str("*")); 39.592 + auto expeced1_a = "test * ab TEST xyz"; 39.593 + 39.594 + cxmutstr repl2_a = cx_strreplace_a(&alloc, csstr, cx_str("test"), cx_str("TEST")); 39.595 + auto expected2_a = "TEST AB ab TEST xyz"; 39.596 + 39.597 + 39.598 + EXPECT_NE(repl.ptr, str.ptr); 39.599 + EXPECT_ZERO_TERMINATED(repl); 39.600 + EXPECT_STREQ(repl.ptr, expected); 39.601 + EXPECT_ZERO_TERMINATED(repln); 39.602 + EXPECT_STREQ(repln.ptr, expectedn); 39.603 + EXPECT_ZERO_TERMINATED(longrepl); 39.604 + EXPECT_STREQ(longrepl.ptr, longexpect); 39.605 + EXPECT_ZERO_TERMINATED(replnotrail); 39.606 + EXPECT_STREQ(replnotrail.ptr, notrailexpect); 39.607 + EXPECT_ZERO_TERMINATED(repleq); 39.608 + EXPECT_STREQ(repleq.ptr, eqexpect); 39.609 + EXPECT_ZERO_TERMINATED(replempty1); 39.610 + EXPECT_STREQ(replempty1.ptr, ""); 39.611 + EXPECT_ZERO_TERMINATED(replempty2); 39.612 + EXPECT_STREQ(replempty2.ptr, emptyexpect2); 39.613 + EXPECT_ZERO_TERMINATED(replpre); 39.614 + EXPECT_STREQ(replpre.ptr, preexpected); 39.615 + EXPECT_ZERO_TERMINATED(replan1); 39.616 + EXPECT_STREQ(replan1.ptr, an1expected); 39.617 + EXPECT_ZERO_TERMINATED(replan4); 39.618 + EXPECT_STREQ(replan4.ptr, an4expected); 39.619 + EXPECT_ZERO_TERMINATED(replan9); 39.620 + EXPECT_STREQ(replan9.ptr, an9expected); 39.621 + EXPECT_ZERO_TERMINATED(replan10); 39.622 + EXPECT_STREQ(replan10.ptr, an10expected); 39.623 + EXPECT_ZERO_TERMINATED(repl1_a); 39.624 + EXPECT_STREQ(repl1_a.ptr, expeced1_a); 39.625 + EXPECT_ZERO_TERMINATED(repl2_a); 39.626 + EXPECT_STREQ(repl2_a.ptr, expected2_a); 39.627 + 39.628 + cx_strfree(&repl); 39.629 + cx_strfree(&repln); 39.630 + cx_strfree(&longrepl); 39.631 + cx_strfree(&replnotrail); 39.632 + cx_strfree(&repleq); 39.633 + cx_strfree(&replempty1); 39.634 + cx_strfree(&replempty2); 39.635 + cx_strfree(&replpre); 39.636 + cx_strfree(&replan1); 39.637 + cx_strfree(&replan4); 39.638 + cx_strfree(&replan9); 39.639 + cx_strfree(&replan10); 39.640 + 39.641 + cx_strfree_a(&alloc, &repl1_a); 39.642 + cx_strfree_a(&alloc, &repl2_a); 39.643 + EXPECT_TRUE(alloc.verify()); 39.644 +} 39.645 + 39.646 +TEST(String, strupper) { 39.647 + cxmutstr str = cx_strdup(cx_str("thIs 1s @ Te$t")); 39.648 + cx_strupper(str); 39.649 + EXPECT_STREQ(str.ptr, "THIS 1S @ TE$T"); 39.650 + cx_strfree(&str); 39.651 +} 39.652 + 39.653 +TEST(String, strlower) { 39.654 + cxmutstr str = cx_strdup(cx_str("thIs 1s @ Te$t")); 39.655 + cx_strlower(str); 39.656 + EXPECT_STREQ(str.ptr, "this 1s @ te$t"); 39.657 + cx_strfree(&str); 39.658 +} 39.659 + 39.660 +TEST(String, strtok) { 39.661 + cxstring str = cx_str("a,comma,separated,string"); 39.662 + cxstring delim = cx_str(","); 39.663 + CxStrtokCtx ctx = cx_strtok(str, delim, 3); 39.664 + EXPECT_EQ(ctx.str.ptr, str.ptr); 39.665 + EXPECT_EQ(ctx.str.length, str.length); 39.666 + EXPECT_EQ(ctx.delim.ptr, delim.ptr); 39.667 + EXPECT_EQ(ctx.delim.length, delim.length); 39.668 + EXPECT_EQ(ctx.limit, 3); 39.669 + EXPECT_EQ(ctx.found, 0); 39.670 + EXPECT_EQ(ctx.pos, 0); 39.671 + EXPECT_EQ(ctx.next_pos, 0); 39.672 + EXPECT_EQ(ctx.delim_more, nullptr); 39.673 + EXPECT_EQ(ctx.delim_more_count, 0); 39.674 +} 39.675 + 39.676 +TEST(String, strtok_m) { 39.677 + cxmutstr str = cx_strdup(cx_str("a,comma,separated,string")); 39.678 + cxstring delim = cx_str(","); 39.679 + CxStrtokCtx ctx = cx_strtok_m(str, delim, 3); 39.680 + EXPECT_EQ(ctx.str.ptr, str.ptr); 39.681 + EXPECT_EQ(ctx.str.length, str.length); 39.682 + EXPECT_EQ(ctx.delim.ptr, delim.ptr); 39.683 + EXPECT_EQ(ctx.delim.length, delim.length); 39.684 + EXPECT_EQ(ctx.limit, 3); 39.685 + EXPECT_EQ(ctx.found, 0); 39.686 + EXPECT_EQ(ctx.pos, 0); 39.687 + EXPECT_EQ(ctx.next_pos, 0); 39.688 + EXPECT_EQ(ctx.delim_more, nullptr); 39.689 + EXPECT_EQ(ctx.delim_more_count, 0); 39.690 + cx_strfree(&str); 39.691 +} 39.692 + 39.693 +TEST(String, strtok_delim) { 39.694 + cxstring str = cx_str("an,arbitrarily|separated;string"); 39.695 + cxstring delim = cx_str(","); 39.696 + cxstring delim_more[2] = {CX_STR("|"), CX_STR(";")}; 39.697 + CxStrtokCtx ctx = cx_strtok(str, delim, 3); 39.698 + cx_strtok_delim(&ctx, delim_more, 2); 39.699 + EXPECT_EQ(ctx.str.ptr, str.ptr); 39.700 + EXPECT_EQ(ctx.str.length, str.length); 39.701 + EXPECT_EQ(ctx.delim.ptr, delim.ptr); 39.702 + EXPECT_EQ(ctx.delim.length, delim.length); 39.703 + EXPECT_EQ(ctx.limit, 3); 39.704 + EXPECT_EQ(ctx.found, 0); 39.705 + EXPECT_EQ(ctx.pos, 0); 39.706 + EXPECT_EQ(ctx.next_pos, 0); 39.707 + EXPECT_EQ(ctx.delim_more, delim_more); 39.708 + EXPECT_EQ(ctx.delim_more_count, 2); 39.709 +} 39.710 + 39.711 +TEST(String, strtok_next_easy) { 39.712 + cxstring str = cx_str("a,comma,separated,string"); 39.713 + cxstring delim = cx_str(","); 39.714 + CxStrtokCtx ctx = cx_strtok(str, delim, 3); 39.715 + bool ret; 39.716 + cxstring tok; 39.717 + 39.718 + ret = cx_strtok_next(&ctx, &tok); 39.719 + ASSERT_TRUE(ret); 39.720 + EXPECT_EQ(cx_strcmp(tok, cx_str("a")), 0); 39.721 + EXPECT_EQ(ctx.pos, 0); 39.722 + EXPECT_EQ(ctx.next_pos, 2); 39.723 + EXPECT_EQ(ctx.delim_pos, 1); 39.724 + EXPECT_EQ(ctx.found, 1); 39.725 + 39.726 + ret = cx_strtok_next(&ctx, &tok); 39.727 + ASSERT_TRUE(ret); 39.728 + EXPECT_EQ(cx_strcmp(tok, cx_str("comma")), 0); 39.729 + EXPECT_EQ(ctx.pos, 2); 39.730 + EXPECT_EQ(ctx.next_pos, 8); 39.731 + EXPECT_EQ(ctx.delim_pos, 7); 39.732 + EXPECT_EQ(ctx.found, 2); 39.733 + 39.734 + ret = cx_strtok_next(&ctx, &tok); 39.735 + ASSERT_TRUE(ret); 39.736 + EXPECT_EQ(cx_strcmp(tok, cx_str("separated")), 0); 39.737 + EXPECT_EQ(ctx.pos, 8); 39.738 + EXPECT_EQ(ctx.next_pos, 18); 39.739 + EXPECT_EQ(ctx.delim_pos, 17); 39.740 + EXPECT_EQ(ctx.found, 3); 39.741 + 39.742 + ret = cx_strtok_next(&ctx, &tok); 39.743 + ASSERT_FALSE(ret); 39.744 + EXPECT_EQ(ctx.pos, 8); 39.745 + EXPECT_EQ(ctx.next_pos, 18); 39.746 + EXPECT_EQ(ctx.delim_pos, 17); 39.747 + EXPECT_EQ(ctx.found, 3); 39.748 +} 39.749 + 39.750 +TEST(String, strtok_next_unlimited) { 39.751 + cxstring str = cx_str("some;-;otherwise;-;separated;-;string;-;"); 39.752 + cxstring delim = cx_str(";-;"); 39.753 + CxStrtokCtx ctx = cx_strtok(str, delim, SIZE_MAX); 39.754 + bool ret; 39.755 + cxstring tok; 39.756 + 39.757 + ret = cx_strtok_next(&ctx, &tok); 39.758 + ASSERT_TRUE(ret); 39.759 + EXPECT_EQ(cx_strcmp(tok, cx_str("some")), 0); 39.760 + EXPECT_EQ(ctx.pos, 0); 39.761 + EXPECT_EQ(ctx.next_pos, 7); 39.762 + EXPECT_EQ(ctx.delim_pos, 4); 39.763 + EXPECT_EQ(ctx.found, 1); 39.764 + 39.765 + ret = cx_strtok_next(&ctx, &tok); 39.766 + ASSERT_TRUE(ret); 39.767 + EXPECT_EQ(cx_strcmp(tok, cx_str("otherwise")), 0); 39.768 + EXPECT_EQ(ctx.pos, 7); 39.769 + EXPECT_EQ(ctx.next_pos, 19); 39.770 + EXPECT_EQ(ctx.delim_pos, 16); 39.771 + EXPECT_EQ(ctx.found, 2); 39.772 + 39.773 + ret = cx_strtok_next(&ctx, &tok); 39.774 + ASSERT_TRUE(ret); 39.775 + EXPECT_EQ(cx_strcmp(tok, cx_str("separated")), 0); 39.776 + EXPECT_EQ(ctx.pos, 19); 39.777 + EXPECT_EQ(ctx.next_pos, 31); 39.778 + EXPECT_EQ(ctx.delim_pos, 28); 39.779 + EXPECT_EQ(ctx.found, 3); 39.780 + 39.781 + ret = cx_strtok_next(&ctx, &tok); 39.782 + ASSERT_TRUE(ret); 39.783 + EXPECT_EQ(cx_strcmp(tok, cx_str("string")), 0); 39.784 + EXPECT_EQ(ctx.pos, 31); 39.785 + EXPECT_EQ(ctx.next_pos, 40); 39.786 + EXPECT_EQ(ctx.delim_pos, 37); 39.787 + EXPECT_EQ(ctx.found, 4); 39.788 + 39.789 + ret = cx_strtok_next(&ctx, &tok); 39.790 + ASSERT_TRUE(ret); 39.791 + EXPECT_EQ(cx_strcmp(tok, cx_str("")), 0); 39.792 + EXPECT_EQ(ctx.pos, 40); 39.793 + EXPECT_EQ(ctx.next_pos, 40); 39.794 + EXPECT_EQ(ctx.delim_pos, 40); 39.795 + EXPECT_EQ(ctx.found, 5); 39.796 + 39.797 + ret = cx_strtok_next(&ctx, &tok); 39.798 + ASSERT_FALSE(ret); 39.799 + EXPECT_EQ(ctx.pos, 40); 39.800 + EXPECT_EQ(ctx.delim_pos, 40); 39.801 + EXPECT_EQ(ctx.found, 5); 39.802 +} 39.803 + 39.804 +TEST(String, strtok_next_advanced) { 39.805 + cxmutstr str = cx_strdup(cx_str("an,arbitrarily;||separated;string")); 39.806 + cxstring delim = cx_str(","); 39.807 + cxstring delim_more[2] = {CX_STR("||"), CX_STR(";")}; 39.808 + CxStrtokCtx ctx = cx_strtok_m(str, delim, 10); 39.809 + cx_strtok_delim(&ctx, delim_more, 2); 39.810 + bool ret; 39.811 + cxmutstr tok; 39.812 + 39.813 + ret = cx_strtok_next_m(&ctx, &tok); 39.814 + ASSERT_TRUE(ret); 39.815 + EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("an")), 0); 39.816 + EXPECT_EQ(ctx.pos, 0); 39.817 + EXPECT_EQ(ctx.next_pos, 3); 39.818 + EXPECT_EQ(ctx.delim_pos, 2); 39.819 + EXPECT_EQ(ctx.found, 1); 39.820 + cx_strupper(tok); 39.821 + 39.822 + ret = cx_strtok_next_m(&ctx, &tok); 39.823 + ASSERT_TRUE(ret); 39.824 + EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("arbitrarily")), 0); 39.825 + EXPECT_EQ(ctx.pos, 3); 39.826 + EXPECT_EQ(ctx.next_pos, 15); 39.827 + EXPECT_EQ(ctx.delim_pos, 14); 39.828 + EXPECT_EQ(ctx.found, 2); 39.829 + cx_strupper(tok); 39.830 + 39.831 + ret = cx_strtok_next_m(&ctx, &tok); 39.832 + ASSERT_TRUE(ret); 39.833 + EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("")), 0); 39.834 + EXPECT_EQ(ctx.pos, 15); 39.835 + EXPECT_EQ(ctx.next_pos, 17); 39.836 + EXPECT_EQ(ctx.delim_pos, 15); 39.837 + EXPECT_EQ(ctx.found, 3); 39.838 + cx_strupper(tok); 39.839 + 39.840 + ret = cx_strtok_next_m(&ctx, &tok); 39.841 + ASSERT_TRUE(ret); 39.842 + EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("separated")), 0); 39.843 + EXPECT_EQ(ctx.pos, 17); 39.844 + EXPECT_EQ(ctx.next_pos, 27); 39.845 + EXPECT_EQ(ctx.delim_pos, 26); 39.846 + EXPECT_EQ(ctx.found, 4); 39.847 + cx_strupper(tok); 39.848 + 39.849 + ret = cx_strtok_next_m(&ctx, &tok); 39.850 + ASSERT_TRUE(ret); 39.851 + EXPECT_EQ(cx_strcmp(cx_strcast(tok), cx_str("string")), 0); 39.852 + EXPECT_EQ(ctx.pos, 27); 39.853 + EXPECT_EQ(ctx.next_pos, 33); 39.854 + EXPECT_EQ(ctx.delim_pos, 33); 39.855 + EXPECT_EQ(ctx.found, 5); 39.856 + cx_strupper(tok); 39.857 + 39.858 + ret = cx_strtok_next_m(&ctx, &tok); 39.859 + ASSERT_FALSE(ret); 39.860 + EXPECT_EQ(ctx.pos, 27); 39.861 + EXPECT_EQ(ctx.next_pos, 33); 39.862 + EXPECT_EQ(ctx.delim_pos, 33); 39.863 + EXPECT_EQ(ctx.found, 5); 39.864 + 39.865 + EXPECT_EQ(cx_strcmp(cx_strcast(str), cx_str("AN,ARBITRARILY;||SEPARATED;STRING")), 0); 39.866 + 39.867 + cx_strfree(&str); 39.868 +}
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 40.2 +++ b/tests/test_tree.cpp Wed Feb 08 20:26:26 2023 +0100 40.3 @@ -0,0 +1,122 @@ 40.4 +/* 40.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 40.6 + * 40.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 40.8 + * 40.9 + * Redistribution and use in source and binary forms, with or without 40.10 + * modification, are permitted provided that the following conditions are met: 40.11 + * 40.12 + * 1. Redistributions of source code must retain the above copyright 40.13 + * notice, this list of conditions and the following disclaimer. 40.14 + * 40.15 + * 2. Redistributions in binary form must reproduce the above copyright 40.16 + * notice, this list of conditions and the following disclaimer in the 40.17 + * documentation and/or other materials provided with the distribution. 40.18 + * 40.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 40.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 40.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 40.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 40.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 40.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 40.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 40.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 40.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 40.29 + * POSSIBILITY OF SUCH DAMAGE. 40.30 + */ 40.31 + 40.32 +#include "cx/tree.h" 40.33 +#include <gtest/gtest.h> 40.34 + 40.35 +struct TestNode { 40.36 + TestNode *parent = nullptr; 40.37 + TestNode *prev = nullptr; 40.38 + TestNode *next = nullptr; 40.39 + 40.40 + TestNode *children_begin = nullptr; 40.41 + TestNode *children_end = nullptr; 40.42 +}; 40.43 + 40.44 +TEST(Tree, cx_tree_add_sibling) { 40.45 + // prepare test tree 40.46 + TestNode root, a; 40.47 + root.children_begin = &a; 40.48 + root.children_end = &a; 40.49 + a.parent = &root; 40.50 + 40.51 + // new test nodes 40.52 + TestNode b, c; 40.53 + 40.54 + // test 40.55 + cx_tree_add_sibling(&a, offsetof(TestNode, prev), offsetof(TestNode, next), offsetof(TestNode, parent), &b); 40.56 + EXPECT_EQ(b.parent, &root); 40.57 + EXPECT_EQ(b.prev, &a); 40.58 + EXPECT_EQ(b.next, nullptr); 40.59 + EXPECT_EQ(a.next, &b); 40.60 + 40.61 + cx_tree_add_sibling(&a, -1, offsetof(TestNode, next), -1, &c); 40.62 + EXPECT_EQ(c.parent, nullptr); 40.63 + EXPECT_EQ(c.prev, nullptr); 40.64 + EXPECT_EQ(c.next, nullptr); 40.65 + EXPECT_EQ(b.next, &c); 40.66 +} 40.67 + 40.68 +TEST(Tree, cx_tree_add_child) { 40.69 + TestNode root, a, b, c, a1; 40.70 + 40.71 + cx_tree_add_child( 40.72 + (void **) &root.children_begin, 40.73 + (void **) &root.children_end, 40.74 + offsetof(TestNode, prev), 40.75 + offsetof(TestNode, next), 40.76 + &a, 40.77 + offsetof(TestNode, parent), 40.78 + &root); 40.79 + EXPECT_EQ(root.children_begin, &a); 40.80 + EXPECT_EQ(root.children_end, &a); 40.81 + EXPECT_EQ(a.parent, &root); 40.82 + EXPECT_EQ(a.prev, nullptr); 40.83 + EXPECT_EQ(a.next, nullptr); 40.84 + 40.85 + cx_tree_add_child( 40.86 + (void **) &root.children_begin, 40.87 + (void **) &root.children_end, 40.88 + offsetof(TestNode, prev), 40.89 + offsetof(TestNode, next), 40.90 + &b, 40.91 + offsetof(TestNode, parent), 40.92 + &root); 40.93 + EXPECT_EQ(root.children_begin, &a); 40.94 + EXPECT_EQ(root.children_begin->next, &b); 40.95 + EXPECT_EQ(root.children_end, &b); 40.96 + EXPECT_EQ(b.parent, &root); 40.97 + EXPECT_EQ(b.prev, &a); 40.98 + 40.99 + cx_tree_add_child( 40.100 + (void **) &root.children_begin, 40.101 + nullptr, 40.102 + -1, 40.103 + offsetof(TestNode, next), 40.104 + &c, 40.105 + -1, 40.106 + &root); 40.107 + EXPECT_EQ(root.children_end, &b); // children_end unchanged 40.108 + EXPECT_EQ(b.next, &c); 40.109 + EXPECT_EQ(c.prev, nullptr); 40.110 + EXPECT_EQ(c.next, nullptr); 40.111 + EXPECT_EQ(c.parent, nullptr); 40.112 + 40.113 + cx_tree_add_child( 40.114 + (void **) &a.children_begin, 40.115 + (void **) &a.children_end, 40.116 + offsetof(TestNode, prev), 40.117 + offsetof(TestNode, next), 40.118 + &a1, 40.119 + offsetof(TestNode, parent), 40.120 + &a); 40.121 + EXPECT_EQ(a.children_begin, &a1); 40.122 + EXPECT_EQ(a1.parent, &a); 40.123 + EXPECT_EQ(root.children_begin, &a); 40.124 + EXPECT_EQ(root.children_begin->children_begin, &a1); 40.125 +}
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 41.2 +++ b/tests/test_utils.cpp Wed Feb 08 20:26:26 2023 +0100 41.3 @@ -0,0 +1,165 @@ 41.4 +/* 41.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 41.6 + * 41.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 41.8 + * 41.9 + * Redistribution and use in source and binary forms, with or without 41.10 + * modification, are permitted provided that the following conditions are met: 41.11 + * 41.12 + * 1. Redistributions of source code must retain the above copyright 41.13 + * notice, this list of conditions and the following disclaimer. 41.14 + * 41.15 + * 2. Redistributions in binary form must reproduce the above copyright 41.16 + * notice, this list of conditions and the following disclaimer in the 41.17 + * documentation and/or other materials provided with the distribution. 41.18 + * 41.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 41.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 41.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 41.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 41.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 41.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 41.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 41.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 41.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41.29 + * POSSIBILITY OF SUCH DAMAGE. 41.30 + */ 41.31 + 41.32 +#include "cx/utils.h" 41.33 + 41.34 +#include <gtest/gtest.h> 41.35 + 41.36 +TEST(Utils, ForN) { 41.37 + unsigned j; 41.38 + j = 0; 41.39 + cx_for_n(i, 50) { 41.40 + EXPECT_EQ(i, j); 41.41 + j++; 41.42 + } 41.43 +} 41.44 + 41.45 +TEST(Utils, swap_ptr) { 41.46 + int i = 5; 41.47 + int j = 8; 41.48 + int *ip = &i; 41.49 + int *jp = &j; 41.50 + cx_swap_ptr(ip, jp); 41.51 + EXPECT_EQ(ip, &j); 41.52 + EXPECT_EQ(jp, &i); 41.53 +} 41.54 + 41.55 +TEST(Utils, szmul) { 41.56 + size_t r; 41.57 + int e; 41.58 + e = cx_szmul(5, 7, &r); 41.59 + EXPECT_EQ(0, e); 41.60 + EXPECT_EQ(35, r); 41.61 + 41.62 + size_t s = SIZE_MAX & ~3; 41.63 + 41.64 + e = cx_szmul(s / 4, 2, &r); 41.65 + EXPECT_EQ(0, e); 41.66 + EXPECT_EQ(s / 2, r); 41.67 + e = cx_szmul(2, s / 4, &r); 41.68 + EXPECT_EQ(0, e); 41.69 + EXPECT_EQ(s / 2, r); 41.70 + 41.71 + e = cx_szmul(s / 4, 4, &r); 41.72 + EXPECT_EQ(0, e); 41.73 + EXPECT_EQ(s, r); 41.74 + 41.75 + e = cx_szmul(4, s / 4, &r); 41.76 + EXPECT_EQ(0, e); 41.77 + EXPECT_EQ(s, r); 41.78 + 41.79 + e = cx_szmul(s / 4, 5, &r); 41.80 + EXPECT_NE(0, e); 41.81 + 41.82 + e = cx_szmul(5, s / 4, &r); 41.83 + EXPECT_NE(0, e); 41.84 + 41.85 + e = cx_szmul(SIZE_MAX - 4, 0, &r); 41.86 + EXPECT_EQ(0, e); 41.87 + EXPECT_EQ(0, r); 41.88 + 41.89 + e = cx_szmul(0, SIZE_MAX - 1, &r); 41.90 + EXPECT_EQ(0, e); 41.91 + EXPECT_EQ(0, r); 41.92 + 41.93 + e = cx_szmul(SIZE_MAX, 0, &r); 41.94 + EXPECT_EQ(0, e); 41.95 + EXPECT_EQ(0, r); 41.96 + 41.97 + e = cx_szmul(0, SIZE_MAX, &r); 41.98 + EXPECT_EQ(0, e); 41.99 + EXPECT_EQ(0, r); 41.100 + 41.101 + e = cx_szmul(0, 0, &r); 41.102 + EXPECT_EQ(0, e); 41.103 + EXPECT_EQ(0, r); 41.104 +} 41.105 + 41.106 +#ifdef CX_SZMUL_BUILTIN 41.107 + 41.108 +// also test the custom implementation 41.109 +struct Utils_szmul_impl : ::testing::Test { 41.110 +#undef CX_SZMUL_BUILTIN 41.111 + 41.112 +#include "../src/utils.c" 41.113 + 41.114 +#define CX_SZMUL_BUILTIN 41.115 +}; 41.116 + 41.117 +TEST_F(Utils_szmul_impl, Test) { 41.118 + size_t r; 41.119 + int e; 41.120 + e = cx_szmul_impl(5, 7, &r); 41.121 + EXPECT_EQ(0, e); 41.122 + EXPECT_EQ(35, r); 41.123 + 41.124 + size_t s = SIZE_MAX & ~3; 41.125 + 41.126 + e = cx_szmul_impl(s / 4, 2, &r); 41.127 + EXPECT_EQ(0, e); 41.128 + EXPECT_EQ(s / 2, r); 41.129 + e = cx_szmul_impl(2, s / 4, &r); 41.130 + EXPECT_EQ(0, e); 41.131 + EXPECT_EQ(s / 2, r); 41.132 + 41.133 + e = cx_szmul_impl(s / 4, 4, &r); 41.134 + EXPECT_EQ(0, e); 41.135 + EXPECT_EQ(s, r); 41.136 + 41.137 + e = cx_szmul_impl(4, s / 4, &r); 41.138 + EXPECT_EQ(0, e); 41.139 + EXPECT_EQ(s, r); 41.140 + 41.141 + e = cx_szmul_impl(s / 4, 5, &r); 41.142 + EXPECT_NE(0, e); 41.143 + 41.144 + e = cx_szmul_impl(5, s / 4, &r); 41.145 + EXPECT_NE(0, e); 41.146 + 41.147 + e = cx_szmul_impl(SIZE_MAX - 4, 0, &r); 41.148 + EXPECT_EQ(0, e); 41.149 + EXPECT_EQ(0, r); 41.150 + 41.151 + e = cx_szmul_impl(0, SIZE_MAX - 1, &r); 41.152 + EXPECT_EQ(0, e); 41.153 + EXPECT_EQ(0, r); 41.154 + 41.155 + e = cx_szmul_impl(SIZE_MAX, 0, &r); 41.156 + EXPECT_EQ(0, e); 41.157 + EXPECT_EQ(0, r); 41.158 + 41.159 + e = cx_szmul_impl(0, SIZE_MAX, &r); 41.160 + EXPECT_EQ(0, e); 41.161 + EXPECT_EQ(0, r); 41.162 + 41.163 + e = cx_szmul_impl(0, 0, &r); 41.164 + EXPECT_EQ(0, e); 41.165 + EXPECT_EQ(0, r); 41.166 +} 41.167 + 41.168 +#endif // CX_SZMUL_BUILTIN
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 42.2 +++ b/tests/util_allocator.cpp Wed Feb 08 20:26:26 2023 +0100 42.3 @@ -0,0 +1,167 @@ 42.4 +/* 42.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 42.6 + * 42.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 42.8 + * 42.9 + * Redistribution and use in source and binary forms, with or without 42.10 + * modification, are permitted provided that the following conditions are met: 42.11 + * 42.12 + * 1. Redistributions of source code must retain the above copyright 42.13 + * notice, this list of conditions and the following disclaimer. 42.14 + * 42.15 + * 2. Redistributions in binary form must reproduce the above copyright 42.16 + * notice, this list of conditions and the following disclaimer in the 42.17 + * documentation and/or other materials provided with the distribution. 42.18 + * 42.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 42.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 42.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 42.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 42.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 42.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 42.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 42.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 42.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42.29 + * POSSIBILITY OF SUCH DAMAGE. 42.30 + */ 42.31 + 42.32 +#include "util_allocator.h" 42.33 + 42.34 +void *cx_malloc_testing(void *d, size_t n) { 42.35 + auto data = reinterpret_cast<CxTestingAllocator *>(d); 42.36 + void *ptr = malloc(n); 42.37 + data->alloc_total++; 42.38 + if (ptr == nullptr) { 42.39 + data->alloc_failed++; 42.40 + } else { 42.41 + data->tracked.insert(ptr); 42.42 + } 42.43 + return ptr; 42.44 +} 42.45 + 42.46 +void *cx_realloc_testing(void *d, void *mem, size_t n) { 42.47 + auto data = reinterpret_cast<CxTestingAllocator *>(d); 42.48 + void *ptr = realloc(mem, n); 42.49 + if (ptr == mem) { 42.50 + return ptr; 42.51 + } else { 42.52 + data->alloc_total++; 42.53 + if (ptr == nullptr) { 42.54 + data->alloc_failed++; 42.55 + } else { 42.56 + data->free_total++; 42.57 + if (data->tracked.erase(mem) == 0) { 42.58 + data->free_failed++; 42.59 + } 42.60 + data->tracked.insert(ptr); 42.61 + } 42.62 + return ptr; 42.63 + } 42.64 +} 42.65 + 42.66 +void *cx_calloc_testing(void *d, size_t nelem, size_t n) { 42.67 + auto data = reinterpret_cast<CxTestingAllocator *>(d); 42.68 + void *ptr = calloc(nelem, n); 42.69 + data->alloc_total++; 42.70 + if (ptr == nullptr) { 42.71 + data->alloc_failed++; 42.72 + } else { 42.73 + data->tracked.insert(ptr); 42.74 + } 42.75 + return ptr; 42.76 +} 42.77 + 42.78 +void cx_free_testing(void *d, void *mem) { 42.79 + auto data = reinterpret_cast<CxTestingAllocator *>(d); 42.80 + data->free_total++; 42.81 + if (data->tracked.erase(mem) == 0) { 42.82 + data->free_failed++; 42.83 + // do not even attempt to free mem, because it is likely to segfault 42.84 + } else { 42.85 + free(mem); 42.86 + } 42.87 +} 42.88 + 42.89 +cx_allocator_class cx_testing_allocator_class = { 42.90 + cx_malloc_testing, 42.91 + cx_realloc_testing, 42.92 + cx_calloc_testing, 42.93 + cx_free_testing 42.94 +}; 42.95 + 42.96 +CxTestingAllocator::CxTestingAllocator() : CxAllocator() { 42.97 + cl = &cx_testing_allocator_class; 42.98 + data = this; 42.99 +} 42.100 + 42.101 +bool CxTestingAllocator::used() const { 42.102 + return alloc_total > 0; 42.103 +} 42.104 + 42.105 +bool CxTestingAllocator::verify() const { 42.106 + return tracked.empty() && alloc_failed == 0 && free_failed == 0 && alloc_total == free_total; 42.107 +} 42.108 + 42.109 +// SELF-TEST 42.110 + 42.111 +#include <gtest/gtest.h> 42.112 + 42.113 +TEST(TestingAllocator, ExpectFree) { 42.114 + CxTestingAllocator allocator; 42.115 + 42.116 + ASSERT_TRUE(allocator.verify()); 42.117 + EXPECT_FALSE(allocator.used()); 42.118 + auto ptr = cxMalloc(&allocator, 16); 42.119 + EXPECT_TRUE(allocator.used()); 42.120 + ASSERT_NE(ptr, nullptr); 42.121 + EXPECT_FALSE(allocator.verify()); 42.122 + 42.123 + cxFree(&allocator, ptr); 42.124 + EXPECT_TRUE(allocator.verify()); 42.125 +} 42.126 + 42.127 +TEST(TestingAllocator, DetectDoubleFree) { 42.128 + CxTestingAllocator allocator; 42.129 + 42.130 + ASSERT_TRUE(allocator.verify()); 42.131 + auto ptr = cxMalloc(&allocator, 16); 42.132 + ASSERT_NE(ptr, nullptr); 42.133 + 42.134 + cxFree(&allocator, ptr); 42.135 + EXPECT_TRUE(allocator.verify()); 42.136 + ASSERT_NO_FATAL_FAILURE(cxFree(&allocator, ptr)); 42.137 + EXPECT_FALSE(allocator.verify()); 42.138 +} 42.139 + 42.140 +TEST(TestingAllocator, FreeUntracked) { 42.141 + CxTestingAllocator allocator; 42.142 + 42.143 + auto ptr = malloc(16); 42.144 + ASSERT_TRUE(allocator.verify()); 42.145 + ASSERT_NO_FATAL_FAILURE(cxFree(&allocator, ptr)); 42.146 + EXPECT_FALSE(allocator.verify()); 42.147 + ASSERT_NO_FATAL_FAILURE(free(ptr)); 42.148 +} 42.149 + 42.150 +TEST(TestingAllocator, FullLifecycleWithRealloc) { 42.151 + CxTestingAllocator allocator; 42.152 + ASSERT_TRUE(allocator.verify()); 42.153 + auto ptr = cxMalloc(&allocator, 16); 42.154 + ASSERT_NE(ptr, nullptr); 42.155 + EXPECT_EQ(allocator.tracked.size(), 1); 42.156 + ptr = cxRealloc(&allocator, ptr, 256); 42.157 + ASSERT_NE(ptr, nullptr); 42.158 + EXPECT_EQ(allocator.tracked.size(), 1); 42.159 + cxFree(&allocator, ptr); 42.160 + EXPECT_TRUE(allocator.verify()); 42.161 +} 42.162 + 42.163 +TEST(TestingAllocator, CallocInitializes) { 42.164 + CxTestingAllocator allocator; 42.165 + const char zeros[16] = {0}; 42.166 + auto ptr = cxCalloc(&allocator, 16, 1); 42.167 + EXPECT_EQ(memcmp(ptr, zeros, 16), 0); 42.168 + cxFree(&allocator, ptr); 42.169 + EXPECT_TRUE(allocator.verify()); 42.170 +}
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 43.2 +++ b/tests/util_allocator.h Wed Feb 08 20:26:26 2023 +0100 43.3 @@ -0,0 +1,81 @@ 43.4 +/* 43.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 43.6 + * 43.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 43.8 + * 43.9 + * Redistribution and use in source and binary forms, with or without 43.10 + * modification, are permitted provided that the following conditions are met: 43.11 + * 43.12 + * 1. Redistributions of source code must retain the above copyright 43.13 + * notice, this list of conditions and the following disclaimer. 43.14 + * 43.15 + * 2. Redistributions in binary form must reproduce the above copyright 43.16 + * notice, this list of conditions and the following disclaimer in the 43.17 + * documentation and/or other materials provided with the distribution. 43.18 + * 43.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 43.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 43.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 43.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 43.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 43.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 43.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 43.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 43.29 + * POSSIBILITY OF SUCH DAMAGE. 43.30 + */ 43.31 + 43.32 +#ifndef UCX_UTIL_ALLOCATOR_H 43.33 +#define UCX_UTIL_ALLOCATOR_H 43.34 + 43.35 +#include "cx/allocator.h" 43.36 + 43.37 +#include <set> 43.38 + 43.39 +struct CxTestingAllocator : public CxAllocator { 43.40 + /** 43.41 + * Total number of all allocations (malloc, calloc, realloc). 43.42 + * A realloc() does only count when the memory has to be moved. 43.43 + */ 43.44 + unsigned alloc_total = 0; 43.45 + /** 43.46 + * Number of failed allocations (malloc, calloc, realloc). 43.47 + */ 43.48 + unsigned alloc_failed = 0; 43.49 + /** 43.50 + * Total number of freed pointers. 43.51 + * A reallocation also counts as a free when the memory has to be moved. 43.52 + */ 43.53 + unsigned free_total = 0; 43.54 + /** 43.55 + * Number of failed free invocations. 43.56 + * A free() is considered failed, if it has not been performed on tracked memory. 43.57 + */ 43.58 + unsigned free_failed = 0; 43.59 + /** 43.60 + * The set of tracked memory blocks. 43.61 + */ 43.62 + std::set<void *> tracked; 43.63 + 43.64 + /** 43.65 + * Constructs a new testing allocator. 43.66 + */ 43.67 + CxTestingAllocator(); 43.68 + 43.69 + /** 43.70 + * Verifies that this allocator has been used. 43.71 + * 43.72 + * @return true if any allocation was attempted using this allocator 43.73 + */ 43.74 + [[nodiscard]] bool used() const; 43.75 + 43.76 + /** 43.77 + * Verifies that all allocated memory blocks are freed and no free occurred twice. 43.78 + * 43.79 + * @return true iff all tracked allocations / deallocations were valid 43.80 + */ 43.81 + [[nodiscard]] bool verify() const; 43.82 +}; 43.83 + 43.84 +#endif // UCX_UTIL_ALLOCATOR_H