SQLite

Check-in [5e19bc360e]
Login

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

Overview
Comment:Add coverage test cases. Have sqlite3_backup_step() transform SQLITE_IOERR_NOMEM to SQLITE_NOMEM before returning.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 5e19bc360e098ec06a72f4a86254d8e62e93ea57
User & Date: dan 2010-06-30 04:29:04.000
Context
2010-06-30
04:36
Do not call pager_open_journal() from within PagerBegin() if the connection is in exclusive-access mode. It will be called from within PagerWrite() just as it is for non-exclusive mode anyway. (check-in: cdf2c5c2dd user: dan tags: trunk)
04:29
Add coverage test cases. Have sqlite3_backup_step() transform SQLITE_IOERR_NOMEM to SQLITE_NOMEM before returning. (check-in: 5e19bc360e user: dan tags: trunk)
2010-06-29
10:30
Add tests to pager1.test and pagerfault.test. (check-in: 008513ee61 user: dan tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/backup.c.
465
466
467
468
469
470
471



472
473
474
475
476
477
478
    if( bCloseTrans ){
      TESTONLY( int rc2 );
      TESTONLY( rc2  = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0);
      TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc);
      assert( rc2==SQLITE_OK );
    }
  



    p->rc = rc;
  }
  if( p->pDestDb ){
    sqlite3_mutex_leave(p->pDestDb->mutex);
  }
  sqlite3BtreeLeave(p->pSrc);
  sqlite3_mutex_leave(p->pSrcDb->mutex);







>
>
>







465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
    if( bCloseTrans ){
      TESTONLY( int rc2 );
      TESTONLY( rc2  = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0);
      TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc);
      assert( rc2==SQLITE_OK );
    }
  
    if( rc==SQLITE_IOERR_NOMEM ){
      rc = SQLITE_NOMEM;
    }
    p->rc = rc;
  }
  if( p->pDestDb ){
    sqlite3_mutex_leave(p->pDestDb->mutex);
  }
  sqlite3BtreeLeave(p->pSrc);
  sqlite3_mutex_leave(p->pSrcDb->mutex);
Changes to src/btree.c.
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597




1598
1599
1600
1601
1602
1603
1604
  BtShared *pBt,          /* The database file */
  Pgno pgno,           /* Number of the page to get */
  MemPage **ppPage     /* Write the page pointer here */
){
  int rc;
  assert( sqlite3_mutex_held(pBt->mutex) );

  if( pgno<=0 || pgno>btreePagecount(pBt) ){
    return SQLITE_CORRUPT_BKPT;
  }
  rc = btreeGetPage(pBt, pgno, ppPage, 0);
  if( rc==SQLITE_OK ){
    rc = btreeInitPage(*ppPage);
    if( rc!=SQLITE_OK ){
      releasePage(*ppPage);
    }
  }




  return rc;
}

/*
** Release a MemPage.  This should be called once for each prior
** call to btreeGetPage.
*/







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







1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
  BtShared *pBt,          /* The database file */
  Pgno pgno,           /* Number of the page to get */
  MemPage **ppPage     /* Write the page pointer here */
){
  int rc;
  assert( sqlite3_mutex_held(pBt->mutex) );

  if( pgno>btreePagecount(pBt) ){
    rc = SQLITE_CORRUPT_BKPT;
  }else{
    rc = btreeGetPage(pBt, pgno, ppPage, 0);
    if( rc==SQLITE_OK ){
      rc = btreeInitPage(*ppPage);
      if( rc!=SQLITE_OK ){
        releasePage(*ppPage);
      }
    }
  }

  testcase( pgno==0 );
  assert( pgno!=0 || rc==SQLITE_CORRUPT );
  return rc;
}

/*
** Release a MemPage.  This should be called once for each prior
** call to btreeGetPage.
*/
Changes to src/pager.c.
4704
4705
4706
4707
4708
4709
4710

