/ Check-in [87a15917]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Add tests to improve coverage of vdbesort.c.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | experimental
Files: files | file ages | folders
SHA1: 87a15917d7d88285054e2a319506dd4a0cac9722
User & Date: dan 2011-08-12 11:59:57
Context
2011-08-12
15:02
Add the SQLITE_OMIT_MERGE_SORT pre-processor directive. To omit the code in vdbesort.c. check-in: 4ced2394 user: dan tags: experimental
11:59
Add tests to improve coverage of vdbesort.c. check-in: 87a15917 user: dan tags: experimental
2011-08-08
19:26
Remove redundant parameter from vdbeSorterInitMerge() in vdbesort.c. check-in: eec8c0df user: dan tags: experimental
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/test_vfs.c.

119
120
121
122
123
124
125


126
127
128
129
130
131
132
...
321
322
323
324
325
326
327

328











329


330
331
332
333
334
335
336
....
1026
1027
1028
1029
1030
1031
1032

1033
1034
1035
1036
1037
1038
1039
#define TESTVFS_SYNC_MASK         0x00000200
#define TESTVFS_DELETE_MASK       0x00000400
#define TESTVFS_CLOSE_MASK        0x00000800
#define TESTVFS_WRITE_MASK        0x00001000
#define TESTVFS_TRUNCATE_MASK     0x00002000
#define TESTVFS_ACCESS_MASK       0x00004000
#define TESTVFS_FULLPATHNAME_MASK 0x00008000


#define TESTVFS_ALL_MASK          0x0001FFFF


#define TESTVFS_MAX_PAGES 1024

/*
** A shared-memory buffer. There is one of these objects for each shared
................................................................................
*/
static int tvfsRead(
  sqlite3_file *pFile, 
  void *zBuf, 
  int iAmt, 
  sqlite_int64 iOfst
){

  TestvfsFd *p = tvfsGetFd(pFile);











  return sqlite3OsRead(p->pReal, zBuf, iAmt, iOfst);


}

/*
** Write data to an tvfs-file.
*/
static int tvfsWrite(
  sqlite3_file *pFile, 
................................................................................
        { "xShmLock",      TESTVFS_SHMLOCK_MASK },
        { "xShmBarrier",   TESTVFS_SHMBARRIER_MASK },
        { "xShmUnmap",     TESTVFS_SHMCLOSE_MASK },
        { "xShmMap",       TESTVFS_SHMMAP_MASK },
        { "xSync",         TESTVFS_SYNC_MASK },
        { "xDelete",       TESTVFS_DELETE_MASK },
        { "xWrite",        TESTVFS_WRITE_MASK },

        { "xTruncate",     TESTVFS_TRUNCATE_MASK },
        { "xOpen",         TESTVFS_OPEN_MASK },
        { "xClose",        TESTVFS_CLOSE_MASK },
        { "xAccess",       TESTVFS_ACCESS_MASK },
        { "xFullPathname", TESTVFS_FULLPATHNAME_MASK },
      };
      Tcl_Obj **apElem = 0;







>
>







 







>
|
>
>
>
>
>
>
>
>
>
>
>
|
>
>







 







>







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
....
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
#define TESTVFS_SYNC_MASK         0x00000200
#define TESTVFS_DELETE_MASK       0x00000400
#define TESTVFS_CLOSE_MASK        0x00000800
#define TESTVFS_WRITE_MASK        0x00001000
#define TESTVFS_TRUNCATE_MASK     0x00002000
#define TESTVFS_ACCESS_MASK       0x00004000
#define TESTVFS_FULLPATHNAME_MASK 0x00008000
#define TESTVFS_READ_MASK         0x00010000

#define TESTVFS_ALL_MASK          0x0001FFFF


#define TESTVFS_MAX_PAGES 1024

/*
** A shared-memory buffer. There is one of these objects for each shared
................................................................................
*/
static int tvfsRead(
  sqlite3_file *pFile, 
  void *zBuf, 
  int iAmt, 
  sqlite_int64 iOfst
){
  int rc = SQLITE_OK;
  TestvfsFd *pFd = tvfsGetFd(pFile);
  Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
  if( p->pScript && p->mask&TESTVFS_READ_MASK ){
    tvfsExecTcl(p, "xRead", 
        Tcl_NewStringObj(pFd->zFilename, -1), pFd->pShmId, 0
    );
    tvfsResultCode(p, &rc);
  }
  if( rc==SQLITE_OK && p->mask&TESTVFS_READ_MASK && tvfsInjectIoerr(p) ){
    rc = SQLITE_IOERR;
  }
  if( rc==SQLITE_OK ){
    rc = sqlite3OsRead(pFd->pReal, zBuf, iAmt, iOfst);
  }
  return rc;
}

