SQLite

Check-in [4941e437d2]
Login

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

Overview
Comment:Add test cases to pager1.test and pagerfault.test.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 4941e437d2638f36ac8510d4a5b4c780afc798bb
User & Date: dan 2010-06-24 19:16:06.000
Context
2010-06-25
11:35
Modify the merge-sort in wal.c so that it does not use recursion. (check-in: daea6c054c user: dan tags: trunk)
2010-06-24
19:16
Add test cases to pager1.test and pagerfault.test. (check-in: 4941e437d2 user: dan tags: trunk)
18:36
Revert to allowing a cache spill during writes of multiple pages within a single sector as long as the spill does not require a journal sync and a new journal header. (check-in: 7d83fbae98 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to test/pager1.test.
36
37
38
39
40
41
42




43
44
45
46
47
48
49
#
# 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
}







>
>
>
>







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#
# 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.
#
# pager1-10.*: Test that the assumed file-system sector-size is limited to
#              64KB.
#              
#

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
}
275
276
277
278
279
280
281




282
283
284
285
286
287
288
#
# pager1.4.4.*: Test hot-journal rollback of journal file with a master
#               journal pointer generated in various "PRAGMA synchronous"
#               modes.
#
# pager1.4.5.*: Test that hot-journal rollback stops if it encounters a
#               journal-record for which the checksum fails.