4711
4712
4713
4714
4715
4716
4717
    ** written to the transaction journal or the ckeckpoint journal
    ** or both.
    **
    ** Higher level routines should have already started a transaction,
    ** which means they have acquired the necessary locks but the rollback
    ** journal might not yet be open.
    */

    rc = sqlite3PagerBegin(pPager, 0, pPager->subjInMemory);
    if( rc!=SQLITE_OK ){
      return rc;
    }
    if( pPager->pInJournal==0
     && pPager->journalMode!=PAGER_JOURNALMODE_OFF 
     && !pagerUseWal(pPager)







>







4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
    ** written to the transaction journal or the ckeckpoint journal
    ** or both.
    **
    ** Higher level routines should have already started a transaction,
    ** which means they have acquired the necessary locks but the rollback
    ** journal might not yet be open.
    */
    assert( pPager->state>PAGER_SHARED );
    rc = sqlite3PagerBegin(pPager, 0, pPager->subjInMemory);
    if( rc!=SQLITE_OK ){
      return rc;
    }
    if( pPager->pInJournal==0
     && pPager->journalMode!=PAGER_JOURNALMODE_OFF 
     && !pagerUseWal(pPager)
Changes to src/test1.c.
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
  Tcl_AppendResult(interp, "wrong # args: should be \"",
      Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
#endif /* SQLITE_OMIT_UTF16 */
  return TCL_ERROR;
}

/*
** Usage:         test_errstr <err code>
**
** Test that the english language string equivalents for sqlite error codes
** are sane. The parameter is an integer representing an sqlite error code.
** The result is a list of two elements, the string representation of the
** error code and the english language explanation.
*/
static int test_errstr(







|







2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
  Tcl_AppendResult(interp, "wrong # args: should be \"",
      Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
#endif /* SQLITE_OMIT_UTF16 */
  return TCL_ERROR;
}

/*
** Usage:         sqlite3_test_errstr <err code>
**
** Test that the english language string equivalents for sqlite error codes
** are sane. The parameter is an integer representing an sqlite error code.
** The result is a list of two elements, the string representation of the
** error code and the english language explanation.
*/
static int test_errstr(
Changes to test/pager1.test.
1613
1614
1615
1616
1617
1618
1619


1620











1621













































1622
1623
1624
    CREATE TABLE t2(a, b);
    PRAGMA writable_schema = 1;
    UPDATE sqlite_master SET rootpage=5 WHERE tbl_name = 't1';
    PRAGMA writable_schema = 0;
    ALTER TABLE t1 RENAME TO x1;
  }
  catchsql { SELECT * FROM x1 }


} {}











db close














































finish_test








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



1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
    CREATE TABLE t2(a, b);
    PRAGMA writable_schema = 1;
    UPDATE sqlite_master SET rootpage=5 WHERE tbl_name = 't1';
    PRAGMA writable_schema = 0;
    ALTER TABLE t1 RENAME TO x1;
  }
  catchsql { SELECT * FROM x1 }
} {1 {database disk image is malformed}}
db close

do_test pager1-18.6 {
  faultsim_delete_and_reopen
  db func a_string a_string
  execsql {
    PRAGMA page_size = 1024;
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(a_string(800));
    INSERT INTO t1 VALUES(a_string(800));
  }

  set root [db one "SELECT rootpage FROM sqlite_master"]
  db close

  hexio_write test.db [expr ($root-1)*1024 + 8] 00000000
  sqlite3 db test.db
  catchsql { SELECT length(x) FROM t1 }
} {1 {database disk image is malformed}}

do_test pager1-19.1 {
  sqlite3 db ""
  db func a_string a_string
  execsql {
    PRAGMA page_size = 512;
    PRAGMA auto_vacuum = 1;
    CREATE TABLE t1(aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am, an,
                    ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm, bn,
                    ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm, cn,
                    da, db, dc, dd, de, df, dg, dh, di, dj, dk, dl, dm, dn,
                    ea, eb, ec, ed, ee, ef, eg, eh, ei, ej, ek, el, em, en,
                    fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn,
                    ga, gb, gc, gd, ge, gf, gg, gh, gi, gj, gk, gl, gm, gn,
                    ha, hb, hc, hd, he, hf, hg, hh, hi, hj, hk, hl, hm, hn,
                    ia, ib, ic, id, ie, if, ig, ih, ii, ij, ik, il, im, ix,
                    ja, jb, jc, jd, je, jf, jg, jh, ji, jj, jk, jl, jm, jn,
                    ka, kb, kc, kd, ke, kf, kg, kh, ki, kj, kk, kl, km, kn,
                    la, lb, lc, ld, le, lf, lg, lh, li, lj, lk, ll, lm, ln,
                    ma, mb, mc, md, me, mf, mg, mh, mi, mj, mk, ml, mm, mn
    );
    CREATE TABLE t2(aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am, an,
                    ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm, bn,
                    ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm, cn,
                    da, db, dc, dd, de, df, dg, dh, di, dj, dk, dl, dm, dn,
                    ea, eb, ec, ed, ee, ef, eg, eh, ei, ej, ek, el, em, en,
                    fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn,
                    ga, gb, gc, gd, ge, gf, gg, gh, gi, gj, gk, gl, gm, gn,
                    ha, hb, hc, hd, he, hf, hg, hh, hi, hj, hk, hl, hm, hn,
                    ia, ib, ic, id, ie, if, ig, ih, ii, ij, ik, il, im, ix,
                    ja, jb, jc, jd, je, jf, jg, jh, ji, jj, jk, jl, jm, jn,
                    ka, kb, kc, kd, ke, kf, kg, kh, ki, kj, kk, kl, km, kn,
                    la, lb, lc, ld, le, lf, lg, lh, li, lj, lk, ll, lm, ln,
                    ma, mb, mc, md, me, mf, mg, mh, mi, mj, mk, ml, mm, mn
    );
    INSERT INTO t1(aa) VALUES( a_string(100000) );
    INSERT INTO t2(aa) VALUES( a_string(100000) );
    VACUUM;
  }
} {}

