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

             Branch data     Line data    Source code
       1                 :             : #include "test_libmem_all.h"
       2                 :             : 
       3                 :             : /**
       4                 :             :  * @brief Verify m_resize behavior with flag combinations on typed point descriptors
       5                 :             :  *
       6                 :             :  * Drives two descriptors over a user-defined point element type
       7                 :             :  * (struct with two int fields, see test_libmem_utils.h) through a
       8                 :             :  * chain of m_resize calls covering the practically interesting flag
       9                 :             :  * combinations. The plain descriptor exercises an unflagged grow.
      10                 :             :  * The second descriptor is taken through a fresh grow with
      11                 :             :  * ZERO_NEW_MEMORY, then through a deterministic combined-flag grow:
      12                 :             :  * the test exposes a tail, writes non-zero typed elements into it,
      13                 :             :  * hides it again without releasing storage, and grows with
      14                 :             :  * ZERO_NEW_MEMORY | RELEASE_UNUSED. That grow has to preserve the
      15                 :             :  * existing payload while clearing every re-exposed tail element. A
      16                 :             :  * shrink with the same combined flags then has to keep the surviving
      17                 :             :  * payload intact. Both read-only and writable views are exercised:
      18                 :             :  * m_data_ro confirms the zero fill through the typed element layout,
      19                 :             :  * and m_data prepares the non-zero payload that resize must clear or
      20                 :             :  * preserve as appropriate.
      21                 :             :  * The final block asserts that both descriptors stayed in data mode
      22                 :             :  * (is_string == false, string_length == 0) for the whole sequence
      23                 :             :  * and that m_del releases each cleanly
      24                 :             :  *
      25                 :             :  * The test guards against two classes of regressions: confusion
      26                 :             :  * between byte size and logical element size in resize bookkeeping
      27                 :             :  * (checking both .x and .y makes the assertion depend on the full
      28                 :             :  * point element, not only its first field), and silent loss of
      29                 :             :  * existing payload across grow/shrink with combined flags
      30                 :             :  *
      31                 :             :  * @return Return describing success or failure
      32                 :             :  */
      33                 :           1 : Return test_libmem_0010(void)
      34                 :             : {
      35                 :           1 :         INITTEST;
      36                 :             : 
      37                 :             :         /* Two typed descriptors over the user-defined point element so resize bookkeeping is exercised on a non-byte payload */
      38                 :           1 :         m_create(point,points);
      39                 :           1 :         m_create(point,zeroed_points);
      40                 :             : 
      41                 :             :         /* Both descriptors must enter the test in data mode with zero cached string length */
      42                 :           1 :         ASSERT(points->string_length == 0);
      43                 :           1 :         ASSERT(points->is_string == false);
      44                 :           1 :         ASSERT(zeroed_points->string_length == 0);
      45                 :           1 :         ASSERT(zeroed_points->is_string == false);
      46                 :             : 
      47                 :             :         /* Exercise an ordinary typed grow and a successful fresh grow with ZERO_NEW_MEMORY */
      48                 :           1 :         ASSERT(SUCCESS == m_resize(points,5));
      49                 :           1 :         ASSERT(SUCCESS == m_resize(zeroed_points,3,ZERO_NEW_MEMORY));
      50                 :             : 
      51                 :             :         /* Writable view receives a non-zero surviving payload that later resize calls must preserve */
      52                 :           1 :         point *zeroed_writer = m_data(point,zeroed_points);
      53                 :           1 :         ASSERT(zeroed_writer != NULL);
      54                 :             : 
      55                 :           1 :         IF(zeroed_writer != NULL)
      56                 :             :         {
      57                 :           1 :                 zeroed_writer[0] = (point){1,1};
      58                 :             :         }
      59                 :             : 
      60                 :             :         /* Expose and dirty the future tail before hiding it inside the retained allocation */
      61                 :           1 :         ASSERT(SUCCESS == m_resize(zeroed_points,6));
      62                 :             : 
      63                 :           1 :         zeroed_writer = m_data(point,zeroed_points);
      64                 :           1 :         ASSERT(zeroed_writer != NULL);
      65                 :             : 
      66                 :           1 :         IF(zeroed_writer != NULL)
      67                 :             :         {
      68                 :           1 :                 zeroed_writer[3] = (point){31,32};
      69                 :           1 :                 zeroed_writer[4] = (point){41,42};
      70                 :           1 :                 zeroed_writer[5] = (point){51,52};
      71                 :             :         }
      72                 :             : 
      73                 :           1 :         ASSERT(SUCCESS == m_resize(zeroed_points,3));
      74                 :             : 
      75                 :             :         /* Grow with the combined flags must preserve the prefix and clear the retained non-zero tail */
      76                 :           1 :         ASSERT(SUCCESS == m_resize(zeroed_points,6,ZERO_NEW_MEMORY | RELEASE_UNUSED));
      77                 :             : 
      78                 :             :         /* Index 0 remains (1,1), while every re-exposed tail point must be all-zero */
      79                 :           1 :         const point *expanded_view = m_data_ro(point,zeroed_points);
      80                 :           1 :         ASSERT(expanded_view != NULL);
      81                 :             : 
      82                 :           1 :         IF(expanded_view != NULL)
      83                 :             :         {
      84                 :           1 :                 ASSERT(expanded_view[0].x == 1);
      85                 :           1 :                 ASSERT(expanded_view[0].y == 1);
      86                 :           1 :                 ASSERT(expanded_view[3].x == 0);
      87                 :           1 :                 ASSERT(expanded_view[3].y == 0);
      88                 :           1 :                 ASSERT(expanded_view[4].x == 0);
      89                 :           1 :                 ASSERT(expanded_view[4].y == 0);
      90                 :           1 :                 ASSERT(expanded_view[5].x == 0);
      91                 :           1 :                 ASSERT(expanded_view[5].y == 0);
      92                 :             :         }
      93                 :             : 
      94                 :             :         /* Shrink with the same flag combination has to keep the previously written surviving element intact */
      95                 :           1 :         ASSERT(SUCCESS == m_resize(zeroed_points,2,ZERO_NEW_MEMORY | RELEASE_UNUSED));
      96                 :             : 
      97                 :             :         /* Logical length now matches the requested two and the surviving element still reads (1,1) */
      98                 :           1 :         const point *shrunk_view = m_data_ro(point,zeroed_points);
      99                 :           1 :         ASSERT(shrunk_view != NULL);
     100                 :             : 
     101                 :           1 :         IF(shrunk_view != NULL)
     102                 :             :         {
     103                 :           1 :                 ASSERT(zeroed_points->length == 2);
     104                 :           1 :                 ASSERT(shrunk_view[0].x == 1);
     105                 :           1 :                 ASSERT(shrunk_view[0].y == 1);
     106                 :             :         }
     107                 :             : 
     108                 :             :         /* Mode invariants survived the full resize chain and m_del releases both descriptors cleanly */
     109                 :           1 :         ASSERT(points->string_length == 0);
     110                 :           1 :         ASSERT(points->is_string == false);
     111                 :           1 :         ASSERT(zeroed_points->string_length == 0);
     112                 :           1 :         ASSERT(zeroed_points->is_string == false);
     113                 :           1 :         call(m_del(points));
     114                 :           1 :         call(m_del(zeroed_points));
     115                 :             : 
     116                 :           1 :         RETURN_STATUS;
     117                 :             : }
        

Generated by: LCOV version 2.0-1