# 
do_test pager1.4.1.1 {
  faultsim_delete_and_reopen
  execsql { 
    CREATE TABLE x(y, z);
    INSERT INTO x VALUES(1, 2);
  }







>
>
>
>







279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
#
# pager1.4.4.*: Test hot-journal rollback of journal file with a master
#               journal pointer generated in various "PRAGMA synchronous"
#               modes.
#
# pager1.4.5.*: Test that hot-journal rollback stops if it encounters a
#               journal-record for which the checksum fails.
#
# pager1.4.6.*: Test that when rolling back a hot-journal that contains a
#               master journal pointer, the master journal file is deleted
#               after all the hot-journals that refer to it are deleted.
# 
do_test pager1.4.1.1 {
  faultsim_delete_and_reopen
  execsql { 
    CREATE TABLE x(y, z);
    INSERT INTO x VALUES(1, 2);
  }
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
# Check the transaction was committed:
#
do_execsql_test pager1.4.5.2 {
  SELECT * FROM t1;
  SELECT * FROM t2;
} {I II 1 2 III IV 3 4}

# Now try three tests:
#
#  pager1-4.5.3: Restore the file-system. Check that the whole transaction 
#                is rolled back.
#
#  pager1-4.5.4: Restore the file-system. Corrupt the first record in the
#                journal. Check the transaction is not rolled back.
#







|







586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
# Check the transaction was committed:
#
do_execsql_test pager1.4.5.2 {
  SELECT * FROM t1;
  SELECT * FROM t2;
} {I II 1 2 III IV 3 4}

# Now try four tests:
#
#  pager1-4.5.3: Restore the file-system. Check that the whole transaction 
#                is rolled back.
#
#  pager1-4.5.4: Restore the file-system. Corrupt the first record in the
#                journal. Check the transaction is not rolled back.
#
619
620
621
622
623
624
625




































































































626
627
628
629
630
631
632
faultsim_restore_and_reopen
db close
sqlite3 db test.db -readonly 1
do_catchsql_test pager1.4.5.6 {
  SELECT * FROM t1;
  SELECT * FROM t2;
} {1 {disk I/O error}}





































































































db close
tv delete

#-------------------------------------------------------------------------
# The following tests deal with multi-file commits.
#







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







627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
faultsim_restore_and_reopen
db close
sqlite3 db test.db -readonly 1
do_catchsql_test pager1.4.5.6 {
  SELECT * FROM t1;
  SELECT * FROM t2;
} {1 {disk I/O error}}
db close

# Snapshot the file-system just before multi-file commit. Save the name
# of the master journal file in $::mj_filename.
#
tv script copy_on_mj_delete
tv filter xDelete
proc copy_on_mj_delete {method filename args} {
  if {[string match *mj* [file tail $filename]]} { 
    set ::mj_filename $filename
    faultsim_save 
  }
  return SQLITE_OK
}
do_test pager1.4.6.1 {
  faultsim_delete_and_reopen
  execsql {
    ATTACH 'test.db2' AS two;
    CREATE TABLE t1(a, b);
    CREATE TABLE two.t2(a, b);
    INSERT INTO t1 VALUES(1, 't1.1');
    INSERT INTO t2 VALUES(1, 't2.1');
    BEGIN;
      UPDATE t1 SET b = 't1.2';
      UPDATE t2 SET b = 't2.2';
    COMMIT;
  }
  tv filter {}
  db close
} {}

faultsim_restore_and_reopen
do_execsql_test pager1.4.6.2 { SELECT * FROM t1 }           {1 t1.1}
do_test         pager1.4.6.3 { file exists $::mj_filename } {1}
do_execsql_test pager1.4.6.4 {
  ATTACH 'test.db2' AS two;
  SELECT * FROM t2;
} {1 t2.1}
do_test pager1.4.6.5 { file exists $::mj_filename } {0}

faultsim_restore_and_reopen
db close
do_test pager1.4.6.8 {
  set ::mj_filename1 $::mj_filename
  tv filter xDelete
  sqlite3 db test.db2
  execsql {
    ATTACH 'test.db3' AS three;
    CREATE TABLE three.t3(a, b);
    INSERT INTO t3 VALUES(1, 't3.1');
    BEGIN;
      UPDATE t2 SET b = 't2.3';
      UPDATE t3 SET b = 't3.3';
    COMMIT;
  }
  expr {$::mj_filename1 != $::mj_filename}
} {1}
faultsim_restore_and_reopen
tv filter {}

# The file-system now contains:
#
#   * three databases
#   * three hot-journal files
#   * two master-journal files.
#
# The hot-journals associated with test.db2 and test.db3 point to
# master journal $::mj_filename. The hot-journal file associated with
# test.db points to master journal $::mj_filename1. So reading from
# test.db should delete $::mj_filename1.
#
do_test pager1.4.6.9 {
  lsort [glob test.db*]
} [lsort [list                                           \
  test.db test.db2 test.db3                              \
  test.db-journal test.db2-journal test.db3-journal      \
  [file tail $::mj_filename] [file tail $::mj_filename1]
]]

# The master-journal $::mj_filename1 contains pointers to test.db and 
# test.db2. However the hot-journal associated with test.db2 points to
# a different master-journal. Therefore, reading from test.db only should
# be enough to cause SQLite to delete $::mj_filename1.
#
do_test         pager1.4.6.10 { file exists $::mj_filename  } {1}
do_test         pager1.4.6.11 { file exists $::mj_filename1 } {1}
do_execsql_test pager1.4.6.12 { SELECT * FROM t1 } {1 t1.1}
do_test         pager1.4.6.13 { file exists $::mj_filename  } {1}
do_test         pager1.4.6.14 { file exists $::mj_filename1 } {0}

do_execsql_test pager1.4.6.12 {
  ATTACH 'test.db2' AS two;
  SELECT * FROM t2;
} {1 t2.1}
do_test         pager1.4.6.13 { file exists $::mj_filename }  {1}
do_execsql_test pager1.4.6.14 {
  ATTACH 'test.db3' AS three;
  SELECT * FROM t3;
} {1 t3.1}
do_test         pager1.4.6.15 { file exists $::mj_filename }  {0}

db close
tv delete

#-------------------------------------------------------------------------
# The following tests deal with multi-file commits.
#
946
947
948
949
950
951
952


953


































































954
955
  }
  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








>
>

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


1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
  }
  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}
db close
db2 close