finish_test

Changes to test/pagerfault.test.
582
583
584
585
586
587
588





589
590
591
592
593
594
595
} -test {
  faultsim_test_result {0 {}}
  faultsim_integrity_check
}


#-------------------------------------------------------------------------





#
do_test pagerfault-13-pre1 {
  faultsim_delete_and_reopen
  db func a_string a_string;
  execsql {
    PRAGMA journal_mode = PERSIST;
    BEGIN;







>
>
>
>
>







582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
} -test {
  faultsim_test_result {0 {}}
  faultsim_integrity_check
}


#-------------------------------------------------------------------------
# Test fault injection when SQLite opens a database where the size of the
# database file is zero bytes but the accompanying journal file is larger
# than that. In this scenario SQLite should delete the journal file 
# without rolling it back, even if it is in all other respects a valid
# hot-journal file.
#
do_test pagerfault-13-pre1 {
  faultsim_delete_and_reopen
  db func a_string a_string;
  execsql {
    PRAGMA journal_mode = PERSIST;
    BEGIN;
605
606
607
608
609
610
611















612
































































613
614
615
  faultsim_restore_and_reopen
} -body {
  execsql { CREATE TABLE xx(a, b) }
} -test {
  faultsim_test_result {0 {}}
}
















}


































































finish_test







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



610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
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
  faultsim_restore_and_reopen
} -body {
  execsql { CREATE TABLE xx(a, b) }
} -test {
  faultsim_test_result {0 {}}
}

#---------------------------------------------------------------------------
# Test fault injection into a small backup operation.
#
do_test pagerfault-14-pre1 {
  faultsim_delete_and_reopen
  db func a_string a_string;
  execsql {
    PRAGMA journal_mode = PERSIST;
    ATTACH 'test.db2' AS two;
    BEGIN;
      CREATE TABLE t1(x, y UNIQUE);
      CREATE TABLE two.t2(x, y UNIQUE);
      INSERT INTO t1 VALUES(a_string(333), a_string(444));
      INSERT INTO t2 VALUES(a_string(333), a_string(444));
    COMMIT;
  }
  faultsim_save_and_close
} {}
do_faultsim_test pagerfault-14 -prep {
  faultsim_restore_and_reopen
} -body {
  if {[catch {db backup test.db2} msg]} { error [regsub {.*: } $msg {}] }
} -test {
  faultsim_test_result {0 {}} {1 {}} {1 {SQL logic error or missing database}}
}

do_test pagerfault-15-pre1 {
  faultsim_delete_and_reopen
  db func a_string a_string;
  execsql {
    BEGIN;
      CREATE TABLE t1(x, y UNIQUE);
      INSERT INTO t1 VALUES(a_string(11), a_string(22));
      INSERT INTO t1 VALUES(a_string(11), a_string(22));
    COMMIT;
  }
  faultsim_save_and_close
} {}
do_faultsim_test pagerfault-15 -prep {
  faultsim_restore_and_reopen
  db func a_string a_string;
} -body {
  db eval { SELECT * FROM t1 LIMIT 1 } {
    execsql {
      BEGIN; INSERT INTO t1 VALUES(a_string(333), a_string(555)); COMMIT;
      BEGIN; INSERT INTO t1 VALUES(a_string(333), a_string(555)); COMMIT;
    }
  }
} -test {
  faultsim_test_result {0 {}}
  faultsim_integrity_check
}

}

do_test pagerfault-16-pre1 {
  faultsim_delete_and_reopen
  execsql { CREATE TABLE t1(x, y UNIQUE) }
  faultsim_save_and_close
} {}
do_faultsim_test pagerfault-16 -prep {
  faultsim_restore_and_reopen
} -body {
  execsql {
    PRAGMA locking_mode = exclusive;
    PRAGMA journal_mode = wal;
    INSERT INTO t1 VALUES(1, 2);
    INSERT INTO t1 VALUES(3, 4);
    PRAGMA journal_mode = delete;
    INSERT INTO t1 VALUES(4, 5);
    PRAGMA journal_mode = wal;
    INSERT INTO t1 VALUES(6, 7);
    PRAGMA journal_mode = persist;
    INSERT INTO t1 VALUES(8, 9);
  }
} -test {
  faultsim_test_result {0 {exclusive wal delete wal persist}}
  faultsim_integrity_check
}



finish_test