LCOV - code coverage report
Current view: top level - src/test/modules/test_resowner - test_resowner_basic.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 107 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 11 0
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*--------------------------------------------------------------------------
       2              :  *
       3              :  * test_resowner_basic.c
       4              :  *              Test basic ResourceOwner functionality
       5              :  *
       6              :  * Copyright (c) 2022-2026, PostgreSQL Global Development Group
       7              :  *
       8              :  * IDENTIFICATION
       9              :  *              src/test/modules/test_resowner/test_resowner_basic.c
      10              :  *
      11              :  * -------------------------------------------------------------------------
      12              :  */
      13              : #include "postgres.h"
      14              : 
      15              : #include "fmgr.h"
      16              : #include "utils/resowner.h"
      17              : 
      18            0 : PG_MODULE_MAGIC;
      19              : 
      20              : static void ReleaseString(Datum res);
      21              : static char *PrintString(Datum res);
      22              : 
      23              : /*
      24              :  * A resource that tracks strings and prints the string when it's released.
      25              :  * This makes the order that the resources are released visible.
      26              :  */
      27              : static const ResourceOwnerDesc string_desc = {
      28              :         .name = "test resource",
      29              :         .release_phase = RESOURCE_RELEASE_AFTER_LOCKS,
      30              :         .release_priority = RELEASE_PRIO_FIRST,
      31              :         .ReleaseResource = ReleaseString,
      32              :         .DebugPrint = PrintString
      33              : };
      34              : 
      35              : static void
      36            0 : ReleaseString(Datum res)
      37              : {
      38            0 :         elog(NOTICE, "releasing string: %s", DatumGetCString(res));
      39            0 : }
      40              : 
      41              : static char *
      42            0 : PrintString(Datum res)
      43              : {
      44            0 :         return psprintf("test string \"%s\"", DatumGetCString(res));
      45              : }
      46              : 
      47              : /* demonstrates phases and priorities between a parent and child context */
      48            0 : PG_FUNCTION_INFO_V1(test_resowner_priorities);
      49              : Datum
      50            0 : test_resowner_priorities(PG_FUNCTION_ARGS)
      51              : {
      52            0 :         int32           nkinds = PG_GETARG_INT32(0);
      53            0 :         int32           nresources = PG_GETARG_INT32(1);
      54            0 :         ResourceOwner parent,
      55              :                                 child;
      56            0 :         ResourceOwnerDesc *before_desc;
      57            0 :         ResourceOwnerDesc *after_desc;
      58              : 
      59            0 :         if (nkinds <= 0)
      60            0 :                 elog(ERROR, "nkinds must be greater than zero");
      61            0 :         if (nresources <= 0)
      62            0 :                 elog(ERROR, "nresources must be greater than zero");
      63              : 
      64            0 :         parent = ResourceOwnerCreate(CurrentResourceOwner, "test parent");
      65            0 :         child = ResourceOwnerCreate(parent, "test child");
      66              : 
      67            0 :         before_desc = palloc(nkinds * sizeof(ResourceOwnerDesc));
      68            0 :         for (int i = 0; i < nkinds; i++)
      69              :         {
      70            0 :                 before_desc[i].name = psprintf("test resource before locks %d", i);
      71            0 :                 before_desc[i].release_phase = RESOURCE_RELEASE_BEFORE_LOCKS;
      72            0 :                 before_desc[i].release_priority = RELEASE_PRIO_FIRST + i;
      73            0 :                 before_desc[i].ReleaseResource = ReleaseString;
      74            0 :                 before_desc[i].DebugPrint = PrintString;
      75            0 :         }
      76            0 :         after_desc = palloc(nkinds * sizeof(ResourceOwnerDesc));
      77            0 :         for (int i = 0; i < nkinds; i++)
      78              :         {
      79            0 :                 after_desc[i].name = psprintf("test resource after locks %d", i);
      80            0 :                 after_desc[i].release_phase = RESOURCE_RELEASE_AFTER_LOCKS;
      81            0 :                 after_desc[i].release_priority = RELEASE_PRIO_FIRST + i;
      82            0 :                 after_desc[i].ReleaseResource = ReleaseString;
      83            0 :                 after_desc[i].DebugPrint = PrintString;
      84            0 :         }
      85              : 
      86              :         /* Add a bunch of resources to child, with different priorities */
      87            0 :         for (int i = 0; i < nresources; i++)
      88              :         {
      89            0 :                 ResourceOwnerDesc *kind = &before_desc[i % nkinds];
      90              : 
      91            0 :                 ResourceOwnerEnlarge(child);
      92            0 :                 ResourceOwnerRemember(child,
      93            0 :                                                           CStringGetDatum(psprintf("child before locks priority %d", kind->release_priority)),
      94            0 :                                                           kind);
      95            0 :         }
      96            0 :         for (int i = 0; i < nresources; i++)
      97              :         {
      98            0 :                 ResourceOwnerDesc *kind = &after_desc[i % nkinds];
      99              : 
     100            0 :                 ResourceOwnerEnlarge(child);
     101            0 :                 ResourceOwnerRemember(child,
     102            0 :                                                           CStringGetDatum(psprintf("child after locks priority %d", kind->release_priority)),
     103            0 :                                                           kind);
     104            0 :         }
     105              : 
     106              :         /* And also to the parent */
     107            0 :         for (int i = 0; i < nresources; i++)
     108              :         {
     109            0 :                 ResourceOwnerDesc *kind = &after_desc[i % nkinds];
     110              : 
     111            0 :                 ResourceOwnerEnlarge(parent);
     112            0 :                 ResourceOwnerRemember(parent,
     113            0 :                                                           CStringGetDatum(psprintf("parent after locks priority %d", kind->release_priority)),
     114            0 :                                                           kind);
     115            0 :         }
     116            0 :         for (int i = 0; i < nresources; i++)
     117              :         {
     118            0 :                 ResourceOwnerDesc *kind = &before_desc[i % nkinds];
     119              : 
     120            0 :                 ResourceOwnerEnlarge(parent);
     121            0 :                 ResourceOwnerRemember(parent,
     122            0 :                                                           CStringGetDatum(psprintf("parent before locks priority %d", kind->release_priority)),
     123            0 :                                                           kind);
     124            0 :         }
     125              : 
     126            0 :         elog(NOTICE, "releasing resources before locks");
     127            0 :         ResourceOwnerRelease(parent, RESOURCE_RELEASE_BEFORE_LOCKS, false, false);
     128            0 :         elog(NOTICE, "releasing locks");
     129            0 :         ResourceOwnerRelease(parent, RESOURCE_RELEASE_LOCKS, false, false);
     130            0 :         elog(NOTICE, "releasing resources after locks");
     131            0 :         ResourceOwnerRelease(parent, RESOURCE_RELEASE_AFTER_LOCKS, false, false);
     132              : 
     133            0 :         ResourceOwnerDelete(parent);
     134              : 
     135            0 :         PG_RETURN_VOID();
     136            0 : }
     137              : 
     138            0 : PG_FUNCTION_INFO_V1(test_resowner_leak);
     139              : Datum
     140            0 : test_resowner_leak(PG_FUNCTION_ARGS)
     141              : {
     142            0 :         ResourceOwner resowner;
     143              : 
     144            0 :         resowner = ResourceOwnerCreate(CurrentResourceOwner, "TestOwner");
     145              : 
     146            0 :         ResourceOwnerEnlarge(resowner);
     147              : 
     148            0 :         ResourceOwnerRemember(resowner, CStringGetDatum("my string"), &string_desc);
     149              : 
     150              :         /* don't call ResourceOwnerForget, so that it is leaked */
     151              : 
     152            0 :         ResourceOwnerRelease(resowner, RESOURCE_RELEASE_BEFORE_LOCKS, true, false);
     153            0 :         ResourceOwnerRelease(resowner, RESOURCE_RELEASE_LOCKS, true, false);
     154            0 :         ResourceOwnerRelease(resowner, RESOURCE_RELEASE_AFTER_LOCKS, true, false);
     155              : 
     156            0 :         ResourceOwnerDelete(resowner);
     157              : 
     158            0 :         PG_RETURN_VOID();
     159            0 : }
     160              : 
     161            0 : PG_FUNCTION_INFO_V1(test_resowner_remember_between_phases);
     162              : Datum
     163            0 : test_resowner_remember_between_phases(PG_FUNCTION_ARGS)
     164              : {
     165            0 :         ResourceOwner resowner;
     166              : 
     167            0 :         resowner = ResourceOwnerCreate(CurrentResourceOwner, "TestOwner");
     168              : 
     169            0 :         ResourceOwnerRelease(resowner, RESOURCE_RELEASE_BEFORE_LOCKS, true, false);
     170              : 
     171              :         /*
     172              :          * Try to remember a new resource.  Fails because we already called
     173              :          * ResourceOwnerRelease.
     174              :          */
     175            0 :         ResourceOwnerEnlarge(resowner);
     176            0 :         ResourceOwnerRemember(resowner, CStringGetDatum("my string"), &string_desc);
     177              : 
     178              :         /* unreachable */
     179            0 :         elog(ERROR, "ResourceOwnerEnlarge should have errored out");
     180              : 
     181            0 :         PG_RETURN_VOID();
     182            0 : }
     183              : 
     184            0 : PG_FUNCTION_INFO_V1(test_resowner_forget_between_phases);
     185              : Datum
     186            0 : test_resowner_forget_between_phases(PG_FUNCTION_ARGS)
     187              : {
     188            0 :         ResourceOwner resowner;
     189            0 :         Datum           str_resource;
     190              : 
     191            0 :         resowner = ResourceOwnerCreate(CurrentResourceOwner, "TestOwner");
     192              : 
     193            0 :         ResourceOwnerEnlarge(resowner);
     194            0 :         str_resource = CStringGetDatum("my string");
     195            0 :         ResourceOwnerRemember(resowner, str_resource, &string_desc);
     196              : 
     197            0 :         ResourceOwnerRelease(resowner, RESOURCE_RELEASE_BEFORE_LOCKS, true, false);
     198              : 
     199              :         /*
     200              :          * Try to forget the resource that was remembered earlier.  Fails because
     201              :          * we already called ResourceOwnerRelease.
     202              :          */
     203            0 :         ResourceOwnerForget(resowner, str_resource, &string_desc);
     204              : 
     205              :         /* unreachable */
     206            0 :         elog(ERROR, "ResourceOwnerForget should have errored out");
     207              : 
     208            0 :         PG_RETURN_VOID();
     209            0 : }
        

Generated by: LCOV version 2.3.2-1