V8 Coverage Report
Files covered Lines
. / test/backup.test.js
83.21 %
233 / 280
    1.      1var sqlite3 = require('..');
    2.      1var assert = require('assert');
    3.      1var fs = require('fs');
    4.      1var helper = require('./support/helper');
    5.      1
    6.      1// Check that the number of rows in two tables matches.
    7.      3function assertRowsMatchDb(db1, table1, db2, table2, done) {
    8.      3    db1.get("SELECT COUNT(*) as count FROM " + table1, function(err, row) {
    9.      0        if (err) throw err;
   10.      3        db2.get("SELECT COUNT(*) as count FROM " + table2, function(err, row2) {
   11.      0            if (err) throw err;
   12.      3            assert.equal(row.count, row2.count);
   13.      3            done();
   14.      3        });
   15.      3    });
   16.      3}
   17.      1
   18.      1// Check that the number of rows in the table "foo" is preserved in a backup.
   19.      2function assertRowsMatchFile(db, backupName, done) {
   20.      2    var db2 = new sqlite3.Database(backupName, sqlite3.OPEN_READONLY, function(err) {
   21.      0        if (err) throw err;
   22.      2        assertRowsMatchDb(db, 'foo', db2, 'foo', function() {
   23.      2            db2.close(done);
   24.      2        });
   25.      2    });
   26.      2}
   27.      1
   28.      1describe('backup', function() {
   29.      1    before(function() {
   30.      1        helper.ensureExists('test/tmp');
   31.      1    });
   32.      1
   33.      1    var db;
   34.     14    beforeEach(function(done) {
   35.     14        helper.deleteFile('test/tmp/backup.db');
   36.     14        helper.deleteFile('test/tmp/backup2.db');
   37.     14        db = new sqlite3.Database('test/support/prepare.db', sqlite3.OPEN_READONLY, done);
   38.     14    });
   39.      1
   40.     14    afterEach(function(done) {
   41.      3        if (!db) { done(); }
   42.     14        db.close(done);
   43.     14    });
   44.      1
   45.      1    it ('output db created once step is called', function(done) {
   46.      1        var backup = db.backup('test/tmp/backup.db', function(err) {
   47.      0            if (err) throw err;
   48.      1            backup.step(1, function(err) {
   49.      0                if (err) throw err;
   50.      1                assert.fileExists('test/tmp/backup.db');
   51.      1                backup.finish(done);
   52.      1            });
   53.      1        });
   54.      1    });
   55.      1
   56.      1    it ('copies source fully with step(-1)', function(done) {
   57.      1        var backup = db.backup('test/tmp/backup.db');
   58.      1        backup.step(-1, function(err) {
   59.      0            if (err) throw err;
   60.      1            assert.fileExists('test/tmp/backup.db');
   61.      1            backup.finish(function(err) {
   62.      0                if (err) throw err;
   63.      1                assertRowsMatchFile(db, 'test/tmp/backup.db', done);
   64.      1            });
   65.      1        });
   66.      1    });
   67.      1
   68.      1    it ('backup db not created if finished immediately', function(done) {
   69.      1        var backup = db.backup('test/tmp/backup.db');
   70.      1        backup.finish(function(err) {
   71.      0            if (err) throw err;
   72.      1            assert.fileDoesNotExist('test/tmp/backup.db');
   73.      1            done();
   74.      1        });
   75.      1    });
   76.      1
   77.      1    it ('error closing db if backup not finished', function(done) {
   78.      1        var backup = db.backup('test/tmp/backup.db');
   79.      1        db.close(function(err) {
   80.      1            db = null;
   81.      0            if (!err) throw new Error('should have an error');
   82.      1            if (err.errno == sqlite3.BUSY) {
   83.      1                done();
   84.      0            }
   85.      0            else throw err;
   86.      1        });
   87.      1    });
   88.      1
   89.      1    it ('using the backup after finished is an error', function(done) {
   90.      1        var backup = db.backup('test/tmp/backup.db');
   91.      1        backup.finish(function(err) {
   92.      0            if (err) throw err;
   93.      1            backup.step(1, function(err) {
   94.      0                if (!err) throw new Error('should have an error');
   95.      1                if (err.errno == sqlite3.MISUSE &&
   96.      1                    err.message === 'SQLITE_MISUSE: Backup is already finished') {
   97.      1                    done();
   98.      0                }
   99.      0                else throw err;
  100.      1            });
  101.      1        });
  102.      1    });
  103.      1
  104.      1    it ('remaining/pageCount are available after call to step', function(done) {
  105.      1        var backup = db.backup('test/tmp/backup.db');
  106.      1        backup.step(0, function(err) {
  107.      0            if (err) throw err;
  108.      1            assert.equal(typeof this.pageCount, 'number');
  109.      1            assert.equal(typeof this.remaining, 'number');
  110.      1            assert.equal(this.remaining, this.pageCount);
  111.      1            var prevRemaining = this.remaining;
  112.      1            var prevPageCount = this.pageCount;
  113.      1            backup.step(1, function(err) {
  114.      0                if (err) throw err;
  115.      1                assert.notEqual(this.remaining, prevRemaining);
  116.      1                assert.equal(this.pageCount, prevPageCount);
  117.      1                backup.finish(done);
  118.      1            });
  119.      1        });
  120.      1    });
  121.      1
  122.      1    it ('backup works if database is modified half-way through', function(done) {
  123.      1        var backup = db.backup('test/tmp/backup.db');
  124.      1        backup.step(-1, function(err) {
  125.      0            if (err) throw err;
  126.      1            backup.finish(function(err) {
  127.      0                if (err) throw err;
  128.      1                var db2 = new sqlite3.Database('test/tmp/backup.db', function(err) {
  129.      0                    if (err) throw err;
  130.      1                    var backup2 = db2.backup('test/tmp/backup2.db');
  131.      1                    backup2.step(1, function(err, completed) {
  132.      0                        if (err) throw err;
  133.      1                        assert.equal(completed, false);  // Page size for the test db
  134.      1                        // should not be raised to high.
  135.      1                        db2.exec("insert into foo(txt) values('hello')", function(err) {
  136.      0                            if (err) throw err;
  137.      1                            backup2.step(-1, function(err, completed) {
  138.      0                                if (err) throw err;
  139.      1                                assert.equal(completed, true);
  140.      1                                assertRowsMatchFile(db2, 'test/tmp/backup2.db', function() {
  141.      1                                    backup2.finish(function(err) {
  142.      0                                        if (err) throw err;
  143.      1                                        db2.close(done);
  144.      1                                    });
  145.      1                                });
  146.      1                            });
  147.      1                        });
  148.      1                    });
  149.      1                });
  150.      1            });
  151.      1        });
  152.      1    });
  153.      1
  154.      0    (sqlite3.VERSION_NUMBER < 3026000 ? it.skip : it) ('can backup from temp to main', function(done) {
  155.      1        db.exec("CREATE TEMP TABLE space (txt TEXT)", function(err) {
  156.      0            if (err) throw err;
  157.      1            db.exec("INSERT INTO space(txt) VALUES('monkey')", function(err) {
  158.      0                if (err) throw err;
  159.      1                var backup = db.backup('test/tmp/backup.db', 'temp', 'main', true, function(err) {
  160.      0                    if (err) throw err;
  161.      1                    backup.step(-1, function(err) {
  162.      0                        if (err) throw err;
  163.      1                        backup.finish(function(err) {
  164.      0                            if (err) throw err;
  165.      1                            var db2 = new sqlite3.Database('test/tmp/backup.db', function(err) {
  166.      0                                if (err) throw err;
  167.      1                                db2.get("SELECT * FROM space", function(err, row) {
  168.      0                                    if (err) throw err;
  169.      1                                    assert.equal(row.txt, 'monkey');
  170.      1                                    db2.close(done);
  171.      1                                });
  172.      1                            });
  173.      1                        });
  174.      1                    });
  175.      1                });
  176.      1            });
  177.      1        });
  178.      1    });
  179.      1
  180.      0    (sqlite3.VERSION_NUMBER < 3026000 ? it.skip : it) ('can backup from main to temp', function(done) {
  181.      1        var backup = db.backup('test/support/prepare.db', 'main', 'temp', false, function(err) {
  182.      0            if (err) throw err;
  183.      1            backup.step(-1, function(err) {
  184.      0                if (err) throw err;
  185.      1                backup.finish(function(err) {
  186.      0                    if (err) throw err;
  187.      1                    assertRowsMatchDb(db, 'temp.foo', db, 'main.foo', done);
  188.      1                });
  189.      1            });
  190.      1        });
  191.      1    });
  192.      1
  193.      1    it ('cannot backup to a locked db', function(done) {
  194.      1        var db2 = new sqlite3.Database('test/tmp/backup.db', function(err) {
  195.      1            db2.exec("PRAGMA locking_mode = EXCLUSIVE");
  196.      1            db2.exec("BEGIN EXCLUSIVE", function(err) {
  197.      0                if (err) throw err;
  198.      1                var backup = db.backup('test/tmp/backup.db');
  199.      1                backup.step(-1, function(stepErr) {
  200.      1                    db2.close(function(err) {
  201.      0                        if (err) throw err;
  202.      1                        if (stepErr.errno == sqlite3.BUSY) {
  203.      1                            backup.finish(done);
  204.      0                        }
  205.      0                        else throw stepErr;
  206.      1                    });
  207.      1                });
  208.      1            });
  209.      1        });
  210.      1    });
  211.      1
  212.      1    it ('fuss-free incremental backups work', function(done) {
  213.      1        var backup = db.backup('test/tmp/backup.db');
  214.      1        var timer;
  215.     81        function makeProgress() {
  216.     80            if (backup.idle) {
  217.     80                backup.step(1);
  218.     80            }
  219.     80            if (backup.completed || backup.failed) {
  220.      1                clearInterval(timer);
  221.      1                assert.equal(backup.completed, true);
  222.      1                assert.equal(backup.failed, false);
  223.      1                done();
  224.      1            }
  225.     81        }
  226.      1        timer = setInterval(makeProgress, 2);
  227.      1    });
  228.      1
  229.      1    it ('setting retryErrors to empty disables automatic finishing', function(done) {
  230.      1        var backup = db.backup('test/tmp/backup.db');
  231.      1        backup.retryErrors = [];
  232.      1        backup.step(-1, function(err) {
  233.      0            if (err) throw err;
  234.      1            db.close(function(err) {
  235.      1                db = null;
  236.      0                if (!err) throw new Error('should have an error');
  237.      1                assert.equal(err.errno, sqlite3.BUSY);
  238.      1                done();
  239.      1            });
  240.      1        });
  241.      1    });
  242.      1
  243.      1    it ('setting retryErrors enables automatic finishing', function(done) {
  244.      1        var backup = db.backup('test/tmp/backup.db');
  245.      1        backup.retryErrors = [sqlite3.OK];
  246.      1        backup.step(-1, function(err) {
  247.      0            if (err) throw err;
  248.      1            db.close(function(err) {
  249.      0                if (err) throw err;
  250.      1                db = null;
  251.      1                done();
  252.      1            });
  253.      1        });
  254.      1    });
  255.      1
  256.      1    it ('default retryErrors will retry on a locked/busy db', function(done) {
  257.      1        var db2 = new sqlite3.Database('test/tmp/backup.db', function(err) {
  258.      1            db2.exec("PRAGMA locking_mode = EXCLUSIVE");
  259.      1            db2.exec("BEGIN EXCLUSIVE", function(err) {
  260.      0                if (err) throw err;
  261.      1                var backup = db.backup('test/tmp/backup.db');
  262.      1                backup.step(-1, function(stepErr) {
  263.      1                    db2.close(function(err) {
  264.      0                        if (err) throw err;
  265.      1                        assert.equal(stepErr.errno, sqlite3.BUSY);
  266.      1                        assert.equal(backup.completed, false);
  267.      1                        assert.equal(backup.failed, false);
  268.      1                        backup.step(-1, function(err) {
  269.      0                            if (err) throw err;
  270.      1                            assert.equal(backup.completed, true);
  271.      1                            assert.equal(backup.failed, false);
  272.      1                            done();
  273.      1                        });
  274.      1                    });
  275.      1                });
  276.      1            });
  277.      1        });
  278.      1    });
  279.      1});
  280.      1