LCOV - code coverage report
Current view: top level - src/test/modules/test_dsa - test_dsa.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 96.2 % 53 51
Test Date: 2026-07-03 19:57:34 Functions: 100.0 % 8 8
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 70.0 % 20 14

             Branch data     Line data    Source code
       1                 :             : /*--------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * test_dsa.c
       4                 :             :  *      Test dynamic shared memory areas (DSAs)
       5                 :             :  *
       6                 :             :  * Copyright (c) 2022-2026, PostgreSQL Global Development Group
       7                 :             :  *
       8                 :             :  * IDENTIFICATION
       9                 :             :  *      src/test/modules/test_dsa/test_dsa.c
      10                 :             :  *
      11                 :             :  * -------------------------------------------------------------------------
      12                 :             :  */
      13                 :             : #include "postgres.h"
      14                 :             : 
      15                 :             : #include "fmgr.h"
      16                 :             : #include "storage/dsm_registry.h"
      17                 :             : #include "storage/lwlock.h"
      18                 :             : #include "utils/dsa.h"
      19                 :             : #include "utils/freepage.h"
      20                 :             : #include "utils/resowner.h"
      21                 :             : 
      22                 :           1 : PG_MODULE_MAGIC;
      23                 :             : 
      24                 :             : static void
      25                 :           1 : init_tranche(void *ptr, void *arg)
      26                 :             : {
      27                 :           1 :     int        *tranche_id = (int *) ptr;
      28                 :             : 
      29                 :           1 :     *tranche_id = LWLockNewTrancheId("test_dsa");
      30                 :           1 : }
      31                 :             : 
      32                 :             : /* Test basic DSA functionality */
      33                 :           2 : PG_FUNCTION_INFO_V1(test_dsa_basic);
      34                 :             : Datum
      35                 :           1 : test_dsa_basic(PG_FUNCTION_ARGS)
      36                 :             : {
      37                 :             :     int        *tranche_id;
      38                 :             :     bool        found;
      39                 :             :     dsa_area   *a;
      40                 :             :     dsa_pointer p[100];
      41                 :             : 
      42                 :           1 :     tranche_id = GetNamedDSMSegment("test_dsa", sizeof(int),
      43                 :             :                                     init_tranche, &found, NULL);
      44                 :             : 
      45                 :           1 :     a = dsa_create(*tranche_id);
      46         [ +  + ]:         101 :     for (int i = 0; i < 100; i++)
      47                 :             :     {
      48                 :         100 :         p[i] = dsa_allocate(a, 1000);
      49                 :         100 :         snprintf(dsa_get_address(a, p[i]), 1000, "foobar%d", i);
      50                 :             :     }
      51                 :             : 
      52         [ +  + ]:         101 :     for (int i = 0; i < 100; i++)
      53                 :             :     {
      54                 :             :         char        buf[100];
      55                 :             : 
      56                 :         100 :         snprintf(buf, 100, "foobar%d", i);
      57         [ -  + ]:         100 :         if (strcmp(dsa_get_address(a, p[i]), buf) != 0)
      58         [ #  # ]:           0 :             elog(ERROR, "no match");
      59                 :             :     }
      60                 :             : 
      61         [ +  + ]:         101 :     for (int i = 0; i < 100; i++)
      62                 :             :     {
      63                 :         100 :         dsa_free(a, p[i]);
      64                 :             :     }
      65                 :             : 
      66                 :           1 :     dsa_detach(a);
      67                 :             : 
      68                 :           1 :     PG_RETURN_VOID();
      69                 :             : }
      70                 :             : 
      71                 :             : /* Test using DSA across different resource owners */
      72                 :           2 : PG_FUNCTION_INFO_V1(test_dsa_resowners);
      73                 :             : Datum
      74                 :           1 : test_dsa_resowners(PG_FUNCTION_ARGS)
      75                 :             : {
      76                 :             :     int        *tranche_id;
      77                 :             :     bool        found;
      78                 :             :     dsa_area   *a;
      79                 :             :     dsa_pointer p[10000];
      80                 :             :     ResourceOwner oldowner;
      81                 :             :     ResourceOwner childowner;
      82                 :             : 
      83                 :           1 :     tranche_id = GetNamedDSMSegment("test_dsa", sizeof(int),
      84                 :             :                                     init_tranche, &found, NULL);
      85                 :             : 
      86                 :             :     /* Create DSA in parent resource owner */
      87                 :           1 :     a = dsa_create(*tranche_id);
      88                 :             : 
      89                 :             :     /*
      90                 :             :      * Switch to child resource owner, and do a bunch of allocations in the
      91                 :             :      * DSA
      92                 :             :      */
      93                 :           1 :     oldowner = CurrentResourceOwner;
      94                 :           1 :     childowner = ResourceOwnerCreate(oldowner, "test_dsa temp owner");
      95                 :           1 :     CurrentResourceOwner = childowner;
      96                 :             : 
      97         [ +  + ]:       10001 :     for (int i = 0; i < 10000; i++)
      98                 :             :     {
      99                 :       10000 :         p[i] = dsa_allocate(a, 1000);
     100                 :       10000 :         snprintf(dsa_get_address(a, p[i]), 1000, "foobar%d", i);
     101                 :             :     }
     102                 :             : 
     103                 :             :     /* Also test freeing, by freeing some of the allocations. */
     104         [ +  + ]:         501 :     for (int i = 0; i < 500; i++)
     105                 :         500 :         dsa_free(a, p[i]);
     106                 :             : 
     107                 :             :     /* Release the child resource owner */
     108                 :           1 :     CurrentResourceOwner = oldowner;
     109                 :           1 :     ResourceOwnerRelease(childowner,
     110                 :             :                          RESOURCE_RELEASE_BEFORE_LOCKS,
     111                 :             :                          true, false);
     112                 :           1 :     ResourceOwnerRelease(childowner,
     113                 :             :                          RESOURCE_RELEASE_LOCKS,
     114                 :             :                          true, false);
     115                 :           1 :     ResourceOwnerRelease(childowner,
     116                 :             :                          RESOURCE_RELEASE_AFTER_LOCKS,
     117                 :             :                          true, false);
     118                 :           1 :     ResourceOwnerDelete(childowner);
     119                 :             : 
     120                 :           1 :     dsa_detach(a);
     121                 :             : 
     122                 :           1 :     PG_RETURN_VOID();
     123                 :             : }
     124                 :             : 
     125                 :             : /*
     126                 :             :  * test_dsa_allocate
     127                 :             :  *
     128                 :             :  * Test DSA allocation across a range of sizes to exercise the pagemap
     129                 :             :  * sizing logic in make_new_segment().  A fresh DSA is created for each
     130                 :             :  * iteration so that each allocation triggers a new segment creation,
     131                 :             :  * including the odd-sized segment path.
     132                 :             :  */
     133                 :           2 : PG_FUNCTION_INFO_V1(test_dsa_allocate);
     134                 :             : Datum
     135                 :           2 : test_dsa_allocate(PG_FUNCTION_ARGS)
     136                 :             : {
     137                 :           2 :     int         start_num_pages = PG_GETARG_INT32(0);
     138                 :           2 :     int         end_num_pages = PG_GETARG_INT32(1);
     139                 :           2 :     int         step = PG_GETARG_INT32(2);
     140                 :             :     size_t      usable_pages;
     141                 :             :     int        *tranche_id;
     142                 :             :     bool        found;
     143                 :             :     dsa_area   *a;
     144                 :             :     dsa_pointer dp;
     145                 :             : 
     146         [ -  + ]:           2 :     if (start_num_pages > end_num_pages)
     147         [ #  # ]:           0 :         elog(ERROR, "incorrect start and end parameters");
     148                 :             : 
     149                 :           2 :     tranche_id = GetNamedDSMSegment("test_dsa", sizeof(int),
     150                 :             :                                     init_tranche, &found, NULL);
     151                 :             : 
     152         [ +  + ]:          13 :     for (usable_pages = start_num_pages; usable_pages < end_num_pages; usable_pages += step)
     153                 :             :     {
     154                 :          11 :         a = dsa_create(*tranche_id);
     155                 :          11 :         dp = dsa_allocate(a, usable_pages * FPM_PAGE_SIZE);
     156                 :             : 
     157                 :          11 :         dsa_free(a, dp);
     158                 :          11 :         dsa_detach(a);
     159                 :             :     }
     160                 :             : 
     161                 :           2 :     PG_RETURN_VOID();
     162                 :             : }
        

Generated by: LCOV version 2.0-1