/*
** Write data to an tvfs-file.
*/
static int tvfsWrite(
  sqlite3_file *pFile, 
................................................................................
        { "xShmLock",      TESTVFS_SHMLOCK_MASK },
        { "xShmBarrier",   TESTVFS_SHMBARRIER_MASK },
        { "xShmUnmap",     TESTVFS_SHMCLOSE_MASK },
        { "xShmMap",       TESTVFS_SHMMAP_MASK },
        { "xSync",         TESTVFS_SYNC_MASK },
        { "xDelete",       TESTVFS_DELETE_MASK },
        { "xWrite",        TESTVFS_WRITE_MASK },
        { "xRead",         TESTVFS_READ_MASK },
        { "xTruncate",     TESTVFS_TRUNCATE_MASK },
        { "xOpen",         TESTVFS_OPEN_MASK },
        { "xClose",        TESTVFS_CLOSE_MASK },
        { "xAccess",       TESTVFS_ACCESS_MASK },
        { "xFullPathname", TESTVFS_FULLPATHNAME_MASK },
      };
      Tcl_Obj **apElem = 0;

Changes to test/indexfault.test.

12
13
14
15
16
17
18






































19
20
21
22
23
24
25
...
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
...
240
241
242
243
244
245
246
247












































































248

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

set testprefix indexfault







































#-------------------------------------------------------------------------
# These tests - indexfault-1.* - Build an index on a smallish table with
# all different kinds of fault-injection. The CREATE INDEX is run once
# with default options and once with a 50KB soft-heap-limit.
#
do_execsql_test 1.0 {
................................................................................
#   3.1: IO errors injected into xOpen() calls.
#   3.2: As 7.1, but with a low (50KB) soft-heap-limit.
#
#   3.3: IO errors injected into the first 200 write() calls made on the
#        second temporary file.
#   3.4: As 7.3, but with a low (50KB) soft-heap-limit.
#
#


# Set up the custom fault-injector. This is further configured by using
# different values for $::custom_filter and different implementations
# of Tcl proc [xCustom] for each test case.

#
set FAULTSIM(custom)            [list      \
  -injectinstall   custom_injectinstall    \
  -injectstart     custom_injectstart      \
  -injectstop      custom_injectstop       \
  -injecterrlist   {{1 {disk I/O error}}}  \
  -injectuninstall custom_injectuninstall  \
]
proc custom_injectinstall {} {
  testvfs shmfault -default true
  shmfault filter $::custom_filter
  shmfault script xCustom
}
proc custom_injectuninstall {} {
  catch {db  close}
  catch {db2 close}
  shmfault delete
}
set ::custom_ifail -1
set ::custom_nfail -1
proc custom_injectstart {iFail} {
  set ::custom_ifail $iFail
  set ::custom_nfail 0
}
proc custom_injectstop {} {
  set ::custom_ifail -1
  return $::custom_nfail
}

# Set up a table to build indexes on. Save the setup using the 
# [faultsim_save_and_close] mechanism.
# 
sqlite3 db test.db
do_execsql_test 3.0 {
  BEGIN;
................................................................................
    set ::nTmpOpen 0
  } -body {
    execsql { CREATE INDEX i1 ON t1(x) }
    faultsim_test_result {0 {}} 
  }
  sqlite3_soft_heap_limit $soft_limit
}













































































finish_test







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







 







|
<
>
|
|
|
>

<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 








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

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
...
158
159
160
161
162
163
164
165

166
167
168
169
170
171

172

























173
174
175
176
177
178
179
...
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
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
330
331
332
333
334
335
336
337

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

set testprefix indexfault

# Set up the custom fault-injector. This is further configured by using
# different values for $::custom_filter and different implementations
# of Tcl proc [xCustom] for each test case.
#
proc install_custom_faultsim {} {
  set ::FAULTSIM(custom)            [list      \
    -injectinstall   custom_injectinstall    \
    -injectstart     custom_injectstart      \
    -injectstop      custom_injectstop       \
    -injecterrlist   {{1 {disk I/O error}}}  \
    -injectuninstall custom_injectuninstall  \
  ]
  proc custom_injectinstall {} {
    testvfs shmfault -default true
    shmfault filter $::custom_filter
    shmfault script xCustom
  }
  proc custom_injectuninstall {} {
    catch {db  close}
    catch {db2 close}
    shmfault delete
  }
  set ::custom_ifail -1
  set ::custom_nfail -1
  proc custom_injectstart {iFail} {
    set ::custom_ifail $iFail
    set ::custom_nfail 0
  }
  proc custom_injectstop {} {
    set ::custom_ifail -1
    return $::custom_nfail
  }
}
proc uninstall_custom_faultsim {} {
  unset -nocomplain ::FAULTSIM(custom)
}


