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

             Branch data     Line data    Source code
       1                 :             : #include "test_libmem_all.h"
       2                 :             : 
       3                 :             : /**
       4                 :             :  * @brief Verify data-to-string conversion for a manually filled char descriptor
       5                 :             :  *
       6                 :             :  * Starts with a data-mode char descriptor, writes `xyz` through the typed
       7                 :             :  * writable data view, and then converts the descriptor to string mode.
       8                 :             :  * The checks prove that conversion appends the missing terminator,
       9                 :             :  * caches the visible string length, and keeps the resulting text
      10                 :             :  * readable through the soft string view
      11                 :             :  *
      12                 :             :  * @return Return describing success or failure
      13                 :             :  */
      14                 :           1 : static Return test_libmem_0015_1(void)
      15                 :             : {
      16                 :           1 :         INITTEST;
      17                 :             : 
      18                 :           1 :         m_create(char,buffer);
      19                 :             : 
      20                 :             :         /* Allocate exactly three data bytes, without room for a terminator yet */
      21                 :           1 :         ASSERT(SUCCESS == m_resize(buffer,3));
      22                 :             : 
      23                 :             :         /* Write a non-terminated payload through the typed writable data view */
      24                 :           1 :         char *bytes = m_data(char,buffer);
      25                 :           1 :         ASSERT(bytes != NULL);
      26                 :             : 
      27                 :           1 :         IF(bytes != NULL)
      28                 :             :         {
      29                 :           1 :                 bytes[0] = 'x';
      30                 :           1 :                 bytes[1] = 'y';
      31                 :           1 :                 bytes[2] = 'z';
      32                 :             :         }
      33                 :             : 
      34                 :             :         /* Conversion from data mode must measure the payload and add one terminator slot */
      35                 :           1 :         ASSERT(buffer->string_length == 0);
      36                 :           1 :         ASSERT(buffer->is_string == false);
      37                 :           1 :         ASSERT(SUCCESS == m_to_string(buffer));
      38                 :           1 :         ASSERT(buffer->string_length == 3);
      39                 :           1 :         ASSERT(buffer->is_string == true);
      40                 :           1 :         ASSERT(buffer->length == 4);
      41                 :           1 :         ASSERT(0 == strcmp(m_text(buffer),"xyz"));
      42                 :             : 
      43                 :           1 :         call(m_del(buffer));
      44                 :             : 
      45                 :           1 :         RETURN_STATUS;
      46                 :             : }
      47                 :             : 
      48                 :             : /**
      49                 :             :  * @brief Verify string resize shrink and zero-length resize with retained reserve
      50                 :             :  *
      51                 :             :  * Builds a string descriptor containing `xyz`, shrinks it to three
      52                 :             :  * logical slots, and verifies that the visible text becomes `xy`.
      53                 :             :  * Then the descriptor is resized to zero without RELEASE_UNUSED; the
      54                 :             :  * already allocated backing block must stay attached, while string
      55                 :             :  * length and logical length are cleared
      56                 :             :  *
      57                 :             :  * @return Return describing success or failure
      58                 :             :  */
      59                 :           1 : static Return test_libmem_0015_2(void)
      60                 :             : {
      61                 :           1 :         INITTEST;
      62                 :             : 
      63                 :           1 :         m_create(char,buffer,MEMORY_STRING);
      64                 :             : 
      65                 :             :         /* Seed the string descriptor with three visible bytes plus a terminator */
      66                 :           1 :         ASSERT(SUCCESS == m_concat_literal(buffer,"xyz"));
      67                 :           1 :         ASSERT(buffer->string_length == 3);
      68                 :           1 :         ASSERT(buffer->is_string == true);
      69                 :           1 :         ASSERT(buffer->length == 4);
      70                 :           1 :         ASSERT(0 == strcmp(m_text(buffer),"xyz"));
      71                 :             : 
      72                 :             :         /* Shrinking to three total slots leaves room for only two visible bytes plus the terminator */
      73                 :           1 :         ASSERT(SUCCESS == m_resize(buffer,3));
      74                 :           1 :         ASSERT(buffer->string_length == 2);
      75                 :           1 :         ASSERT(buffer->is_string == true);
      76                 :           1 :         ASSERT(buffer->length == 3);
      77                 :           1 :         ASSERT(0 == strcmp(m_text(buffer),"xy"));
      78                 :             : 
      79                 :             :         /* Remember the attached allocation; zero resize without RELEASE_UNUSED must keep it reserved */
      80                 :           1 :         void *const retained_string_data = buffer->data;
      81                 :           1 :         const size_t retained_string_bytes = buffer->actually_allocated_bytes;
      82                 :             : 
      83                 :           1 :         ASSERT(retained_string_data != NULL);
      84                 :           1 :         ASSERT(retained_string_bytes > 0);
      85                 :             : 
      86                 :             :         /* Logical zeroing clears the string while keeping the backing block available for reuse */
      87                 :           1 :         ASSERT(SUCCESS == m_resize(buffer,0));
      88                 :           1 :         ASSERT(buffer->data == retained_string_data);
      89                 :           1 :         ASSERT(buffer->actually_allocated_bytes == retained_string_bytes);
      90                 :           1 :         ASSERT(buffer->length == 0);
      91                 :           1 :         ASSERT(buffer->string_length == 0);
      92                 :           1 :         ASSERT(buffer->is_string == true);
      93                 :           1 :         ASSERT(0 == strcmp(m_text(buffer),""));
      94                 :             : 
      95                 :           1 :         call(m_del(buffer));
      96                 :             : 
      97                 :           1 :         RETURN_STATUS;
      98                 :             : }
      99                 :             : 
     100                 :             : /**
     101                 :             :  * @brief Verify refill after zero resize and raw writable mutation of string storage
     102                 :             :  *
     103                 :             :  * Reuses a string descriptor after `m_resize(buffer,0)` without
     104                 :             :  * RELEASE_UNUSED, then writes through m_raw_data. The test proves that
     105                 :             :  * refill reuses the retained backing block and that raw writes expose
     106                 :             :  * the live string storage without recalculating cached metadata
     107                 :             :  *
     108                 :             :  * @return Return describing success or failure
     109                 :             :  */
     110                 :           1 : static Return test_libmem_0015_3(void)
     111                 :             : {
     112                 :           1 :         INITTEST;
     113                 :             : 
     114                 :           1 :         m_create(char,buffer,MEMORY_STRING);
     115                 :             :         static const char refill[] = "hi";
     116                 :             : 
     117                 :             :         /* Create and then logically clear a string while keeping its allocation */
     118                 :           1 :         ASSERT(SUCCESS == m_concat_literal(buffer,"xy"));
     119                 :           1 :         void *const retained_string_data = buffer->data;
     120                 :           1 :         const size_t retained_string_bytes = buffer->actually_allocated_bytes;
     121                 :             : 
     122                 :           1 :         ASSERT(retained_string_data != NULL);
     123                 :           1 :         ASSERT(retained_string_bytes > 0);
     124                 :           1 :         ASSERT(SUCCESS == m_resize(buffer,0));
     125                 :           1 :         ASSERT(buffer->data == retained_string_data);
     126                 :           1 :         ASSERT(buffer->actually_allocated_bytes == retained_string_bytes);
     127                 :             : 
     128                 :             :         /* Refill through the string API and require the previously retained block to be reused */
     129                 :           1 :         ASSERT(SUCCESS == m_concat_fixed_string(buffer,sizeof(refill),refill));
     130                 :           1 :         ASSERT(buffer->data == retained_string_data);
     131                 :           1 :         ASSERT(buffer->actually_allocated_bytes == retained_string_bytes);
     132                 :           1 :         ASSERT(buffer->string_length == 2);
     133                 :           1 :         ASSERT(buffer->is_string == true);
     134                 :           1 :         ASSERT(buffer->length == 3);
     135                 :           1 :         ASSERT(0 == strcmp(m_text(buffer),"hi"));
     136                 :             : 
     137                 :             :         /* Raw access exposes the live storage but intentionally leaves cached metadata unchanged */
     138                 :           1 :         char *raw_bytes = (char *)m_raw_data(buffer);
     139                 :           1 :         ASSERT(raw_bytes != NULL);
     140                 :             : 
     141                 :           1 :         IF(raw_bytes != NULL)
     142                 :             :         {
     143                 :           1 :                 raw_bytes[0] = 'b';
     144                 :           1 :                 raw_bytes[1] = 'y';
     145                 :           1 :                 raw_bytes[2] = '\0';
     146                 :             :         }
     147                 :             : 
     148                 :             :         /* The same string descriptor now reads as "by" while its cached length remains valid */
     149                 :           1 :         ASSERT(buffer->data == retained_string_data);
     150                 :           1 :         ASSERT(buffer->string_length == 2);
     151                 :           1 :         ASSERT(buffer->is_string == true);
     152                 :           1 :         ASSERT(buffer->length == 3);
     153                 :           1 :         ASSERT(0 == strcmp(m_text(buffer),"by"));
     154                 :             : 
     155                 :           1 :         call(m_del(buffer));
     156                 :             : 
     157                 :           1 :         RETURN_STATUS;
     158                 :             : }
     159                 :             : 
     160                 :             : /**
     161                 :             :  * @brief Verify m_del clears string descriptor storage while preserving string mode
     162                 :             :  *
     163                 :             :  * Deletes a non-empty string descriptor and checks the postcondition:
     164                 :             :  * allocated storage and logical counters are cleared, while the
     165                 :             :  * descriptor's string mode flag remains set for possible later reuse
     166                 :             :  *
     167                 :             :  * @return Return describing success or failure
     168                 :             :  */
     169                 :           1 : static Return test_libmem_0015_4(void)
     170                 :             : {
     171                 :           1 :         INITTEST;
     172                 :             : 
     173                 :           1 :         m_create(char,buffer,MEMORY_STRING);
     174                 :             : 
     175                 :             :         /* Make deletion meaningful by giving the descriptor live string storage first */
     176                 :           1 :         ASSERT(SUCCESS == m_concat_literal(buffer,"hi"));
     177                 :           1 :         ASSERT(buffer->data != NULL);
     178                 :           1 :         ASSERT(buffer->actually_allocated_bytes > 0);
     179                 :             : 
     180                 :             :         /* m_del frees storage and lengths, but preserves the descriptor mode */
     181                 :           1 :         call(m_del(buffer));
     182                 :           1 :         ASSERT(buffer->length == 0);
     183                 :           1 :         ASSERT(buffer->string_length == 0);
     184                 :           1 :         ASSERT(buffer->is_string == true);
     185                 :           1 :         ASSERT(buffer->data == NULL);
     186                 :           1 :         ASSERT(buffer->actually_allocated_bytes == 0);
     187                 :             : 
     188                 :           1 :         RETURN_STATUS;
     189                 :             : }
     190                 :             : 
     191                 :             : /**
     192                 :             :  * @brief Verify string conversion, resizing, raw access, and cleanup metadata
     193                 :             :  *
     194                 :             :  * In plain terms, this suite follows the life of a small char string
     195                 :             :  * descriptor through the operations that are easiest to desynchronize:
     196                 :             :  * converting raw bytes into a string, shrinking a string while keeping
     197                 :             :  * its cached length correct, resizing to zero without releasing the
     198                 :             :  * reserved block, refilling the retained block, mutating the live
     199                 :             :  * storage through m_raw_data, and finally deleting the descriptor.
     200                 :             :  * The nested tests keep those contracts separate so a failure points at
     201                 :             :  * the specific state transition that broke cached string metadata
     202                 :             :  *
     203                 :             :  * @return Return describing success or failure
     204                 :             :  */
     205                 :           1 : Return test_libmem_0015(void)
     206                 :             : {
     207                 :           1 :         INITTEST;
     208                 :             : 
     209                 :           1 :         TEST(test_libmem_0015_1,"m_to_string finalizes manually filled char data");
     210                 :           1 :         TEST(test_libmem_0015_2,"String resize shrink and zero resize keep metadata coherent");
     211                 :           1 :         TEST(test_libmem_0015_3,"Refill after zero resize and raw mutation reuse live storage");
     212                 :           1 :         TEST(test_libmem_0015_4,"m_del clears string storage while preserving string mode");
     213                 :             : 
     214                 :           1 :         RETURN_STATUS;
     215                 :             : }
        

Generated by: LCOV version 2.0-1