LCOV - code coverage report
Current view: top level - tests/src - test0015.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 91.7 % 617 566
Test Date: 2026-03-01 04:31:48 Functions: 100.0 % 32 32
Branches: 48.0 % 1034 496

             Branch data     Line data    Source code
       1                 :             : #include "sute.h"
       2                 :             : #include "db_upgrade.h"
       3                 :             : 
       4                 :             : #define LEGACY_V3_UTF8_DB "0015_database_v3 это база данных с пробелами и символами UTF-8.db"
       5                 :             : #define LEGACY_V4_UTF8_DB "0015_database_v4 это база данных с пробелами и символами UTF-8.db"
       6                 :             : 
       7                 :          38 : static Return open_db_from_tmpdir(
       8                 :             :         const char *db_filename,
       9                 :             :         const int  open_flags,
      10                 :             :         sqlite3    **db_out)
      11                 :             : {
      12                 :             :         /* Status returned by this function through provide()
      13                 :             :            Default value assumes successful completion */
      14                 :          38 :         Return status = SUCCESS;
      15                 :             : 
      16                 :          38 :         create(char,db_path);
      17                 :             : 
      18   [ +  -  -  + ]:          38 :         if(db_filename == NULL || db_out == NULL)
      19                 :             :         {
      20                 :           0 :                 status = FAILURE;
      21                 :             :         }
      22                 :             : 
      23         [ +  - ]:          38 :         if(SUCCESS == status)
      24                 :             :         {
      25                 :          38 :                 status = construct_path(db_filename,db_path);
      26                 :             :         }
      27                 :             : 
      28         [ +  - ]:          38 :         if(SUCCESS == status)
      29                 :             :         {
      30                 :          38 :                 *db_out = NULL;
      31                 :             : 
      32         [ -  + ]:          38 :                 if(SQLITE_OK != sqlite3_open_v2(getcstring(db_path),db_out,open_flags,NULL))
      33                 :             :                 {
      34                 :           0 :                         status = FAILURE;
      35                 :             : 
      36         [ #  # ]:           0 :                         if(*db_out != NULL)
      37                 :             :                         {
      38                 :           0 :                                 (void)sqlite3_close(*db_out);
      39                 :           0 :                                 *db_out = NULL;
      40                 :             :                         }
      41                 :             :                 }
      42                 :             :         }
      43                 :             : 
      44                 :          38 :         del(db_path);
      45                 :             : 
      46                 :          38 :         return(status);
      47                 :             : }
      48                 :             : 
      49                 :           6 : static Return read_first_row_id(
      50                 :             :         const char    *db_filename,
      51                 :             :         sqlite3_int64 *row_id_out)
      52                 :             : {
      53                 :             :         /* Status returned by this function through provide()
      54                 :             :            Default value assumes successful completion */
      55                 :           6 :         Return status = SUCCESS;
      56                 :           6 :         sqlite3 *db = NULL;
      57                 :           6 :         sqlite3_stmt *stmt = NULL;
      58                 :           6 :         const char *sql = "SELECT ID FROM files ORDER BY ID ASC LIMIT 1;";
      59                 :             : 
      60   [ +  -  -  + ]:           6 :         if(db_filename == NULL || row_id_out == NULL)
      61                 :             :         {
      62                 :           0 :                 status = FAILURE;
      63                 :             :         }
      64                 :             : 
      65         [ +  - ]:           6 :         if(SUCCESS == status)
      66                 :             :         {
      67                 :           6 :                 status = open_db_from_tmpdir(db_filename,SQLITE_OPEN_READONLY,&db);
      68                 :             :         }
      69                 :             : 
      70   [ +  -  -  + ]:           6 :         if(SUCCESS == status && SQLITE_OK != sqlite3_prepare_v2(db,sql,-1,&stmt,NULL))
      71                 :             :         {
      72                 :           0 :                 status = FAILURE;
      73                 :             :         }
      74                 :             : 
      75         [ +  - ]:           6 :         if(SUCCESS == status)
      76                 :             :         {
      77                 :           6 :                 int rc = sqlite3_step(stmt);
      78                 :             : 
      79         [ +  - ]:           6 :                 if(SQLITE_ROW == rc)
      80                 :             :                 {
      81                 :           6 :                         *row_id_out = sqlite3_column_int64(stmt,0);
      82                 :           6 :                         rc = sqlite3_step(stmt);
      83                 :             : 
      84         [ -  + ]:           6 :                         if(SQLITE_DONE != rc)
      85                 :             :                         {
      86                 :           0 :                                 status = FAILURE;
      87                 :             :                         }
      88                 :             :                 } else {
      89                 :           0 :                         status = FAILURE;
      90                 :             :                 }
      91                 :             :         }
      92                 :             : 
      93         [ +  - ]:           6 :         if(stmt != NULL)
      94                 :             :         {
      95                 :           6 :                 (void)sqlite3_finalize(stmt);
      96                 :             :         }
      97                 :             : 
      98         [ +  - ]:           6 :         if(db != NULL)
      99                 :             :         {
     100                 :           6 :                 (void)sqlite3_close(db);
     101                 :             :         }
     102                 :             : 
     103                 :           6 :         return(status);
     104                 :             : }
     105                 :             : 
     106                 :           4 : static Return overwrite_stat_blob_by_row_id(
     107                 :             :         const char          *db_filename,
     108                 :             :         const sqlite3_int64 row_id,
     109                 :             :         const void          *blob,
     110                 :             :         const int           blob_size)
     111                 :             : {
     112                 :             :         /* Status returned by this function through provide()
     113                 :             :            Default value assumes successful completion */
     114                 :           4 :         Return status = SUCCESS;
     115                 :           4 :         sqlite3 *db = NULL;
     116                 :           4 :         sqlite3_stmt *stmt = NULL;
     117                 :           4 :         const char *sql = "UPDATE files SET stat = ?1 WHERE ID = ?2;";
     118                 :             : 
     119   [ +  -  +  -  :           4 :         if(db_filename == NULL || blob == NULL || blob_size < 0)
                   -  + ]
     120                 :             :         {
     121                 :           0 :                 status = FAILURE;
     122                 :             :         }
     123                 :             : 
     124         [ +  - ]:           4 :         if(SUCCESS == status)
     125                 :             :         {
     126                 :           4 :                 status = open_db_from_tmpdir(db_filename,SQLITE_OPEN_READWRITE,&db);
     127                 :             :         }
     128                 :             : 
     129   [ +  -  -  + ]:           4 :         if(SUCCESS == status && SQLITE_OK != sqlite3_prepare_v2(db,sql,-1,&stmt,NULL))
     130                 :             :         {
     131                 :           0 :                 status = FAILURE;
     132                 :             :         }
     133                 :             : 
     134   [ +  -  -  + ]:           4 :         if(SUCCESS == status && SQLITE_OK != sqlite3_bind_blob(stmt,1,blob,blob_size,SQLITE_TRANSIENT))
     135                 :             :         {
     136                 :           0 :                 status = FAILURE;
     137                 :             :         }
     138                 :             : 
     139   [ +  -  -  + ]:           4 :         if(SUCCESS == status && SQLITE_OK != sqlite3_bind_int64(stmt,2,row_id))
     140                 :             :         {
     141                 :           0 :                 status = FAILURE;
     142                 :             :         }
     143                 :             : 
     144   [ +  -  -  + ]:           4 :         if(SUCCESS == status && SQLITE_DONE != sqlite3_step(stmt))
     145                 :             :         {
     146                 :           0 :                 status = FAILURE;
     147                 :             :         }
     148                 :             : 
     149   [ +  -  -  + ]:           4 :         if(SUCCESS == status && sqlite3_changes(db) < 1)
     150                 :             :         {
     151                 :           0 :                 status = FAILURE;
     152                 :             :         }
     153                 :             : 
     154         [ +  - ]:           4 :         if(stmt != NULL)
     155                 :             :         {
     156                 :           4 :                 (void)sqlite3_finalize(stmt);
     157                 :             :         }
     158                 :             : 
     159         [ +  - ]:           4 :         if(db != NULL)
     160                 :             :         {
     161                 :           4 :                 (void)sqlite3_close(db);
     162                 :             :         }
     163                 :             : 
     164                 :           4 :         return(status);
     165                 :             : }
     166                 :             : 
     167                 :           2 : static Return read_files_count(
     168                 :             :         const char *db_filename,
     169                 :             :         int        *count_out)
     170                 :             : {
     171                 :             :         /* Status returned by this function through provide()
     172                 :             :            Default value assumes successful completion */
     173                 :           2 :         Return status = SUCCESS;
     174                 :           2 :         sqlite3 *db = NULL;
     175                 :           2 :         sqlite3_stmt *stmt = NULL;
     176                 :           2 :         const char *sql = "SELECT COUNT(*) FROM files;";
     177                 :             : 
     178   [ +  -  -  + ]:           2 :         if(db_filename == NULL || count_out == NULL)
     179                 :             :         {
     180                 :           0 :                 status = FAILURE;
     181                 :             :         }
     182                 :             : 
     183         [ +  - ]:           2 :         if(SUCCESS == status)
     184                 :             :         {
     185                 :           2 :                 status = open_db_from_tmpdir(db_filename,SQLITE_OPEN_READONLY,&db);
     186                 :             :         }
     187                 :             : 
     188   [ +  -  -  + ]:           2 :         if(SUCCESS == status && SQLITE_OK != sqlite3_prepare_v2(db,sql,-1,&stmt,NULL))
     189                 :             :         {
     190                 :           0 :                 status = FAILURE;
     191                 :             :         }
     192                 :             : 
     193         [ +  - ]:           2 :         if(SUCCESS == status)
     194                 :             :         {
     195                 :           2 :                 int rc = sqlite3_step(stmt);
     196                 :             : 
     197         [ +  - ]:           2 :                 if(SQLITE_ROW == rc)
     198                 :             :                 {
     199                 :           2 :                         *count_out = sqlite3_column_int(stmt,0);
     200                 :           2 :                         rc = sqlite3_step(stmt);
     201                 :             : 
     202         [ -  + ]:           2 :                         if(SQLITE_DONE != rc)
     203                 :             :                         {
     204                 :           0 :                                 status = FAILURE;
     205                 :             :                         }
     206                 :             :                 } else {
     207                 :           0 :                         status = FAILURE;
     208                 :             :                 }
     209                 :             :         }
     210                 :             : 
     211         [ +  - ]:           2 :         if(stmt != NULL)
     212                 :             :         {
     213                 :           2 :                 (void)sqlite3_finalize(stmt);
     214                 :             :         }
     215                 :             : 
     216         [ +  - ]:           2 :         if(db != NULL)
     217                 :             :         {
     218                 :           2 :                 (void)sqlite3_close(db);
     219                 :             :         }
     220                 :             : 
     221                 :           2 :         return(status);
     222                 :             : }
     223                 :             : 
     224                 :           4 : static Return read_files_count_with_blob_size(
     225                 :             :         const char *db_filename,
     226                 :             :         const int  blob_size,
     227                 :             :         int        *count_out)
     228                 :             : {
     229                 :             :         /* Status returned by this function through provide()
     230                 :             :            Default value assumes successful completion */
     231                 :           4 :         Return status = SUCCESS;
     232                 :           4 :         sqlite3 *db = NULL;
     233                 :           4 :         sqlite3_stmt *stmt = NULL;
     234                 :           4 :         const char *sql = "SELECT COUNT(*) FROM files WHERE length(stat) = ?1;";
     235                 :             : 
     236   [ +  -  +  -  :           4 :         if(db_filename == NULL || blob_size < 0 || count_out == NULL)
                   -  + ]
     237                 :             :         {
     238                 :           0 :                 status = FAILURE;
     239                 :             :         }
     240                 :             : 
     241         [ +  - ]:           4 :         if(SUCCESS == status)
     242                 :             :         {
     243                 :           4 :                 status = open_db_from_tmpdir(db_filename,SQLITE_OPEN_READONLY,&db);
     244                 :             :         }
     245                 :             : 
     246   [ +  -  -  + ]:           4 :         if(SUCCESS == status && SQLITE_OK != sqlite3_prepare_v2(db,sql,-1,&stmt,NULL))
     247                 :             :         {
     248                 :           0 :                 status = FAILURE;
     249                 :             :         }
     250                 :             : 
     251   [ +  -  -  + ]:           4 :         if(SUCCESS == status && SQLITE_OK != sqlite3_bind_int(stmt,1,blob_size))
     252                 :             :         {
     253                 :           0 :                 status = FAILURE;
     254                 :             :         }
     255                 :             : 
     256         [ +  - ]:           4 :         if(SUCCESS == status)
     257                 :             :         {
     258                 :           4 :                 int rc = sqlite3_step(stmt);
     259                 :             : 
     260         [ +  - ]:           4 :                 if(SQLITE_ROW == rc)
     261                 :             :                 {
     262                 :           4 :                         *count_out = sqlite3_column_int(stmt,0);
     263                 :           4 :                         rc = sqlite3_step(stmt);
     264                 :             : 
     265         [ -  + ]:           4 :                         if(SQLITE_DONE != rc)
     266                 :             :                         {
     267                 :           0 :                                 status = FAILURE;
     268                 :             :                         }
     269                 :             :                 } else {
     270                 :           0 :                         status = FAILURE;
     271                 :             :                 }
     272                 :             :         }
     273                 :             : 
     274         [ +  - ]:           4 :         if(stmt != NULL)
     275                 :             :         {
     276                 :           4 :                 (void)sqlite3_finalize(stmt);
     277                 :             :         }
     278                 :             : 
     279         [ +  - ]:           4 :         if(db != NULL)
     280                 :             :         {
     281                 :           4 :                 (void)sqlite3_close(db);
     282                 :             :         }
     283                 :             : 
     284                 :           4 :         return(status);
     285                 :             : }
     286                 :             : 
     287                 :          10 : static Return read_db_version_from_metadata(
     288                 :             :         const char *db_filename,
     289                 :             :         int        *db_version_out)
     290                 :             : {
     291                 :             :         /* Status returned by this function through provide()
     292                 :             :            Default value assumes successful completion */
     293                 :          10 :         Return status = SUCCESS;
     294                 :          10 :         sqlite3 *db = NULL;
     295                 :          10 :         sqlite3_stmt *stmt = NULL;
     296                 :          10 :         const char *sql = "SELECT db_version FROM metadata LIMIT 1;";
     297                 :             : 
     298   [ +  -  -  + ]:          10 :         if(db_filename == NULL || db_version_out == NULL)
     299                 :             :         {
     300                 :           0 :                 status = FAILURE;
     301                 :             :         }
     302                 :             : 
     303         [ +  - ]:          10 :         if(SUCCESS == status)
     304                 :             :         {
     305                 :          10 :                 status = open_db_from_tmpdir(db_filename,SQLITE_OPEN_READONLY,&db);
     306                 :             :         }
     307                 :             : 
     308   [ +  -  -  + ]:          10 :         if(SUCCESS == status && SQLITE_OK != sqlite3_prepare_v2(db,sql,-1,&stmt,NULL))
     309                 :             :         {
     310                 :           0 :                 status = FAILURE;
     311                 :             :         }
     312                 :             : 
     313         [ +  - ]:          10 :         if(SUCCESS == status)
     314                 :             :         {
     315                 :          10 :                 int rc = sqlite3_step(stmt);
     316                 :             : 
     317         [ +  - ]:          10 :                 if(SQLITE_ROW == rc)
     318                 :             :                 {
     319                 :          10 :                         *db_version_out = sqlite3_column_int(stmt,0);
     320                 :          10 :                         rc = sqlite3_step(stmt);
     321                 :             : 
     322         [ -  + ]:          10 :                         if(SQLITE_DONE != rc)
     323                 :             :                         {
     324                 :           0 :                                 status = FAILURE;
     325                 :             :                         }
     326                 :             :                 } else {
     327                 :           0 :                         status = FAILURE;
     328                 :             :                 }
     329                 :             :         }
     330                 :             : 
     331         [ +  - ]:          10 :         if(stmt != NULL)
     332                 :             :         {
     333                 :          10 :                 (void)sqlite3_finalize(stmt);
     334                 :             :         }
     335                 :             : 
     336         [ +  - ]:          10 :         if(db != NULL)
     337                 :             :         {
     338                 :          10 :                 (void)sqlite3_close(db);
     339                 :             :         }
     340                 :             : 
     341                 :          10 :         return(status);
     342                 :             : }
     343                 :             : 
     344                 :           2 : static Return set_db_version_in_metadata(
     345                 :             :         const char *db_filename,
     346                 :             :         const int  db_version)
     347                 :             : {
     348                 :             :         /* Status returned by this function through provide()
     349                 :             :            Default value assumes successful completion */
     350                 :           2 :         Return status = SUCCESS;
     351                 :           2 :         sqlite3 *db = NULL;
     352                 :           2 :         sqlite3_stmt *stmt = NULL;
     353                 :           2 :         const char *sql = "UPDATE metadata SET db_version = ?1;";
     354                 :             : 
     355   [ +  -  -  + ]:           2 :         if(db_filename == NULL || db_version < 0)
     356                 :             :         {
     357                 :           0 :                 status = FAILURE;
     358                 :             :         }
     359                 :             : 
     360         [ +  - ]:           2 :         if(SUCCESS == status)
     361                 :             :         {
     362                 :           2 :                 status = open_db_from_tmpdir(db_filename,SQLITE_OPEN_READWRITE,&db);
     363                 :             :         }
     364                 :             : 
     365   [ +  -  -  + ]:           2 :         if(SUCCESS == status && SQLITE_OK != sqlite3_prepare_v2(db,sql,-1,&stmt,NULL))
     366                 :             :         {
     367                 :           0 :                 status = FAILURE;
     368                 :             :         }
     369                 :             : 
     370   [ +  -  -  + ]:           2 :         if(SUCCESS == status && SQLITE_OK != sqlite3_bind_int(stmt,1,db_version))
     371                 :             :         {
     372                 :           0 :                 status = FAILURE;
     373                 :             :         }
     374                 :             : 
     375   [ +  -  -  + ]:           2 :         if(SUCCESS == status && SQLITE_DONE != sqlite3_step(stmt))
     376                 :             :         {
     377                 :           0 :                 status = FAILURE;
     378                 :             :         }
     379                 :             : 
     380   [ +  -  -  + ]:           2 :         if(SUCCESS == status && sqlite3_changes(db) < 1)
     381                 :             :         {
     382                 :           0 :                 status = FAILURE;
     383                 :             :         }
     384                 :             : 
     385         [ +  - ]:           2 :         if(stmt != NULL)
     386                 :             :         {
     387                 :           2 :                 (void)sqlite3_finalize(stmt);
     388                 :             :         }
     389                 :             : 
     390         [ +  - ]:           2 :         if(db != NULL)
     391                 :             :         {
     392                 :           2 :                 (void)sqlite3_close(db);
     393                 :             :         }
     394                 :             : 
     395                 :           2 :         return(status);
     396                 :             : }
     397                 :             : 
     398                 :           8 : static Return read_stat_blob_by_row_id(
     399                 :             :         const char          *db_filename,
     400                 :             :         const sqlite3_int64 row_id,
     401                 :             :         unsigned char       *blob_out,
     402                 :             :         const size_t        blob_out_size,
     403                 :             :         int                 *blob_size_out)
     404                 :             : {
     405                 :             :         /* Status returned by this function through provide()
     406                 :             :            Default value assumes successful completion */
     407                 :           8 :         Return status = SUCCESS;
     408                 :           8 :         sqlite3 *db = NULL;
     409                 :           8 :         sqlite3_stmt *stmt = NULL;
     410                 :           8 :         const char *sql = "SELECT stat FROM files WHERE ID = ?1;";
     411                 :             : 
     412   [ +  -  -  + ]:           8 :         if(db_filename == NULL || blob_size_out == NULL)
     413                 :             :         {
     414                 :           0 :                 status = FAILURE;
     415                 :             :         }
     416                 :             : 
     417         [ +  - ]:           8 :         if(SUCCESS == status)
     418                 :             :         {
     419                 :           8 :                 status = open_db_from_tmpdir(db_filename,SQLITE_OPEN_READONLY,&db);
     420                 :             :         }
     421                 :             : 
     422   [ +  -  -  + ]:           8 :         if(SUCCESS == status && SQLITE_OK != sqlite3_prepare_v2(db,sql,-1,&stmt,NULL))
     423                 :             :         {
     424                 :           0 :                 status = FAILURE;
     425                 :             :         }
     426                 :             : 
     427   [ +  -  -  + ]:           8 :         if(SUCCESS == status && SQLITE_OK != sqlite3_bind_int64(stmt,1,row_id))
     428                 :             :         {
     429                 :           0 :                 status = FAILURE;
     430                 :             :         }
     431                 :             : 
     432         [ +  - ]:           8 :         if(SUCCESS == status)
     433                 :             :         {
     434                 :           8 :                 int rc = sqlite3_step(stmt);
     435                 :             : 
     436         [ +  - ]:           8 :                 if(SQLITE_ROW == rc)
     437                 :             :                 {
     438                 :           8 :                         const void *blob = sqlite3_column_blob(stmt,0);
     439                 :           8 :                         const int blob_size = sqlite3_column_bytes(stmt,0);
     440                 :             : 
     441         [ -  + ]:           8 :                         if(blob_size < 0)
     442                 :             :                         {
     443                 :           0 :                                 status = FAILURE;
     444                 :             :                         }
     445                 :             : 
     446   [ +  -  +  -  :           8 :                         if(SUCCESS == status && blob_size > 0 && blob == NULL)
                   -  + ]
     447                 :             :                         {
     448                 :           0 :                                 status = FAILURE;
     449                 :             :                         }
     450                 :             : 
     451   [ +  -  +  - ]:           8 :                         if(SUCCESS == status && blob_out != NULL)
     452                 :             :                         {
     453         [ -  + ]:           8 :                                 if((size_t)blob_size > blob_out_size)
     454                 :             :                                 {
     455                 :           0 :                                         status = FAILURE;
     456         [ +  - ]:           8 :                                 } else if(blob_size > 0){
     457                 :           8 :                                         memcpy(blob_out,blob,(size_t)blob_size);
     458                 :             :                                 }
     459                 :             :                         }
     460                 :             : 
     461         [ +  - ]:           8 :                         if(SUCCESS == status)
     462                 :             :                         {
     463                 :           8 :                                 *blob_size_out = blob_size;
     464                 :             :                         }
     465                 :             : 
     466                 :           8 :                         rc = sqlite3_step(stmt);
     467                 :             : 
     468   [ +  -  -  + ]:           8 :                         if(SUCCESS == status && SQLITE_DONE != rc)
     469                 :             :                         {
     470                 :           0 :                                 status = FAILURE;
     471                 :             :                         }
     472                 :             :                 } else {
     473                 :           0 :                         status = FAILURE;
     474                 :             :                 }
     475                 :             :         }
     476                 :             : 
     477         [ +  - ]:           8 :         if(stmt != NULL)
     478                 :             :         {
     479                 :           8 :                 (void)sqlite3_finalize(stmt);
     480                 :             :         }
     481                 :             : 
     482         [ +  - ]:           8 :         if(db != NULL)
     483                 :             :         {
     484                 :           8 :                 (void)sqlite3_close(db);
     485                 :             :         }
     486                 :             : 
     487                 :           8 :         return(status);
     488                 :             : }
     489                 :             : 
     490                 :           4 : static Return read_cmpctstat_by_row_id(
     491                 :             :         const char          *db_filename,
     492                 :             :         const sqlite3_int64 row_id,
     493                 :             :         CmpctStat           *stat_out)
     494                 :             : {
     495                 :             :         /* Status returned by this function through provide()
     496                 :             :            Default value assumes successful completion */
     497                 :           4 :         Return status = SUCCESS;
     498                 :             :         unsigned char raw[sizeof(CmpctStat)];
     499                 :           4 :         int blob_size = 0;
     500                 :             : 
     501         [ -  + ]:           4 :         if(stat_out == NULL)
     502                 :             :         {
     503                 :           0 :                 status = FAILURE;
     504                 :             :         }
     505                 :             : 
     506         [ +  - ]:           4 :         if(SUCCESS == status)
     507                 :             :         {
     508                 :           4 :                 status = read_stat_blob_by_row_id(db_filename,row_id,raw,sizeof(raw),&blob_size);
     509                 :             :         }
     510                 :             : 
     511   [ +  -  -  + ]:           4 :         if(SUCCESS == status && blob_size != (int)sizeof(CmpctStat))
     512                 :             :         {
     513                 :           0 :                 status = FAILURE;
     514                 :             :         }
     515                 :             : 
     516         [ +  - ]:           4 :         if(SUCCESS == status)
     517                 :             :         {
     518                 :           4 :                 memcpy(stat_out,raw,sizeof(CmpctStat));
     519                 :             :         }
     520                 :             : 
     521                 :           4 :         return(status);
     522                 :             : }
     523                 :             : 
     524                 :           4 : static Return verify_zero_converted_cmpctstat(
     525                 :             :         const CmpctStat *stat)
     526                 :             : {
     527         [ -  + ]:           4 :         if(stat == NULL)
     528                 :             :         {
     529                 :           0 :                 return FAILURE;
     530                 :             :         }
     531                 :             : 
     532         [ -  + ]:           4 :         if(stat->st_size != 0)
     533                 :             :         {
     534                 :           0 :                 return FAILURE;
     535                 :             :         }
     536                 :             : 
     537         [ -  + ]:           4 :         if(stat->st_blocks != BLKCNT_UNKNOWN)
     538                 :             :         {
     539                 :           0 :                 return FAILURE;
     540                 :             :         }
     541                 :             : 
     542   [ +  -  -  + ]:           4 :         if(stat->st_dev != 0 || stat->st_ino != 0)
     543                 :             :         {
     544                 :           0 :                 return FAILURE;
     545                 :             :         }
     546                 :             : 
     547   [ +  -  -  + ]:           4 :         if(stat->mtim_tv_sec != 0 || stat->mtim_tv_nsec != 0)
     548                 :             :         {
     549                 :           0 :                 return FAILURE;
     550                 :             :         }
     551                 :             : 
     552   [ +  -  -  + ]:           4 :         if(stat->ctim_tv_sec != 0 || stat->ctim_tv_nsec != 0)
     553                 :             :         {
     554                 :           0 :                 return FAILURE;
     555                 :             :         }
     556                 :             : 
     557                 :           4 :         return SUCCESS;
     558                 :             : }
     559                 :             : 
     560                 :           4 : static Return corrupt_first_row_stat_blob(
     561                 :             :         const char    *db_filename,
     562                 :             :         sqlite3_int64 *row_id_out)
     563                 :             : {
     564                 :             :         /* Status returned by this function through provide()
     565                 :             :            Default value assumes successful completion */
     566                 :           4 :         Return status = SUCCESS;
     567                 :           4 :         sqlite3_int64 row_id = 0;
     568                 :           4 :         const unsigned char corrupt_blob[] = {0xA5};
     569                 :             : 
     570         [ +  - ]:           4 :         if(SUCCESS == status)
     571                 :             :         {
     572                 :           4 :                 status = read_first_row_id(db_filename,&row_id);
     573                 :             :         }
     574                 :             : 
     575         [ +  - ]:           4 :         if(SUCCESS == status)
     576                 :             :         {
     577                 :           4 :                 status = overwrite_stat_blob_by_row_id(db_filename,row_id,corrupt_blob,(int)sizeof(corrupt_blob));
     578                 :             :         }
     579                 :             : 
     580   [ +  -  +  - ]:           4 :         if(SUCCESS == status && row_id_out != NULL)
     581                 :             :         {
     582                 :           4 :                 *row_id_out = row_id;
     583                 :             :         }
     584                 :             : 
     585                 :           4 :         return(status);
     586                 :             : }
     587                 :             : 
     588                 :           2 : static Return create_abort_on_second_stat_update_trigger(
     589                 :             :         const char *db_filename)
     590                 :             : {
     591                 :             :         /* Status returned by this function through provide()
     592                 :             :            Default value assumes successful completion */
     593                 :           2 :         Return status = SUCCESS;
     594                 :           2 :         sqlite3 *db = NULL;
     595                 :           2 :         const char *sql =
     596                 :             :                 "DROP TRIGGER IF EXISTS __test_abort_on_second_update;"
     597                 :             :                 "DROP TABLE IF EXISTS __test_fail_counter;"
     598                 :             :                 "CREATE TABLE __test_fail_counter(n INTEGER NOT NULL);"
     599                 :             :                 "INSERT INTO __test_fail_counter(n) VALUES(0);"
     600                 :             :                 "CREATE TRIGGER __test_abort_on_second_update "
     601                 :             :                 "BEFORE UPDATE OF stat ON files "
     602                 :             :                 "BEGIN "
     603                 :             :                 "UPDATE __test_fail_counter SET n = n + 1;"
     604                 :             :                 "SELECT CASE WHEN (SELECT n FROM __test_fail_counter LIMIT 1) >= 2 "
     605                 :             :                 "THEN RAISE(ABORT,'forced rollback test failure') END;"
     606                 :             :                 "END;";
     607                 :             : 
     608         [ -  + ]:           2 :         if(db_filename == NULL)
     609                 :             :         {
     610                 :           0 :                 status = FAILURE;
     611                 :             :         }
     612                 :             : 
     613         [ +  - ]:           2 :         if(SUCCESS == status)
     614                 :             :         {
     615                 :           2 :                 status = open_db_from_tmpdir(db_filename,SQLITE_OPEN_READWRITE,&db);
     616                 :             :         }
     617                 :             : 
     618   [ +  -  -  + ]:           2 :         if(SUCCESS == status && SQLITE_OK != sqlite3_exec(db,sql,NULL,NULL,NULL))
     619                 :             :         {
     620                 :           0 :                 status = FAILURE;
     621                 :             :         }
     622                 :             : 
     623         [ +  - ]:           2 :         if(db != NULL)
     624                 :             :         {
     625                 :           2 :                 (void)sqlite3_close(db);
     626                 :             :         }
     627                 :             : 
     628                 :           2 :         return(status);
     629                 :             : }
     630                 :             : 
     631                 :             : /**
     632                 :             :  *
     633                 :             :  * Upgrade a DB from version 0 to the current version as the primary database.
     634                 :             :  * Verify the run fails without the --update parameter and prints the proper error.
     635                 :             :  *
     636                 :             :  */
     637                 :           2 : Return test0015_1(void)
     638                 :             : {
     639                 :           2 :         INITTEST;
     640                 :             : 
     641   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     642                 :             : 
     643                 :           2 :         const char *command = "cp -a ${ORIGIN_DIR}/tests/templates/0015_database_v0.db ${TMPDIR}/";
     644                 :             : 
     645   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
     646                 :             : 
     647                 :           2 :         const char *arguments = "--database=./0015_database_v0.db tests/fixtures/diffs/diff1";
     648                 :             : 
     649                 :           2 :         create(char,result);
     650                 :           2 :         create(char,pattern);
     651                 :             : 
     652                 :           2 :         const char *filename = "templates/0015_001.txt";
     653                 :             : 
     654   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,WARNING,ALLOW_BOTH));
     655                 :             : 
     656   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     657                 :             : 
     658                 :             :         // Match the result against the pattern
     659   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     660                 :             : 
     661                 :             :         // Clean to use it iteratively
     662                 :           2 :         del(pattern);
     663                 :           2 :         del(result);
     664                 :             : 
     665                 :             :         // Clean up test results
     666                 :           2 :         command = "rm \"${TMPDIR}/0015_database_v0.db\"";
     667                 :             : 
     668   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
     669                 :             : 
     670   [ +  -  -  +  :           2 :         RETURN_STATUS;
          -  -  -  +  +  
                      - ]
     671                 :             : }
     672                 :             : 
     673                 :             : /**
     674                 :             :  *
     675                 :             :  * Upgrade a DB from version 0 to the current version as the primary database.
     676                 :             :  * Running the test with the --update parameter to ensure the update
     677                 :             :  * completes successfully
     678                 :             :  *
     679                 :             :  */
     680                 :           2 : Return test0015_2(void)
     681                 :             : {
     682                 :           2 :         INITTEST;
     683                 :             : 
     684                 :           2 :         const char *command = "cp -a ${ORIGIN_DIR}/tests/templates/0015_database_v0.db ${TMPDIR}/";
     685                 :             : 
     686   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
     687                 :             : 
     688   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     689                 :             : 
     690                 :           2 :         const char *arguments = "--update --database=0015_database_v0.db "
     691                 :             :                 "tests/fixtures/diffs/diff1";
     692                 :             : 
     693                 :           2 :         create(char,result);
     694                 :           2 :         create(char,pattern);
     695                 :             : 
     696                 :           2 :         const char *filename = "templates/0015_002_1.txt";
     697                 :             : 
     698   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
     699                 :             : 
     700   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     701                 :             : 
     702                 :             :         // Match the result against the pattern
     703   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     704                 :             : 
     705                 :             :         // Clean up test results
     706                 :           2 :         command = "rm \"${TMPDIR}/0015_database_v0.db\"";
     707                 :             : 
     708   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
     709                 :             : 
     710                 :             :         // Clean to use it iteratively
     711                 :           2 :         del(pattern);
     712                 :           2 :         del(result);
     713                 :             : 
     714   [ +  -  -  +  :           2 :         RETURN_STATUS;
          -  -  -  +  +  
                      - ]
     715                 :             : }
     716                 :             : 
     717                 :             : /**
     718                 :             :  *
     719                 :             :  * Upgrade a DB from version 0 to the current version as the primary database.
     720                 :             :  * Running the test with the --update and --watch-timestamps parameters to ensure
     721                 :             :  * the update completes successfully with according details in output
     722                 :             :  *
     723                 :             :  */
     724                 :           2 : Return test0015_3(void)
     725                 :             : {
     726                 :           2 :         INITTEST;
     727                 :             : 
     728                 :           2 :         const char *command = "cp -a ${ORIGIN_DIR}/tests/templates/0015_database_v0.db ${TMPDIR}/";
     729                 :             : 
     730   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
     731                 :             : 
     732   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     733                 :             : 
     734                 :           2 :         const char *arguments = "--watch-timestamps --update --database=0015_database_v0.db "
     735                 :             :                 "tests/fixtures/diffs/diff1";
     736                 :             : 
     737                 :           2 :         create(char,result);
     738                 :           2 :         create(char,pattern);
     739                 :             : 
     740                 :           2 :         const char *filename = "templates/0015_002_2.txt";
     741                 :             : 
     742   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
     743                 :             : 
     744   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     745                 :             : 
     746                 :             :         // Match the result against the pattern
     747   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     748                 :             : 
     749                 :             :         // Clean to use it iteratively
     750                 :           2 :         del(pattern);
     751                 :           2 :         del(result);
     752                 :             : 
     753   [ +  -  -  +  :           2 :         RETURN_STATUS;
          -  -  -  +  +  
                      - ]
     754                 :             : }
     755                 :             : 
     756                 :             : /**
     757                 :             :  *
     758                 :             :  * Run the program again to verify that the database
     759                 :             :  * is actually at the current version
     760                 :             :  *
     761                 :             :  */
     762                 :           2 : Return test0015_4(void)
     763                 :             : {
     764                 :           2 :         INITTEST;
     765                 :             : 
     766                 :           2 :         create(char,result);
     767                 :           2 :         create(char,pattern);
     768                 :             : 
     769                 :           2 :         const char *filename = "templates/0015_003.txt";
     770                 :             : 
     771   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     772                 :             : 
     773                 :           2 :         const char *arguments = "--update --database=./0015_database_v0.db "
     774                 :             :                 "tests/fixtures/diffs/diff1";
     775                 :             : 
     776   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
     777                 :             : 
     778   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     779                 :             : 
     780                 :             :         // Match the result against the pattern
     781   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     782                 :             : 
     783                 :             :         // Clean to use it iteratively
     784                 :           2 :         del(pattern);
     785                 :           2 :         del(result);
     786                 :             : 
     787                 :             :         // Clean up test results
     788                 :           2 :         const char *command = "rm \"${TMPDIR}/0015_database_v0.db\"";
     789                 :             : 
     790   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
     791                 :             : 
     792   [ +  -  -  +  :           2 :         RETURN_STATUS;
          -  -  -  +  +  
                      - ]
     793                 :             : }
     794                 :             : 
     795                 :             : /**
     796                 :             :  *
     797                 :             :  * Run the program again to verify that the database is actually at the current version
     798                 :             :  * Create a database with the default name
     799                 :             :  *
     800                 :             :  */
     801                 :           2 : Return test0015_5(void)
     802                 :             : {
     803                 :           2 :         INITTEST;
     804                 :             : 
     805   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     806                 :             : 
     807                 :             :         // Get the output of an external program
     808                 :           2 :         const char *arguments = "tests/fixtures/diffs/diff1";
     809                 :             : 
     810                 :           2 :         const char *filename = "templates/0015_004.txt";  // File name
     811                 :           2 :         const char *template = "%DB_NAME%";
     812                 :             : 
     813                 :           2 :         const char *replacement = getenv("DBNAME");  // Database name
     814                 :             : 
     815   [ +  -  +  - ]:           2 :         ASSERT(replacement != NULL);
     816                 :             : 
     817   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == match_app_output(arguments,filename,template,replacement,COMPLETED));
     818                 :             : 
     819   [ +  -  -  +  :           2 :         RETURN_STATUS;
          -  -  -  +  +  
                      - ]
     820                 :             : }
     821                 :             : 
     822                 :             : /**
     823                 :             :  *
     824                 :             :  * Run the program with the --compare parameter to compare databases
     825                 :             :  * when one of them has an older version — this should generate an
     826                 :             :  * appropriate error message
     827                 :             :  *
     828                 :             :  */
     829                 :           2 : Return test0015_6(void)
     830                 :             : {
     831                 :           2 :         INITTEST;
     832                 :             : 
     833   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     834                 :             : 
     835                 :             :         // Get the output of an external program
     836                 :           2 :         const char *command = "cp -a ${ORIGIN_DIR}/tests/templates/0015_database_v0.db ${TMPDIR}/";
     837                 :             : 
     838   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
     839                 :             : 
     840                 :           2 :         const char *arguments = "--compare $DBNAME 0015_database_v0.db";
     841                 :             : 
     842                 :           2 :         const char *filename = "templates/0015_005.txt";  // File name
     843                 :           2 :         const char *template = "%DB_NAME%";
     844                 :             : 
     845                 :           2 :         const char *replacement = getenv("DBNAME");  // Database name
     846                 :             : 
     847   [ +  -  +  - ]:           2 :         ASSERT(replacement != NULL);
     848                 :             : 
     849   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == match_app_output(arguments,filename,template,replacement,WARNING));
     850                 :             : 
     851   [ +  -  -  +  :           2 :         RETURN_STATUS;
          -  -  -  +  +  
                      - ]
     852                 :             : }
     853                 :             : 
     854                 :             : /**
     855                 :             :  *
     856                 :             :  * Run the database comparison again using the --compare parameter, but this time with
     857                 :             :  * the --update option. The database should be upgraded accordingly.
     858                 :             :  * Upgrading from 0 to the last version
     859                 :             :  *
     860                 :             :  */
     861                 :           2 : Return test0015_7(void)
     862                 :             : {
     863                 :           2 :         INITTEST;
     864                 :             : 
     865   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     866                 :             : 
     867                 :             :         // Get the output of an external program
     868                 :           2 :         const char *arguments = "--compare --update $DBNAME 0015_database_v0.db";
     869                 :             : 
     870                 :           2 :         const char *filename = "templates/0015_006.txt";  // File name
     871                 :           2 :         const char *template = "%DB_NAME%";
     872                 :             : 
     873                 :           2 :         const char *replacement = getenv("DBNAME");  // Database name
     874                 :             : 
     875   [ +  -  +  - ]:           2 :         ASSERT(replacement != NULL);
     876                 :             : 
     877   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == match_app_output(arguments,filename,template,replacement,COMPLETED));
     878                 :             : 
     879                 :             :         // Clean up test results
     880                 :           2 :         const char *command = "rm \"${TMPDIR}/0015_database_v0.db\"";
     881                 :             : 
     882   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
     883                 :             : 
     884   [ +  -  -  +  :           2 :         RETURN_STATUS;
          -  -  -  +  +  
                      - ]
     885                 :             : }
     886                 :             : 
     887                 :             : /**
     888                 :             :  *
     889                 :             :  * Upgrade a DB from version 1 to the current version as the primary database.
     890                 :             :  * Running the test with the --update parameter to ensure the update
     891                 :             :  * completes successfully
     892                 :             :  *
     893                 :             :  */
     894                 :           2 : Return test0015_8(void)
     895                 :             : {
     896                 :           2 :         INITTEST;
     897                 :             : 
     898   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     899                 :             : 
     900                 :           2 :         const char *command = "cp -a ${ORIGIN_DIR}/tests/templates/0015_database_v1.db ${TMPDIR}/";
     901                 :             : 
     902   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
     903                 :             : 
     904                 :           2 :         const char *arguments = "--update --database=0015_database_v1.db "
     905                 :             :                 "tests/fixtures/diffs/diff1";
     906                 :             : 
     907                 :           2 :         create(char,result);
     908                 :           2 :         create(char,pattern);
     909                 :             : 
     910                 :           2 :         const char *filename = "templates/0015_007.txt";
     911                 :             : 
     912   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
     913                 :             : 
     914   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     915                 :             : 
     916                 :             :         // Match the result against the pattern
     917   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     918                 :             : 
     919                 :             :         // Clean to use it iteratively
     920                 :           2 :         del(pattern);
     921                 :           2 :         del(result);
     922                 :             : 
     923   [ +  -  -  +  :           2 :         RETURN_STATUS;
          -  -  -  +  +  
                      - ]
     924                 :             : }
     925                 :             : 
     926                 :             : /**
     927                 :             :  *
     928                 :             :  * Run the program again to verify that the database
     929                 :             :  * is actually at the current version
     930                 :             :  *
     931                 :             :  */
     932                 :           2 : Return test0015_9(void)
     933                 :             : {
     934                 :           2 :         INITTEST;
     935                 :             : 
     936                 :           2 :         create(char,result);
     937                 :           2 :         create(char,pattern);
     938                 :             : 
     939                 :           2 :         const char *filename = "templates/0015_008.txt";
     940                 :             : 
     941   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     942                 :             : 
     943                 :           2 :         const char *arguments = "--update --database=./0015_database_v1.db "
     944                 :             :                 "tests/fixtures/diffs/diff1";
     945                 :             : 
     946   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
     947                 :             : 
     948   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     949                 :             : 
     950                 :             :         // Match the result against the pattern
     951   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     952                 :             : 
     953                 :             :         // Clean to use it iteratively
     954                 :           2 :         del(pattern);
     955                 :           2 :         del(result);
     956                 :             : 
     957                 :             :         // Clean up test results
     958                 :           2 :         const char *command = "rm \"${TMPDIR}/0015_database_v1.db\"";
     959                 :             : 
     960   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
     961                 :             : 
     962   [ +  -  -  +  :           2 :         RETURN_STATUS;
          -  -  -  +  +  
                      - ]
     963                 :             : }
     964                 :             : 
     965                 :             : /**
     966                 :             :  *
     967                 :             :  * Run the database comparison again using the --compare and --update parameters.
     968                 :             :  * Upgrading from 1 to the last version
     969                 :             :  *
     970                 :             :  */
     971                 :           2 : Return test0015_10(void)
     972                 :             : {
     973                 :           2 :         INITTEST;
     974                 :             : 
     975   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     976                 :             : 
     977                 :             :         // Get the output of an external program
     978                 :           2 :         const char *command = "cp -a ${ORIGIN_DIR}/tests/templates/0015_database_v1.db ${TMPDIR}/";
     979                 :             : 
     980   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
     981                 :             : 
     982                 :           2 :         const char *arguments = "--compare --update $DBNAME 0015_database_v1.db";
     983                 :             : 
     984                 :           2 :         const char *filename = "templates/0015_009.txt";  // File name
     985                 :           2 :         const char *template = "%DB_NAME%";
     986                 :             : 
     987                 :           2 :         const char *replacement = getenv("DBNAME");  // Database name
     988                 :             : 
     989   [ +  -  +  - ]:           2 :         ASSERT(replacement != NULL);
     990                 :             : 
     991   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == match_app_output(arguments,filename,template,replacement,COMPLETED));
     992                 :             : 
     993                 :             :         // Clean up test results
     994                 :           2 :         command = "rm \"${TMPDIR}/0015_database_v1.db\"";
     995                 :             : 
     996   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
     997                 :             : 
     998   [ +  -  -  +  :           2 :         RETURN_STATUS;
          -  -  -  +  +  
                      - ]
     999                 :             : }
    1000                 :             : 
    1001                 :             : /**
    1002                 :             :  *
    1003                 :             :  * Upgrade a DB from version 2 to the current version as the primary database.
    1004                 :             :  * Running the test with the --update parameter to ensure the update
    1005                 :             :  * completes successfully
    1006                 :             :  *
    1007                 :             :  */
    1008                 :           2 : Return test0015_11(void)
    1009                 :             : {
    1010                 :           2 :         INITTEST;
    1011                 :             : 
    1012   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
    1013                 :             : 
    1014                 :           2 :         const char *command = "cp -a ${ORIGIN_DIR}/tests/templates/0015_database_v2.db ${TMPDIR}/";
    1015                 :             : 
    1016   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
    1017                 :             : 
    1018                 :           2 :         const char *arguments = "--update --database=0015_database_v2.db --verbose "
    1019                 :             :                 "tests/fixtures/diffs/diff1";
    1020                 :             : 
    1021                 :           2 :         create(char,result);
    1022                 :           2 :         create(char,pattern);
    1023                 :             : 
    1024   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
    1025                 :             : 
    1026                 :           2 :         const char *filename = "templates/0015_010.txt";
    1027                 :             : 
    1028   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
    1029                 :             : 
    1030                 :             :         // Match the result against the pattern
    1031   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
    1032                 :             : 
    1033                 :             :         // Clean up test results
    1034                 :           2 :         command = "rm \"${TMPDIR}/0015_database_v2.db\"";
    1035                 :             : 
    1036   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
    1037                 :             : 
    1038                 :             :         // Clean to use it iteratively
    1039                 :           2 :         del(pattern);
    1040                 :           2 :         del(result);
    1041                 :             : 
    1042   [ +  -  -  +  :           2 :         RETURN_STATUS;
          -  -  -  +  +  
                      - ]
    1043                 :             : }
    1044                 :             : 
    1045                 :             : /**
    1046                 :             :  *
    1047                 :             :  * Run the database comparison again using the --compare and --update parameters.
    1048                 :             :  * Upgrading from 2 to the last version
    1049                 :             :  *
    1050                 :             :  */
    1051                 :           2 : Return test0015_12(void)
    1052                 :             : {
    1053                 :           2 :         INITTEST;
    1054                 :             : 
    1055   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
    1056                 :             : 
    1057                 :             :         // Get the output of an external program
    1058                 :           2 :         const char *command = "cp -a ${ORIGIN_DIR}/tests/templates/0015_database_v2.db ${TMPDIR}/";
    1059                 :             : 
    1060   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
    1061                 :             : 
    1062                 :           2 :         const char *arguments = "--compare --update $DBNAME 0015_database_v2.db";
    1063                 :             : 
    1064                 :           2 :         const char *filename = "templates/0015_011.txt";  // File name
    1065                 :           2 :         const char *template = "%DB_NAME%";
    1066                 :             : 
    1067                 :           2 :         const char *replacement = getenv("DBNAME");  // Database name
    1068                 :             : 
    1069   [ +  -  +  - ]:           2 :         ASSERT(replacement != NULL);
    1070                 :             : 
    1071   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == match_app_output(arguments,filename,template,replacement,COMPLETED));
    1072                 :             : 
    1073                 :             :         // Clean up test results
    1074                 :           2 :         command = "rm \"${TMPDIR}/${DBNAME}\" && "
    1075                 :             :                 "rm \"${TMPDIR}/0015_database_v2.db\"";
    1076                 :             : 
    1077   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
    1078                 :             : 
    1079   [ +  -  -  +  :           2 :         RETURN_STATUS;
          -  -  -  +  +  
                      - ]
    1080                 :             : }
    1081                 :             : 
    1082                 :             : /**
    1083                 :             :  *
    1084                 :             :  * Upgrade a DB with UTF-8 name from version 3 to the current version
    1085                 :             :  * as the primary database using --update.
    1086                 :             :  *
    1087                 :             :  */
    1088                 :           2 : Return test0015_13(void)
    1089                 :             : {
    1090                 :           2 :         INITTEST;
    1091                 :             : 
    1092   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
    1093                 :             : 
    1094                 :           2 :         const char *command = "cp -a \"${ORIGIN_DIR}/tests/templates/0015_database_v3 это база данных с пробелами и символами UTF-8.db\" ${TMPDIR}/";
    1095                 :             : 
    1096   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
    1097                 :             : 
    1098                 :           2 :         const char *arguments = "--update --database=\"0015_database_v3 это база данных с пробелами и символами UTF-8.db\" "
    1099                 :             :                 "tests/fixtures/diffs/diff1";
    1100                 :             : 
    1101                 :           2 :         create(char,result);
    1102                 :             : 
    1103   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
    1104                 :             : 
    1105                 :           2 :         const char *filename = "templates/0015_012.txt";
    1106                 :             : 
    1107                 :           2 :         create(char,pattern);
    1108                 :             : 
    1109   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
    1110                 :             : 
    1111                 :             :         // Match the result against the pattern
    1112   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
    1113                 :             : 
    1114                 :             :         // Clean up test results
    1115                 :           2 :         command = "rm \"${TMPDIR}/0015_database_v3 это база данных с пробелами и символами UTF-8.db\"";
    1116                 :             : 
    1117   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
    1118                 :             : 
    1119                 :             :         // Clean to use it iteratively
    1120                 :           2 :         del(pattern);
    1121                 :           2 :         del(result);
    1122                 :             : 
    1123   [ +  -  -  +  :           2 :         RETURN_STATUS;
          -  -  -  +  +  
                      - ]
    1124                 :             : }
    1125                 :             : 
    1126                 :             : /**
    1127                 :             :  * Upgrade from version 3 during database comparison using
    1128                 :             :  * --compare and --update parameters.
    1129                 :             :  */
    1130                 :           2 : Return test0015_14(void)
    1131                 :             : {
    1132                 :           2 :         INITTEST;
    1133                 :             : 
    1134   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
    1135                 :             : 
    1136                 :           2 :         const char *command = "cp -a \"${ORIGIN_DIR}/tests/templates/0015_database_v3 это база данных с пробелами и символами UTF-8.db\" ${TMPDIR}/ && "
    1137                 :             :                 "cp -a \"${ORIGIN_DIR}/tests/templates/0015_database_v4 это база данных с пробелами и символами UTF-8.db\" ${TMPDIR}/";
    1138                 :             : 
    1139   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
    1140                 :             : 
    1141                 :           2 :         const char *arguments = "--compare --update "
    1142                 :             :                 "\"0015_database_v3 это база данных с пробелами и символами UTF-8.db\" "
    1143                 :             :                 "\"0015_database_v4 это база данных с пробелами и символами UTF-8.db\"";
    1144                 :             : 
    1145                 :           2 :         create(char,result);
    1146                 :           2 :         create(char,pattern);
    1147                 :             : 
    1148   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
    1149                 :             : 
    1150                 :           2 :         const char *filename = "templates/0015_013.txt";
    1151                 :             : 
    1152   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
    1153                 :             : 
    1154                 :             :         // Match the result against the pattern
    1155   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
    1156                 :             : 
    1157                 :           2 :         del(result);
    1158                 :           2 :         del(pattern);
    1159                 :             : 
    1160                 :           2 :         command = "rm \"${TMPDIR}/0015_database_v3 это база данных с пробелами и символами UTF-8.db\" "
    1161                 :             :                 "\"${TMPDIR}/0015_database_v4 это база данных с пробелами и символами UTF-8.db\"";
    1162                 :             : 
    1163   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
    1164                 :             : 
    1165   [ +  -  -  +  :           2 :         RETURN_STATUS;
          -  -  -  +  +  
                      - ]
    1166                 :             : }
    1167                 :             : 
    1168                 :             : /**
    1169                 :             :  * Create a fresh database inside tests/fixtures/diffs/ with the UTF-8 name
    1170                 :             :  * "Это новая база данных.db" and ensure the app can read/write it despite
    1171                 :             :  * spaces and non-ASCII characters.
    1172                 :             :  * Then compare it against the legacy database
    1173                 :             :  * "0015_database_v4 это база данных с пробелами и символами UTF-8.db" that was
    1174                 :             :  * produced by a well-tested older release when upgraded to the version 4.
    1175                 :             :  * If the files and checksums match, the current checksum calculation is
    1176                 :             :  * considered compatible with the legacy well-tested algorithm.
    1177                 :             :  */
    1178                 :           2 : Return test0015_15(void)
    1179                 :             : {
    1180                 :           2 :         INITTEST;
    1181                 :             : 
    1182   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
    1183                 :             : 
    1184                 :           2 :         const char *command = "cp -a \"${ORIGIN_DIR}/tests/templates/0015_database_v4 это база данных с пробелами и символами UTF-8.db\" ${TMPDIR}/";
    1185                 :             : 
    1186   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
    1187                 :             : 
    1188                 :           2 :         create(char,pattern);
    1189                 :           2 :         create(char,result);
    1190                 :           2 :         create(char,chunk);
    1191                 :             : 
    1192                 :           2 :         const char *arguments = "--database=\"Это новая база данных.db\" "
    1193                 :             :                 "tests/fixtures/diffs/diff1";
    1194                 :             : 
    1195   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == runit(arguments,chunk,NULL,COMPLETED,ALLOW_BOTH));
    1196   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == copy(result,chunk));
    1197                 :             : 
    1198                 :           2 :         arguments = "--compare \"Это новая база данных.db\" "
    1199                 :             :                 "\"0015_database_v4 это база данных с пробелами и символами UTF-8.db\"";
    1200                 :             : 
    1201   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == runit(arguments,chunk,NULL,COMPLETED,ALLOW_BOTH));
    1202   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == concat_strings(result,chunk));
    1203                 :             : 
    1204                 :           2 :         const char *filename = "templates/0015_014.txt";
    1205                 :             : 
    1206   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
    1207                 :             : 
    1208                 :             :         // Match the result against the pattern
    1209   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
    1210                 :             : 
    1211                 :             :         // Clean to use it iteratively
    1212                 :           2 :         del(pattern);
    1213                 :           2 :         del(result);
    1214                 :           2 :         del(chunk);
    1215                 :             : 
    1216                 :             :         // Clean up test results
    1217                 :           2 :         command = "rm \"${TMPDIR}/Это новая база данных.db\" \"${TMPDIR}/0015_database_v4 это база данных с пробелами и символами UTF-8.db\"";
    1218                 :             : 
    1219   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
    1220                 :             : 
    1221   [ +  -  -  +  :           2 :         RETURN_STATUS;
          -  -  -  +  +  
                      - ]
    1222                 :             : }
    1223                 :             : 
    1224                 :             : /**
    1225                 :             :  * Corrupt one v0 row stat blob and verify that upgrade still completes.
    1226                 :             :  * The corrupted row must end up as converted "zero source" v4 compact stat.
    1227                 :             :  */
    1228                 :           2 : Return test0015_16(void)
    1229                 :             : {
    1230                 :           2 :         INITTEST;
    1231                 :             : 
    1232   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
    1233                 :             : 
    1234                 :           2 :         const char *command =
    1235                 :             :                 "cp -a \"${ORIGIN_DIR}/tests/templates/0015_database_v0.db\" "
    1236                 :             :                 "\"${TMPDIR}/0015_database_v0_corrupt.db\" && "
    1237                 :             :                 "cp -a \"${ORIGIN_DIR}/tests/templates/" LEGACY_V4_UTF8_DB "\" "
    1238                 :             :                 "\"${TMPDIR}/0015_database_v4_reference.db\"";
    1239                 :             : 
    1240   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
    1241                 :             : 
    1242                 :           2 :         sqlite3_int64 row_id = 0;
    1243   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == corrupt_first_row_stat_blob("0015_database_v0_corrupt.db",&row_id));
    1244                 :             : 
    1245                 :           2 :         create(char,result);
    1246                 :           2 :         create(char,pattern);
    1247                 :             : 
    1248                 :           2 :         const char *arguments = "--compare --update "
    1249                 :             :                 "0015_database_v4_reference.db 0015_database_v0_corrupt.db";
    1250                 :             : 
    1251   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
    1252                 :           2 :         const char *filename = "templates/0015_015.txt";
    1253   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
    1254   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
    1255                 :             : 
    1256                 :           2 :         int db_version = 0;
    1257   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == read_db_version_from_metadata("0015_database_v0_corrupt.db",&db_version));
    1258   [ +  -  +  - ]:           2 :         ASSERT(db_version == 4);
    1259                 :             : 
    1260                 :           2 :         CmpctStat stat = {0};
    1261   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == read_cmpctstat_by_row_id("0015_database_v0_corrupt.db",row_id,&stat));
    1262   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == verify_zero_converted_cmpctstat(&stat));
    1263                 :             : 
    1264                 :           2 :         command = "rm -f \"${TMPDIR}/0015_database_v0_corrupt.db\" "
    1265                 :             :                 "\"${TMPDIR}/0015_database_v4_reference.db\"";
    1266                 :             : 
    1267   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
    1268                 :             : 
    1269                 :           2 :         del(result);
    1270                 :           2 :         del(pattern);
    1271                 :             : 
    1272   [ +  -  -  +  :           2 :         RETURN_STATUS;
          -  -  -  +  +  
                      - ]
    1273                 :             : }
    1274                 :             : 
    1275                 :             : /**
    1276                 :             :  * Corrupt one v3 row stat blob and verify that upgrade still completes.
    1277                 :             :  * The corrupted row must be stored using zero-source conversion logic.
    1278                 :             :  */
    1279                 :           2 : Return test0015_17(void)
    1280                 :             : {
    1281                 :           2 :         INITTEST;
    1282                 :             : 
    1283   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
    1284                 :             : 
    1285                 :           2 :         const char *command =
    1286                 :             :                 "cp -a \"${ORIGIN_DIR}/tests/templates/" LEGACY_V3_UTF8_DB "\" "
    1287                 :             :                 "\"${TMPDIR}/0015_database_v3_corrupt.db\" && "
    1288                 :             :                 "cp -a \"${ORIGIN_DIR}/tests/templates/" LEGACY_V4_UTF8_DB "\" "
    1289                 :             :                 "\"${TMPDIR}/0015_database_v4_reference.db\"";
    1290                 :             : 
    1291   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
    1292                 :             : 
    1293                 :           2 :         sqlite3_int64 row_id = 0;
    1294   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == corrupt_first_row_stat_blob("0015_database_v3_corrupt.db",&row_id));
    1295                 :             : 
    1296                 :           2 :         create(char,result);
    1297                 :           2 :         create(char,pattern);
    1298                 :             : 
    1299                 :           2 :         const char *arguments = "--compare --update "
    1300                 :             :                 "0015_database_v4_reference.db 0015_database_v3_corrupt.db";
    1301                 :             : 
    1302   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
    1303                 :           2 :         const char *filename = "templates/0015_016.txt";
    1304   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
    1305   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
    1306                 :             : 
    1307                 :           2 :         int db_version = 0;
    1308   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == read_db_version_from_metadata("0015_database_v3_corrupt.db",&db_version));
    1309   [ +  -  +  - ]:           2 :         ASSERT(db_version == 4);
    1310                 :             : 
    1311                 :           2 :         CmpctStat stat = {0};
    1312   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == read_cmpctstat_by_row_id("0015_database_v3_corrupt.db",row_id,&stat));
    1313   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == verify_zero_converted_cmpctstat(&stat));
    1314                 :             : 
    1315                 :           2 :         command = "rm -f \"${TMPDIR}/0015_database_v3_corrupt.db\" "
    1316                 :             :                 "\"${TMPDIR}/0015_database_v4_reference.db\"";
    1317                 :             : 
    1318   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
    1319                 :             : 
    1320                 :           2 :         del(result);
    1321                 :           2 :         del(pattern);
    1322                 :             : 
    1323   [ +  -  -  +  :           2 :         RETURN_STATUS;
          -  -  -  +  +  
                      - ]
    1324                 :             : }
    1325                 :             : 
    1326                 :             : /**
    1327                 :             :  * Regression test: when a SQLite error occurs during 3->4 migration,
    1328                 :             :  * the opened transaction must be rolled back.
    1329                 :             :  */
    1330                 :           2 : Return test0015_18(void)
    1331                 :             : {
    1332                 :           2 :         INITTEST;
    1333                 :             : 
    1334   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
    1335                 :             : 
    1336                 :           2 :         const char *command =
    1337                 :             :                 "cp -a \"${ORIGIN_DIR}/tests/templates/" LEGACY_V3_UTF8_DB "\" "
    1338                 :             :                 "\"${TMPDIR}/0015_database_v3_rollback.db\" && "
    1339                 :             :                 "cp -a \"${ORIGIN_DIR}/tests/templates/" LEGACY_V4_UTF8_DB "\" "
    1340                 :             :                 "\"${TMPDIR}/0015_database_v4_reference.db\"";
    1341                 :             : 
    1342   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
    1343                 :             : 
    1344                 :           2 :         int files_count = 0;
    1345   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == read_files_count("0015_database_v3_rollback.db",&files_count));
    1346   [ +  -  +  - ]:           2 :         ASSERT(files_count >= 2);
    1347                 :             : 
    1348                 :           2 :         sqlite3_int64 row_id = 0;
    1349   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == read_first_row_id("0015_database_v3_rollback.db",&row_id));
    1350                 :             : 
    1351                 :             :         unsigned char before_blob[512];
    1352                 :           2 :         int before_blob_size = 0;
    1353   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == read_stat_blob_by_row_id("0015_database_v3_rollback.db",
    1354                 :             :                                                    row_id,
    1355                 :             :                                                    before_blob,
    1356                 :             :                                                    sizeof(before_blob),
    1357                 :             :                                                    &before_blob_size));
    1358                 :             : 
    1359                 :           2 :         int v1_rows_before = 0;
    1360   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == read_files_count_with_blob_size("0015_database_v3_rollback.db",
    1361                 :             :                                                           (int)sizeof(CmpctStat_v1),
    1362                 :             :                                                           &v1_rows_before));
    1363                 :             : 
    1364   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == create_abort_on_second_stat_update_trigger("0015_database_v3_rollback.db"));
    1365                 :             : 
    1366                 :           2 :         create(char,result);
    1367                 :           2 :         create(char,pattern);
    1368                 :             : 
    1369                 :           2 :         const char *arguments = "--compare --update "
    1370                 :             :                 "0015_database_v4_reference.db 0015_database_v3_rollback.db";
    1371                 :             : 
    1372   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,FAILURE,ALLOW_BOTH));
    1373                 :           2 :         const char *filename = "templates/0015_017.txt";
    1374   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
    1375   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
    1376                 :             : 
    1377                 :           2 :         int db_version = 0;
    1378   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == read_db_version_from_metadata("0015_database_v3_rollback.db",&db_version));
    1379   [ +  -  +  - ]:           2 :         ASSERT(db_version == 3);
    1380                 :             : 
    1381                 :             :         unsigned char after_blob[512];
    1382                 :           2 :         int after_blob_size = 0;
    1383   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == read_stat_blob_by_row_id("0015_database_v3_rollback.db",
    1384                 :             :                                                    row_id,
    1385                 :             :                                                    after_blob,
    1386                 :             :                                                    sizeof(after_blob),
    1387                 :             :                                                    &after_blob_size));
    1388                 :             : 
    1389   [ +  -  +  - ]:           2 :         ASSERT(before_blob_size == after_blob_size);
    1390                 :             : 
    1391         [ +  - ]:           2 :         if(before_blob_size > 0)
    1392                 :             :         {
    1393   [ +  -  +  - ]:           2 :                 ASSERT(0 == memcmp(before_blob,after_blob,(size_t)before_blob_size));
    1394                 :             :         }
    1395                 :             : 
    1396                 :           2 :         int v1_rows_after = 0;
    1397   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == read_files_count_with_blob_size("0015_database_v3_rollback.db",
    1398                 :             :                                                           (int)sizeof(CmpctStat_v1),
    1399                 :             :                                                           &v1_rows_after));
    1400   [ +  -  +  - ]:           2 :         ASSERT(v1_rows_before == v1_rows_after);
    1401                 :             : 
    1402                 :           2 :         command = "rm -f \"${TMPDIR}/0015_database_v3_rollback.db\" "
    1403                 :             :                 "\"${TMPDIR}/0015_database_v4_reference.db\"";
    1404                 :             : 
    1405   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
    1406                 :             : 
    1407                 :           2 :         del(result);
    1408                 :           2 :         del(pattern);
    1409                 :             : 
    1410   [ +  -  -  +  :           2 :         RETURN_STATUS;
          -  -  -  +  +  
                      - ]
    1411                 :             : }
    1412                 :             : 
    1413                 :             : /**
    1414                 :             :  * Generate a fresh database, force future metadata version and verify warning path
    1415                 :             :  */
    1416                 :           2 : Return test0015_19(void)
    1417                 :             : {
    1418                 :           2 :         INITTEST;
    1419                 :             : 
    1420   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
    1421                 :             : 
    1422                 :           2 :         const char *db_filename = "0015_database_future_version.db";
    1423                 :           2 :         const char *command = "rm -f \"${TMPDIR}/0015_database_future_version.db\"";
    1424                 :             : 
    1425   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
    1426                 :             : 
    1427                 :           2 :         const char *arguments = "--database=0015_database_future_version.db "
    1428                 :             :                 "tests/fixtures/diffs/diff1";
    1429                 :             : 
    1430                 :           2 :         create(char,result);
    1431                 :           2 :         create(char,pattern);
    1432                 :             : 
    1433   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == runit(arguments,NULL,NULL,COMPLETED,ALLOW_BOTH));
    1434   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_db_version_in_metadata(db_filename,CURRENT_DB_VERSION + 1));
    1435                 :             : 
    1436                 :           2 :         int db_version = 0;
    1437   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == read_db_version_from_metadata(db_filename,&db_version));
    1438   [ +  -  +  - ]:           2 :         ASSERT(db_version == CURRENT_DB_VERSION + 1);
    1439                 :             : 
    1440   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,WARNING,ALLOW_BOTH));
    1441                 :             : 
    1442                 :           2 :         const char *filename = "templates/0015_018_1.txt";
    1443                 :             : 
    1444   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
    1445   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
    1446                 :             : 
    1447   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == read_db_version_from_metadata(db_filename,&db_version));
    1448   [ +  -  +  - ]:           2 :         ASSERT(db_version == CURRENT_DB_VERSION + 1);
    1449                 :             : 
    1450   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
    1451   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,WARNING,ALLOW_BOTH));
    1452                 :             : 
    1453                 :           2 :         filename = "templates/0015_018_2.txt";
    1454                 :             : 
    1455   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
    1456   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
    1457                 :             : 
    1458   [ +  -  +  - ]:           2 :         ASSERT(SUCCESS == external_call(command,NULL,NULL,COMPLETED,ALLOW_BOTH));
    1459                 :             : 
    1460                 :           2 :         del(result);
    1461                 :           2 :         del(pattern);
    1462                 :             : 
    1463   [ +  -  -  +  :           2 :         RETURN_STATUS;
          -  -  -  +  +  
                      - ]
    1464                 :             : }
    1465                 :             : 
    1466                 :             : /**
    1467                 :             :  * Testing scenario 15
    1468                 :             :  *
    1469                 :             :  * Database upgrade testing:
    1470                 :             :  * - Upgrade DBs from versions 0, 1, 2, and 3 to the current version as the primary database using --update
    1471                 :             :  * - Upgrade DBs from versions 0, 1, 2, and 3 during comparison using --compare --update
    1472                 :             :  * - Launch the program without specifying a database to ensure that a new database is created with the correct version
    1473                 :             :  * - Compare a current database with an outdated version (v0) without --update and check for the expected error
    1474                 :             :  * - Validate UTF-8 database names and checksum compatibility against a legacy v4 database
    1475                 :             :  * - Verify upgrade resilience for corrupted stat blobs in legacy DB v0 and v3
    1476                 :             :  * - Regression-check rollback behavior on forced SQLite failure during migration
    1477                 :             :  * - Generate a fresh DB and verify warning behavior for future DB version
    1478                 :             :  */
    1479                 :           2 : Return test0015(void)
    1480                 :             : {
    1481                 :           2 :         INITTEST;
    1482                 :             : 
    1483         [ +  - ]:           2 :         TEST(test0015_1,"Upgrade a DB from v0 to the current version. Error handling…");
    1484         [ +  - ]:           2 :         TEST(test0015_2,"Upgrade a DB from v0 to the current version as the primary database…");
    1485         [ +  - ]:           2 :         TEST(test0015_3,"Upgrade a DB from v0 to the current version with --watch-timestamps…");
    1486         [ +  - ]:           2 :         TEST(test0015_4,"Verify that the DB is actually at the current version…");
    1487         [ +  - ]:           2 :         TEST(test0015_5,"Create default name database…");
    1488         [ +  - ]:           2 :         TEST(test0015_6,"Attempting an upgrade with a single --compare parameter…");
    1489         [ +  - ]:           2 :         TEST(test0015_7,"Upgrading from 0 to the last version using the --compare and --update…");
    1490         [ +  - ]:           2 :         TEST(test0015_8,"Upgrade a DB from v1 to the current version as the primary database…");
    1491         [ +  - ]:           2 :         TEST(test0015_9,"Verify that the DB is actually at the current version…");
    1492         [ +  - ]:           2 :         TEST(test0015_10,"Upgrading from 1 to the last version using the --compare and --update…");
    1493         [ +  - ]:           2 :         TEST(test0015_11,"Upgrade a DB from v2 to the current version as the primary database…");
    1494         [ +  - ]:           2 :         TEST(test0015_12,"Upgrading from 2 to the last version using the --compare and --update…");
    1495         [ +  - ]:           2 :         TEST(test0015_13,"Upgrading from 3 with UTF-8 name to the last version using the --update…");
    1496         [ +  - ]:           2 :         TEST(test0015_14,"Upgrading from 3 to the last version using the --compare and --update…");
    1497         [ +  - ]:           2 :         TEST(test0015_15,"Create and compare DBs with UTF-8 names and checksums from legacy DB…");
    1498         [ +  - ]:           2 :         TEST(test0015_16,"Corrupted v0 stat blob does not break the full upgrade…");
    1499         [ +  - ]:           2 :         TEST(test0015_17,"Corrupted v3 stat blob does not break the full upgrade…");
    1500         [ +  - ]:           2 :         TEST(test0015_18,"Forced SQLite failure triggers rollback during 3->4 migration…");
    1501         [ +  - ]:           2 :         TEST(test0015_19,"Fresh DB with forced future version returns warning and stays unchanged…");
    1502                 :             : 
    1503   [ +  -  -  +  :           2 :         RETURN_STATUS;
          -  -  -  +  +  
                      - ]
    1504                 :             : }
        

Generated by: LCOV version 2.0-1