#-------------------------------------------------------------------------
# These tests - indexfault-1.* - Build an index on a smallish table with
# all different kinds of fault-injection. The CREATE INDEX is run once
# with default options and once with a 50KB soft-heap-limit.
#
do_execsql_test 1.0 {
................................................................................
#   3.1: IO errors injected into xOpen() calls.
#   3.2: As 7.1, but with a low (50KB) soft-heap-limit.
#
#   3.3: IO errors injected into the first 200 write() calls made on the
#        second temporary file.
#   3.4: As 7.3, but with a low (50KB) soft-heap-limit.
#
#   3.5: After a certain amount of data has been read from the main database

#        file (and written into the temporary b-tree), sqlite3_release_memory()
#        is called to free as much memory as possible. This causes the temp
#        b-tree to be flushed to disk. So that before its contents can be 
#        transfered to a PMA they must be read back from disk - creating extra
#        opportunities for IO errors.
#

install_custom_faultsim


























# Set up a table to build indexes on. Save the setup using the 
# [faultsim_save_and_close] mechanism.
# 
sqlite3 db test.db
do_execsql_test 3.0 {
  BEGIN;
................................................................................
    set ::nTmpOpen 0
  } -body {
    execsql { CREATE INDEX i1 ON t1(x) }
    faultsim_test_result {0 {}} 
  }
  sqlite3_soft_heap_limit $soft_limit
}

uninstall_custom_faultsim

#-------------------------------------------------------------------------
# Test 4: After a certain amount of data has been read from the main database
# file (and written into the temporary b-tree), sqlite3_release_memory() is
# called to free as much memory as possible. This causes the temp b-tree to be
# flushed to disk. So that before its contents can be transfered to a PMA they
# must be read back from disk - creating extra opportunities for IO errors.
# 
install_custom_faultsim

catch { db close }
forcedelete test.db
sqlite3 db test.db

do_execsql_test 4.0 {
  BEGIN;
    DROP TABLE IF EXISTS t1;
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(randomblob(11000));
    INSERT INTO t1 SELECT randomblob(11001) FROM t1;     --     2
    INSERT INTO t1 SELECT randomblob(11002) FROM t1;     --     4
    INSERT INTO t1 SELECT randomblob(11003) FROM t1;     --     8
    INSERT INTO t1 SELECT randomblob(11004) FROM t1;     --    16
    INSERT INTO t1 SELECT randomblob(11005) FROM t1;     --    32
    INSERT INTO t1 SELECT randomblob(11005) FROM t1;     --    64
  COMMIT;
}
faultsim_save_and_close

testvfs tvfs 
tvfs script xRead
tvfs filter xRead
set ::nRead 0
proc xRead {method file args} {
  if {[file tail $file] == "test.db"} { incr ::nRead }
}

do_test 4.1 {
  sqlite3 db test.db -vfs tvfs
  execsql { CREATE INDEX i1 ON t1(x) }
} {}

db close
tvfs delete

set ::custom_filter xRead
proc xCustom {method file args} {
  incr ::nReadCall
  if {$::nReadCall >= ($::nRead/5)} {
    if {$::nReadCall == ($::nRead/5)} {
      set nByte [sqlite3_release_memory [expr 64*1024*1024]]
      sqlite3_soft_heap_limit 20000
    }
    if {$file == ""} {
      incr ::custom_ifail -1
      if {$::custom_ifail==0} {
        incr ::custom_nfail
        return "SQLITE_IOERR"
      }
    }
  }
  return "SQLITE_OK"
}

do_faultsim_test 4.2 -faults custom -prep {
  faultsim_restore_and_reopen
  set ::nReadCall 0
  sqlite3_soft_heap_limit 0
} -body {
  execsql { CREATE INDEX i1 ON t1(x) }
  faultsim_test_result {0 {}} 
}

uninstall_custom_faultsim

finish_test

Changes to test/wal2.test.

602
603
604
605
606
607
608

609
610
611
612
613
614
615
    set ::shm_file [lindex $args 0]
    if {$method == "xShmLock"} { lappend ::locks [lindex $args 2] }
    return "SQLITE_OK"
  }
  testvfs tvfs
  tvfs script tvfs_cb
  sqlite3 db test.db -vfs tvfs

} {}

set RECOVERY {
  {0 1 lock exclusive} {1 7 lock exclusive} 
  {1 7 unlock exclusive} {0 1 unlock exclusive}
}
set READMARK0_READ {







>







602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
    set ::shm_file [lindex $args 0]
    if {$method == "xShmLock"} { lappend ::locks [lindex $args 2] }
    return "SQLITE_OK"
  }
  testvfs tvfs
  tvfs script tvfs_cb
  sqlite3 db test.db -vfs tvfs
  set {} {}
} {}

set RECOVERY {
  {0 1 lock exclusive} {1 7 lock exclusive} 
  {1 7 unlock exclusive} {0 1 unlock exclusive}
}
set READMARK0_READ {