SQLite

Check-in [7aac9ad6dd]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add coverage tests. Remove a NEVER macro from pager.c, as the condition can now be true in wal mode.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 7aac9ad6dd14b1c56eb8e4750ac769c6197c30bd
User & Date: dan 2010-06-24 10:50:18.000
Context
2010-06-24
13:24
Add a coverage test to pagerfault.test. (check-in: b58db67e97 user: dan tags: trunk)
10:50
Add coverage tests. Remove a NEVER macro from pager.c, as the condition can now be true in wal mode. (check-in: 7aac9ad6dd user: dan tags: trunk)
02:46
Make sure the wal-index reader detects an incorrect version number even if it had to hold a lock in order to read the wal-index. Also, expand and enhance various comments in wal.c. (check-in: 2e6a462ceb user: drh tags: trunk)
Changes
Unified Diff Show Whitespace Changes Patch
Changes to src/pager.c.
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
){
  int rc = SQLITE_OK;             /* Return code */

  /* The dbOrigSize is never set if journal_mode=OFF */
  assert( pPager->journalMode!=PAGER_JOURNALMODE_OFF || pPager->dbOrigSize==0 );

  /* If a prior error occurred, report that error again. */
  if( NEVER(pPager->errCode) ) return pPager->errCode;

  PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", 
      pPager->zFilename, zMaster, pPager->dbSize));

  if( MEMDB && pPager->dbModified ){
    /* If this is an in-memory db, or no pages have been written to, or this
    ** function has already been called, it is mostly a no-op.  However, any







|







5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
){
  int rc = SQLITE_OK;             /* Return code */

  /* The dbOrigSize is never set if journal_mode=OFF */
  assert( pPager->journalMode!=PAGER_JOURNALMODE_OFF || pPager->dbOrigSize==0 );

  /* If a prior error occurred, report that error again. */
  if( pPager->errCode ) return pPager->errCode;

  PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n", 
      pPager->zFilename, zMaster, pPager->dbSize));

  if( MEMDB && pPager->dbModified ){
    /* If this is an in-memory db, or no pages have been written to, or this
    ** function has already been called, it is mostly a no-op.  However, any
Changes to test/malloc_common.tcl.
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209



210
211
212
213
214
215
216
  set ::sqlite_io_error_pending 0
  set ::sqlite_io_error_hardhit 0
  set ::sqlite_io_error_hit     0
  set ::sqlite_io_error_pending 0
  return $sv
}


# The following procs are used as [do_one_faultsim_test] callbacks when 
# injecting shared-memory related error faults into test cases.
#
proc shmerr_injectinstall {} {
  testvfs shmfault -default true
  shmfault filter {xShmOpen xShmMap xShmLock}
}
proc shmerr_injectuninstall {} {
  catch {db  close}
  catch {db2 close}
  shmfault delete
}
proc shmerr_injectstart {persist iFail} {
  shmfault ioerr $iFail $persist
}
proc shmerr_injectstop {} {
  shmfault ioerr 0 0
}




proc fullerr_injectinstall {} {
  testvfs shmfault -default true
}
proc fullerr_injectuninstall {} {
  catch {db  close}
  catch {db2 close}
  shmfault delete







<



















>
>
>







183
184
185
186
187
188
189

190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
  set ::sqlite_io_error_pending 0
  set ::sqlite_io_error_hardhit 0
  set ::sqlite_io_error_hit     0
  set ::sqlite_io_error_pending 0
  return $sv
}


# The following procs are used as [do_one_faultsim_test] callbacks when 
# injecting shared-memory related error faults into test cases.
#
proc shmerr_injectinstall {} {
  testvfs shmfault -default true
  shmfault filter {xShmOpen xShmMap xShmLock}
}
proc shmerr_injectuninstall {} {
  catch {db  close}
  catch {db2 close}
  shmfault delete
}
proc shmerr_injectstart {persist iFail} {
  shmfault ioerr $iFail $persist
}
proc shmerr_injectstop {} {
  shmfault ioerr 0 0
}

# The following procs are used as [do_one_faultsim_test] callbacks when 
# injecting SQLITE_FULL error faults into test cases.
#
proc fullerr_injectinstall {} {
  testvfs shmfault -default true
}
proc fullerr_injectuninstall {} {
  catch {db  close}
  catch {db2 close}
  shmfault delete
Changes to test/pager1.test.
34
35
36
37
38
39
40


41
42
43
44
45
46
47
#
# pager1-6.*: Cases related to "PRAGMA max_page_count"
#
# pager1-7.*: Cases specific to "PRAGMA journal_mode=TRUNCATE"
#
# pager1-8.*: Cases using temporary and in-memory databases.
#



set a_string_counter 1
proc a_string {n} {
  global a_string_counter
  incr a_string_counter
  string range [string repeat "${a_string_counter}." $n] 1 $n
}







>
>







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#
# pager1-6.*: Cases related to "PRAGMA max_page_count"
#
# pager1-7.*: Cases specific to "PRAGMA journal_mode=TRUNCATE"
#
# pager1-8.*: Cases using temporary and in-memory databases.
#
# pager1-9.*: Tests related to the backup API.
#

set a_string_counter 1
proc a_string {n} {
  global a_string_counter
  incr a_string_counter
  string range [string repeat "${a_string_counter}." $n] 1 $n
}
182
183
184
185
186
187
188



189
190
191
192
193
194
195
  do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {21 one 22 two 23 three}
  do_test pager1-$tn.28 { sql3 { SELECT * FROM t1 } } {21 one 22 two 23 three}
}

#-------------------------------------------------------------------------
# Savepoint related test cases.
# 



do_test pager1-3.1.1 {
  faultsim_delete_and_reopen
  execsql {
    CREATE TABLE t1(a PRIMARY KEY, b);
    CREATE TABLE counter(
      i CHECK (i<5), 
      u CHECK (u<10)







>
>
>







184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
  do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {21 one 22 two 23 three}
  do_test pager1-$tn.28 { sql3 { SELECT * FROM t1 } } {21 one 22 two 23 three}
}

#-------------------------------------------------------------------------
# Savepoint related test cases.
# 
# pager1-3.1.2.*: Force a savepoint rollback to cause the database file
#                 to grow.
# 
do_test pager1-3.1.1 {
  faultsim_delete_and_reopen
  execsql {
    CREATE TABLE t1(a PRIMARY KEY, b);
    CREATE TABLE counter(
      i CHECK (i<5), 
      u CHECK (u<10)
214
215
216
217
218
219
220

































221
222
223
224
225
226
227
} {3 0}
do_catchsql_test pager1-3.1.3 {
    INSERT INTO t1 SELECT a+3, randomblob(1500) FROM t1
} {1 {constraint failed}}
do_execsql_test pager1-3.4 { SELECT * FROM counter } {3 0}
do_execsql_test pager1-3.5 { SELECT a FROM t1 } {1 2 3}
do_execsql_test pager1-3.6 { COMMIT } {}


































#-------------------------------------------------------------------------
# Hot journal rollback related test cases.
#
# pager1.4.1.*: Test that the pager module deletes very small invalid
#               journal files.
#







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
} {3 0}
do_catchsql_test pager1-3.1.3 {
    INSERT INTO t1 SELECT a+3, randomblob(1500) FROM t1
} {1 {constraint failed}}
do_execsql_test pager1-3.4 { SELECT * FROM counter } {3 0}
do_execsql_test pager1-3.5 { SELECT a FROM t1 } {1 2 3}
do_execsql_test pager1-3.6 { COMMIT } {}

do_test pager1-3.2.1 {
  faultsim_delete_and_reopen
  db func a_string a_string
  execsql {
    PRAGMA auto_vacuum = 2;
    PRAGMA cache_size = 10;
    CREATE TABLE z(x INTEGER PRIMARY KEY, y);
    BEGIN;
      INSERT INTO z VALUES(NULL, a_string(800));
      INSERT INTO z SELECT NULL, a_string(800) FROM z;     --   2
      INSERT INTO z SELECT NULL, a_string(800) FROM z;     --   4
      INSERT INTO z SELECT NULL, a_string(800) FROM z;     --   8
      INSERT INTO z SELECT NULL, a_string(800) FROM z;     --  16
      INSERT INTO z SELECT NULL, a_string(800) FROM z;     --  32
      INSERT INTO z SELECT NULL, a_string(800) FROM z;     --  64
      INSERT INTO z SELECT NULL, a_string(800) FROM z;     -- 128
      INSERT INTO z SELECT NULL, a_string(800) FROM z;     -- 256
    COMMIT;
  }
  execsql { PRAGMA auto_vacuum }
} {2}
do_execsql_test pager1-3.2.2 {
  BEGIN;
    INSERT INTO z VALUES(NULL, a_string(800));
    INSERT INTO z VALUES(NULL, a_string(800));
    SAVEPOINT one;
      DELETE FROM z WHERE x>256;
      PRAGMA incremental_vacuum;
      SELECT count(*) FROM z WHERE x < 100;
    ROLLBACK TO one;
  COMMIT;
} {99}

#-------------------------------------------------------------------------
# Hot journal rollback related test cases.
#
# pager1.4.1.*: Test that the pager module deletes very small invalid
#               journal files.
#
837
838
839
840
841
842
843
844







































































845
846
  do_execsql_test pager1-8.$tn.3 {
    BEGIN;
      INSERT INTO x1 VALUES('William');
      INSERT INTO x1 VALUES('Anne');
    ROLLBACK;
  } {}
}








































































finish_test









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
  do_execsql_test pager1-8.$tn.3 {
    BEGIN;
      INSERT INTO x1 VALUES('William');
      INSERT INTO x1 VALUES('Anne');
    ROLLBACK;
  } {}
}

#-------------------------------------------------------------------------
# The next block of tests - pager1-9.* - deal with interactions between
# the pager and the backup API. Test cases:
#
#   pager1-9.1.*: Test that a backup completes successfully even if the
#                 source db is written to during the backup op.
#
#   pager1-9.2.*: Test that a backup completes successfully even if the
#                 source db is written to and then rolled back during a 
#                 backup operation.
#
do_test pager1-9.0.1 {
  faultsim_delete_and_reopen
  db func a_string a_string
  execsql {
    PRAGMA cache_size = 10;
    BEGIN;
      CREATE TABLE ab(a, b, UNIQUE(a, b));
      INSERT INTO ab VALUES( a_string(200), a_string(300) );
      INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab;
      INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab;
      INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab;
      INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab;
      INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab;
      INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab;
      INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab;
    COMMIT;
  }
} {}
do_test pager1-9.0.2 {
  sqlite3 db2 test.db2
  db2 eval { PRAGMA cache_size = 10 }
  sqlite3_backup B db2 main db main
  list [B step 10000] [B finish]
} {SQLITE_DONE SQLITE_OK}
do_test pager1-9.0.3 {
 db one {SELECT md5sum(a, b) FROM ab}
} [db2 one {SELECT md5sum(a, b) FROM ab}]

do_test pager1-9.1.1 {
  execsql { UPDATE ab SET a = a_string(201) }
  sqlite3_backup B db2 main db main
  B step 30
} {SQLITE_OK}
do_test pager1-9.1.2 {
  execsql { UPDATE ab SET b = a_string(301) }
  list [B step 10000] [B finish]
} {SQLITE_DONE SQLITE_OK}
do_test pager1-9.1.3 {
 db one {SELECT md5sum(a, b) FROM ab}
} [db2 one {SELECT md5sum(a, b) FROM ab}]
do_test pager1-9.1.4 { execsql { SELECT count(*) FROM ab } } {128}

do_test pager1-9.2.1 {
  execsql { UPDATE ab SET a = a_string(202) }
  sqlite3_backup B db2 main db main
  B step 30
} {SQLITE_OK}
do_test pager1-9.2.2 {
  execsql { 
    BEGIN;
      UPDATE ab SET b = a_string(301);
    ROLLBACK;
  }
  list [B step 10000] [B finish]
} {SQLITE_DONE SQLITE_OK}
do_test pager1-9.2.3 {
 db one {SELECT md5sum(a, b) FROM ab}
} [db2 one {SELECT md5sum(a, b) FROM ab}]
do_test pager1-9.2.4 { execsql { SELECT count(*) FROM ab } } {128}

finish_test

Changes to test/pagerfault.test.
303
304
305
306
307
308
309













310
311
312
313
314
315
316
#     SELECT DISTINCT x FROM t1;
#   }
# } -test {
#   faultsim_test_result {0 {5 6 7 8}}
#   faultsim_integrity_check
# }
#













do_test pagerfault-7-pre1 {
  faultsim_delete_and_reopen
  execsql {
    CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
    BEGIN;
      INSERT INTO t2 VALUES(NULL, randomblob(1500));
      INSERT INTO t2 VALUES(NULL, randomblob(1500));







>
>
>
>
>
>
>
>
>
>
>
>
>







303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
#     SELECT DISTINCT x FROM t1;
#   }
# } -test {
#   faultsim_test_result {0 {5 6 7 8}}
#   faultsim_integrity_check
# }
#

# This is designed to provoke a special case in the pager code:
#
# If an error (specifically, a FULL or IOERR error) occurs while writing a
# dirty page to the file-system in order to free up memory, the pager enters
# the "error state". An IO error causes SQLite to roll back the current
# transaction (exiting the error state). A FULL error, however, may only
# rollback the current statement.
#
# This block tests that nothing goes wrong if a FULL error occurs while
# writing a dirty page out to free memory from within a statement that has
# opened a statement transaction.
#
do_test pagerfault-7-pre1 {
  faultsim_delete_and_reopen
  execsql {
    CREATE TABLE t2(a INTEGER PRIMARY KEY, b);
    BEGIN;
      INSERT INTO t2 VALUES(NULL, randomblob(1500));
      INSERT INTO t2 VALUES(NULL, randomblob(1500));
331
332
333
334
335
336
337






































338
339
340
341
342
343
344
  execsql { 
    PRAGMA cache_size = 10;
    BEGIN;
      UPDATE t1 SET b = randomblob(1500);
  }
} -body {
  execsql { UPDATE t1 SET a = 65, b = randomblob(1500) WHERE (a+1)>200 }






































  execsql COMMIT
} -test {
  faultsim_test_result {0 {}}
  faultsim_integrity_check
}

finish_test







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
  execsql { 
    PRAGMA cache_size = 10;
    BEGIN;
      UPDATE t1 SET b = randomblob(1500);
  }
} -body {
  execsql { UPDATE t1 SET a = 65, b = randomblob(1500) WHERE (a+1)>200 }
  execsql COMMIT
} -test {
  faultsim_test_result {0 {}}
  faultsim_integrity_check
}

do_test pagerfault-8-pre1 {
  faultsim_delete_and_reopen
  execsql {
    PRAGMA auto_vacuum = 1;
    CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
    BEGIN;
      INSERT INTO t1 VALUES(NULL, randomblob(1500));
      INSERT INTO t1 VALUES(NULL, randomblob(1500));
      INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1;    --  4
      INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1;    --  8
      INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1;    -- 16
      INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1;    -- 32
      INSERT INTO t1 SELECT NULL, randomblob(1500) FROM t1;    -- 64
    COMMIT;
  }
  faultsim_save_and_close
  set filesize [file size test.db]
  set {} {}
} {}
do_test pagerfault-8-pre2 {
  faultsim_restore_and_reopen
  execsql { DELETE FROM t1 WHERE a>32 }
  expr {[file size test.db] < $filesize}
} {1}
breakpoint
do_faultsim_test pagerfault-8 -prep {
  faultsim_restore_and_reopen
  execsql { 
    BEGIN;
    DELETE FROM t1 WHERE a>32;
  }
} -body {
  execsql COMMIT
} -test {
  faultsim_test_result {0 {}}
  faultsim_integrity_check
}

finish_test