SQLite

Check-in [9cb5f8dab6]
Login

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

Overview
Comment:Further test cases for wal2 mode.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | wal2
Files: files | file ages | folders
SHA3-256: 9cb5f8dab685f5ea36ad142cfa588dee82e87f3a89e8dcf84e0ee124bb29bc7f
User & Date: dan 2018-12-15 20:20:13.338
Context
2018-12-17
15:22
Add extra test case to wal2recover.test. (check-in: 1a5aa73435 user: dan tags: wal2)
2018-12-15
20:59
Merge latest wal2 changes into this branch. (check-in: 06bb80eeb8 user: dan tags: begin-concurrent-wal2)
20:20
Further test cases for wal2 mode. (check-in: 9cb5f8dab6 user: dan tags: wal2)
2018-12-14
19:53
Add further tests for wal2 mode. (check-in: 54e628f902 user: dan tags: wal2)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/test_hexio.c.
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
219
220
221
222
223
224
225
226
227



228

229
230
231
232
233
234
235
  sqlite3_free(aOut);
  fclose(out);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(written));
  return TCL_OK;
}

/*
** USAGE:   hexio_get_int   HEXDATA
**
** Interpret the HEXDATA argument as a big-endian integer.  Return
** the value of that integer.  HEXDATA can contain between 2 and 8
** hexadecimal digits.
*/
static int SQLITE_TCLAPI hexio_get_int(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int val;
  int nIn, nOut;
  const unsigned char *zIn;
  unsigned char *aOut;
  unsigned char aNum[4];


  if( objc!=2 ){







    Tcl_WrongNumArgs(interp, 1, objv, "HEXDATA");
    return TCL_ERROR;
  }
  zIn = (const unsigned char *)Tcl_GetStringFromObj(objv[1], &nIn);
  aOut = sqlite3_malloc( nIn/2 );
  if( aOut==0 ){
    return TCL_ERROR;
  }
  nOut = sqlite3TestHexToBin(zIn, nIn, aOut);
  if( nOut>=4 ){
    memcpy(aNum, aOut, 4);
  }else{
    memset(aNum, 0, sizeof(aNum));
    memcpy(&aNum[4-nOut], aOut, nOut);
  }
  sqlite3_free(aOut);



  val = (aNum[0]<<24) | (aNum[1]<<16) | (aNum[2]<<8) | aNum[3];

  Tcl_SetObjResult(interp, Tcl_NewIntObj(val));
  return TCL_OK;
}


/*
** USAGE:   hexio_render_int16   INTEGER







|
















>

|
>
>
>
>
>
>
>
|


|












>
>
>
|
>







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
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
  sqlite3_free(aOut);
  fclose(out);
  Tcl_SetObjResult(interp, Tcl_NewIntObj(written));
  return TCL_OK;
}

/*
** USAGE:   hexio_get_int [-littleendian] HEXDATA
**
** Interpret the HEXDATA argument as a big-endian integer.  Return
** the value of that integer.  HEXDATA can contain between 2 and 8
** hexadecimal digits.
*/
static int SQLITE_TCLAPI hexio_get_int(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  int val;
  int nIn, nOut;
  const unsigned char *zIn;
  unsigned char *aOut;
  unsigned char aNum[4];
  int bLittle = 0;

  if( objc==3 ){
    int n;
    char *z = Tcl_GetStringFromObj(objv[1], &n);
    if( n>=2 && n<=13 && memcmp(z, "-littleendian", n)==0 ){
      bLittle = 1;
    }
  }
  if( (objc-bLittle)!=2 ){
    Tcl_WrongNumArgs(interp, 1, objv, "[-littleendian] HEXDATA");
    return TCL_ERROR;
  }
  zIn = (const unsigned char *)Tcl_GetStringFromObj(objv[1+bLittle], &nIn);
  aOut = sqlite3_malloc( nIn/2 );
  if( aOut==0 ){
    return TCL_ERROR;
  }
  nOut = sqlite3TestHexToBin(zIn, nIn, aOut);
  if( nOut>=4 ){
    memcpy(aNum, aOut, 4);
  }else{
    memset(aNum, 0, sizeof(aNum));
    memcpy(&aNum[4-nOut], aOut, nOut);
  }
  sqlite3_free(aOut);
  if( bLittle ){
    val = (aNum[3]<<24) | (aNum[2]<<16) | (aNum[1]<<8) | aNum[0];
  }else{
    val = (aNum[0]<<24) | (aNum[1]<<16) | (aNum[2]<<8) | aNum[3];
  }
  Tcl_SetObjResult(interp, Tcl_NewIntObj(val));
  return TCL_OK;
}


