github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/sysfault.test (about)

     1  # 2011 March 28
     2  #
     3  # The author disclaims copyright to this source code.  In place of
     4  # a legal notice, here is a blessing:
     5  #
     6  #    May you do good and not evil.
     7  #    May you find forgiveness for yourself and forgive others.
     8  #    May you share freely, never taking more than you give.
     9  #
    10  #***********************************************************************
    11  #
    12  
    13  set testdir [file dirname $argv0]
    14  source $testdir/tester.tcl
    15  source $testdir/lock_common.tcl
    16  source $testdir/malloc_common.tcl
    17  
    18  if {[llength [info commands test_syscall]]==0} {
    19    finish_test
    20    return
    21  } 
    22  
    23  set testprefix sysfault
    24  
    25  set FAULTSIM(vfsfault-transient) [list             \
    26    -injectinstall   vfsfault_install                \
    27    -injectstart     vfsfault_injectstart_t          \
    28    -injectstop      vfsfault_injectstop             \
    29    -injecterrlist   {}                              \
    30    -injectuninstall {test_syscall uninstall}        \
    31  ]
    32  set FAULTSIM(vfsfault-persistent) [list            \
    33    -injectinstall   vfsfault_install                \
    34    -injectstart     vfsfault_injectstart_p          \
    35    -injectstop      vfsfault_injectstop             \
    36    -injecterrlist   {}                              \
    37    -injectuninstall {test_syscall uninstall}        \
    38  ]
    39  
    40  proc vfsfault_injectstart_t {iFail} { test_syscall fault $iFail 0 }
    41  proc vfsfault_injectstart_p {iFail} { test_syscall fault $iFail 1 }
    42  proc vfsfault_injectstop    {}      { test_syscall fault }
    43  
    44  faultsim_save_and_close
    45  
    46  
    47  set open_and_write_body {
    48    sqlite3 db test.db
    49    db eval {
    50      CREATE TABLE t1(a, b);
    51      INSERT INTO t1 VALUES(1, 2);
    52      PRAGMA journal_mode = WAL;
    53      INSERT INTO t1 VALUES(3, 4);
    54      SELECT * FROM t1;
    55      CREATE TEMP TABLE t2(x);
    56      INSERT INTO t2 VALUES('y');
    57    }
    58  }
    59  
    60  proc vfsfault_install {} { test_syscall install {open getcwd} }
    61  do_faultsim_test 1 -faults vfsfault-* -prep {
    62    faultsim_restore
    63  } -body $open_and_write_body -test {
    64    faultsim_test_result {0 {wal 1 2 3 4}}       \
    65      {1 {unable to open database file}}         \
    66      {1 {attempt to write a readonly database}}
    67  }
    68  
    69  #-------------------------------------------------------------------------
    70  # Errors in the fstat() function when opening and writing a file. Cases
    71  # where fstat() fails and sets errno to ENOMEM and EOVERFLOW are both
    72  # tested. EOVERFLOW is interpreted as meaning that a file on disk is
    73  # too large to be opened by the OS.
    74  #
    75  foreach {tn errno errlist} {
    76    1 ENOMEM       {{disk I/O error}}
    77    2 EOVERFLOW    {{disk I/O error} {large file support is disabled}}
    78  } {
    79    proc vfsfault_install {} { test_syscall install fstat }
    80    set errs [list]
    81    foreach e $errlist { lappend errs [list 1 $e] }
    82    do_faultsim_test 1.2.$tn -faults vfsfault-* -prep {
    83      faultsim_restore
    84    } -body "
    85      test_syscall errno fstat $errno
    86      $open_and_write_body 
    87    " -test "
    88      faultsim_test_result {0 {wal 1 2 3 4}} $errs
    89    "
    90  }
    91  
    92  #-------------------------------------------------------------------------
    93  # Various errors in locking functions. 
    94  #
    95  foreach vfs {unix unix-excl} {
    96    foreach {tn errno errlist} {
    97      1 EAGAIN       {{database is locked} {disk I/O error}}
    98      2 ETIMEDOUT    {{database is locked} {disk I/O error}}
    99      3 EBUSY        {{database is locked} {disk I/O error}}
   100      4 EINTR        {{database is locked} {disk I/O error}}
   101      5 ENOLCK       {{database is locked} {disk I/O error}}
   102      6 EACCES       {{database is locked} {disk I/O error}}
   103      7 EPERM        {{access permission denied} {disk I/O error}}
   104      8 EDEADLK      {{disk I/O error}}
   105      9 ENOMEM       {{disk I/O error}}
   106    } {
   107      proc vfsfault_install {} { test_syscall install fcntl }
   108      set errs [list]
   109      foreach e $errlist { lappend errs [list 1 $e] }
   110    
   111      set body [string map [list %VFS% $vfs] {
   112        sqlite3 db test.db
   113        db eval {
   114          CREATE TABLE t1(a, b);
   115          INSERT INTO t1 VALUES(1, 2);
   116        }
   117        set fd [open test.db-journal w]
   118        puts $fd "hello world"
   119        close $fd
   120        sqlite3 db test.db -vfs %VFS%
   121        db eval {
   122          SELECT * FROM t1;
   123        }
   124      }]
   125    
   126      do_faultsim_test 1.3.$vfs.$tn -faults vfsfault-* -prep {
   127        faultsim_restore
   128      } -body "
   129        test_syscall errno fcntl $errno
   130        $body
   131      " -test "
   132        faultsim_test_result {0 {1 2}} $errs
   133      "
   134    }
   135  }
   136  
   137  #-------------------------------------------------------------------------
   138  # Check that a single EINTR error does not affect processing.
   139  #
   140  proc vfsfault_install {} { 
   141    test_syscall reset
   142    test_syscall install {open ftruncate close read pread pread64 write fallocate}
   143  }
   144  
   145  forcedelete test.db test.db2
   146  sqlite3 db test.db
   147  do_test 2.setup {
   148    execsql {
   149      CREATE TABLE t1(a, b, c, PRIMARY KEY(a));
   150      INSERT INTO t1 VALUES('abc', 'def', 'ghi');
   151      ATTACH 'test.db2' AS 'aux';
   152      CREATE TABLE aux.t2(x);
   153      INSERT INTO t2 VALUES(1);
   154    }
   155    faultsim_save_and_close
   156  } {}
   157  
   158  do_faultsim_test 2.1 -faults vfsfault-transient -prep {
   159    catch { db close }
   160    faultsim_restore
   161  } -body {
   162    test_syscall errno open      EINTR
   163    test_syscall errno ftruncate EINTR
   164    test_syscall errno close     EINTR
   165    test_syscall errno read      EINTR
   166    test_syscall errno pread     EINTR
   167    test_syscall errno pread64   EINTR
   168    test_syscall errno write     EINTR
   169    test_syscall errno fallocate EINTR
   170  
   171    sqlite3 db test.db
   172    file_control_chunksize_test db main 8192
   173  
   174    set res [db eval {
   175      ATTACH 'test.db2' AS 'aux';
   176      SELECT * FROM t1;
   177      PRAGMA journal_mode = truncate;
   178      BEGIN;
   179        INSERT INTO t1 VALUES('jkl', 'mno', 'pqr');
   180        INSERT INTO t1 VALUES(randomblob(10000), 0, 0);
   181        UPDATE t2 SET x = 2;
   182      COMMIT;
   183      DELETE FROM t1 WHERE length(a)>3;
   184      SELECT * FROM t1;
   185      SELECT * FROM t2;
   186    }]
   187    db close
   188    set res
   189  } -test {
   190    faultsim_test_result {0 {abc def ghi truncate abc def ghi jkl mno pqr 2}}
   191  }
   192  
   193  do_faultsim_test 2.2 -faults vfsfault-* -prep {
   194    catch { db close }
   195    faultsim_restore
   196  } -body {
   197    sqlite3 db test.db
   198    set res [db eval {
   199      ATTACH 'test.db2' AS 'aux';
   200      SELECT * FROM t1;
   201      PRAGMA journal_mode = truncate;
   202      BEGIN;
   203        INSERT INTO t1 VALUES('jkl', 'mno', 'pqr');
   204        UPDATE t2 SET x = 2;
   205      COMMIT;
   206      SELECT * FROM t1;
   207      SELECT * FROM t2;
   208    }]
   209    db close
   210    set res
   211  } -test {
   212    faultsim_test_result {0 {abc def ghi truncate abc def ghi jkl mno pqr 2}} \
   213      {1 {unable to open database file}}                                      \
   214      {1 {unable to open database: test.db2}}                                 \
   215      {1 {attempt to write a readonly database}}                              \
   216      {1 {disk I/O error}}                                                  
   217  }
   218  
   219  #-------------------------------------------------------------------------
   220  
   221  proc vfsfault_install {} { 
   222    test_syscall reset
   223    test_syscall install {fstat fallocate}
   224  }
   225  do_faultsim_test 3 -faults vfsfault-* -prep {
   226    faultsim_delete_and_reopen
   227    file_control_chunksize_test db main 8192
   228    execsql {
   229      PRAGMA synchronous=OFF;
   230      CREATE TABLE t1(a, b);
   231      BEGIN;
   232        SELECT * FROM t1;
   233    }
   234  } -body {
   235    test_syscall errno fstat     EIO
   236    test_syscall errno fallocate EIO
   237  
   238    execsql {
   239      INSERT INTO t1 VALUES(randomblob(10000), randomblob(10000));
   240      SELECT length(a) + length(b) FROM t1;
   241      COMMIT;
   242    }
   243  } -test {
   244    faultsim_test_result {0 20000}
   245  }
   246  
   247  #-------------------------------------------------------------------------
   248  # Test errors in mmap().
   249  #
   250  proc vfsfault_install {} { 
   251    test_syscall reset
   252    test_syscall install {mmap}
   253  }
   254  
   255  faultsim_delete_and_reopen
   256  execsql {
   257    CREATE TABLE t1(a, b);
   258    INSERT INTO t1 VALUES(1, 2);
   259  }
   260  faultsim_save_and_close
   261  
   262  do_faultsim_test 4 -faults vfsfault-* -prep {
   263    faultsim_restore_and_reopen
   264    file_control_chunksize_test db main 8192
   265    execsql { 
   266      PRAGMA mmap_size = 1000000;
   267    }
   268  } -body {
   269    test_syscall errno mmap     EACCES
   270  
   271    execsql {
   272      SELECT * FROM t1;
   273    }
   274  } -test {
   275    faultsim_test_result {0 {1 2}} {1 {disk I/O error}}
   276  }
   277  
   278  finish_test