LCOV - code coverage report
Current view: top level - src - db_check_changes.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 75.8 % 66 50
Test Date: 2026-03-01 04:31:48 Functions: 100.0 % 3 3
Branches: 64.6 % 48 31

             Branch data     Line data    Source code
       1                 :             : #include "precizer.h"
       2                 :             : #include <utime.h>
       3                 :             : 
       4                 :             : #ifdef TESTITALL_TEST_HOOKS
       5                 :             : /**
       6                 :             :  * @brief Test-only hook to simulate unexpected DB metadata change in dry-run mode.
       7                 :             :  *
       8                 :             :  * When enabled by environment variable
       9                 :             :  * `PRECIZER_TEST_DB_FILE_TIMESTAMPS_WILL_BUMPED=true`, this helper updates
      10                 :             :  * database file timestamps via utime(), forcing metadata drift before the final
      11                 :             :  * `stat()` comparison in db_check_changes().
      12                 :             :  *
      13                 :             :  * The hook is intentionally limited to dry-run on an existing primary DB file.
      14                 :             :  */
      15                 :          92 : static Return run_test_hook_bump_db_timestamps(void)
      16                 :             : {
      17                 :             :         /* Status returned by this function through provide()
      18                 :             :            Default value assumes successful completion */
      19                 :          92 :         Return status = SUCCESS;
      20                 :             : 
      21                 :          92 :         const char *flag_value = getenv("PRECIZER_TEST_DB_FILE_TIMESTAMPS_WILL_BUMPED");
      22                 :             : 
      23   [ +  +  +  + ]:          92 :         if(flag_value == NULL || strcmp(flag_value,"true") != 0)
      24                 :             :         {
      25                 :          90 :                 return(status);
      26                 :             :         }
      27                 :             : 
      28         [ -  + ]:           2 :         if(config->dry_run != true)
      29                 :             :         {
      30                 :           0 :                 slog(ERROR,"Test hook failed: PRECIZER_TEST_DB_FILE_TIMESTAMPS_WILL_BUMPED requires --dry-run\n");
      31                 :           0 :                 return(FAILURE);
      32                 :             :         }
      33                 :             : 
      34         [ -  + ]:           2 :         if(config->db_primary_file_exists != true)
      35                 :             :         {
      36                 :           0 :                 return(status);
      37                 :             :         }
      38                 :             : 
      39                 :           2 :         const char *db_path = confstr(db_primary_file_path);
      40                 :             : 
      41   [ +  -  -  + ]:           2 :         if(db_path == NULL || db_path[0] == '\0')
      42                 :             :         {
      43                 :           0 :                 slog(ERROR,"Test hook failed: database path is empty\n");
      44                 :           0 :                 return(FAILURE);
      45                 :             :         }
      46                 :             : 
      47         [ -  + ]:           2 :         if(utime(db_path,NULL) != 0)
      48                 :             :         {
      49                 :           0 :                 slog(ERROR,"Test hook failed: unable to bump timestamps for %s\n",db_path);
      50                 :           0 :                 return(FAILURE);
      51                 :             :         }
      52                 :             : 
      53                 :           2 :         slog(TESTING,"Test hook: database file timestamps were bumped for %s\n",confstr(db_file_name));
      54                 :             : 
      55                 :           2 :         return(status);
      56                 :             : }
      57                 :             : 
      58                 :             : /**
      59                 :             :  * @brief Test-only hook to simulate missing DB metadata drift during update mode.
      60                 :             :  *
      61                 :             :  * When enabled by environment variable
      62                 :             :  * `PRECIZER_TEST_DB_FILE_STAT_WILL_BE_RESYNCED=true`, this helper overwrites
      63                 :             :  * the saved baseline stat (`config->db_file_stat`) with the current DB file
      64                 :             :  * stat. This forces metadata comparison in db_check_changes() to report
      65                 :             :  * IDENTICAL, even if the database was modified earlier in the same run.
      66                 :             :  *
      67                 :             :  * The hook is intentionally limited to non-dry-run mode and to cases where
      68                 :             :  * `config->db_primary_file_modified` is already true.
      69                 :             :  */
      70                 :          92 : static Return run_test_hook_resync_db_stat_baseline(const struct stat *db_current_stat)
      71                 :             : {
      72                 :             :         /* Status returned by this function through provide()
      73                 :             :            Default value assumes successful completion */
      74                 :          92 :         Return status = SUCCESS;
      75                 :             : 
      76                 :          92 :         const char *flag_value = getenv("PRECIZER_TEST_DB_FILE_STAT_WILL_BE_RESYNCED");
      77                 :             : 
      78   [ +  +  +  + ]:          92 :         if(flag_value == NULL || strcmp(flag_value,"true") != 0)
      79                 :             :         {
      80                 :          90 :                 return(status);
      81                 :             :         }
      82                 :             : 
      83         [ -  + ]:           2 :         if(config->dry_run == true)
      84                 :             :         {
      85                 :           0 :                 slog(ERROR,"Test hook failed: PRECIZER_TEST_DB_FILE_STAT_WILL_BE_RESYNCED requires non-dry-run mode\n");
      86                 :           0 :                 return(FAILURE);
      87                 :             :         }
      88                 :             : 
      89         [ -  + ]:           2 :         if(config->db_primary_file_exists != true)
      90                 :             :         {
      91                 :           0 :                 return(status);
      92                 :             :         }
      93                 :             : 
      94         [ -  + ]:           2 :         if(config->db_primary_file_modified != true)
      95                 :             :         {
      96                 :           0 :                 slog(ERROR,"Test hook failed: baseline resync requested, but database modification flag is false\n");
      97                 :           0 :                 return(FAILURE);
      98                 :             :         }
      99                 :             : 
     100         [ -  + ]:           2 :         if(db_current_stat == NULL)
     101                 :             :         {
     102                 :           0 :                 slog(ERROR,"Test hook failed: current database stat is unavailable\n");
     103                 :           0 :                 return(FAILURE);
     104                 :             :         }
     105                 :             : 
     106                 :             :         /*
     107                 :             :          * Intentionally corrupt the comparison baseline for test coverage:
     108                 :             :          * make "before" equal to "after" even after a real DB update.
     109                 :             :          */
     110                 :           2 :         config->db_file_stat = *db_current_stat;
     111                 :             : 
     112                 :           2 :         slog(TESTING,"Test hook: baseline database stat was resynced to current metadata for %s\n",confstr(db_file_name));
     113                 :             : 
     114                 :           2 :         return(status);
     115                 :             : }
     116                 :             : #endif
     117                 :             : 
     118                 :          92 : Return db_check_changes(void)
     119                 :             : {
     120                 :             :         /* Status returned by this function through provide()
     121                 :             :            Default value assumes successful completion */
     122                 :          92 :         Return status = SUCCESS;
     123                 :             : 
     124                 :          92 :         struct stat db_current_stat = {0};
     125                 :             : 
     126                 :             : #ifdef TESTITALL_TEST_HOOKS
     127         [ +  - ]:          92 :         if(SUCCESS == status)
     128                 :             :         {
     129                 :          92 :                 status = run_test_hook_bump_db_timestamps();
     130                 :             :         }
     131                 :             : #endif
     132                 :             : 
     133                 :          92 :         int rc = stat(confstr(db_primary_file_path),&db_current_stat);
     134                 :             : 
     135         [ -  + ]:          92 :         if(rc < 0)
     136                 :             :         {
     137                 :           0 :                 report("Stat of %s failed with error code: %d",confstr(db_primary_file_path),rc);
     138                 :           0 :                 status = FAILURE;
     139                 :             :         }
     140                 :             : 
     141                 :             : #ifdef TESTITALL_TEST_HOOKS
     142         [ +  - ]:          92 :         if(SUCCESS == status)
     143                 :             :         {
     144                 :          92 :                 status = run_test_hook_resync_db_stat_baseline(&db_current_stat);
     145                 :             :         }
     146                 :             : #endif
     147                 :             : 
     148                 :          92 :         CmpctStat before = {0};
     149                 :          92 :         CmpctStat after = {0};
     150                 :             : 
     151   [ +  -  -  + ]:          92 :         run(stat_copy(&config->db_file_stat,&before));
     152   [ +  -  -  + ]:          92 :         run(stat_copy(&db_current_stat,&after));
     153                 :             : 
     154                 :          92 :         Changed changes = file_compare_metadata_equivalence(&before,&after);
     155                 :             : 
     156         [ +  + ]:          92 :         if(IDENTICAL != changes)
     157                 :             :         {
     158         [ +  + ]:          58 :                 if(config->db_primary_file_modified == true)
     159                 :             :                 {
     160                 :          56 :                         slog(EVERY,BOLD "The database file %s has been modified since the program was launched" RESET "\n",confstr(db_file_name));
     161                 :             :                 } else {
     162                 :           2 :                         slog(ERROR,"Internal error: The database file %s has changed, but according to the global variable tracking modification status, this should not have happened!\n",confstr(db_file_name));
     163                 :             : 
     164         [ +  - ]:           2 :                         if(!(rational_logger_mode & SILENT))
     165                 :             :                         {
     166                 :           2 :                                 show_difference(changes,&before,&after);
     167                 :             :                         }
     168                 :           2 :                         status = WARNING;
     169                 :             :                 }
     170                 :             :         } else {
     171         [ +  + ]:          34 :                 if(config->db_primary_file_modified == true)
     172                 :             :                 {
     173                 :           2 :                         slog(ERROR,"Internal error. The database file %s has NOT changed, but according to the state of the global variable tracking modifications, it should have!\n",confstr(db_file_name));
     174                 :           2 :                         status = WARNING;
     175                 :             :                 } else {
     176                 :          32 :                         slog(EVERY,BOLD "The database file %s has NOT been modified since the program was launched" RESET "\n",confstr(db_file_name));
     177                 :             :                 }
     178                 :             :         }
     179                 :             : 
     180                 :          92 :         provide(status);
     181                 :             : }
        

Generated by: LCOV version 2.0-1