gitlab.com/CoiaPrant/sqlite3@v1.19.1/testdata/tcl/crashtest1.c (about)

     1  /*
     2  ** This program tests the ability of SQLite database to recover from a crash.
     3  ** This program runs under Unix only, but the results are applicable to all
     4  ** systems.
     5  **
     6  ** The main process first constructs a test database, then starts creating
     7  ** subprocesses that write to that database.  Each subprocess is killed off,
     8  ** without a chance to clean up its database connection, after a random
     9  ** delay.  This killing of the subprocesses simulates a crash or power
    10  ** failure.  The next subprocess to open the database should rollback
    11  ** whatever operation was in process at the time of the simulated crash.
    12  **
    13  ** If any problems are encountered, an error is reported and the test stops.
    14  ** If no problems are seen after a large number of tests, we assume that
    15  ** the rollback mechanism is working.
    16  */
    17  #include <stdio.h>
    18  #include <unistd.h>
    19  #include <sys/types.h>
    20  #include <sys/wait.h>
    21  #include <signal.h>
    22  #include <stdlib.h>
    23  #include <string.h>
    24  #include <sched.h>
    25  #include "sqlite.h"
    26  
    27  static void do_some_sql(int parent){
    28    char *zErr;
    29    int rc = SQLITE_OK;
    30    sqlite *db;
    31    int cnt = 0;
    32    static char zBig[] = 
    33      "-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    34      "-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    35  
    36    if( access("./test.db-journal",0)==0 ){
    37      /*printf("pid %d: journal exists.  rollback will be required\n",getpid());*/    unlink("test.db-saved");
    38      system("cp test.db test.db-saved");
    39      unlink("test.db-journal-saved");
    40      system("cp test.db-journal test.db-journal-saved");
    41    }
    42    db = sqlite_open("./test.db", 0, &zErr);
    43    if( db==0 ){
    44      printf("ERROR: %s\n", zErr);
    45      if( strcmp(zErr,"database disk image is malformed")==0 ){
    46        kill(parent, SIGKILL);
    47      }
    48      exit(1);
    49    }
    50    srand(getpid());
    51    while( rc==SQLITE_OK ){
    52      cnt++;
    53      rc = sqlite_exec_printf(db, 
    54         "INSERT INTO t1 VALUES(%d,'%d%s')", 0, 0, &zErr,
    55         rand(), rand(), zBig);
    56    }
    57    if( rc!=SQLITE_OK ){
    58      printf("ERROR #%d: %s\n", rc, zErr);
    59      if( rc==SQLITE_CORRUPT ){
    60        kill(parent, SIGKILL);
    61      }
    62    }
    63    printf("pid %d: cnt=%d\n", getpid(), cnt);
    64  }
    65  
    66  
    67  int main(int argc, char **argv){
    68    int i;
    69    sqlite *db;
    70    char *zErr;
    71    int status;
    72    int parent = getpid();
    73  
    74    unlink("test.db");
    75    unlink("test.db-journal");
    76    db = sqlite_open("test.db", 0, &zErr);
    77    if( db==0 ){
    78      printf("Cannot initialize: %s\n", zErr);
    79      return 1;
    80    }
    81    sqlite_exec(db, "CREATE TABLE t1(a,b)", 0, 0, 0);
    82    sqlite_close(db);
    83    for(i=0; i<10000; i++){
    84      int pid = fork();
    85      if( pid==0 ){
    86        sched_yield();
    87        do_some_sql(parent);
    88        return 0;
    89      }
    90      printf("test %d, pid=%d\n", i, pid);
    91      usleep(rand()%10000 + 1000);
    92      kill(pid, SIGKILL);
    93      waitpid(pid, &status, 0);
    94    }
    95    return 0;
    96  }