#-------------------------------------------------------------------------
# Test that regardless of the value returned by xSectorSize(), the
# minimum effective sector-size is 512 and the maximum 65536 bytes.
#
testvfs tv -default 1
foreach sectorsize {
    32   64   128   256   512   1024   2048 
    4096 8192 16384 32768 65536 131072 262144
} {
  tv sectorsize $sectorsize
  set eff $sectorsize
  if {$sectorsize < 512}   { set eff 512 }
  if {$sectorsize > 65536} { set eff 65536 }

  do_test pager1-10.$sectorsize {
    faultsim_delete_and_reopen
    execsql {
      PRAGMA journal_mode = PERSIST;
      PRAGMA page_size = 1024;
      CREATE TABLE t1(a, b);
    }
    file size test.db-journal
  } [expr $sectorsize > 65536 ? 65536 : $sectorsize]
}
db close
tv delete

testvfs tv -default 1
faultsim_delete_and_reopen
db func a_string a_string
do_execsql_test pager1-11.1 {
  PRAGMA cache_size = 10;
  BEGIN;
    CREATE TABLE zz(top PRIMARY KEY);
    INSERT INTO zz VALUES(a_string(222));
    INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz;
    INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz;
    INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz;
    INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz;
    INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz;
  COMMIT;
  BEGIN;
    UPDATE zz SET top = a_string(345);
} {}

proc lockout {method args} { return SQLITE_IOERR }
tv script lockout
tv filter {xWrite xTruncate xSync}
do_catchsql_test pager1-11.2 { COMMIT } {1 {disk I/O error}}

tv script {}
do_test pager1-11.3 {
  sqlite3 db2 test.db
  execsql {
    PRAGMA journal_mode = TRUNCATE;
    PRAGMA integrity_check;
  } db2
} {truncate ok}
do_test pager1-11.4 {
  db2 close
  file size test.db-journal
} {0}
breakpoint
do_execsql_test pager1-11.5 { SELECT count(*) FROM zz } {32}
  

finish_test

Changes to test/pagerfault.test.
93
94
95
96
97
98
99
100

101
102
103
104
105
106
107
  execsql { SELECT * FROM abc }
} -test {
  set answer [split [string repeat "ottffs" 128] ""]
  faultsim_test_result [list 0 $answer]
  faultsim_integrity_check
  set res [db eval { SELECT * FROM abc }]
  if {$res != $answer} { error "Database content appears incorrect ($res)" }
} -faults oom-transient


#-------------------------------------------------------------------------
# Test fault-injection while rolling back hot-journals that were created
# as part of a multi-file transaction.
#
do_test pagerfault-3-pre1 {
  testvfs tstvfs -default 1







<
>







93
94
95
96
97
98
99

100
101
102
103
104
105
106
107
  execsql { SELECT * FROM abc }
} -test {
  set answer [split [string repeat "ottffs" 128] ""]
  faultsim_test_result [list 0 $answer]
  faultsim_integrity_check
  set res [db eval { SELECT * FROM abc }]
  if {$res != $answer} { error "Database content appears incorrect ($res)" }

} 

#-------------------------------------------------------------------------
# Test fault-injection while rolling back hot-journals that were created
# as part of a multi-file transaction.
#
do_test pagerfault-3-pre1 {
  testvfs tstvfs -default 1
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
      REPLACE INTO t2 SELECT * FROM t1;
    COMMIT;
  }

  db close
  tstvfs delete
} {}
do_faultsim_test pagerfault-3 -faults ioerr-persistent -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { 
    ATTACH 'test.db2' AS aux;
    SELECT count(*) FROM t2;
    SELECT count(*) FROM t1;
  }







|







137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
      REPLACE INTO t2 SELECT * FROM t1;
    COMMIT;
  }

  db close
  tstvfs delete
} {}
do_faultsim_test pagerfault-3 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql { 
    ATTACH 'test.db2' AS aux;
    SELECT count(*) FROM t2;
    SELECT count(*) FROM t1;
  }
