LCOV - code coverage report
Current view: top level - libs/mem/tests/src - test_libmem_0000.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 400 400
Test Date: 2026-07-12 01:01:34 Functions: 100.0 % 26 26
Branches: 100.0 % 10 10

             Branch data     Line data    Source code
       1                 :             : #include "test_libmem_all.h"
       2                 :             : 
       3                 :             : /**
       4                 :             :  * @brief Run README example 01 that intentionally shows a frame error
       5                 :             :  *
       6                 :             :  * This example creates a default data descriptor and then calls a string
       7                 :             :  * helper on it. The library must reject that programmer-side frame mistake
       8                 :             :  * with FAILURE and a clear diagnostic, while the descriptor remains safe to
       9                 :             :  * delete afterwards
      10                 :             :  *
      11                 :             :  * @return Return describing success or failure
      12                 :             :  */
      13                 :           1 : static Return test_libmem_0000_01_body(void)
      14                 :             : {
      15                 :           1 :         INITTEST;
      16                 :             : 
      17                 :           1 :         m_create(char,destinations_string);
      18                 :             : 
      19                 :           1 :         const char *source_string = "Hello world";
      20                 :             : 
      21                 :           1 :         ASSERT(FAILURE == m_copy_string(destinations_string,source_string));
      22                 :           1 :         call(m_del(destinations_string));
      23                 :             : 
      24                 :           1 :         deliver(status);
      25                 :             : }
      26                 :             : 
      27                 :             : /**
      28                 :             :  * @brief Check README example 01 diagnostic capture
      29                 :             :  *
      30                 :             :  * @return Return describing success or failure
      31                 :             :  */
      32                 :           1 : static Return test_libmem_0000_01(void)
      33                 :             : {
      34                 :           1 :         INITTEST;
      35                 :             : 
      36                 :             :         static const char expected_stderr_pattern_libmem_0000_01[] =
      37                 :             :                 "\\A"
      38                 :             :                 "ERROR: src/mem_core_string\\.c:mem_core_string:\\d+ Memory management; Destination must be a string descriptor Errno: [^\\n]+ \\(errno: [0-9]+\\)\n"
      39                 :             :                 "\\Z";
      40                 :             : 
      41                 :           1 :         ASSERT(SUCCESS == match_function_output(NULL,expected_stderr_pattern_libmem_0000_01,test_libmem_0000_01_body));
      42                 :             : 
      43                 :           1 :         RETURN_STATUS;
      44                 :             : }
      45                 :             : 
      46                 :             : /**
      47                 :             :  * @brief Check README example 02 with a descriptor created as MEMORY_STRING
      48                 :             :  *
      49                 :             :  * @return Return describing success or failure
      50                 :             :  */
      51                 :           1 : static Return test_libmem_0000_02(void)
      52                 :             : {
      53                 :           1 :         INITTEST;
      54                 :             : 
      55                 :           1 :         m_create(char,destinations_string,MEMORY_STRING);
      56                 :             : 
      57                 :           1 :         const char *source_string = "Hello world";
      58                 :             : 
      59                 :           1 :         ASSERT(SUCCESS == m_copy_string(destinations_string,source_string));
      60                 :           1 :         ASSERT(destinations_string->is_string == true);
      61                 :           1 :         ASSERT(destinations_string->string_length == strlen(source_string));
      62                 :           1 :         ASSERT(destinations_string->length == strlen(source_string) + 1U);
      63                 :           1 :         ASSERT(strcmp(m_text(destinations_string),source_string) == 0);
      64                 :             : 
      65                 :           1 :         call(m_del(destinations_string));
      66                 :             : 
      67                 :           1 :         RETURN_STATUS;
      68                 :             : }
      69                 :             : 
      70                 :             : /**
      71                 :             :  * @brief Check README example 03 with explicit conversion to string mode
      72                 :             :  *
      73                 :             :  * @return Return describing success or failure
      74                 :             :  */
      75                 :           1 : static Return test_libmem_0000_03(void)
      76                 :             : {
      77                 :           1 :         INITTEST;
      78                 :             : 
      79                 :           1 :         m_create(char,destinations_string);
      80                 :             : 
      81                 :           1 :         const char *source_string = "Hello world";
      82                 :             : 
      83                 :           1 :         ASSERT(destinations_string->is_string == false);
      84                 :           1 :         ASSERT(SUCCESS == m_to_string(destinations_string));
      85                 :           1 :         ASSERT(destinations_string->is_string == true);
      86                 :           1 :         ASSERT(SUCCESS == m_copy_string(destinations_string,source_string));
      87                 :           1 :         ASSERT(destinations_string->string_length == strlen(source_string));
      88                 :           1 :         ASSERT(destinations_string->length == strlen(source_string) + 1U);
      89                 :           1 :         ASSERT(strcmp(m_text(destinations_string),source_string) == 0);
      90                 :             : 
      91                 :           1 :         call(m_del(destinations_string));
      92                 :             : 
      93                 :           1 :         RETURN_STATUS;
      94                 :             : }
      95                 :             : 
      96                 :             : /**
      97                 :             :  * @brief Check README example 04 with typed data and self-aliased append
      98                 :             :  *
      99                 :             :  * Builds a typed point descriptor whose initial payload fits exactly in one
     100                 :             :  * allocation block, copies it to the destination, and then appends the
     101                 :             :  * destination to itself. The append must grow the destination reserve while
     102                 :             :  * preserving both copies of every original point, proving that a source view
     103                 :             :  * inside storage being resized remains valid for the operation
     104                 :             :  *
     105                 :             :  * @return Return describing success or failure
     106                 :             :  */
     107                 :           1 : static Return test_libmem_0000_04(void)
     108                 :             : {
     109                 :           1 :         INITTEST;
     110                 :             : 
     111                 :           1 :         m_create(point,points);
     112                 :           1 :         m_create(point,mirror);
     113                 :             : 
     114                 :             :         /* Fill one reserve block so self-append must grow the destination storage */
     115                 :           1 :         const size_t original_point_count = MEMORY_BLOCK_BYTES / sizeof(point);
     116                 :           1 :         ASSERT(original_point_count > 0U);
     117                 :           1 :         ASSERT(SUCCESS == m_resize(points,original_point_count));
     118                 :             : 
     119                 :           1 :         point *p = m_data(point,points);
     120                 :           1 :         ASSERT(p != NULL);
     121                 :             : 
     122                 :           1 :         IF(p != NULL)
     123                 :             :         {
     124         [ +  + ]:         513 :                 for(size_t i = 0; i < points->length; ++i)
     125                 :             :                 {
     126                 :         512 :                         p[i] = (point){(int)i,(int)i};
     127                 :             :                 }
     128                 :             :         }
     129                 :             : 
     130                 :             :         /* Append mirror to itself while its source payload is owned by the buffer being enlarged */
     131                 :           1 :         ASSERT(SUCCESS == m_copy(mirror,points));
     132                 :           1 :         const size_t allocated_before_append = mirror->actually_allocated_bytes;
     133                 :           1 :         ASSERT(allocated_before_append == MEMORY_BLOCK_BYTES);
     134                 :           1 :         ASSERT(SUCCESS == m_concat_data(mirror,mirror));
     135                 :           1 :         ASSERT(mirror->is_string == false);
     136                 :           1 :         ASSERT(mirror->single_element_size == sizeof(point));
     137                 :           1 :         ASSERT(mirror->length == original_point_count * 2U);
     138                 :           1 :         ASSERT(mirror->actually_allocated_bytes > allocated_before_append);
     139                 :             : 
     140                 :           1 :         const point *view = m_data_ro(point,mirror);
     141                 :           1 :         ASSERT(view != NULL);
     142                 :             : 
     143                 :           1 :         IF(view != NULL)
     144                 :             :         {
     145         [ +  + ]:         513 :                 for(size_t i = 0; i < original_point_count; ++i)
     146                 :             :                 {
     147                 :         512 :                         ASSERT(view[i].x == (int)i);
     148                 :         512 :                         ASSERT(view[i].y == (int)i);
     149                 :         512 :                         ASSERT(view[i + original_point_count].x == (int)i);
     150                 :         512 :                         ASSERT(view[i + original_point_count].y == (int)i);
     151                 :             :                 }
     152                 :             :         }
     153                 :             : 
     154                 :           1 :         call(m_del(points));
     155                 :           1 :         call(m_del(mirror));
     156                 :             : 
     157                 :           1 :         RETURN_STATUS;
     158                 :             : }
     159                 :             : 
     160                 :             : /**
     161                 :             :  * @brief Check README example 05 converting data to text within existing reserve
     162                 :             :  *
     163                 :             :  * Builds a log prefix as raw byte data in a block that already has room for a
     164                 :             :  * trailing zero terminator. Conversion to string mode must preserve the same
     165                 :             :  * physical allocation while expanding the logical payload by one terminator
     166                 :             :  * element and enabling later string concatenation
     167                 :             :  *
     168                 :             :  * @return Return describing success or failure
     169                 :             :  */
     170                 :           1 : static Return test_libmem_0000_05(void)
     171                 :             : {
     172                 :           1 :         INITTEST;
     173                 :             : 
     174                 :           1 :         m_create(char,log,MEMORY_DATA);
     175                 :             : 
     176                 :             :         /* Phase one stores raw bytes without string-mode terminator semantics */
     177                 :           1 :         ASSERT(SUCCESS == m_copy_buffer(log,5,"GET /"));
     178                 :           1 :         ASSERT(SUCCESS == m_concat_buffer(log,4,"api "));
     179                 :           1 :         ASSERT(log->is_string == false);
     180                 :           1 :         ASSERT(log->length == 9U);
     181                 :           1 :         ASSERT(log->data != NULL);
     182                 :           1 :         ASSERT(log->actually_allocated_bytes > log->length);
     183                 :             : 
     184                 :           1 :         const void *const data_before_conversion = log->data;
     185                 :           1 :         const size_t allocated_before_conversion = log->actually_allocated_bytes;
     186                 :             : 
     187                 :             :         /* Spare reserve lets conversion add a terminator without replacing the physical buffer */
     188                 :           1 :         ASSERT(SUCCESS == m_to_string(log));
     189                 :           1 :         ASSERT(log->data == data_before_conversion);
     190                 :           1 :         ASSERT(log->actually_allocated_bytes == allocated_before_conversion);
     191                 :           1 :         ASSERT(log->is_string == true);
     192                 :           1 :         ASSERT(log->string_length == strlen("GET /api "));
     193                 :           1 :         ASSERT(log->length == strlen("GET /api ") + 1U);
     194                 :           1 :         ASSERT(strcmp(m_text(log),"GET /api ") == 0);
     195                 :             : 
     196                 :           1 :         ASSERT(SUCCESS == m_concat_literal(log,"200 OK"));
     197                 :           1 :         ASSERT(log->string_length == strlen("GET /api 200 OK"));
     198                 :           1 :         ASSERT(log->length == strlen("GET /api 200 OK") + 1U);
     199                 :           1 :         ASSERT(strcmp(m_text(log),"GET /api 200 OK") == 0);
     200                 :             : 
     201                 :           1 :         call(m_del(log));
     202                 :             : 
     203                 :           1 :         RETURN_STATUS;
     204                 :             : }
     205                 :             : 
     206                 :             : /**
     207                 :             :  * @brief Check README example 06 reusing a descriptor after buffer release
     208                 :             :  *
     209                 :             :  * Stores a string, releases its descriptor-owned buffer with @ref m_del, and
     210                 :             :  * verifies that the descriptor is reset while preserving string mode. A later
     211                 :             :  * string copy through the same descriptor must allocate usable storage again
     212                 :             :  *
     213                 :             :  * @return Return describing success or failure
     214                 :             :  */
     215                 :           1 : static Return test_libmem_0000_06(void)
     216                 :             : {
     217                 :           1 :         INITTEST;
     218                 :             : 
     219                 :           1 :         m_create(char,greeting,MEMORY_STRING);
     220                 :             : 
     221                 :           1 :         ASSERT(SUCCESS == m_copy_literal(greeting,"alive"));
     222                 :           1 :         ASSERT(strcmp(m_text(greeting),"alive") == 0);
     223                 :             : 
     224                 :             :         /* Release owned storage while retaining an initialized string descriptor */
     225                 :           1 :         call(m_del(greeting));
     226                 :           1 :         ASSERT(greeting->data == NULL);
     227                 :           1 :         ASSERT(greeting->length == 0U);
     228                 :           1 :         ASSERT(greeting->string_length == 0U);
     229                 :           1 :         ASSERT(greeting->is_string == true);
     230                 :             : 
     231                 :             :         /* Reuse the cleared descriptor through the API, not any pointer to its former buffer */
     232                 :           1 :         ASSERT(SUCCESS == m_copy_literal(greeting,"reborn"));
     233                 :           1 :         ASSERT(greeting->is_string == true);
     234                 :           1 :         ASSERT(greeting->string_length == strlen("reborn"));
     235                 :           1 :         ASSERT(strcmp(m_text(greeting),"reborn") == 0);
     236                 :             : 
     237                 :           1 :         call(m_del(greeting));
     238                 :             : 
     239                 :           1 :         RETURN_STATUS;
     240                 :             : }
     241                 :             : 
     242                 :             : /**
     243                 :             :  * @brief Check README example 07 reusing an imported string terminator
     244                 :             :  *
     245                 :             :  * Copies the complete terminated byte representation of `"abc"` into a data
     246                 :             :  * descriptor. Conversion to string mode must recognize the imported zero
     247                 :             :  * terminator, cache the visible length, and leave the logical element count
     248                 :             :  * unchanged
     249                 :             :  *
     250                 :             :  * @return Return describing success or failure
     251                 :             :  */
     252                 :           1 : static Return test_libmem_0000_07(void)
     253                 :             : {
     254                 :           1 :         INITTEST;
     255                 :             : 
     256                 :           1 :         m_create(char,buffer);
     257                 :             : 
     258                 :             :         /* Copy raw payload together with its trailing zero element in data mode */
     259                 :           1 :         ASSERT(SUCCESS == m_copy_buffer(buffer,sizeof("abc"),"abc"));
     260                 :           1 :         ASSERT(buffer->is_string == false);
     261                 :           1 :         ASSERT(buffer->length == sizeof("abc"));
     262                 :             : 
     263                 :             :         /* Conversion recognizes the existing terminator instead of adding an element */
     264                 :           1 :         ASSERT(SUCCESS == m_to_string(buffer));
     265                 :           1 :         ASSERT(buffer->is_string == true);
     266                 :           1 :         ASSERT(buffer->string_length == 3U);
     267                 :           1 :         ASSERT(buffer->length == sizeof("abc"));
     268                 :           1 :         ASSERT(strcmp(m_text(buffer),"abc") == 0);
     269                 :             : 
     270                 :           1 :         call(m_del(buffer));
     271                 :             : 
     272                 :           1 :         RETURN_STATUS;
     273                 :             : }
     274                 :             : 
     275                 :             : /**
     276                 :             :  * @brief Check README example 08 literal copy expands to fixed-string semantics
     277                 :             :  *
     278                 :             :  * Copies a C string literal through the convenience macro and verifies that
     279                 :             :  * it stores the same visible length and terminator-inclusive logical length
     280                 :             :  * as an explicit fixed-string copy of the same literal
     281                 :             :  *
     282                 :             :  * @return Return describing success or failure
     283                 :             :  */
     284                 :           1 : static Return test_libmem_0000_08(void)
     285                 :             : {
     286                 :           1 :         INITTEST;
     287                 :             : 
     288                 :           1 :         m_create(char,title,MEMORY_STRING);
     289                 :             : 
     290                 :             :         /* The literal wrapper must derive the complete terminated array size */
     291                 :           1 :         ASSERT(SUCCESS == m_copy_literal(title,"hello"));
     292                 :           1 :         ASSERT(title->string_length == strlen("hello"));
     293                 :           1 :         ASSERT(title->length == sizeof("hello"));
     294                 :           1 :         ASSERT(strcmp(m_text(title),"hello") == 0);
     295                 :             : 
     296                 :             :         /* Spelling out sizeof(...) explicitly must produce the same string state */
     297                 :           1 :         ASSERT(SUCCESS == m_copy_fixed_string(title,sizeof("hello"),"hello"));
     298                 :           1 :         ASSERT(title->string_length == strlen("hello"));
     299                 :           1 :         ASSERT(title->length == sizeof("hello"));
     300                 :           1 :         ASSERT(strcmp(m_text(title),"hello") == 0);
     301                 :             : 
     302                 :           1 :         call(m_del(title));
     303                 :             : 
     304                 :           1 :         RETURN_STATUS;
     305                 :             : }
     306                 :             : 
     307                 :             : /**
     308                 :             :  * @brief Check README example 09 for formatted string construction
     309                 :             :  *
     310                 :             :  * Formats an unsigned value into a file-name pattern using a byte-sized string
     311                 :             :  * descriptor. The rendered result must remain in string mode, cache its
     312                 :             :  * visible length, and account for one final terminator in its logical length
     313                 :             :  *
     314                 :             :  * @return Return describing success or failure
     315                 :             :  */
     316                 :           1 : static Return test_libmem_0000_09(void)
     317                 :             : {
     318                 :           1 :         INITTEST;
     319                 :             : 
     320                 :           1 :         m_create(char,title,MEMORY_STRING);
     321                 :             : 
     322                 :           1 :         ASSERT(SUCCESS == m_formatted_string(title,"file-%u.txt",7U));
     323                 :           1 :         ASSERT(title->is_string == true);
     324                 :           1 :         ASSERT(title->string_length == strlen("file-7.txt"));
     325                 :           1 :         ASSERT(title->length == strlen("file-7.txt") + 1U);
     326                 :           1 :         ASSERT(strcmp(m_text(title),"file-7.txt") == 0);
     327                 :             : 
     328                 :           1 :         call(m_del(title));
     329                 :             : 
     330                 :           1 :         RETURN_STATUS;
     331                 :             : }
     332                 :             : 
     333                 :             : /**
     334                 :             :  * @brief Check README example 10 that finalizes a shortened direct write
     335                 :             :  *
     336                 :             :  * Starts with a complete string descriptor, overwrites only a shorter visible
     337                 :             :  * prefix through its writable buffer, and finalizes that prefix as `"ALPHA"`.
     338                 :             :  * Finalization must update the cached string length and terminator without
     339                 :             :  * reducing the descriptor's existing logical length
     340                 :             :  *
     341                 :             :  * @return Return describing success or failure
     342                 :             :  */
     343                 :           1 : static Return test_libmem_0000_10(void)
     344                 :             : {
     345                 :           1 :         INITTEST;
     346                 :             : 
     347                 :           1 :         m_create(char,buffer,MEMORY_STRING);
     348                 :             : 
     349                 :             :         /* Prepare a longer string whose existing storage will be rewritten in place */
     350                 :           1 :         ASSERT(SUCCESS == m_copy_literal(buffer,"alphabet"));
     351                 :           1 :         ASSERT(buffer->length == sizeof("alphabet"));
     352                 :             : 
     353                 :           1 :         char *writable = m_data(char,buffer);
     354                 :           1 :         ASSERT(writable != NULL);
     355                 :             : 
     356                 :             :         /* Directly replace only the visible prefix while leaving its old tail present */
     357                 :           1 :         IF(writable != NULL)
     358                 :             :         {
     359                 :           1 :                 writable[0] = 'A';
     360                 :           1 :                 writable[1] = 'L';
     361                 :           1 :                 writable[2] = 'P';
     362                 :           1 :                 writable[3] = 'H';
     363                 :           1 :                 writable[4] = 'A';
     364                 :             :         }
     365                 :             : 
     366                 :             :         /* Finalization makes only the rewritten prefix visible and leaves reserve available */
     367                 :           1 :         ASSERT(SUCCESS == m_finalize_string(buffer,5));
     368                 :           1 :         ASSERT(buffer->is_string == true);
     369                 :           1 :         ASSERT(buffer->string_length == 5U);
     370                 :           1 :         ASSERT(buffer->length == sizeof("alphabet"));
     371                 :           1 :         ASSERT(strcmp(m_text(buffer),"ALPHA") == 0);
     372                 :             : 
     373                 :           1 :         call(m_del(buffer));
     374                 :             : 
     375                 :           1 :         RETURN_STATUS;
     376                 :             : }
     377                 :             : 
     378                 :             : /**
     379                 :             :  * @brief Check README example 11 for explicit fixed-string copying
     380                 :             :  *
     381                 :             :  * Copies a named fixed-size character array whose final element is guaranteed
     382                 :             :  * to be the zero terminator. This demonstrates the fixed-string contract:
     383                 :             :  * m_copy_fixed_string(...) accepts a trusted complete source size and produces
     384                 :             :  * a string descriptor with the matching visible and terminator-inclusive lengths
     385                 :             :  *
     386                 :             :  * @return Return describing success or failure
     387                 :             :  */
     388                 :           1 : static Return test_libmem_0000_11(void)
     389                 :             : {
     390                 :           1 :         INITTEST;
     391                 :             : 
     392                 :           1 :         m_create(char,dest,MEMORY_STRING);
     393                 :             : 
     394                 :           1 :         const char text[] = {'H','e','l','l','o','\0'};
     395                 :             : 
     396                 :           1 :         ASSERT(SUCCESS == m_copy_fixed_string(dest,sizeof(text),text));
     397                 :           1 :         ASSERT(dest->is_string == true);
     398                 :           1 :         ASSERT(dest->string_length == strlen("Hello"));
     399                 :           1 :         ASSERT(dest->length == sizeof(text));
     400                 :           1 :         ASSERT(strcmp(m_text(dest),"Hello") == 0);
     401                 :             : 
     402                 :           1 :         call(m_del(dest));
     403                 :             : 
     404                 :           1 :         RETURN_STATUS;
     405                 :             : }
     406                 :             : 
     407                 :             : /**
     408                 :             :  * @brief Check README example 12 for explicit fixed-string append
     409                 :             :  *
     410                 :             :  * Starts with an existing string and appends a named fixed-size suffix whose
     411                 :             :  * final element is guaranteed to be the zero terminator. This demonstrates
     412                 :             :  * that m_concat_fixed_string(...) extends the visible text while trusting the
     413                 :             :  * supplied complete source size instead of scanning for a terminator
     414                 :             :  *
     415                 :             :  * @return Return describing success or failure
     416                 :             :  */
     417                 :           1 : static Return test_libmem_0000_12(void)
     418                 :             : {
     419                 :           1 :         INITTEST;
     420                 :             : 
     421                 :           1 :         m_create(char,dest,MEMORY_STRING);
     422                 :             : 
     423                 :           1 :         const char suffix[] = {'-','e','n','d','\0'};
     424                 :             : 
     425                 :           1 :         ASSERT(SUCCESS == m_copy_literal(dest,"start"));
     426                 :           1 :         ASSERT(SUCCESS == m_concat_fixed_string(dest,sizeof(suffix),suffix));
     427                 :           1 :         ASSERT(dest->is_string == true);
     428                 :           1 :         ASSERT(dest->string_length == strlen("start-end"));
     429                 :           1 :         ASSERT(dest->length == strlen("start-end") + 1U);
     430                 :           1 :         ASSERT(strcmp(m_text(dest),"start-end") == 0);
     431                 :             : 
     432                 :           1 :         call(m_del(dest));
     433                 :             : 
     434                 :           1 :         RETURN_STATUS;
     435                 :             : }
     436                 :             : 
     437                 :             : /**
     438                 :             :  * @brief Check README example 13 for literal append and fixed-string equivalence
     439                 :             :  *
     440                 :             :  * Appends the same literal first through the convenience macro and then through
     441                 :             :  * the explicit fixed-string helper. Both paths must produce matching visible
     442                 :             :  * text and terminator-inclusive descriptor lengths because the macro supplies
     443                 :             :  * the complete literal size automatically
     444                 :             :  *
     445                 :             :  * @return Return describing success or failure
     446                 :             :  */
     447                 :           1 : static Return test_libmem_0000_13(void)
     448                 :             : {
     449                 :           1 :         INITTEST;
     450                 :             : 
     451                 :           1 :         m_create(char,dest,MEMORY_STRING);
     452                 :             : 
     453                 :           1 :         ASSERT(SUCCESS == m_copy_literal(dest,"base"));
     454                 :           1 :         ASSERT(SUCCESS == m_concat_literal(dest,"-suffix"));
     455                 :           1 :         ASSERT(dest->string_length == strlen("base-suffix"));
     456                 :           1 :         ASSERT(dest->length == strlen("base-suffix") + 1U);
     457                 :           1 :         ASSERT(strcmp(m_text(dest),"base-suffix") == 0);
     458                 :             : 
     459                 :           1 :         ASSERT(SUCCESS == m_copy_literal(dest,"base"));
     460                 :           1 :         ASSERT(SUCCESS == m_concat_fixed_string(dest,sizeof("-suffix"),"-suffix"));
     461                 :           1 :         ASSERT(dest->string_length == strlen("base-suffix"));
     462                 :           1 :         ASSERT(dest->length == strlen("base-suffix") + 1U);
     463                 :           1 :         ASSERT(strcmp(m_text(dest),"base-suffix") == 0);
     464                 :             : 
     465                 :           1 :         call(m_del(dest));
     466                 :             : 
     467                 :           1 :         RETURN_STATUS;
     468                 :             : }
     469                 :             : 
     470                 :             : /**
     471                 :             :  * @brief Run README example 14 for finalized writes and descriptor concatenation
     472                 :             :  *
     473                 :             :  * Creates two string descriptors with reserved writable capacity, fills their
     474                 :             :  * visible payloads through raw pointers, and finalizes their cached lengths
     475                 :             :  * before appending one descriptor to the other and printing the concatenated
     476                 :             :  * result for output validation
     477                 :             :  *
     478                 :             :  * @return Return describing success or failure
     479                 :             :  */
     480                 :           1 : static Return test_libmem_0000_14_body(void)
     481                 :             : {
     482                 :           1 :         INITTEST;
     483                 :             : 
     484                 :             :         /* Keep both directly written operands in string mode from creation */
     485                 :           1 :         m_create(char,first,MEMORY_STRING);
     486                 :           1 :         m_create(char,second,MEMORY_STRING);
     487                 :             : 
     488                 :             :         /* Reserve writable capacity for the two strings and their terminators */
     489                 :           1 :         ASSERT(SUCCESS == m_resize(first,16));
     490                 :           1 :         ASSERT(SUCCESS == m_resize(second,16));
     491                 :             : 
     492                 :             :         /* Obtain raw views for the intentionally direct writes shown in the README */
     493                 :           1 :         char *first_buf = m_raw_data(first);
     494                 :           1 :         char *second_buf = m_raw_data(second);
     495                 :           1 :         ASSERT(first_buf != NULL);
     496                 :           1 :         ASSERT(second_buf != NULL);
     497                 :             : 
     498                 :           1 :         int first_written = -1;
     499                 :           1 :         int second_written = -1;
     500                 :             : 
     501                 :           1 :         IF(first_buf != NULL && second_buf != NULL)
     502                 :             :         {
     503                 :           1 :                 first_written = snprintf(first_buf,first->length,"Hello");
     504                 :           1 :                 second_written = snprintf(second_buf,second->length," world!");
     505                 :             :         }
     506                 :             : 
     507                 :           1 :         ASSERT(first_written >= 0);
     508                 :           1 :         ASSERT(second_written >= 0);
     509                 :           1 :         ASSERT((size_t)first_written < first->length);
     510                 :           1 :         ASSERT((size_t)second_written < second->length);
     511                 :             : 
     512                 :             :         /* Publish the visible lengths before concatenation consumes their cached values */
     513                 :           1 :         ASSERT(SUCCESS == m_finalize_string(first,(size_t)first_written));
     514                 :           1 :         ASSERT(SUCCESS == m_finalize_string(second,(size_t)second_written));
     515                 :           1 :         ASSERT(SUCCESS == m_concat_strings(first,second));
     516                 :             : 
     517                 :             :         /* Validate the concatenated descriptor before printing the documented result */
     518                 :           1 :         ASSERT(strcmp(m_text(first),"Hello world!") == 0);
     519                 :             : 
     520                 :             :         /* The enclosing test matches this printed result against the README promise */
     521                 :           1 :         printf("%s\n",m_text(first));
     522                 :             : 
     523                 :           1 :         call(m_del(first));
     524                 :           1 :         call(m_del(second));
     525                 :             : 
     526                 :           1 :         deliver(status);
     527                 :             : }
     528                 :             : 
     529                 :             : /**
     530                 :             :  * @brief Check README example 14 stdout and descriptor behavior
     531                 :             :  *
     532                 :             :  * Captures the documented construction scenario output and verifies that the
     533                 :             :  * finalized descriptors produce exactly the concatenated string promised by
     534                 :             :  * the example
     535                 :             :  *
     536                 :             :  * @return Return describing success or failure
     537                 :             :  */
     538                 :           1 : static Return test_libmem_0000_14(void)
     539                 :             : {
     540                 :           1 :         INITTEST;
     541                 :             : 
     542                 :             :         static const char expected_stdout_pattern_libmem_0000_14[] =
     543                 :             :                 "\\A"
     544                 :             :                 "Hello world!\n"
     545                 :             :                 "\\Z";
     546                 :             : 
     547                 :           1 :         ASSERT(SUCCESS == match_function_output(expected_stdout_pattern_libmem_0000_14,NULL,test_libmem_0000_14_body));
     548                 :             : 
     549                 :           1 :         RETURN_STATUS;
     550                 :             : }
     551                 :             : 
     552                 :             : /**
     553                 :             :  * @brief Run README example 15 that prints a safe string view and empty length
     554                 :             :  *
     555                 :             :  * Builds one finalized byte string for regular read-only access and keeps a
     556                 :             :  * second string descriptor empty. The soft m_text(...) accessor must expose
     557                 :             :  * both the completed text and a readable empty fallback view, while
     558                 :             :  * m_string_length(...) reports zero visible elements for the empty descriptor
     559                 :             :  *
     560                 :             :  * @return Return describing success or failure
     561                 :             :  */
     562                 :           1 : static Return test_libmem_0000_15_body(void)
     563                 :             : {
     564                 :           1 :         INITTEST;
     565                 :             : 
     566                 :           1 :         m_create(char,buffer,MEMORY_STRING);
     567                 :           1 :         m_create(char,scratch,MEMORY_STRING);
     568                 :           1 :         size_t scratch_length = 0;
     569                 :             : 
     570                 :             :         /* Reserve writable capacity before obtaining the pointer used for direct construction */
     571                 :           1 :         ASSERT(SUCCESS == m_resize(buffer,32,ZERO_NEW_MEMORY));
     572                 :             : 
     573                 :           1 :         char *writable = m_data(char,buffer);
     574                 :           1 :         ASSERT(writable != NULL);
     575                 :             : 
     576                 :           1 :         int written = -1;
     577                 :             : 
     578                 :           1 :         IF(writable != NULL)
     579                 :             :         {
     580                 :           1 :                 written = snprintf(writable,buffer->length,"Hello world!");
     581                 :             :         }
     582                 :             : 
     583                 :           1 :         ASSERT(written >= 0);
     584                 :           1 :         ASSERT((size_t)written < buffer->length);
     585                 :           1 :         ASSERT(SUCCESS == m_finalize_string(buffer,(size_t)written));
     586                 :             : 
     587                 :             :         /* Expose the finalized byte string through the soft read-only accessor */
     588                 :           1 :         const char *view = m_text(buffer);
     589                 :           1 :         ASSERT(view != NULL);
     590                 :           1 :         ASSERT(strcmp(view,"Hello world!") == 0);
     591                 :             : 
     592                 :           1 :         printf("%s\n",view);
     593                 :             : 
     594                 :             :         /* An empty initialized string still exposes an empty read-only string and zero length */
     595                 :           1 :         const char *scratch_view = m_text(scratch);
     596                 :           1 :         ASSERT(scratch_view != NULL);
     597                 :           1 :         ASSERT(strcmp(scratch_view,"") == 0);
     598                 :           1 :         printf("scratch text: \"%s\"\n",scratch_view);
     599                 :             : 
     600                 :           1 :         ASSERT(SUCCESS == m_string_length(scratch,&scratch_length));
     601                 :           1 :         ASSERT(scratch_length == 0U);
     602                 :             : 
     603                 :           1 :         printf("scratch length: %zu\n",scratch_length);
     604                 :             : 
     605                 :           1 :         call(m_del(buffer));
     606                 :           1 :         call(m_del(scratch));
     607                 :             : 
     608                 :           1 :         deliver(status);
     609                 :             : }
     610                 :             : 
     611                 :             : /**
     612                 :             :  * @brief Check README example 15 stdout with empty text and length
     613                 :             :  *
     614                 :             :  * Captures the printed normal view, empty fallback view, and empty-string
     615                 :             :  * length after its in-function assertions validate both m_text(...) results
     616                 :             :  *
     617                 :             :  * @return Return describing success or failure
     618                 :             :  */
     619                 :           1 : static Return test_libmem_0000_15(void)
     620                 :             : {
     621                 :           1 :         INITTEST;
     622                 :             : 
     623                 :             :         static const char expected_stdout_pattern_libmem_0000_15[] =
     624                 :             :                 "\\A"
     625                 :             :                 "Hello world!\n"
     626                 :             :                 "scratch text: \"\"\n"
     627                 :             :                 "scratch length: 0\n"
     628                 :             :                 "\\Z";
     629                 :             : 
     630                 :           1 :         ASSERT(SUCCESS == match_function_output(expected_stdout_pattern_libmem_0000_15,NULL,test_libmem_0000_15_body));
     631                 :             : 
     632                 :           1 :         RETURN_STATUS;
     633                 :             : }
     634                 :             : 
     635                 :             : /**
     636                 :             :  * @brief Check README example 16 for formatted message construction
     637                 :             :  *
     638                 :             :  * Builds a human-readable file-size message from string and numeric format
     639                 :             :  * arguments. The formatted helper must keep the destination in string mode,
     640                 :             :  * cache the visible rendered length, and expose the complete resulting text
     641                 :             :  *
     642                 :             :  * @return Return describing success or failure
     643                 :             :  */
     644                 :           1 : static Return test_libmem_0000_16(void)
     645                 :             : {
     646                 :           1 :         INITTEST;
     647                 :             : 
     648                 :           1 :         m_create(char,message,MEMORY_STRING);
     649                 :             : 
     650                 :           1 :         const char *name = "archive.tar";
     651                 :           1 :         const size_t size = 4096;
     652                 :             : 
     653                 :           1 :         ASSERT(SUCCESS == m_formatted_string(message,"File %s: %zu bytes",name,size));
     654                 :           1 :         ASSERT(message->is_string == true);
     655                 :           1 :         ASSERT(message->string_length == strlen("File archive.tar: 4096 bytes"));
     656                 :           1 :         ASSERT(strcmp(m_text(message),"File archive.tar: 4096 bytes") == 0);
     657                 :             : 
     658                 :           1 :         call(m_del(message));
     659                 :             : 
     660                 :           1 :         RETURN_STATUS;
     661                 :             : }
     662                 :             : 
     663                 :             : /**
     664                 :             :  * @brief Check README example 17 for bounded copy and bounded append
     665                 :             :  *
     666                 :             :  * Copies a database path and appends a suffix from two source buffers whose
     667                 :             :  * readable ranges contain bytes after their first zero terminators. The
     668                 :             :  * bounded string helpers must keep only each visible prefix and leave the
     669                 :             :  * destination as one coherent terminated string
     670                 :             :  *
     671                 :             :  * @return Return describing success or failure
     672                 :             :  */
     673                 :           1 : static Return test_libmem_0000_17(void)
     674                 :             : {
     675                 :           1 :         INITTEST;
     676                 :             : 
     677                 :           1 :         m_create(char,db_path,MEMORY_STRING);
     678                 :             : 
     679                 :           1 :         const char in_memory_db_path[] = {':','m','e','m','o','r','y',':','\0','x','x'};
     680                 :           1 :         const char limited_suffix[] = {'-','n','e','w','\0','x','x'};
     681                 :             : 
     682                 :             :         /* Bounded copy stops at the first terminator and ignores readable tail bytes */
     683                 :           1 :         ASSERT(SUCCESS == m_copy_string(db_path,sizeof(in_memory_db_path),in_memory_db_path));
     684                 :           1 :         ASSERT(db_path->is_string == true);
     685                 :           1 :         ASSERT(db_path->string_length == strlen(":memory:"));
     686                 :           1 :         ASSERT(db_path->length == strlen(":memory:") + 1U);
     687                 :           1 :         ASSERT(strcmp(m_text(db_path),":memory:") == 0);
     688                 :             : 
     689                 :             :         /* Bounded append applies the same visible-prefix rule to a suffix buffer */
     690                 :           1 :         ASSERT(SUCCESS == m_concat_string(db_path,sizeof(limited_suffix),limited_suffix));
     691                 :           1 :         ASSERT(db_path->is_string == true);
     692                 :           1 :         ASSERT(db_path->string_length == strlen(":memory:-new"));
     693                 :           1 :         ASSERT(db_path->length == strlen(":memory:-new") + 1U);
     694                 :           1 :         ASSERT(strcmp(m_text(db_path),":memory:-new") == 0);
     695                 :             : 
     696                 :           1 :         call(m_del(db_path));
     697                 :             : 
     698                 :           1 :         RETURN_STATUS;
     699                 :             : }
     700                 :             : 
     701                 :             : /**
     702                 :             :  * @brief Check README example 18 for direct write followed by finalization
     703                 :             :  *
     704                 :             :  * Allocates room for a terminated draft string, writes it through the checked
     705                 :             :  * writable view, and finalizes the descriptor so its cached visible length
     706                 :             :  * agrees with the directly written payload
     707                 :             :  *
     708                 :             :  * @return Return describing success or failure
     709                 :             :  */
     710                 :           1 : static Return test_libmem_0000_18(void)
     711                 :             : {
     712                 :           1 :         INITTEST;
     713                 :             : 
     714                 :           1 :         m_create(char,title,MEMORY_STRING);
     715                 :             : 
     716                 :           1 :         const char draft[] = "draft";
     717                 :             : 
     718                 :             :         /* Prepare string storage and write a complete terminated C string
     719                 :             :            through the checked writable view */
     720                 :           1 :         ASSERT(SUCCESS == m_resize(title,sizeof(draft)));
     721                 :             : 
     722                 :           1 :         char *title_view = m_data(char,title);
     723                 :           1 :         ASSERT(title_view != NULL);
     724                 :             : 
     725                 :           1 :         IF(title_view != NULL)
     726                 :             :         {
     727                 :           1 :                 memcpy(title_view,draft,sizeof(draft));
     728                 :             :         }
     729                 :             : 
     730                 :             :         /* Synchronize cached string metadata after the direct buffer write */
     731                 :           1 :         ASSERT(SUCCESS == m_finalize_string(title,sizeof(draft) - 1U));
     732                 :           1 :         ASSERT(title->is_string == true);
     733                 :           1 :         ASSERT(title->string_length == strlen("draft"));
     734                 :           1 :         ASSERT(title->length == sizeof(draft));
     735                 :           1 :         ASSERT(strcmp(m_text(title),"draft") == 0);
     736                 :             : 
     737                 :           1 :         call(m_del(title));
     738                 :             : 
     739                 :           1 :         RETURN_STATUS;
     740                 :             : }
     741                 :             : 
     742                 :             : /**
     743                 :             :  * @brief Check README example 19 for unbounded and bounded string array append
     744                 :             :  *
     745                 :             :  * Builds a root data descriptor that owns three inline string descriptors.
     746                 :             :  * It covers both zero-terminated and bounded sources, confirms that each
     747                 :             :  * child remains a char string descriptor, and deletes all owned storage
     748                 :             :  * through the array cleanup helper
     749                 :             :  *
     750                 :             :  * @return Return describing success or failure
     751                 :             :  */
     752                 :           1 : static Return test_libmem_0000_19(void)
     753                 :             : {
     754                 :           1 :         INITTEST;
     755                 :             : 
     756                 :           1 :         m_create(memory,names);
     757                 :             : 
     758                 :           1 :         const char source[] = {'z','e','t','a','\0','x'};
     759                 :             : 
     760                 :             :         /* Append ordinary zero-terminated strings as owned child descriptors */
     761                 :           1 :         ASSERT(SUCCESS == m_string_array_append(names,char,"delta"));
     762                 :           1 :         ASSERT(SUCCESS == m_string_array_append(names,char,"epsilon"));
     763                 :             : 
     764                 :             :         /* Append only the visible prefix of a bounded source with tail bytes */
     765                 :           1 :         ASSERT(SUCCESS == m_string_array_append(names,char,sizeof(source),source));
     766                 :           1 :         ASSERT(names->is_string == false);
     767                 :           1 :         ASSERT(names->single_element_size == sizeof(memory));
     768                 :           1 :         ASSERT(names->length == 3U);
     769                 :             : 
     770                 :           1 :         const memory *items = m_data_ro(memory,names);
     771                 :           1 :         ASSERT(items != NULL);
     772                 :             : 
     773                 :           1 :         IF(items != NULL)
     774                 :             :         {
     775                 :             :                 /* Each array element is an owned char string descriptor */
     776                 :           1 :                 ASSERT(items[0].is_string == true);
     777                 :           1 :                 ASSERT(items[0].single_element_size == sizeof(char));
     778                 :           1 :                 ASSERT(strcmp(m_text(&items[0]),"delta") == 0);
     779                 :           1 :                 ASSERT(items[1].is_string == true);
     780                 :           1 :                 ASSERT(items[1].single_element_size == sizeof(char));
     781                 :           1 :                 ASSERT(strcmp(m_text(&items[1]),"epsilon") == 0);
     782                 :           1 :                 ASSERT(items[2].is_string == true);
     783                 :           1 :                 ASSERT(items[2].single_element_size == sizeof(char));
     784                 :           1 :                 ASSERT(strcmp(m_text(&items[2]),"zeta") == 0);
     785                 :             :         }
     786                 :             : 
     787                 :             :         /* Delete the child strings and their root descriptor in one operation */
     788                 :           1 :         call(m_array_del(names));
     789                 :           1 :         ASSERT(names->data == NULL);
     790                 :           1 :         ASSERT(names->length == 0U);
     791                 :           1 :         ASSERT(names->string_length == 0U);
     792                 :             : 
     793                 :           1 :         RETURN_STATUS;
     794                 :             : }
     795                 :             : 
     796                 :             : /**
     797                 :             :  * @brief Run README example 20 that iterates over a string descriptor array
     798                 :             :  *
     799                 :             :  * Appends three child strings, visits them through m_string_array_foreach(...),
     800                 :             :  * prints them in insertion order, and counts the visited descriptors
     801                 :             :  *
     802                 :             :  * @return Return describing success or failure
     803                 :             :  */
     804                 :           1 : static Return test_libmem_0000_20_body(void)
     805                 :             : {
     806                 :           1 :         INITTEST;
     807                 :             : 
     808                 :           1 :         m_create(memory,names);
     809                 :             : 
     810                 :           1 :         ASSERT(SUCCESS == m_string_array_append(names,char,"alpha"));
     811                 :           1 :         ASSERT(SUCCESS == m_string_array_append(names,char,"beta"));
     812                 :           1 :         ASSERT(SUCCESS == m_string_array_append(names,char,"gamma"));
     813                 :             : 
     814                 :           1 :         size_t item_count = 0;
     815                 :             : 
     816   [ +  +  +  + ]:           5 :         m_string_array_foreach(names,item)
     817                 :             :         {
     818                 :           3 :                 printf("%s\n",m_text(item));
     819                 :           3 :                 ++item_count;
     820                 :             :         }
     821                 :             : 
     822                 :           1 :         ASSERT(item_count == 3U);
     823                 :             : 
     824                 :           1 :         call(m_array_del(names));
     825                 :             : 
     826                 :           1 :         deliver(status);
     827                 :             : }
     828                 :             : 
     829                 :             : /**
     830                 :             :  * @brief Check README example 20 stdout and string array traversal
     831                 :             :  *
     832                 :             :  * Captures the README example output and requires all appended strings to be
     833                 :             :  * printed once in insertion order
     834                 :             :  *
     835                 :             :  * @return Return describing success or failure
     836                 :             :  */
     837                 :           1 : static Return test_libmem_0000_20(void)
     838                 :             : {
     839                 :           1 :         INITTEST;
     840                 :             : 
     841                 :             :         static const char expected_stdout_pattern_libmem_0000_20[] =
     842                 :             :                 "\\A"
     843                 :             :                 "alpha\n"
     844                 :             :                 "beta\n"
     845                 :             :                 "gamma\n"
     846                 :             :                 "\\Z";
     847                 :             : 
     848                 :           1 :         ASSERT(SUCCESS == match_function_output(expected_stdout_pattern_libmem_0000_20,NULL,test_libmem_0000_20_body));
     849                 :             : 
     850                 :           1 :         RETURN_STATUS;
     851                 :             : }
     852                 :             : 
     853                 :             : /**
     854                 :             :  * @brief Check README example 21 for resize flags
     855                 :             :  *
     856                 :             :  * Grows a typed point descriptor past one allocation block while requiring
     857                 :             :  * the newly exposed payload to be zeroed, then shrinks it to a small prefix
     858                 :             :  * with RELEASE_UNUSED and verifies that the excess reserve is returned
     859                 :             :  *
     860                 :             :  * @return Return describing success or failure
     861                 :             :  */
     862                 :           1 : static Return test_libmem_0000_21(void)
     863                 :             : {
     864                 :           1 :         INITTEST;
     865                 :             : 
     866                 :           1 :         m_create(point,points);
     867                 :             : 
     868                 :           1 :         const size_t points_per_block = MEMORY_BLOCK_BYTES / sizeof(point);
     869                 :           1 :         const size_t large_length = points_per_block + 1U;
     870                 :           1 :         const size_t surviving_length = 4U;
     871                 :             : 
     872                 :           1 :         ASSERT(points_per_block > 0U);
     873                 :           1 :         ASSERT(large_length > surviving_length);
     874                 :             : 
     875                 :             :         /* Grow across a reserve-block boundary and zero all newly exposed points */
     876                 :           1 :         ASSERT((CRITICAL & m_resize(points,large_length,ZERO_NEW_MEMORY)) == 0);
     877                 :           1 :         ASSERT(points->length == large_length);
     878                 :           1 :         const size_t allocated_before_shrink = points->actually_allocated_bytes;
     879                 :           1 :         ASSERT(allocated_before_shrink > MEMORY_BLOCK_BYTES);
     880                 :             : 
     881                 :           1 :         point *items = m_data(point,points);
     882                 :           1 :         ASSERT(items != NULL);
     883                 :             : 
     884                 :           1 :         IF(items != NULL)
     885                 :             :         {
     886         [ +  + ]:         514 :                 for(size_t i = 0; i < points->length; ++i)
     887                 :             :                 {
     888                 :         513 :                         ASSERT(items[i].x == 0);
     889                 :         513 :                         ASSERT(items[i].y == 0);
     890                 :             :                 }
     891                 :             :         }
     892                 :             : 
     893                 :             :         /* Shrink to a small prefix and require the extra reserve block to be returned */
     894                 :           1 :         ASSERT((CRITICAL & m_resize(points,surviving_length,RELEASE_UNUSED)) == 0);
     895                 :           1 :         ASSERT(points->length == surviving_length);
     896                 :           1 :         ASSERT(points->data != NULL);
     897                 :           1 :         ASSERT(points->actually_allocated_bytes == MEMORY_BLOCK_BYTES);
     898                 :           1 :         ASSERT(points->actually_allocated_bytes < allocated_before_shrink);
     899                 :             : 
     900                 :           1 :         call(m_del(points));
     901                 :             : 
     902                 :           1 :         RETURN_STATUS;
     903                 :             : }
     904                 :             : 
     905                 :             : /**
     906                 :             :  * @brief Verify all numbered C examples maintained in the libmem README
     907                 :             :  *
     908                 :             :  * This suite is a living index of README examples. Each nested test is
     909                 :             :  * numbered so the README can link to the matching regression case directly.
     910                 :             :  * The checks intentionally validate both the visible result and the descriptor
     911                 :             :  * metadata that makes the example safe: mode, logical length, cached string
     912                 :             :  * length, typed access, captured output, and cleanup behavior
     913                 :             :  *
     914                 :             :  * @return Return describing success or failure
     915                 :             :  */
     916                 :           1 : Return test_libmem_0000(void)
     917                 :             : {
     918                 :           1 :         INITTEST;
     919                 :             : 
     920                 :           1 :         TEST(test_libmem_0000_01,"README example 01: data descriptor rejects string copy");
     921                 :           1 :         TEST(test_libmem_0000_02,"README example 02: MEMORY_STRING descriptor accepts string copy");
     922                 :           1 :         TEST(test_libmem_0000_03,"README example 03: m_to_string enables later string copy");
     923                 :           1 :         TEST(test_libmem_0000_04,"README example 04: typed point self-append survives destination storage growth");
     924                 :           1 :         TEST(test_libmem_0000_05,"README example 05: data-to-string conversion reuses spare reserved storage");
     925                 :           1 :         TEST(test_libmem_0000_06,"README example 06: descriptor can be reused after m_del");
     926                 :           1 :         TEST(test_libmem_0000_07,"README example 07: copied raw bytes reuse their existing terminator as a string");
     927                 :           1 :         TEST(test_libmem_0000_08,"README example 08: literal copy derives the same fixed-string size");
     928                 :           1 :         TEST(test_libmem_0000_09,"README example 09: formatted string renders file name");
     929                 :           1 :         TEST(test_libmem_0000_10,"README example 10: direct rewrite is finalized as a shorter string");
     930                 :           1 :         TEST(test_libmem_0000_11,"README example 11: fixed-size string copy keeps one terminator");
     931                 :           1 :         TEST(test_libmem_0000_12,"README example 12: fixed-size string append extends text");
     932                 :           1 :         TEST(test_libmem_0000_13,"README example 13: literal append matches fixed-string append");
     933                 :           1 :         TEST(test_libmem_0000_14,"README example 14: raw direct writes are finalized before concat");
     934                 :           1 :         TEST(test_libmem_0000_15,"README example 15: m_text exposes text and empty views with zero length");
     935                 :           1 :         TEST(test_libmem_0000_16,"README example 16: formatted message is stored in a descriptor");
     936                 :           1 :         TEST(test_libmem_0000_17,"README example 17: bounded string copy and append ignore tail bytes");
     937                 :           1 :         TEST(test_libmem_0000_18,"README example 18: direct buffer write becomes a valid string");
     938                 :           1 :         TEST(test_libmem_0000_19,"README example 19: string array append owns nested descriptors");
     939                 :           1 :         TEST(test_libmem_0000_20,"README example 20: string array foreach visits every item");
     940                 :           1 :         TEST(test_libmem_0000_21,"README example 21: m_resize flags zero and release storage");
     941                 :             : 
     942                 :           1 :         RETURN_STATUS;
     943                 :             : }
        

Generated by: LCOV version 2.0-1