LCOV - code coverage report
Current view: top level - tests/src - test0015.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 97.9 % 381 373
Test Date: 2026-07-12 01:01:34 Functions: 100.0 % 22 22
Branches: 50.0 % 28 14

             Branch data     Line data    Source code
       1                 :             : #include "sute.h"
       2                 :             : #include "db_upgrade.h"
       3                 :             : 
       4                 :             : /**
       5                 :             :  * @brief Validate zero-converted CmpctStat values after migration fixups
       6                 :             :  *
       7                 :             :  * @param[in] stat Compact stat structure to verify
       8                 :             :  *
       9                 :             :  * @return Return status code:
      10                 :             :  *         - SUCCESS: Structure matches expected zero-converted values
      11                 :             :  *         - FAILURE: One or more fields differ from expected values
      12                 :             :  */
      13                 :           4 : static Return db_verify_zero_converted_cmpctstat(const CmpctStat *stat)
      14                 :             : {
      15         [ -  + ]:           4 :         if(stat == NULL)
      16                 :             :         {
      17                 :           0 :                 return FAILURE;
      18                 :             :         }
      19                 :             : 
      20         [ -  + ]:           4 :         if(stat->st_size != 0)
      21                 :             :         {
      22                 :           0 :                 return FAILURE;
      23                 :             :         }
      24                 :             : 
      25         [ -  + ]:           4 :         if(stat->st_blocks != BLKCNT_UNKNOWN)
      26                 :             :         {
      27                 :           0 :                 return FAILURE;
      28                 :             :         }
      29                 :             : 
      30   [ +  -  -  + ]:           4 :         if(stat->st_dev != 0 || stat->st_ino != 0)
      31                 :             :         {
      32                 :           0 :                 return FAILURE;
      33                 :             :         }
      34                 :             : 
      35   [ +  -  -  + ]:           4 :         if(stat->mtim_tv_sec != 0 || stat->mtim_tv_nsec != 0)
      36                 :             :         {
      37                 :           0 :                 return FAILURE;
      38                 :             :         }
      39                 :             : 
      40   [ +  -  -  + ]:           4 :         if(stat->ctim_tv_sec != 0 || stat->ctim_tv_nsec != 0)
      41                 :             :         {
      42                 :           0 :                 return FAILURE;
      43                 :             :         }
      44                 :             : 
      45                 :           4 :         return SUCCESS;
      46                 :             : }
      47                 :             : 
      48                 :             : /**
      49                 :             :  * @brief Create trigger that aborts on second stat update in files table
      50                 :             :  *
      51                 :             :  * @param[in] db_filename Database filename relative to TMPDIR
      52                 :             :  *
      53                 :             :  * @return Return status code:
      54                 :             :  *         - SUCCESS: Trigger and helper table were created
      55                 :             :  *         - FAILURE: Validation, DB open, or SQL execution failed
      56                 :             :  */
      57                 :           2 : static Return db_create_abort_on_second_stat_update_trigger(const char *db_filename)
      58                 :             : {
      59                 :             :         /* Status returned by this function through provide()
      60                 :             :            Default value assumes successful completion */
      61                 :           2 :         Return status = SUCCESS;
      62                 :           2 :         sqlite3 *db = NULL;
      63                 :           2 :         const char *sql =
      64                 :             :                 "DROP TRIGGER IF EXISTS __test_abort_on_second_update;"
      65                 :             :                 "DROP TABLE IF EXISTS __test_fail_counter;"
      66                 :             :                 "CREATE TABLE __test_fail_counter(n INTEGER NOT NULL);"
      67                 :             :                 "INSERT INTO __test_fail_counter(n) VALUES(0);"
      68                 :             :                 "CREATE TRIGGER __test_abort_on_second_update "
      69                 :             :                 "BEFORE UPDATE OF stat ON files "
      70                 :             :                 "BEGIN "
      71                 :             :                 "UPDATE __test_fail_counter SET n = n + 1;"
      72                 :             :                 "SELECT CASE WHEN (SELECT n FROM __test_fail_counter LIMIT 1) >= 2 "
      73                 :             :                 "THEN RAISE(ABORT,'forced rollback test failure') END;"
      74                 :             :                 "END;";
      75                 :             : 
      76         [ -  + ]:           2 :         if(db_filename == NULL)
      77                 :             :         {
      78                 :           0 :                 status = FAILURE;
      79                 :             :         }
      80                 :             : 
      81         [ +  - ]:           2 :         if(SUCCESS == status)
      82                 :             :         {
      83                 :           2 :                 status = open_db_from_tmpdir(db_filename,SQLITE_OPEN_READWRITE,&db);
      84                 :             :         }
      85                 :             : 
      86   [ +  -  -  + ]:           2 :         if(SUCCESS == status && SQLITE_OK != sqlite3_exec(db,sql,NULL,NULL,NULL))
      87                 :             :         {
      88                 :           0 :                 status = FAILURE;
      89                 :             :         }
      90                 :             : 
      91                 :           2 :         (void)sqlite3_close(db);
      92                 :             : 
      93                 :           2 :         return(status);
      94                 :             : }
      95                 :             : 
      96                 :             : /**
      97                 :             :  * @brief Reject using a legacy v0 DB as the primary database without --update
      98                 :             :  *
      99                 :             :  * Verify the run fails and prints the expected warning for the upgrade path
     100                 :             :  */
     101                 :           2 : Return test0015_1(void)
     102                 :             : {
     103                 :           2 :         INITTEST;
     104                 :             : 
     105                 :           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     106                 :           2 :         ASSERT(SUCCESS == copy_path("tests/templates/0015_database_v0.db","0015_database_v0.db"));
     107                 :             : 
     108                 :           2 :         const char *arguments = "--database=./0015_database_v0.db tests/fixtures/diffs/diff1";
     109                 :             : 
     110                 :           2 :         m_create(char,result,MEMORY_STRING);
     111                 :           2 :         m_create(char,pattern,MEMORY_STRING);
     112                 :             : 
     113                 :           2 :         const char *filename = "templates/0015_001.txt";
     114                 :             : 
     115                 :           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,WARNING,ALLOW_BOTH));
     116                 :             : 
     117                 :           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     118                 :             : 
     119                 :             :         // Match the result against the pattern
     120                 :           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     121                 :             : 
     122                 :             :         // Clean to use it iteratively
     123                 :           2 :         m_del(pattern);
     124                 :           2 :         m_del(result);
     125                 :             : 
     126                 :             :         // Clean up test results
     127                 :           2 :         ASSERT(SUCCESS == delete_path("0015_database_v0.db"));
     128                 :             : 
     129                 :           2 :         RETURN_STATUS;
     130                 :             : }
     131                 :             : 
     132                 :             : /**
     133                 :             :  * @brief Upgrade a legacy v0 DB as the primary database with --update
     134                 :             :  *
     135                 :             :  * Verify the upgrade succeeds and produces the expected output
     136                 :             :  */
     137                 :           2 : Return test0015_2(void)
     138                 :             : {
     139                 :           2 :         INITTEST;
     140                 :           2 :         ASSERT(SUCCESS == copy_path("tests/templates/0015_database_v0.db","0015_database_v0.db"));
     141                 :             : 
     142                 :           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     143                 :             : 
     144                 :           2 :         const char *arguments = "--update --database=0015_database_v0.db "
     145                 :             :                 "tests/fixtures/diffs/diff1";
     146                 :             : 
     147                 :           2 :         m_create(char,result,MEMORY_STRING);
     148                 :           2 :         m_create(char,pattern,MEMORY_STRING);
     149                 :             : 
     150                 :           2 :         const char *filename = "templates/0015_002_1.txt";
     151                 :             : 
     152                 :           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
     153                 :             : 
     154                 :           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     155                 :             : 
     156                 :             :         // Match the result against the pattern
     157                 :           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     158                 :             : 
     159                 :             :         // Clean up test results
     160                 :           2 :         ASSERT(SUCCESS == delete_path("0015_database_v0.db"));
     161                 :             : 
     162                 :             :         // Clean to use it iteratively
     163                 :           2 :         m_del(pattern);
     164                 :           2 :         m_del(result);
     165                 :             : 
     166                 :           2 :         RETURN_STATUS;
     167                 :             : }
     168                 :             : 
     169                 :             : /**
     170                 :             :  * @brief Upgrade a legacy v0 DB with --watch-timestamps enabled
     171                 :             :  *
     172                 :             :  * Verify the upgrade succeeds and reports timestamp details in the output
     173                 :             :  */
     174                 :           2 : Return test0015_3(void)
     175                 :             : {
     176                 :           2 :         INITTEST;
     177                 :           2 :         ASSERT(SUCCESS == copy_path("tests/templates/0015_database_v0.db","0015_database_v0.db"));
     178                 :             : 
     179                 :           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     180                 :             : 
     181                 :           2 :         const char *arguments = "--watch-timestamps --update --database=0015_database_v0.db "
     182                 :             :                 "tests/fixtures/diffs/diff1";
     183                 :             : 
     184                 :           2 :         m_create(char,result,MEMORY_STRING);
     185                 :           2 :         m_create(char,pattern,MEMORY_STRING);
     186                 :             : 
     187                 :           2 :         const char *filename = "templates/0015_002_2.txt";
     188                 :             : 
     189                 :           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
     190                 :             : 
     191                 :           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     192                 :             : 
     193                 :             :         // Match the result against the pattern
     194                 :           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     195                 :             : 
     196                 :             :         // Clean to use it iteratively
     197                 :           2 :         m_del(pattern);
     198                 :           2 :         m_del(result);
     199                 :             : 
     200                 :           2 :         RETURN_STATUS;
     201                 :             : }
     202                 :             : 
     203                 :             : /**
     204                 :             :  * @brief Re-run upgrade for the already upgraded v0 DB
     205                 :             :  *
     206                 :             :  * Verify the database is treated as current and the run stays successful
     207                 :             :  */
     208                 :           2 : Return test0015_4(void)
     209                 :             : {
     210                 :           2 :         INITTEST;
     211                 :             : 
     212                 :           2 :         m_create(char,result,MEMORY_STRING);
     213                 :           2 :         m_create(char,pattern,MEMORY_STRING);
     214                 :             : 
     215                 :           2 :         const char *filename = "templates/0015_003.txt";
     216                 :             : 
     217                 :           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     218                 :             : 
     219                 :           2 :         const char *arguments = "--update --database=./0015_database_v0.db "
     220                 :             :                 "tests/fixtures/diffs/diff1";
     221                 :             : 
     222                 :           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
     223                 :             : 
     224                 :           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     225                 :             : 
     226                 :             :         // Match the result against the pattern
     227                 :           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     228                 :             : 
     229                 :             :         // Clean to use it iteratively
     230                 :           2 :         m_del(pattern);
     231                 :           2 :         m_del(result);
     232                 :             : 
     233                 :             :         // Clean up test results
     234                 :           2 :         ASSERT(SUCCESS == delete_path("0015_database_v0.db"));
     235                 :             : 
     236                 :           2 :         RETURN_STATUS;
     237                 :             : }
     238                 :             : 
     239                 :             : /**
     240                 :             :  * @brief Create a fresh DB with the default generated filename
     241                 :             :  *
     242                 :             :  * Verify the application reports the generated DB name in the expected output
     243                 :             :  */
     244                 :           2 : Return test0015_5(void)
     245                 :             : {
     246                 :           2 :         INITTEST;
     247                 :             : 
     248                 :           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     249                 :             : 
     250                 :             :         // Run the application without an explicit DB name
     251                 :           2 :         const char *arguments = "tests/fixtures/diffs/diff1";
     252                 :             : 
     253                 :           2 :         const char *filename = "templates/0015_004.txt"; // File name
     254                 :           2 :         const char *template = "%DB_NAME%";
     255                 :             : 
     256                 :           2 :         const char *replacement = getenv("DBNAME"); // Database name
     257                 :             : 
     258                 :           2 :         ASSERT(replacement != NULL);
     259                 :             : 
     260                 :           2 :         ASSERT(SUCCESS == match_app_output(arguments,filename,template,replacement,COMPLETED));
     261                 :             : 
     262                 :           2 :         RETURN_STATUS;
     263                 :             : }
     264                 :             : 
     265                 :             : /**
     266                 :             :  * @brief Compare a current DB against a legacy v0 DB without --update
     267                 :             :  *
     268                 :             :  * Verify the application warns that the legacy DB must be upgraded first
     269                 :             :  */
     270                 :           2 : Return test0015_6(void)
     271                 :             : {
     272                 :           2 :         INITTEST;
     273                 :             : 
     274                 :           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     275                 :             : 
     276                 :           2 :         ASSERT(SUCCESS == copy_path("tests/templates/0015_database_v0.db","0015_database_v0.db"));
     277                 :             : 
     278                 :           2 :         const char *arguments = "--compare $DBNAME 0015_database_v0.db";
     279                 :             : 
     280                 :           2 :         const char *filename = "templates/0015_005.txt"; // File name
     281                 :           2 :         const char *template = "%DB_NAME%";
     282                 :             : 
     283                 :           2 :         const char *replacement = getenv("DBNAME"); // Database name
     284                 :             : 
     285                 :           2 :         ASSERT(replacement != NULL);
     286                 :             : 
     287                 :           2 :         ASSERT(SUCCESS == match_app_output(arguments,filename,template,replacement,WARNING));
     288                 :             : 
     289                 :           2 :         RETURN_STATUS;
     290                 :             : }
     291                 :             : 
     292                 :             : /**
     293                 :             :  * @brief Compare and upgrade a legacy v0 DB with --compare --update
     294                 :             :  *
     295                 :             :  * Verify the legacy DB is upgraded during comparison and the run completes
     296                 :             :  */
     297                 :           2 : Return test0015_7(void)
     298                 :             : {
     299                 :           2 :         INITTEST;
     300                 :             : 
     301                 :           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     302                 :             : 
     303                 :             :         // Run the comparison and upgrade flow
     304                 :           2 :         const char *arguments = "--compare --update $DBNAME 0015_database_v0.db";
     305                 :             : 
     306                 :           2 :         const char *filename = "templates/0015_006.txt"; // File name
     307                 :           2 :         const char *template = "%DB_NAME%";
     308                 :             : 
     309                 :           2 :         const char *replacement = getenv("DBNAME"); // Database name
     310                 :             : 
     311                 :           2 :         ASSERT(replacement != NULL);
     312                 :             : 
     313                 :           2 :         ASSERT(SUCCESS == match_app_output(arguments,filename,template,replacement,COMPLETED));
     314                 :             : 
     315                 :             :         // Clean up test results
     316                 :           2 :         ASSERT(SUCCESS == delete_path("0015_database_v0.db"));
     317                 :             : 
     318                 :           2 :         RETURN_STATUS;
     319                 :             : }
     320                 :             : 
     321                 :             : /**
     322                 :             :  * @brief Upgrade a legacy v1 DB as the primary database with --update
     323                 :             :  *
     324                 :             :  * Verify the upgrade succeeds and produces the expected output
     325                 :             :  */
     326                 :           2 : Return test0015_8(void)
     327                 :             : {
     328                 :           2 :         INITTEST;
     329                 :             : 
     330                 :           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     331                 :           2 :         ASSERT(SUCCESS == copy_path("tests/templates/0015_database_v1.db","0015_database_v1.db"));
     332                 :             : 
     333                 :           2 :         const char *arguments = "--update --database=0015_database_v1.db "
     334                 :             :                 "tests/fixtures/diffs/diff1";
     335                 :             : 
     336                 :           2 :         m_create(char,result,MEMORY_STRING);
     337                 :           2 :         m_create(char,pattern,MEMORY_STRING);
     338                 :             : 
     339                 :           2 :         const char *filename = "templates/0015_007.txt";
     340                 :             : 
     341                 :           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
     342                 :             : 
     343                 :           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     344                 :             : 
     345                 :             :         // Match the result against the pattern
     346                 :           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     347                 :             : 
     348                 :             :         // Clean to use it iteratively
     349                 :           2 :         m_del(pattern);
     350                 :           2 :         m_del(result);
     351                 :             : 
     352                 :           2 :         RETURN_STATUS;
     353                 :             : }
     354                 :             : 
     355                 :             : /**
     356                 :             :  * @brief Re-run upgrade for the already upgraded v1 DB
     357                 :             :  *
     358                 :             :  * Verify the database is treated as current and the run stays successful
     359                 :             :  */
     360                 :           2 : Return test0015_9(void)
     361                 :             : {
     362                 :           2 :         INITTEST;
     363                 :             : 
     364                 :           2 :         m_create(char,result,MEMORY_STRING);
     365                 :           2 :         m_create(char,pattern,MEMORY_STRING);
     366                 :             : 
     367                 :           2 :         const char *filename = "templates/0015_008.txt";
     368                 :             : 
     369                 :           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     370                 :             : 
     371                 :           2 :         const char *arguments = "--update --database=./0015_database_v1.db "
     372                 :             :                 "tests/fixtures/diffs/diff1";
     373                 :             : 
     374                 :           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
     375                 :             : 
     376                 :           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     377                 :             : 
     378                 :             :         // Match the result against the pattern
     379                 :           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     380                 :             : 
     381                 :             :         // Clean to use it iteratively
     382                 :           2 :         m_del(pattern);
     383                 :           2 :         m_del(result);
     384                 :             : 
     385                 :             :         // Clean up test results
     386                 :           2 :         ASSERT(SUCCESS == delete_path("0015_database_v1.db"));
     387                 :             : 
     388                 :           2 :         RETURN_STATUS;
     389                 :             : }
     390                 :             : 
     391                 :             : /**
     392                 :             :  * @brief Compare and upgrade a legacy v1 DB with --compare --update
     393                 :             :  *
     394                 :             :  * Verify the legacy DB is upgraded during comparison and the run completes
     395                 :             :  */
     396                 :           2 : Return test0015_10(void)
     397                 :             : {
     398                 :           2 :         INITTEST;
     399                 :             : 
     400                 :           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     401                 :             : 
     402                 :             :         // Run the comparison and upgrade flow
     403                 :           2 :         ASSERT(SUCCESS == copy_path("tests/templates/0015_database_v1.db","0015_database_v1.db"));
     404                 :             : 
     405                 :           2 :         const char *arguments = "--compare --update $DBNAME 0015_database_v1.db";
     406                 :             : 
     407                 :           2 :         const char *filename = "templates/0015_009.txt"; // File name
     408                 :           2 :         const char *template = "%DB_NAME%";
     409                 :             : 
     410                 :           2 :         const char *replacement = getenv("DBNAME"); // Database name
     411                 :             : 
     412                 :           2 :         ASSERT(replacement != NULL);
     413                 :             : 
     414                 :           2 :         ASSERT(SUCCESS == match_app_output(arguments,filename,template,replacement,COMPLETED));
     415                 :             : 
     416                 :             :         // Clean up test results
     417                 :           2 :         ASSERT(SUCCESS == delete_path("0015_database_v1.db"));
     418                 :             : 
     419                 :           2 :         RETURN_STATUS;
     420                 :             : }
     421                 :             : 
     422                 :             : /**
     423                 :             :  * @brief Upgrade a legacy v2 DB as the primary database with --update
     424                 :             :  *
     425                 :             :  * Verify the upgrade succeeds and prints the verbose migration details
     426                 :             :  */
     427                 :           2 : Return test0015_11(void)
     428                 :             : {
     429                 :           2 :         INITTEST;
     430                 :             : 
     431                 :           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
     432                 :           2 :         ASSERT(SUCCESS == copy_path("tests/templates/0015_database_v2.db","0015_database_v2.db"));
     433                 :             : 
     434                 :           2 :         const char *arguments = "--update --database=0015_database_v2.db --verbose "
     435                 :             :                 "tests/fixtures/diffs/diff1";
     436                 :             : 
     437                 :           2 :         m_create(char,result,MEMORY_STRING);
     438                 :           2 :         m_create(char,pattern,MEMORY_STRING);
     439                 :             : 
     440                 :           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
     441                 :             : 
     442                 :           2 :         const char *filename = "templates/0015_010.txt";
     443                 :             : 
     444                 :           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     445                 :             : 
     446                 :             :         // Match the result against the pattern
     447                 :           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     448                 :             : 
     449                 :             :         // Clean up test results
     450                 :           2 :         ASSERT(SUCCESS == delete_path("0015_database_v2.db"));
     451                 :             : 
     452                 :             :         // Clean to use it iteratively
     453                 :           2 :         m_del(pattern);
     454                 :           2 :         m_del(result);
     455                 :             : 
     456                 :           2 :         RETURN_STATUS;
     457                 :             : }
     458                 :             : 
     459                 :             : /**
     460                 :             :  * @brief Compare and upgrade a legacy v2 DB with --compare --update
     461                 :             :  *
     462                 :             :  * Verify the legacy DB is upgraded during comparison and the run completes
     463                 :             :  */
     464                 :           2 : Return test0015_12(void)
     465                 :             : {
     466                 :           2 :         INITTEST;
     467                 :             : 
     468                 :           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     469                 :             : 
     470                 :             :         // Run the comparison and upgrade flow
     471                 :           2 :         ASSERT(SUCCESS == copy_path("tests/templates/0015_database_v2.db","0015_database_v2.db"));
     472                 :             : 
     473                 :           2 :         const char *arguments = "--compare --update $DBNAME 0015_database_v2.db";
     474                 :             : 
     475                 :           2 :         const char *filename = "templates/0015_011.txt"; // File name
     476                 :           2 :         const char *template = "%DB_NAME%";
     477                 :             : 
     478                 :           2 :         const char *replacement = getenv("DBNAME"); // Database name
     479                 :             : 
     480                 :           2 :         ASSERT(replacement != NULL);
     481                 :             : 
     482                 :           2 :         ASSERT(SUCCESS == match_app_output(arguments,filename,template,replacement,COMPLETED));
     483                 :             : 
     484                 :             :         // Clean up test results
     485                 :           2 :         ASSERT(SUCCESS == delete_path(replacement));
     486                 :           2 :         ASSERT(SUCCESS == delete_path("0015_database_v2.db"));
     487                 :             : 
     488                 :           2 :         RETURN_STATUS;
     489                 :             : }
     490                 :             : 
     491                 :             : /**
     492                 :             :  * @brief Upgrade a legacy v3 DB whose filename contains UTF-8 characters
     493                 :             :  *
     494                 :             :  * Verify the primary DB upgrade works with spaces and non-ASCII characters
     495                 :             :  */
     496                 :           2 : Return test0015_13(void)
     497                 :             : {
     498                 :           2 :         INITTEST;
     499                 :             : 
     500                 :           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     501                 :             : 
     502                 :           2 :         ASSERT(SUCCESS == copy_path("tests/templates/0015_database_v3 это база данных с пробелами и символами UTF-8.db","0015_database_v3 это база данных с пробелами и символами UTF-8.db"));
     503                 :             : 
     504                 :           2 :         const char *arguments = "--update --database=\"0015_database_v3 это база данных с пробелами и символами UTF-8.db\" "
     505                 :             :                 "tests/fixtures/diffs/diff1";
     506                 :             : 
     507                 :           2 :         m_create(char,result,MEMORY_STRING);
     508                 :             : 
     509                 :           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
     510                 :             : 
     511                 :           2 :         const char *filename = "templates/0015_012.txt";
     512                 :             : 
     513                 :           2 :         m_create(char,pattern,MEMORY_STRING);
     514                 :             : 
     515                 :           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     516                 :             : 
     517                 :             :         // Match the result against the pattern
     518                 :           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     519                 :             : 
     520                 :             :         // Clean up test results
     521                 :           2 :         ASSERT(SUCCESS == delete_path("0015_database_v3 это база данных с пробелами и символами UTF-8.db"));
     522                 :             : 
     523                 :             :         // Clean to use it iteratively
     524                 :           2 :         m_del(pattern);
     525                 :           2 :         m_del(result);
     526                 :             : 
     527                 :           2 :         RETURN_STATUS;
     528                 :             : }
     529                 :             : 
     530                 :             : /**
     531                 :             :  * @brief Compare and upgrade a legacy v3 UTF-8 DB with --compare --update
     532                 :             :  *
     533                 :             :  * Verify the upgrade path works when both compared DB filenames contain UTF-8
     534                 :             :  */
     535                 :           2 : Return test0015_14(void)
     536                 :             : {
     537                 :           2 :         INITTEST;
     538                 :             : 
     539                 :           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     540                 :             : 
     541                 :           2 :         ASSERT(SUCCESS == copy_path("tests/templates/0015_database_v3 это база данных с пробелами и символами UTF-8.db","0015_database_v3 это база данных с пробелами и символами UTF-8.db"));
     542                 :             : 
     543                 :           2 :         ASSERT(SUCCESS == copy_path("tests/templates/0015_database_v4 это база данных с пробелами и символами UTF-8.db","0015_database_v4 это база данных с пробелами и символами UTF-8.db"));
     544                 :             : 
     545                 :           2 :         const char *arguments = "--compare --update "
     546                 :             :                 "\"0015_database_v3 это база данных с пробелами и символами UTF-8.db\" "
     547                 :             :                 "\"0015_database_v4 это база данных с пробелами и символами UTF-8.db\"";
     548                 :             : 
     549                 :           2 :         m_create(char,result,MEMORY_STRING);
     550                 :           2 :         m_create(char,pattern,MEMORY_STRING);
     551                 :             : 
     552                 :           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
     553                 :             : 
     554                 :           2 :         const char *filename = "templates/0015_013.txt";
     555                 :             : 
     556                 :           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     557                 :             : 
     558                 :             :         // Match the result against the pattern
     559                 :           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     560                 :             : 
     561                 :           2 :         m_del(result);
     562                 :           2 :         m_del(pattern);
     563                 :             : 
     564                 :           2 :         ASSERT(SUCCESS == delete_path("0015_database_v3 это база данных с пробелами и символами UTF-8.db"));
     565                 :           2 :         ASSERT(SUCCESS == delete_path("0015_database_v4 это база данных с пробелами и символами UTF-8.db"));
     566                 :             : 
     567                 :           2 :         RETURN_STATUS;
     568                 :             : }
     569                 :             : 
     570                 :             : /**
     571                 :             :  * @brief Compare a fresh UTF-8 DB against a legacy UTF-8 v4 reference DB
     572                 :             :  *
     573                 :             :  * Verify the application can create, read, and compare DB filenames with
     574                 :             :  * spaces and non-ASCII characters while keeping checksum compatibility
     575                 :             :  */
     576                 :           2 : Return test0015_15(void)
     577                 :             : {
     578                 :           2 :         INITTEST;
     579                 :             : 
     580                 :           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     581                 :             : 
     582                 :           2 :         ASSERT(SUCCESS == copy_path("tests/templates/0015_database_v4 это база данных с пробелами и символами UTF-8.db","0015_database_v4 это база данных с пробелами и символами UTF-8.db"));
     583                 :             : 
     584                 :           2 :         m_create(char,pattern,MEMORY_STRING);
     585                 :           2 :         m_create(char,result,MEMORY_STRING);
     586                 :           2 :         m_create(char,chunk,MEMORY_STRING);
     587                 :             : 
     588                 :           2 :         const char *arguments = "--database=\"Это новая база данных.db\" "
     589                 :             :                 "tests/fixtures/diffs/diff1";
     590                 :             : 
     591                 :           2 :         ASSERT(SUCCESS == runit(arguments,chunk,NULL,COMPLETED,ALLOW_BOTH));
     592                 :           2 :         ASSERT(SUCCESS == m_copy(result,chunk));
     593                 :             : 
     594                 :           2 :         arguments = "--compare \"Это новая база данных.db\" "
     595                 :             :                 "\"0015_database_v4 это база данных с пробелами и символами UTF-8.db\"";
     596                 :             : 
     597                 :           2 :         ASSERT(SUCCESS == runit(arguments,chunk,NULL,COMPLETED,ALLOW_BOTH));
     598                 :           2 :         ASSERT(SUCCESS == m_concat_strings(result,chunk));
     599                 :             : 
     600                 :           2 :         const char *filename = "templates/0015_014.txt";
     601                 :             : 
     602                 :           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     603                 :             : 
     604                 :             :         // Match the result against the pattern
     605                 :           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     606                 :             : 
     607                 :             :         // Clean to use it iteratively
     608                 :           2 :         m_del(pattern);
     609                 :           2 :         m_del(result);
     610                 :           2 :         m_del(chunk);
     611                 :             : 
     612                 :             :         // Clean up test results
     613                 :           2 :         ASSERT(SUCCESS == delete_path("Это новая база данных.db"));
     614                 :           2 :         ASSERT(SUCCESS == delete_path("0015_database_v4 это база данных с пробелами и символами UTF-8.db"));
     615                 :             : 
     616                 :           2 :         RETURN_STATUS;
     617                 :             : }
     618                 :             : 
     619                 :             : /**
     620                 :             :  * @brief Upgrade a v0 DB with one corrupted legacy stat blob
     621                 :             :  *
     622                 :             :  * Verify the full upgrade still completes and the corrupted row is converted
     623                 :             :  * into the expected zero-source compact stat representation
     624                 :             :  */
     625                 :           2 : Return test0015_16(void)
     626                 :             : {
     627                 :           2 :         INITTEST;
     628                 :           2 :         const char *corrupted_db_filename = "0015_database_v0_corrupt.db";
     629                 :           2 :         const char *reference_db_filename = "0015_database_v4_reference.db";
     630                 :             : 
     631                 :           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     632                 :           2 :         ASSERT(SUCCESS == copy_path("tests/templates/0015_database_v0.db",corrupted_db_filename));
     633                 :           2 :         ASSERT(SUCCESS == copy_path("tests/templates/0015_database_v4 это база данных с пробелами и символами UTF-8.db",reference_db_filename));
     634                 :             : 
     635                 :           2 :         sqlite3_int64 row_id = 0;
     636                 :             : 
     637                 :           2 :         ASSERT(SUCCESS == db_corrupt_first_row_stat_blob(corrupted_db_filename,&row_id));
     638                 :             : 
     639                 :           2 :         m_create(char,result,MEMORY_STRING);
     640                 :           2 :         m_create(char,pattern,MEMORY_STRING);
     641                 :             : 
     642                 :           2 :         const char *arguments = "--compare --update 0015_database_v4_reference.db 0015_database_v0_corrupt.db";
     643                 :             : 
     644                 :           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
     645                 :           2 :         const char *filename = "templates/0015_015.txt";
     646                 :           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     647                 :           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     648                 :             : 
     649                 :           2 :         int db_version = 0;
     650                 :           2 :         ASSERT(SUCCESS == read_db_version_from_metadata(corrupted_db_filename,&db_version));
     651                 :           2 :         ASSERT(db_version == 4);
     652                 :             : 
     653                 :           2 :         CmpctStat stat = {0};
     654                 :           2 :         ASSERT(SUCCESS == db_read_cmpctstat_by_row_id(corrupted_db_filename,row_id,&stat));
     655                 :           2 :         ASSERT(SUCCESS == db_verify_zero_converted_cmpctstat(&stat));
     656                 :             : 
     657                 :           2 :         ASSERT(SUCCESS == delete_path(corrupted_db_filename));
     658                 :           2 :         ASSERT(SUCCESS == delete_path(reference_db_filename));
     659                 :             : 
     660                 :           2 :         m_del(result);
     661                 :           2 :         m_del(pattern);
     662                 :             : 
     663                 :           2 :         RETURN_STATUS;
     664                 :             : }
     665                 :             : 
     666                 :             : /**
     667                 :             :  * @brief Upgrade a v3 DB with one corrupted legacy stat blob
     668                 :             :  *
     669                 :             :  * Verify the full upgrade still completes and the corrupted row is stored
     670                 :             :  * using the zero-source conversion logic
     671                 :             :  */
     672                 :           2 : Return test0015_17(void)
     673                 :             : {
     674                 :           2 :         INITTEST;
     675                 :           2 :         const char *corrupted_db_filename = "0015_database_v3_corrupt.db";
     676                 :           2 :         const char *reference_db_filename = "0015_database_v4_reference.db";
     677                 :             : 
     678                 :           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     679                 :           2 :         ASSERT(SUCCESS == copy_path("tests/templates/0015_database_v3 это база данных с пробелами и символами UTF-8.db",corrupted_db_filename));
     680                 :           2 :         ASSERT(SUCCESS == copy_path("tests/templates/0015_database_v4 это база данных с пробелами и символами UTF-8.db",reference_db_filename));
     681                 :             : 
     682                 :           2 :         sqlite3_int64 row_id = 0;
     683                 :           2 :         ASSERT(SUCCESS == db_corrupt_first_row_stat_blob(corrupted_db_filename,&row_id));
     684                 :             : 
     685                 :           2 :         const char *arguments = "--compare --update 0015_database_v4_reference.db 0015_database_v3_corrupt.db";
     686                 :             : 
     687                 :           2 :         m_create(char,result,MEMORY_STRING);
     688                 :           2 :         m_create(char,pattern,MEMORY_STRING);
     689                 :             : 
     690                 :           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
     691                 :           2 :         const char *filename = "templates/0015_016.txt";
     692                 :           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     693                 :           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     694                 :             : 
     695                 :           2 :         int db_version = 0;
     696                 :           2 :         ASSERT(SUCCESS == read_db_version_from_metadata(corrupted_db_filename,&db_version));
     697                 :           2 :         ASSERT(db_version == 4);
     698                 :             : 
     699                 :           2 :         CmpctStat stat = {0};
     700                 :           2 :         ASSERT(SUCCESS == db_read_cmpctstat_by_row_id(corrupted_db_filename,row_id,&stat));
     701                 :           2 :         ASSERT(SUCCESS == db_verify_zero_converted_cmpctstat(&stat));
     702                 :             : 
     703                 :           2 :         ASSERT(SUCCESS == delete_path(corrupted_db_filename));
     704                 :           2 :         ASSERT(SUCCESS == delete_path(reference_db_filename));
     705                 :             : 
     706                 :           2 :         m_del(result);
     707                 :           2 :         m_del(pattern);
     708                 :             : 
     709                 :           2 :         RETURN_STATUS;
     710                 :             : }
     711                 :             : 
     712                 :             : /**
     713                 :             :  * @brief Roll back 3->4 migration when SQLite fails during stat conversion
     714                 :             :  *
     715                 :             :  * Verify the transaction is rolled back and the DB content stays unchanged
     716                 :             :  */
     717                 :           2 : Return test0015_18(void)
     718                 :             : {
     719                 :           2 :         INITTEST;
     720                 :           2 :         const char *rollback_db_filename = "0015_database_v3_rollback.db";
     721                 :           2 :         const char *reference_db_filename = "0015_database_v4_reference.db";
     722                 :             : 
     723                 :           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     724                 :           2 :         ASSERT(SUCCESS == copy_path("tests/templates/0015_database_v3 это база данных с пробелами и символами UTF-8.db",rollback_db_filename));
     725                 :           2 :         ASSERT(SUCCESS == copy_path("tests/templates/0015_database_v4 это база данных с пробелами и символами UTF-8.db",reference_db_filename));
     726                 :             : 
     727                 :           2 :         int files_count = 0;
     728                 :           2 :         ASSERT(SUCCESS == db_read_files_count(rollback_db_filename,&files_count));
     729                 :           2 :         ASSERT(files_count >= 2);
     730                 :             : 
     731                 :           2 :         sqlite3_int64 row_id = 0;
     732                 :           2 :         ASSERT(SUCCESS == db_read_first_row_id(rollback_db_filename,&row_id));
     733                 :             : 
     734                 :             :         unsigned char before_blob[512];
     735                 :           2 :         int before_blob_size = 0;
     736                 :           2 :         ASSERT(SUCCESS == db_read_stat_blob_by_row_id(rollback_db_filename,
     737                 :             :                 row_id,
     738                 :             :                 before_blob,
     739                 :             :                 sizeof(before_blob),
     740                 :             :                 &before_blob_size));
     741                 :             : 
     742                 :           2 :         int v1_rows_before = 0;
     743                 :           2 :         ASSERT(SUCCESS == db_read_files_count_with_blob_size(rollback_db_filename,
     744                 :             :                 (int)sizeof(CmpctStat_v1),
     745                 :             :                 &v1_rows_before));
     746                 :             : 
     747                 :           2 :         ASSERT(SUCCESS == db_create_abort_on_second_stat_update_trigger(rollback_db_filename));
     748                 :             : 
     749                 :           2 :         const char *arguments = "--compare --update 0015_database_v4_reference.db 0015_database_v3_rollback.db";
     750                 :             : 
     751                 :           2 :         m_create(char,result,MEMORY_STRING);
     752                 :           2 :         m_create(char,pattern,MEMORY_STRING);
     753                 :             : 
     754                 :           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,FAILURE,ALLOW_BOTH));
     755                 :           2 :         const char *filename = "templates/0015_017.txt";
     756                 :           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     757                 :           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     758                 :             : 
     759                 :           2 :         int db_version = 0;
     760                 :           2 :         ASSERT(SUCCESS == read_db_version_from_metadata(rollback_db_filename,&db_version));
     761                 :           2 :         ASSERT(db_version == 3);
     762                 :             : 
     763                 :             :         unsigned char after_blob[512];
     764                 :           2 :         int after_blob_size = 0;
     765                 :           2 :         ASSERT(SUCCESS == db_read_stat_blob_by_row_id(rollback_db_filename,
     766                 :             :                 row_id,
     767                 :             :                 after_blob,
     768                 :             :                 sizeof(after_blob),
     769                 :             :                 &after_blob_size));
     770                 :             : 
     771                 :           2 :         ASSERT(before_blob_size == after_blob_size);
     772                 :             : 
     773         [ +  - ]:           2 :         if(before_blob_size > 0)
     774                 :             :         {
     775                 :           2 :                 ASSERT(0 == memcmp(before_blob,after_blob,(size_t)before_blob_size));
     776                 :             :         }
     777                 :             : 
     778                 :           2 :         int v1_rows_after = 0;
     779                 :           2 :         ASSERT(SUCCESS == db_read_files_count_with_blob_size(rollback_db_filename,
     780                 :             :                 (int)sizeof(CmpctStat_v1),
     781                 :             :                 &v1_rows_after));
     782                 :           2 :         ASSERT(v1_rows_before == v1_rows_after);
     783                 :             : 
     784                 :           2 :         ASSERT(SUCCESS == delete_path(rollback_db_filename));
     785                 :           2 :         ASSERT(SUCCESS == delete_path(reference_db_filename));
     786                 :             : 
     787                 :           2 :         m_del(result);
     788                 :           2 :         m_del(pattern);
     789                 :             : 
     790                 :           2 :         RETURN_STATUS;
     791                 :             : }
     792                 :             : 
     793                 :             : /**
     794                 :             :  * @brief Warn when metadata declares a DB version newer than supported
     795                 :             :  *
     796                 :             :  * Verify both testing and non-testing modes keep the future DB unchanged
     797                 :             :  */
     798                 :           2 : Return test0015_19(void)
     799                 :             : {
     800                 :           2 :         INITTEST;
     801                 :             : 
     802                 :           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
     803                 :             : 
     804                 :           2 :         const char *db_filename = "0015_database_future_version.db";
     805                 :           2 :         const char *arguments = "--database=0015_database_future_version.db "
     806                 :             :                 "tests/fixtures/diffs/diff1";
     807                 :             : 
     808                 :           2 :         m_create(char,result,MEMORY_STRING);
     809                 :           2 :         m_create(char,pattern,MEMORY_STRING);
     810                 :             : 
     811                 :           2 :         ASSERT(SUCCESS == runit(arguments,NULL,NULL,COMPLETED,ALLOW_BOTH));
     812                 :           2 :         ASSERT(SUCCESS == set_db_version_in_metadata(db_filename,CURRENT_DB_VERSION + 1));
     813                 :             : 
     814                 :           2 :         int db_version = 0;
     815                 :           2 :         ASSERT(SUCCESS == read_db_version_from_metadata(db_filename,&db_version));
     816                 :           2 :         ASSERT(db_version == CURRENT_DB_VERSION + 1);
     817                 :             : 
     818                 :           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,WARNING,ALLOW_BOTH));
     819                 :             : 
     820                 :           2 :         const char *filename = "templates/0015_018_1.txt";
     821                 :             : 
     822                 :           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     823                 :           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     824                 :             : 
     825                 :           2 :         ASSERT(SUCCESS == read_db_version_from_metadata(db_filename,&db_version));
     826                 :           2 :         ASSERT(db_version == CURRENT_DB_VERSION + 1);
     827                 :             : 
     828                 :           2 :         ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
     829                 :           2 :         ASSERT(SUCCESS == runit(arguments,result,NULL,WARNING,ALLOW_BOTH));
     830                 :             : 
     831                 :           2 :         filename = "templates/0015_018_2.txt";
     832                 :             : 
     833                 :           2 :         ASSERT(SUCCESS == get_file_content(filename,pattern));
     834                 :           2 :         ASSERT(SUCCESS == match_pattern(result,pattern,filename));
     835                 :             : 
     836                 :           2 :         ASSERT(SUCCESS == delete_path(db_filename));
     837                 :             : 
     838                 :           2 :         m_del(result);
     839                 :           2 :         m_del(pattern);
     840                 :             : 
     841                 :           2 :         RETURN_STATUS;
     842                 :             : }
     843                 :             : 
     844                 :             : /**
     845                 :             :  * @brief Exercise DB upgrade and migration regressions across legacy formats
     846                 :             :  *
     847                 :             :  * This scenario covers primary DB upgrades from legacy versions 0 through 3,
     848                 :             :  * comparison-driven upgrades, default DB creation, UTF-8 filename handling,
     849                 :             :  * checksum compatibility against a legacy v4 reference DB, resilient handling
     850                 :             :  * of corrupted legacy stat blobs, rollback on forced SQLite migration failure,
     851                 :             :  * and warning behavior for a DB that reports a future metadata version
     852                 :             :  */
     853                 :           2 : Return test0015(void)
     854                 :             : {
     855                 :           2 :         INITTEST;
     856                 :             : 
     857                 :           2 :         TEST(test0015_1,"Upgrade a DB from v0 to the current version. Error handling");
     858                 :           2 :         TEST(test0015_2,"Upgrade a DB from v0 to the current version as the primary database");
     859                 :           2 :         TEST(test0015_3,"Upgrade a DB from v0 to the current version with --watch-timestamps");
     860                 :           2 :         TEST(test0015_4,"Verify that the upgraded v0 DB is actually at the current version");
     861                 :           2 :         TEST(test0015_5,"Create default name database");
     862                 :           2 :         TEST(test0015_6,"Attempting an upgrade with a single --compare parameter");
     863                 :           2 :         TEST(test0015_7,"Upgrading from 0 to the last version using the --compare and --update");
     864                 :           2 :         TEST(test0015_8,"Upgrade a DB from v1 to the current version as the primary database");
     865                 :           2 :         TEST(test0015_9,"Verify that the upgraded v1 DB is actually at the current version");
     866                 :           2 :         TEST(test0015_10,"Upgrading from 1 to the last version using the --compare and --update");
     867                 :           2 :         TEST(test0015_11,"Upgrade a DB from v2 to the current version as the primary database");
     868                 :           2 :         TEST(test0015_12,"Upgrading from 2 to the last version using the --compare and --update");
     869                 :           2 :         TEST(test0015_13,"Upgrading from 3 with UTF-8 name to the last version using the --update");
     870                 :           2 :         TEST(test0015_14,"Upgrading from 3 to the last version using the --compare and --update");
     871                 :           2 :         TEST(test0015_15,"Create and compare DBs with UTF-8 names and checksums from legacy DB");
     872                 :           2 :         TEST(test0015_16,"Corrupted v0 stat blob does not break the full upgrade");
     873                 :           2 :         TEST(test0015_17,"Corrupted v3 stat blob does not break the full upgrade");
     874                 :           2 :         TEST(test0015_18,"Forced SQLite failure triggers rollback during 3->4 migration");
     875                 :           2 :         TEST(test0015_19,"Fresh DB with forced future version returns warning and stays unchanged");
     876                 :             : 
     877                 :           2 :         RETURN_STATUS;
     878                 :             : }
        

Generated by: LCOV version 2.0-1