216
217
218
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
  }
} -body {
  execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
} -test {
  faultsim_test_result {0 {}}
  faultsim_integrity_check
}
do_faultsim_test pagerfault-5.3 -prep {
  faultsim_restore_and_reopen
  db func a_string a_string
  file delete -force test2.db test2.db-journal test2.db-wal
  execsql { 
    PRAGMA journal_mode = PERSIST;
    ATTACH 'test2.db' AS aux;
    PRAGMA aux.journal_mode = PERSIST;
    PRAGMA aux.journal_size_limit = 0;
  }
} -body {
  execsql {
    BEGIN;
      INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
      CREATE TABLE aux.t2 AS SELECT * FROM t1;
    COMMIT;
  }
} -test {
  faultsim_test_result {0 {}}

}






#-------------------------------------------------------------------------
# Test fault-injection as part of a commit when using 
# journal_mode=TRUNCATE.
#
do_test pagerfault-6-pre1 {
  faultsim_delete_and_reopen







|


















>
|
>
>
>
>
>







216
217
218
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
  }
} -body {
  execsql { INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1 }
} -test {
  faultsim_test_result {0 {}}
  faultsim_integrity_check
}
do_faultsim_test pagerfault-5.3 -faults oom-transient -prep {
  faultsim_restore_and_reopen
  db func a_string a_string
  file delete -force test2.db test2.db-journal test2.db-wal
  execsql { 
    PRAGMA journal_mode = PERSIST;
    ATTACH 'test2.db' AS aux;
    PRAGMA aux.journal_mode = PERSIST;
    PRAGMA aux.journal_size_limit = 0;
  }
} -body {
  execsql {
    BEGIN;
      INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1;
      CREATE TABLE aux.t2 AS SELECT * FROM t1;
    COMMIT;
  }
} -test {
  faultsim_test_result {0 {}}
  faultsim_integrity_check

  set res ""
  set rc [catch { set res [db one { PRAGMA aux.integrity_check }] }]
  if {$rc!=0 || $res != "ok"} {error "integrity-check problem:$rc $res"}
}


#-------------------------------------------------------------------------
# Test fault-injection as part of a commit when using 
# journal_mode=TRUNCATE.
#
do_test pagerfault-6-pre1 {
  faultsim_delete_and_reopen
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
    COMMIT;
    CREATE TABLE t1(a PRIMARY KEY, b);
    INSERT INTO t1 SELECT * FROM t2;
    DROP TABLE t2;
  }
  faultsim_save_and_close
} {}
do_faultsim_test pagerfault-7 -faults full -prep {
  faultsim_restore_and_reopen
  execsql { 
    PRAGMA cache_size = 10;
    BEGIN;
      UPDATE t1 SET b = randomblob(1500);
  }
} -body {







|







341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
    COMMIT;
    CREATE TABLE t1(a PRIMARY KEY, b);
    INSERT INTO t1 SELECT * FROM t2;
    DROP TABLE t2;
  }
  faultsim_save_and_close
} {}
do_faultsim_test pagerfault-7 -prep {
  faultsim_restore_and_reopen
  execsql { 
    PRAGMA cache_size = 10;
    BEGIN;
      UPDATE t1 SET b = randomblob(1500);
  }
} -body {
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
    INSERT INTO t1 VALUES(randomblob(900));
    INSERT INTO t1 VALUES(randomblob(900));
    DELETE FROM t1;
  }
  faultsim_save_and_close
} {}

do_faultsim_test pagerfault-9 -faults oom-transient -prep {
  faultsim_restore_and_reopen
  execsql { 
    BEGIN;
      INSERT INTO t1 VALUES(randomblob(900));
      INSERT INTO t1 VALUES(randomblob(900));
      DROP TABLE t3;
      DROP TABLE t2;







|







408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
    INSERT INTO t1 VALUES(randomblob(900));
    INSERT INTO t1 VALUES(randomblob(900));
    DELETE FROM t1;
  }
  faultsim_save_and_close
} {}

do_faultsim_test pagerfault-9 -prep {
  faultsim_restore_and_reopen
  execsql { 
    BEGIN;
      INSERT INTO t1 VALUES(randomblob(900));
      INSERT INTO t1 VALUES(randomblob(900));
      DROP TABLE t3;
      DROP TABLE t2;