1# 2009 January 30
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# This file implements regression tests for SQLite library.  The
12# focus of this file is testing the sqlite3_backup_XXX API.
13#
14# $Id: backup.test,v 1.11 2009/06/05 17:09:12 drh Exp $
15
16set testdir [file dirname $argv0]
17source $testdir/tester.tcl
18
19do_not_use_codec
20
21#---------------------------------------------------------------------
22# Test organization:
23#
24# backup-1.*: Warm-body tests.
25#
26# backup-2.*: Test backup under various conditions. To and from in-memory
27#             databases. To and from empty/populated databases. etc.
28#
29# backup-3.*: Verify that the locking-page (pending byte page) is handled.
30#
31# backup-4.*: Test various error conditions.
32#
33# backup-5.*: Test the source database being modified during a backup.
34#
35# backup-6.*: Test the backup_remaining() and backup_pagecount() APIs.
36#
37# backup-7.*: Test SQLITE_BUSY and SQLITE_LOCKED errors.
38#
39# backup-8.*: Test multiple simultaneous backup operations.
40#
41# backup-9.*: Test that passing a negative argument to backup_step() is
42#             interpreted as "copy the whole file".
43#
44# backup-10.*: Test writing the source database mid backup.
45#
46
47proc data_checksum {db file} { $db one "SELECT md5sum(a, b) FROM ${file}.t1" }
48proc test_contents {name db1 file1 db2 file2} {
49  $db2 eval {select * from sqlite_master}
50  $db1 eval {select * from sqlite_master}
51  set checksum [data_checksum $db2 $file2]
52  uplevel [list do_test $name [list data_checksum $db1 $file1] $checksum]
53}
54
55do_test backup-1.1 {
56  execsql {
57    BEGIN;
58    CREATE TABLE t1(a, b);
59    CREATE INDEX i1 ON t1(a, b);
60    INSERT INTO t1 VALUES(1, randstr(1000,1000));
61    INSERT INTO t1 VALUES(2, randstr(1000,1000));
62    INSERT INTO t1 VALUES(3, randstr(1000,1000));
63    INSERT INTO t1 VALUES(4, randstr(1000,1000));
64    INSERT INTO t1 VALUES(5, randstr(1000,1000));
65    COMMIT;
66  }
67} {}
68
69# Sanity check to verify that the [test_contents] proc works.
70#
71test_contents backup-1.2 db main db main
72
73# Check that it is possible to create and finish backup operations.
74#
75do_test backup-1.3.1 {
76  file delete test2.db
77  sqlite3 db2 test2.db
78  sqlite3_backup B db2 main db main
79} {B}
80do_test backup-1.3.2 {
81  B finish
82} {SQLITE_OK}
83do_test backup-1.3.3 {
84  info commands B
85} {}
86
87# Simplest backup operation. Backup test.db to test2.db. test2.db is
88# initially empty. test.db uses the default page size.
89#
90do_test backup-1.4.1 {
91  sqlite3_backup B db2 main db main
92} {B}
93do_test backup-1.4.2 {
94  B step 200
95} {SQLITE_DONE}
96do_test backup-1.4.3 {
97  B finish
98} {SQLITE_OK}
99do_test backup-1.4.4 {
100  info commands B
101} {}
102test_contents backup-1.4.5 db2 main db main
103db close
104db2 close
105#
106# End of backup-1.* tests.
107#---------------------------------------------------------------------
108
109
110#---------------------------------------------------------------------
111# The following tests, backup-2.*, are based on the following procedure:
112#
113#   1) Populate the source database.
114#   2) Populate the destination database.
115#   3) Run the backup to completion. (backup-2.*.1)
116#   4) Integrity check the destination db. (backup-2.*.2)
117#   5) Check that the contents of the destination db is the same as that
118#      of the source db. (backup-2.*.3)
119#
120# The test is run with all possible combinations of the following
121# input parameters, except that if the destination is an in-memory
122# database, the only page size tested is 1024 bytes (the same as the
123# source page-size).
124#
125#   * Source database is an in-memory database, OR
126#   * Source database is a file-backed database.
127#
128#   * Target database is an in-memory database, OR
129#   * Target database is a file-backed database.
130#
131#   * Destination database is a main file, OR
132#   * Destination database is an attached file, OR
133#   * Destination database is a temp database.
134#
135#   * Target database is empty (zero bytes), OR
136#   * Target database is larger than the source, OR
137#   * Target database is smaller than the source.
138#
139#   * Target database page-size is the same as the source, OR
140#   * Target database page-size is larger than the source, OR
141#   * Target database page-size is smaller than the source.
142#
143#   * Each call to step copies a single page, OR
144#   * A single call to step copies the entire source database.
145#
146set iTest 1
147foreach zSrcFile {test.db :memory:} {
148foreach zDestFile {test2.db :memory:} {
149foreach zOpenScript [list {
150  sqlite3 db $zSrcFile
151  sqlite3 db2 $zSrcFile
152  db2 eval "ATTACH '$zDestFile' AS bak"
153  set db_dest db2
154  set file_dest bak
155} {
156  sqlite3 db $zSrcFile
157  sqlite3 db2 $zDestFile
158  set db_dest db2
159  set file_dest main
160} {
161  sqlite3 db $zSrcFile
162  sqlite3 db2 $zDestFile
163  set db_dest db2
164  set file_dest temp
165}] {
166foreach rows_dest {0 3 10} {
167foreach pgsz_dest {1024} {
168foreach nPagePerStep {1 200} {
169
170  # Open the databases.
171  catch { file delete -force -- test.db }
172  catch { file delete -force -- test2.db }
173  eval $zOpenScript
174
175  # Set to true if copying to an in-memory destination. Copying to an
176  # in-memory destination is only possible if the initial destination
177  # page size is the same as the source page size (in this case 1024 bytes).
178  #
179  set isMemDest [expr {
180    $zDestFile eq ":memory:" || $file_dest eq "temp" && $TEMP_STORE>=2
181  }]
182
183  if { $isMemDest==0 || $pgsz_dest == 1024 } {
184    if 0 {
185      puts -nonewline "Test $iTest: src=$zSrcFile dest=$zDestFile"
186      puts -nonewline " (as $db_dest.$file_dest)"
187      puts -nonewline " rows_dest=$rows_dest pgsz_dest=$pgsz_dest"
188      puts ""
189    }
190
191    # Set up the content of the source database.
192    execsql {
193      PRAGMA page_size = 1024;
194      PRAGMA cache_size = 4000;
195      BEGIN;
196      CREATE TABLE t1(a, b);
197      CREATE INDEX i1 ON t1(a, b);
198      INSERT INTO t1 VALUES(1, randstr(1000,1000));
199      INSERT INTO t1 VALUES(2, randstr(1000,1000));
200      INSERT INTO t1 VALUES(3, randstr(1000,1000));
201      INSERT INTO t1 VALUES(4, randstr(1000,1000));
202      INSERT INTO t1 VALUES(5, randstr(1000,1000));
203      COMMIT;
204    }
205
206
207
208    # Set up the content of the target database.
209    execsql "PRAGMA ${file_dest}.page_size = ${pgsz_dest}" $db_dest
210    execsql "PRAGMA ${file_dest}.cache_size = 4000" $db_dest
211    if {$rows_dest != 0} {
212      execsql "
213        CREATE TABLE ${file_dest}.t1(a, b);
214        CREATE INDEX ${file_dest}.i1 ON t1(a, b);
215      " $db_dest
216      for {set ii 0} {$ii < $rows_dest} {incr ii} {
217        execsql "
218          INSERT INTO ${file_dest}.t1 VALUES(1, randstr(1000,1000))
219        " $db_dest
220      }
221    }
222
223    # Backup the source database.
224    do_test backup-2.$iTest.1 {
225      sqlite3_backup B $db_dest $file_dest db main
226      while {[B step $nPagePerStep]=="SQLITE_OK"} {}
227      B finish
228    } {SQLITE_OK}
229
230    # Run integrity check on the backup.
231    do_test backup-2.$iTest.2 {
232      execsql "PRAGMA ${file_dest}.integrity_check" $db_dest
233    } {ok}
234
235    test_contents backup-2.$iTest.3 db main $db_dest $file_dest
236
237  }
238
239  db close
240  catch {db2 close}
241  incr iTest
242
243} } } } } }
244#
245# End of backup-2.* tests.
246#---------------------------------------------------------------------
247
248
249#---------------------------------------------------------------------
250# The following tests, backup-4.*, test various error conditions:
251#
252# backup-4.1.*: Test invalid database names.
253#
254# backup-4.2.*: Test that the source database cannot be detached while
255#               a backup is in progress.
256#
257# backup-4.3.*: Test that the source database handle cannot be closed
258#               while a backup is in progress.
259#
260# backup-4.4.*: Test an attempt to specify the same handle for the
261#               source and destination databases.
262#
263# backup-4.5.*: Test that an in-memory destination with a different
264#               page-size to the source database is an error.
265#
266sqlite3 db test.db
267sqlite3 db2 test2.db
268
269do_test backup-4.1.1 {
270  catch { sqlite3_backup B db aux db2 main }
271} {1}
272do_test backup-4.1.2 {
273  sqlite3_errmsg db
274} {unknown database aux}
275do_test backup-4.1.3 {
276  catch { sqlite3_backup B db main db2 aux }
277} {1}
278do_test backup-4.1.4 {
279  sqlite3_errmsg db
280} {unknown database aux}
281
282do_test backup-4.2.1 {
283  catch { file delete -force test3.db }
284  catch { file delete -force test4.db }
285  execsql {
286    ATTACH 'test3.db' AS aux1;
287    CREATE TABLE aux1.t1(a, b);
288  }
289  execsql {
290    ATTACH 'test4.db' AS aux2;
291    CREATE TABLE aux2.t2(a, b);
292  } db2
293  sqlite3_backup B db aux1 db2 aux2
294} {B}
295do_test backup-4.2.2 {
296  catchsql { DETACH aux2 } db2
297} {1 {database aux2 is locked}}
298do_test backup-4.2.3 {
299  B step 50
300} {SQLITE_DONE}
301do_test backup-4.2.4 {
302  B finish
303} {SQLITE_OK}
304
305do_test backup-4.3.1 {
306  sqlite3_backup B db aux1 db2 aux2
307} {B}
308do_test backup-4.3.2 {
309  db2 cache flush
310  sqlite3_close db2
311} {SQLITE_BUSY}
312do_test backup-4.3.3 {
313  sqlite3_errmsg db2
314} {unable to close due to unfinished backup operation}
315do_test backup-4.3.4 {
316  B step 50
317} {SQLITE_DONE}
318do_test backup-4.3.5 {
319  B finish
320} {SQLITE_OK}
321
322do_test backup-4.4.1 {
323  set rc [catch {sqlite3_backup B db main db aux1}]
324  list $rc [sqlite3_errcode db] [sqlite3_errmsg db]
325} {1 SQLITE_ERROR {source and destination must be distinct}}
326db close
327db2 close
328
329do_test backup-4.5.1 {
330  catch { file delete -force -- test.db }
331  sqlite3 db test.db
332  sqlite3 db2 :memory:
333  execsql {
334    CREATE TABLE t1(a, b);
335    INSERT INTO t1 VALUES(1, 2);
336  }
337  execsql {
338    PRAGMA page_size = 4096;
339    CREATE TABLE t2(a, b);
340    INSERT INTO t2 VALUES(3, 4);
341  } db2
342  sqlite3_backup B db2 main db main
343} {B}
344do_test backup-4.5.2 {
345  B step 5000
346} {SQLITE_READONLY}
347do_test backup-4.5.3 {
348  B finish
349} {SQLITE_READONLY}
350
351db close
352db2 close
353#
354# End of backup-5.* tests.
355#---------------------------------------------------------------------
356
357#---------------------------------------------------------------------
358# The following tests, backup-5.*, test that the backup works properly
359# when the source database is modified during the backup. Test cases
360# are organized as follows:
361#
362# backup-5.x.1.*: Nothing special. Modify the database mid-backup.
363#
364# backup-5.x.2.*: Modify the database mid-backup so that one or more
365#                 pages are written out due to cache stress. Then
366#                 rollback the transaction.
367#
368# backup-5.x.3.*: Database is vacuumed.
369#
370# backup-5.x.4.*: Database is vacuumed and the page-size modified.
371#
372# backup-5.x.5.*: Database is shrunk via incr-vacuum.
373#
374# Each test is run three times, in the following configurations:
375#
376#   1) Backing up file-to-file. The writer writes via an external pager.
377#   2) Backing up file-to-file. The writer writes via the same pager as
378#      is used by the backup operation.
379#   3) Backing up memory-to-file.
380#
381set iTest 0
382file delete -force bak.db-wal
383foreach {writer file} {db test.db db :memory:} {
384  incr iTest
385  catch { file delete -force bak.db }
386  sqlite3 db2 bak.db
387  catch { file delete -force $file }
388  sqlite3 db $file
389  sqlite3 db3 $file
390
391  do_test backup-5.$iTest.1.1 {
392    execsql {
393      BEGIN;
394      CREATE TABLE t1(a, b);
395      CREATE INDEX i1 ON t1(a, b);
396      INSERT INTO t1 VALUES(1, randstr(1000,1000));
397      INSERT INTO t1 VALUES(2, randstr(1000,1000));
398      INSERT INTO t1 VALUES(3, randstr(1000,1000));
399      INSERT INTO t1 VALUES(4, randstr(1000,1000));
400      INSERT INTO t1 VALUES(5, randstr(1000,1000));
401      COMMIT;
402    }
403    expr {[execsql {PRAGMA page_count}] > 10}
404  } {1}
405  do_test backup-5.$iTest.1.2 {
406    sqlite3_backup B db2 main db main
407    B step 5
408  } {SQLITE_OK}
409  do_test backup-5.$iTest.1.3 {
410    execsql { UPDATE t1 SET a = a + 1 } $writer
411    B step 500
412  } {SQLITE_DONE}
413  do_test backup-5.$iTest.1.4 {
414    B finish
415  } {SQLITE_OK}
416  integrity_check backup-5.$iTest.1.5 db2
417  test_contents backup-5.$iTest.1.6 db main db2 main
418
419  do_test backup-5.$iTest.2.1 {
420    execsql {
421      PRAGMA cache_size = 10;
422      BEGIN;
423      INSERT INTO t1 SELECT '', randstr(1000,1000) FROM t1;
424      INSERT INTO t1 SELECT '', randstr(1000,1000) FROM t1;
425      INSERT INTO t1 SELECT '', randstr(1000,1000) FROM t1;
426      INSERT INTO t1 SELECT '', randstr(1000,1000) FROM t1;
427      COMMIT;
428    }
429  } {}
430  do_test backup-5.$iTest.2.2 {
431    sqlite3_backup B db2 main db main
432    B step 50
433  } {SQLITE_OK}
434  do_test backup-5.$iTest.2.3 {
435    execsql {
436      BEGIN;
437      UPDATE t1 SET a = a + 1;
438      ROLLBACK;
439    } $writer
440    B step 5000
441  } {SQLITE_DONE}
442  do_test backup-5.$iTest.2.4 {
443    B finish
444  } {SQLITE_OK}
445  integrity_check backup-5.$iTest.2.5 db2
446  test_contents backup-5.$iTest.2.6 db main db2 main
447
448  do_test backup-5.$iTest.3.1 {
449    execsql { UPDATE t1 SET b = randstr(1000,1000) }
450  } {}
451  do_test backup-5.$iTest.3.2 {
452    sqlite3_backup B db2 main db main
453    B step 50
454  } {SQLITE_OK}
455  do_test backup-5.$iTest.3.3 {
456    execsql { VACUUM } $writer
457    B step 5000
458  } {SQLITE_DONE}
459  do_test backup-5.$iTest.3.4 {
460    B finish
461  } {SQLITE_OK}
462  integrity_check backup-5.$iTest.3.5 db2
463  test_contents backup-5.$iTest.3.6 db main db2 main
464
465  do_test backup-5.$iTest.4.1 {
466    execsql { UPDATE t1 SET b = randstr(1000,1000) }
467  } {}
468  do_test backup-5.$iTest.4.2 {
469    sqlite3_backup B db2 main db main
470    B step 50
471  } {SQLITE_OK}
472  do_test backup-5.$iTest.4.3 {
473    execsql {
474      PRAGMA page_size = 2048;
475      VACUUM;
476    } $writer
477    B step 5000
478  } {SQLITE_DONE}
479  do_test backup-5.$iTest.4.4 {
480    B finish
481  } {SQLITE_OK}
482  integrity_check backup-5.$iTest.4.5 db2
483  test_contents backup-5.$iTest.4.6 db main db2 main
484
485  catch {db close}
486  catch {db2 close}
487  catch {db3 close}
488  catch { file delete -force -- bak.db }
489  sqlite3 db2 bak.db
490  catch { file delete -force -- $file }
491  sqlite3 db $file
492  sqlite3 db3 $file
493  do_test backup-5.$iTest.5.1 {
494    execsql {
495      PRAGMA auto_vacuum = incremental;
496      BEGIN;
497      CREATE TABLE t1(a, b);
498      CREATE INDEX i1 ON t1(a, b);
499      INSERT INTO t1 VALUES(1, randstr(1000,1000));
500      INSERT INTO t1 VALUES(2, randstr(1000,1000));
501      INSERT INTO t1 VALUES(3, randstr(1000,1000));
502      INSERT INTO t1 VALUES(4, randstr(1000,1000));
503      INSERT INTO t1 VALUES(5, randstr(1000,1000));
504      COMMIT;
505    }
506  } {}
507  do_test backup-5.$iTest.5.2 {
508    sqlite3_backup B db2 main db main
509    B step 8
510  } {SQLITE_OK}
511  do_test backup-5.$iTest.5.3 {
512    execsql {
513      DELETE FROM t1;
514      PRAGMA incremental_vacuum;
515    } $writer
516    B step 50
517  } {SQLITE_DONE}
518  do_test backup-5.$iTest.5.4 {
519    B finish
520  } {SQLITE_OK}
521  integrity_check backup-5.$iTest.5.5 db2
522  catch {db close}
523  catch {db2 close}
524  catch {db3 close}
525}
526#
527# End of backup-5.* tests.
528#---------------------------------------------------------------------
529
530#---------------------------------------------------------------------
531# Test the sqlite3_backup_remaining() and backup_pagecount() APIs.
532#
533do_test backup-6.1 {
534  catch { file delete -force -- test.db }
535  catch { file delete -force -- test2.db }
536  sqlite3 db test.db
537  sqlite3 db2 test2.db
538  execsql {
539    BEGIN;
540    CREATE TABLE t1(a, b);
541    CREATE INDEX i1 ON t1(a, b);
542    INSERT INTO t1 VALUES(1, randstr(1000,1000));
543    INSERT INTO t1 VALUES(2, randstr(1000,1000));
544    INSERT INTO t1 VALUES(3, randstr(1000,1000));
545    INSERT INTO t1 VALUES(4, randstr(1000,1000));
546    INSERT INTO t1 VALUES(5, randstr(1000,1000));
547    COMMIT;
548  }
549} {}
550do_test backup-6.2 {
551  set nTotal [expr {[file size test.db]/1024}]
552  sqlite3_backup B db2 main db main
553  B step 1
554} {SQLITE_OK}
555do_test backup-6.3 {
556  B pagecount
557} $nTotal
558do_test backup-6.4 {
559  B remaining
560} [expr $nTotal-1]
561do_test backup-6.5 {
562  B step 5
563  list [B remaining] [B pagecount]
564} [list [expr $nTotal-6] $nTotal]
565do_test backup-6.6 {
566  execsql { CREATE TABLE t2(a PRIMARY KEY, b) }
567  B step 1
568  list [B remaining] [B pagecount]
569} [list [expr $nTotal-5] [expr $nTotal+2]]
570
571do_test backup-6.X {
572  B finish
573} {SQLITE_OK}
574
575catch {db close}
576catch {db2 close}
577
578#---------------------------------------------------------------------
579# Test cases backup-7.* test that SQLITE_BUSY and SQLITE_LOCKED errors
580# are returned correctly:
581#
582# backup-7.1.*: Source database is externally locked (return SQLITE_BUSY).
583#
584# backup-7.2.*: Attempt to step the backup process while a
585#               write-transaction is underway on the source pager (return
586#               SQLITE_LOCKED).
587#
588# backup-7.3.*: Destination database is externally locked (return SQLITE_BUSY).
589#
590do_test backup-7.0 {
591  catch { file delete -force -- test.db }
592  catch { file delete -force -- test2.db }
593  sqlite3 db2 test2.db
594  sqlite3 db test.db
595  sqlite3 db3 test.db
596  execsql {
597    CREATE TABLE t1(a, b);
598    CREATE INDEX i1 ON t1(a, b);
599    INSERT INTO t1 VALUES(1, randstr(1000,1000));
600    INSERT INTO t1 SELECT a+ 1, randstr(1000,1000) FROM t1;
601    INSERT INTO t1 SELECT a+ 2, randstr(1000,1000) FROM t1;
602    INSERT INTO t1 SELECT a+ 4, randstr(1000,1000) FROM t1;
603    INSERT INTO t1 SELECT a+ 8, randstr(1000,1000) FROM t1;
604    INSERT INTO t1 SELECT a+16, randstr(1000,1000) FROM t1;
605    INSERT INTO t1 SELECT a+32, randstr(1000,1000) FROM t1;
606    INSERT INTO t1 SELECT a+64, randstr(1000,1000) FROM t1;
607  }
608} {}
609
610do_test backup-7.1.1 {
611  sqlite3_backup B db2 main db main
612  B step 5
613} {SQLITE_OK}
614do_test backup-7.2.1 {
615  execsql {
616    BEGIN;
617    INSERT INTO t1 VALUES(1, 4);
618  }
619} {}
620do_test backup-7.2.3 {
621  execsql { ROLLBACK }
622  B step 5000
623} {SQLITE_DONE}
624do_test backup-7.2.4 {
625  B finish
626} {SQLITE_OK}
627test_contents backup-7.2.5 db main db2 main
628integrity_check backup-7.3.6 db2
629
630do_test backup-7.3.1 {
631  db2 close
632  db3 close
633  file delete -force -- test2.db
634  sqlite3 db2 test2.db
635  sqlite3 db3 test2.db
636
637  sqlite3_backup B db2 main db main
638  execsql { BEGIN ; CREATE TABLE t2(a, b); COMMIT; } db3
639
640  B step 5
641} {SQLITE_BUSY}
642do_test backup-7.3.2 {
643  catch { db3 close }
644  B step 5000
645} {SQLITE_DONE}
646do_test backup-7.3.3 {
647  B finish
648} {SQLITE_OK}
649test_contents backup-7.3.4 db main db2 main
650integrity_check backup-7.3.5 db2
651catch { db2 close }
652
653#-----------------------------------------------------------------------
654# The following tests, backup-8.*, test attaching multiple backup
655# processes to the same source database. Also, reading from the source
656# database while a read transaction is active.
657#
658# These tests reuse the database "test.db" left over from backup-7.*.
659#
660do_test backup-8.1 {
661  catch { file delete -force -- test2.db }
662  catch { file delete -force -- test3.db }
663  sqlite3 db2 test2.db
664  sqlite3 db3 test3.db
665
666  sqlite3_backup B2 db2 main db main
667  sqlite3_backup B3 db3 main db main
668  list [B2 finish] [B3 finish]
669} {SQLITE_OK SQLITE_OK}
670do_test backup-8.2 {
671  sqlite3_backup B3 db3 main db main
672  sqlite3_backup B2 db2 main db main
673  list [B2 finish] [B3 finish]
674} {SQLITE_OK SQLITE_OK}
675do_test backup-8.3 {
676  sqlite3_backup B2 db2 main db main
677  sqlite3_backup B3 db3 main db main
678  B2 step 5
679} {SQLITE_OK}
680do_test backup-8.4 {
681  execsql {
682    BEGIN;
683    SELECT * FROM sqlite_master;
684  }
685  B3 step 5
686} {SQLITE_OK}
687do_test backup-8.5 {
688  list [B3 step 5000] [B3 finish]
689} {SQLITE_DONE SQLITE_OK}
690do_test backup-8.6 {
691  list [B2 step 5000] [B2 finish]
692} {SQLITE_DONE SQLITE_OK}
693test_contents backup-8.7 db main db2 main
694test_contents backup-8.8 db main db3 main
695do_test backup-8.9 {
696  execsql { PRAGMA lock_status }
697} {main shared temp closed}
698do_test backup-8.10 {
699  execsql COMMIT
700} {}
701catch { db2 close }
702catch { db3 close }
703
704#-----------------------------------------------------------------------
705# The following tests, backup-9.*, test that:
706#
707#   * Passing 0 as an argument to sqlite3_backup_step() means no pages
708#     are backed up (backup-9.1.*), and
709#   * Passing a negative value as an argument to sqlite3_backup_step() means
710#     all pages are backed up (backup-9.2.*).
711#
712# These tests reuse the database "test.db" left over from backup-7.*.
713#
714do_test backup-9.1.1 {
715  sqlite3 db2 test2.db
716  sqlite3_backup B db2 main db main
717  B step 1
718} {SQLITE_OK}
719do_test backup-9.1.2 {
720  set nRemaining [B remaining]
721  expr {$nRemaining>100}
722} {1}
723do_test backup-9.1.3 {
724  B step 0
725} {SQLITE_OK}
726do_test backup-9.1.4 {
727  B remaining
728} $nRemaining
729
730do_test backup-9.2.1 {
731  B step -1
732} {SQLITE_DONE}
733do_test backup-9.2.2 {
734  B remaining
735} {0}
736do_test backup-9.2.3 {
737  B finish
738} {SQLITE_OK}
739catch {db2 close}
740
741ifcapable memorymanage {
742  db close
743  file delete -force -- test.db
744  file delete -force -- bak.db
745
746  sqlite3 db test.db
747  sqlite3 db2 test.db
748  sqlite3 db3 bak.db
749
750  do_test backup-10.1.1 {
751    execsql {
752      BEGIN;
753      CREATE TABLE t1(a, b);
754      INSERT INTO t1 VALUES(1, randstr(1000,1000));
755      INSERT INTO t1 VALUES(2, randstr(1000,1000));
756      INSERT INTO t1 VALUES(3, randstr(1000,1000));
757      INSERT INTO t1 VALUES(4, randstr(1000,1000));
758      INSERT INTO t1 VALUES(5, randstr(1000,1000));
759      CREATE INDEX i1 ON t1(a, b);
760      COMMIT;
761    }
762  } {}
763  do_test backup-10.1.2 {
764    sqlite3_backup B db3 main db2 main
765    B step 5
766  } {SQLITE_OK}
767  do_test backup-10.1.3 {
768    execsql {
769      UPDATE t1 SET b = randstr(500,500);
770    }
771  } {}
772  sqlite3_release_memory [expr 1024*1024]
773  do_test backup-10.1.3 {
774    B step 50
775  } {SQLITE_DONE}
776  do_test backup-10.1.4 {
777    B finish
778  } {SQLITE_OK}
779  do_test backup-10.1.5 {
780    execsql { PRAGMA integrity_check } db3
781  } {ok}
782
783  db2 close
784  db3 close
785}
786
787
788#-----------------------------------------------------------------------
789# Test that if the database is written to via the same database handle being
790# used as the source by a backup operation:
791#
792#   10.1.*: If the db is in-memory, the backup is restarted.
793#   10.2.*: If the db is a file, the backup is restarted.
794#   10.3.*: If the db is in-memory, and not updated, the backup is not
795#           restarted
796#   10.4.*: If the db is a file,and not updated, the backup is not
797#           restarted
798#
799db close
800file delete -force -- test.db test.db-journal
801foreach {tn file update rc} {
802  1 test.db  1 SQLITE_OK
803  2 :memory: 1 SQLITE_OK
804  1 test.db  0 SQLITE_DONE
805  2 :memory: 0 SQLITE_DONE
806} {
807  do_test backup-10.$tn.1 {
808    sqlite3 db $file
809    execsql {
810      DROP TABLE IF EXISTS t1;
811      CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB);
812      BEGIN;
813        INSERT INTO t1 VALUES(NULL, randomblob(200));
814        INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
815        INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
816        INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
817        INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
818        INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
819        INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
820        INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
821        INSERT INTO t1 SELECT NULL, randomblob(200) FROM t1;
822      COMMIT;
823      SELECT count(*) FROM t1;
824    }
825  } {256}
826
827  do_test backup-10.$tn.3 {
828    file delete -force -- bak.db bak.db-journal
829    sqlite3 db2 bak.db
830    sqlite3_backup B db2 main db main
831    B step 50
832  } {SQLITE_OK}
833
834  if { $update == 1 } {
835    do_test backup-10.$tn.4 {
836      execsql { UPDATE t1 SET b = randomblob(200) WHERE a IN (1, 250) }
837    } {}
838  }
839
840  do_test backup-10.$tn.5 {
841    B step 50
842  } $rc
843
844  do_test backup-10.$tn.6 {
845    B finish
846  } {SQLITE_OK}
847
848  db2 close
849}
850
851finish_test
852