/*
** USAGE:   hexio_render_int16   INTEGER
Changes to src/wal.c.
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
    assert( iWal!=0 || nBackfill!=1 || eLock==WAL_LOCK_PART1 );
    assert( iWal!=0 || nBackfill!=0 || eLock==WAL_LOCK_PART1_FULL2 );
    assert( iWal!=1 || nBackfill!=1 || eLock==WAL_LOCK_PART2 );
    assert( iWal!=1 || nBackfill!=0 || eLock==WAL_LOCK_PART2_FULL1 );

    rc = walLockShared(pWal, WAL_READ_LOCK(eLock));
    if( rc!=SQLITE_OK ){
      return rc;
    }
    walShmBarrier(pWal);
    if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){
      walUnlockShared(pWal, WAL_READ_LOCK(eLock));
      return WAL_RETRY;
    }else{
      pWal->readLock = eLock;







|







3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
    assert( iWal!=0 || nBackfill!=1 || eLock==WAL_LOCK_PART1 );
    assert( iWal!=0 || nBackfill!=0 || eLock==WAL_LOCK_PART1_FULL2 );
    assert( iWal!=1 || nBackfill!=1 || eLock==WAL_LOCK_PART2 );
    assert( iWal!=1 || nBackfill!=0 || eLock==WAL_LOCK_PART2_FULL1 );

    rc = walLockShared(pWal, WAL_READ_LOCK(eLock));
    if( rc!=SQLITE_OK ){
      return (rc==SQLITE_BUSY ? WAL_RETRY : rc);
    }
    walShmBarrier(pWal);
    if( memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) ){
      walUnlockShared(pWal, WAL_READ_LOCK(eLock));
      return WAL_RETRY;
    }else{
      pWal->readLock = eLock;
Changes to test/permutations.test.
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
wal3.test wal4.test wal5.test
wal64k.test wal6.test wal7.test wal8.test wal9.test
walbak.test walbig.test walblock.test walcksum.test 
walfault.test walhook.test walmode.test walnoshm.test
waloverwrite.test walpersist.test walprotocol2.test
walprotocol.test walro2.test walrofault.test walro.test
walshared.test walslow.test wal.test
wal2savepoint.test
} 

test_suite "coverage-pager" -description {
  Coverage tests for file pager.c.
} -files {
  pager1.test    pager2.test  pagerfault.test  pagerfault2.test
  walfault.test  walbak.test  journal2.test    tkt-9d68c883.test







|







435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
wal3.test wal4.test wal5.test
wal64k.test wal6.test wal7.test wal8.test wal9.test
walbak.test walbig.test walblock.test walcksum.test 
walfault.test walhook.test walmode.test walnoshm.test
waloverwrite.test walpersist.test walprotocol2.test
walprotocol.test walro2.test walrofault.test walro.test
walshared.test walslow.test wal.test
wal2savepoint.test wal2lock.test wal2recover2.test
} 

test_suite "coverage-pager" -description {
  Coverage tests for file pager.c.
} -files {
  pager1.test    pager2.test  pagerfault.test  pagerfault2.test
  walfault.test  walbak.test  journal2.test    tkt-9d68c883.test
Added test/wal2lock.test.




















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# 2018 December 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the operation of the library in
# "PRAGMA journal_mode=WAL2" mode.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl

set testprefix wal2lock
ifcapable !wal {finish_test ; return }

db close
testvfs tvfs 
sqlite3 db test.db -vfs tvfs

do_execsql_test 1.0 {
  PRAGMA journal_mode = wal2;
  CREATE TABLE y1(y, yy);
  CREATE INDEX y1y ON y1(y);
  CREATE INDEX y1yy ON y1(yy);
  INSERT INTO y1 VALUES(1, 2), (3, 4), (5, 6);
} {wal2}

tvfs script vfs_callback
tvfs filter xShmLock

set ::lock [list]
proc vfs_callback {func file name lock} {
  lappend ::lock $lock
  return SQLITE_OK
}

do_execsql_test 1.1.1 {
  SELECT * FROM y1
} {1 2 3 4 5 6}
do_test 1.1.2 {
  set ::lock
} {{4 1 lock shared} {4 1 unlock shared}}

set ::bFirst 1
proc vfs_callback {func file name lock} {
  if {$::bFirst} {
    set ::bFirst 0
    return SQLITE_BUSY
  }
  return SQLITE_OK
}
do_execsql_test 1.2 {
  SELECT * FROM y1
} {1 2 3 4 5 6}

set ::bFirst 1
proc vfs_callback {func file name lock} {
  if {$::bFirst} {
    set ::bFirst 0
    return SQLITE_IOERR
  }
  return SQLITE_OK
}
do_catchsql_test 1.3 {
  SELECT * FROM y1
} {1 {disk I/O error}}

puts "# Warning: This next test case causes SQLite to call xSleep(1) 100 times."
puts "# Normally this equates to a delay of roughly 10 seconds, but if SQLite"
puts "# is built on unix without HAVE_USLEEP defined, it may be much longer."
proc vfs_callback {func file name lock} { return SQLITE_BUSY }
do_catchsql_test 1.4 {
  SELECT * FROM y1
} {1 {locking protocol}}
proc vfs_callback {func file name lock} { return SQLITE_OK }

sqlite3 db2 test.db -vfs tvfs
set ::bFirst 1

proc vfs_callback {func file name lock} {
  if {$::bFirst} {
    set ::bFirst 0
    db2 eval { INSERT INTO y1 VALUES(7, 8) }
  }
}

do_execsql_test 1.5.1 {
  SELECT * FROM y1
} {1 2 3 4 5 6 7 8}
do_execsql_test 1.5.2 {
  SELECT * FROM y1
} {1 2 3 4 5 6 7 8}

db close
db2 close
tvfs delete
finish_test
Changes to test/wal2recover.test.
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
266
    PRAGMA integrity_check;
  }
} {211 ok}

do_test 3.5 {
  list [file size test.db] [file size test.db-wal] [file size test.db-wal2]
} {5120 15752 18896}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 4.0 {
  PRAGMA journal_mode = wal2;
  CREATE TABLE xyz(x, y, z);
  INSERT INTO xyz VALUES('x', 'y', 'z');
} {wal2}
db close
do_test 4.1 {
  close [open test.db-wal w]
  file mkdir test.db-wal2
  sqlite3 db test.db
  catchsql { SELECT * FROM xyz }
} {1 {unable to open database file}}
db close
file delete test.db-wal2

do_test 4.2 {
  sqlite3 db test.db
  execsql { 
    INSERT INTO xyz VALUES('a', 'b', 'c');
  }
  forcecopy test.db test.db2
  forcecopy test.db-wal test.db2-wal
  forcedelete test.db2-wal2
  file mkdir test.db2-wal2
  sqlite3 db2 test.db2
  catchsql { SELECT * FROM xyz } db2
} {1 {unable to open database file}}
db2 close
file delete test.db2-wal2



finish_test








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




222
223
224
225
226
227
228


































229
230
231
232
    PRAGMA integrity_check;
  }
} {211 ok}

do_test 3.5 {
  list [file size test.db] [file size test.db-wal] [file size test.db-wal2]
} {5120 15752 18896}




































finish_test

Added test/wal2recover2.test.






































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
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
219
220
221
222
223
224
225
226
227
# 2018 December 13
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the operation of the library in
# "PRAGMA journal_mode=WAL2" mode.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/malloc_common.tcl
source $testdir/wal_common.tcl

set testprefix wal2recover2
ifcapable !wal {finish_test ; return }

do_execsql_test 1.0 {
  CREATE TABLE t1(x);
  CREATE TABLE t2(x);
  WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1500 )
    INSERT INTO t1 SELECT i FROM s;
  WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1500 )
    INSERT INTO t2 SELECT i FROM s;

  PRAGMA journal_mode = wal2;
  PRAGMA journal_size_limit = 10000;
} {wal2 10000}

set ::L 1125750
set ::M 1126500
set ::H 1127250

do_execsql_test 1.1 {
  UPDATE t1 SET x=x+1;
  UPDATE t2 SET x=x+1 WHERE rowid<=750;

  SELECT sum(x) FROM t1;
  SELECT sum(x) FROM t2;
} [list $H $M]

do_test 1.2 {
  list [file size test.db] [file size test.db-wal] [file size test.db-wal2]
} {31744 14704 7368}

proc cksum {zIn data} {
  if {[string length $zIn]==0} {
    set s0 0
    set s1 0
  } else {
    set s0 [hexio_get_int [string range $zIn 0 7]]
    set s1 [hexio_get_int [string range $zIn 8 15]]
  }
  set n [expr [string length $data] / 8]

  for {set i 0} {$i < $n} {incr i 2} {
    set x0 [hexio_get_int -l [string range $data [expr $i*8]   [expr $i*8+7]]]
    set x1 [hexio_get_int -l [string range $data [expr $i*8+8] [expr $i*8+8+7]]]

    set s0 [expr ($s0 + $x0 + $s1) & 0xFFFFFFFF]
    set s1 [expr ($s1 + $x1 + $s0) & 0xFFFFFFFF]
  }

  return "[hexio_render_int32 $s0][hexio_render_int32 $s1]"
}

proc fix_wal_cksums {file} {
  # Fix the checksum on the wal header.
  set data [hexio_read $file 0 32]
  set cksum [cksum {} [string range $data 0 47]]
  set salt [hexio_read $file 16 8]
  hexio_write $file 24 $cksum

  # Fix the checksums for all pages in the wal file.
  set pgsz [hexio_get_int [hexio_read $file 8 4]]
  set sz [file size $file]
  for {set off 32} {$off < $sz} {incr off [expr $pgsz+24]} {
    set e [hexio_read $file $off 8]
    set cksum [cksum $cksum $e]

    set p [hexio_read $file [expr $off+24] $pgsz]
    set cksum [cksum $cksum $p]

    hexio_write $file [expr $off+8] $salt
    hexio_write $file [expr $off+16] $cksum
  }
}

proc wal_incr_hdrfield {file field} {
  switch -- $field {
    nCkpt { set offset 12 }
    salt0 { set offset 16 }
    salt1 { set offset 20 }
    default {
      error "unknown field $field - should be \"nCkpt\", \"salt0\" or \"salt1\""
    }
  }

  # Increment the value in the wal header.
  set v [hexio_get_int [hexio_read $file $offset 4]]
  incr v
  hexio_write $file $offset [hexio_render_int32 $v]
  
  # Fix various checksums
  fix_wal_cksums $file
}

proc wal_set_nckpt {file val} {
  # Increment the value in the wal header.
  hexio_write $file 12 [hexio_render_int32 $val]
  
  # Fix various checksums
  fix_wal_cksums $file
}

proc wal_set_follow {file prevfile} {
  set pgsz [hexio_get_int [hexio_read $prevfile 8 4]]
  set sz [file size $prevfile]
  set cksum [hexio_read $prevfile [expr $sz-$pgsz-8] 8]

  hexio_write $file 16 $cksum
  fix_wal_cksums $file
}

foreach {tn file field} {
  1 test.db2-wal    salt0
  2 test.db2-wal    salt1
  3 test.db2-wal    nCkpt
  4 test.db2-wal2   salt0
  5 test.db2-wal2   salt1
  6 test.db2-wal2   nCkpt
} {
  do_test 1.3.$tn {
    forcecopy test.db test.db2
    forcecopy test.db-wal test.db2-wal
    forcecopy test.db-wal2 test.db2-wal2
    wal_incr_hdrfield $file $field
    sqlite3 db2 test.db2
    execsql {
      SELECT sum(x) FROM t1;
      SELECT sum(x) FROM t2;
    } db2
  } [list $H $L]
  db2 close
}

do_test 1.4 {
  forcecopy test.db test.db2
  forcecopy test.db-wal2 test.db2-wal
  forcedelete test.db2-wal2
  sqlite3 db2 test.db2
  execsql {
    SELECT sum(x) FROM t1;
    SELECT sum(x) FROM t2;
  } db2
} [list $L $M]

do_test 1.5 {
  forcecopy test.db test.db2
  forcecopy test.db-wal2 test.db2-wal
  forcecopy test.db-wal test.db2-wal2
  sqlite3 db2 test.db2
  execsql {
    SELECT sum(x) FROM t1;
    SELECT sum(x) FROM t2;
  } db2
} [list $H $M]

foreach {tn file field} {
  1 test.db2-wal    salt0
  2 test.db2-wal    salt1
  3 test.db2-wal2   salt0
  4 test.db2-wal2   salt1
} {
  do_test 1.6.$tn {
    forcecopy test.db test.db2
    forcecopy test.db-wal2 test.db2-wal
    forcecopy test.db-wal test.db2-wal2
    wal_incr_hdrfield $file $field
    breakpoint
    sqlite3 db2 test.db2
    execsql {
      SELECT sum(x) FROM t1;
      SELECT sum(x) FROM t2;
    } db2
  } [list $H $L]
  db2 close
}

foreach {tn nCkpt1 nCkpt2 res} [list \
  1   2 1   "$H $M"                  \
  2   2 2   "$L $M"                  \
  3   3 1   "$H $L"                  \
  4   15 14 "$H $M"                  \
  5   0 15  "$H $M"                  \
  6   1 15  "$L $M"                  \
] {
  do_test 1.7.$tn {
    forcecopy test.db test.db2
    forcecopy test.db-wal2 test.db2-wal
    forcecopy test.db-wal test.db2-wal2

    wal_set_nckpt test.db2-wal2 $nCkpt2
    wal_set_nckpt test.db2-wal  $nCkpt1
    wal_set_follow test.db2-wal test.db2-wal2

    if {$tn==1} breakpoint

    sqlite3 db2 test.db2
    execsql {
      SELECT sum(x) FROM t1;
      SELECT sum(x) FROM t2;
    } db2
  } $res
  db2 close
}


finish_test