| /* global PouchDB, PouchDBVersion110, PouchDBVersion200, |
| PouchDBVersion220, PouchDBVersion306, PouchDBVersion320, |
| PouchDBVersion360 */ |
| 'use strict'; |
| |
| describe('migration', function () { |
| |
| function usingDefaultPreferredAdapters() { |
| var pref = PouchDB.preferredAdapters; |
| // Firefox will have ['idb'], Chrome will have ['idb', 'websql'] |
| return (pref.length === 1 && pref[0] === 'idb') || |
| (pref.length === 2 && pref[0] === 'idb' && pref[1] === 'websql'); |
| } |
| |
| var scenarios = [ |
| 'PouchDB v1.1.0', |
| 'PouchDB v2.0.0', |
| 'PouchDB v2.2.0', |
| 'PouchDB v3.0.6', |
| 'PouchDB v3.2.0', |
| 'PouchDB v3.6.0', |
| 'websql' |
| ]; |
| |
| var skip = false; |
| |
| before(function () { |
| var isNodeWebkit = typeof window !== 'undefined' && |
| typeof process !== 'undefined'; |
| |
| var skipMigration = 'SKIP_MIGRATION' in testUtils.params() && |
| testUtils.params().SKIP_MIGRATION; |
| |
| if (!usingDefaultPreferredAdapters() || window.msIndexedDB || |
| isNodeWebkit || skipMigration) { |
| skip = true; |
| } |
| |
| if (skip) { |
| return; |
| } |
| // conditionally load all legacy PouchDB scripts to avoid pulling them in |
| // for test runs that don't test migrations |
| return Promise.all(scenarios.map(function (scenario) { |
| var match = scenario.match(/PouchDB v([.\d]+)/); |
| if (!match) { |
| return testUtils.Promise.resolve(); |
| } |
| return new testUtils.Promise(function (resolve, reject) { |
| var script = document.createElement('script'); |
| script.onload = resolve; |
| script.onerror = reject; |
| script.src = 'deps/pouchdb-' + match[1] + '-postfixed.js'; |
| document.body.appendChild(script); |
| }); |
| })); |
| }); |
| |
| after(function () { |
| if (skip) { |
| return; |
| } |
| // free memory |
| delete window.PouchDBVersion110; |
| delete window.PouchDBVersion200; |
| delete window.PouchDBVersion220; |
| delete window.PouchDBVersion306; |
| delete window.PouchDBVersion320; |
| delete window.PouchDBVersion360; |
| }); |
| |
| scenarios.forEach(function (scenario) { |
| |
| describe('migrate from ' + scenario, function () { |
| |
| var dbs = {}; |
| var constructors = {}; |
| |
| var post220 = [ |
| 'PouchDB v2.2.0', |
| 'PouchDB v3.0.6', |
| 'PouchDB v3.2.0', |
| 'PouchDB v3.6.0' |
| ].indexOf(scenario) !== -1; |
| var post306 = [ |
| 'PouchDB v3.0.6', |
| 'PouchDB v3.2.0', |
| 'PouchDB v3.6.0' |
| ].indexOf(scenario) !== -1; |
| var post320 = [ |
| 'PouchDB v3.2.0', |
| 'PouchDB v3.6.0' |
| ].indexOf(scenario) !== -1; |
| var post360 = [ |
| 'PouchDB v3.6.0' |
| ].indexOf(scenario) !== -1; |
| |
| beforeEach(function (done) { |
| if (skip) { |
| return done(); |
| } |
| |
| constructors = { |
| 'PouchDB v1.1.0': PouchDBVersion110, |
| 'PouchDB v2.0.0': PouchDBVersion200, |
| 'PouchDB v2.2.0': PouchDBVersion220, |
| 'PouchDB v3.0.6': PouchDBVersion306, |
| 'PouchDB v3.2.0': PouchDBVersion320, |
| 'PouchDB v3.6.0': PouchDBVersion360, |
| PouchDB: PouchDB |
| }; |
| |
| // need actual unique db names for these tests |
| var localName = testUtils.adapterUrl('local', 'test_migration_local'); |
| var remoteName = testUtils.adapterUrl('http', 'test_migration_remote'); |
| |
| dbs.first = { |
| pouch : constructors[scenario] || PouchDB, |
| local : localName, |
| remote : remoteName, |
| localOpts : {} |
| }; |
| |
| dbs.second = { |
| pouch : PouchDB, |
| local : localName, |
| remote : remoteName |
| }; |
| |
| if (scenario in PouchDB.adapters) { |
| dbs.first.localOpts.adapter = scenario; |
| } |
| // else scenario might not make sense for this browser, so just use |
| // same adapter for both |
| |
| testUtils.cleanup([dbs.first.local, dbs.second.local], done); |
| |
| }); |
| |
| afterEach(function (done) { |
| if (skip) { |
| return done(); |
| } |
| testUtils.cleanup([dbs.first.local, dbs.second.local], done); |
| }); |
| |
| var origDocs = [ |
| {_id: '0', a: 1, b: 1}, |
| {_id: '3', a: 4, b: 16}, |
| {_id: '1', a: 2, b: 4}, |
| {_id: '2', a: 3, b: 9} |
| ]; |
| |
| it('Testing basic migration integrity', function (done) { |
| if (skip) { return done(); } |
| var oldPouch = |
| new dbs.first.pouch(dbs.first.local, dbs.first.localOpts, |
| function (err) { |
| should.not.exist(err, 'got error: ' + JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| }); |
| oldPouch.bulkDocs({docs: origDocs}, function (err, res) { |
| var removedDoc = {_deleted: true, _rev: res[0].rev, _id: res[0].id}; |
| oldPouch.remove(removedDoc, function () { |
| oldPouch.close(function (err) { |
| should.not.exist(err, 'got error: ' + JSON.stringify(err)); |
| var newPouch = new dbs.second.pouch(dbs.second.local); |
| return newPouch.allDocs({key: '2'}).then(function (res) { |
| res.total_rows.should.equal(3); |
| res.rows.should.have.length(1); |
| return newPouch.allDocs({key: '0'}); |
| }).then(function (res) { |
| res.total_rows.should.equal(3); |
| res.rows.should.have.length(0); |
| done(); |
| }).catch(function (err) { |
| should.not.exist(err, 'got error: ' + JSON.stringify(err)); |
| done(); |
| }); |
| }); |
| }); |
| }); |
| }); |
| |
| it("Test basic replication with migration", function (done) { |
| if (skip) { return done(); } |
| var docs = [ |
| {_id: "0", integer: 0, string: '0'}, |
| {_id: "1", integer: 1, string: '1'}, |
| {_id: "2", integer: 2, string: '2'}, |
| {_id: "3", integer: 3, string: '3', _deleted : true}, |
| {_id: "4", integer: 4, string: '4', _deleted : true} |
| ]; |
| |
| var oldPouch = new dbs.first.pouch(dbs.first.remote); |
| oldPouch.bulkDocs({docs: docs}, {}, function (err) { |
| should.not.exist(err, 'got error in bulkDocs: ' + |
| JSON.stringify(err)); |
| var oldLocalPouch = new dbs.first.pouch(dbs.first.local, |
| dbs.first.localOpts); |
| oldPouch.replicate.to(oldLocalPouch, function (err, result) { |
| should.not.exist(err, 'got error in replicate: ' + |
| JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| should.exist(result.ok, 'replication was ok'); |
| oldPouch.close(function (err) { |
| should.not.exist(err, 'got error in close: ' + |
| JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| should.not.exist(err, 'got error: ' + JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| oldLocalPouch.close(function (err) { |
| should.not.exist(err, 'got error in close: ' + |
| JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| var newPouch = new dbs.second.pouch(dbs.second.local); |
| if (err) { |
| done(); |
| } |
| newPouch.allDocs({}, function (err, res) { |
| should.not.exist(err, 'got error in allDocs: ' + |
| JSON.stringify(err)); |
| res.rows.should.have.length(3, 'unexpected rows: ' + |
| JSON.stringify(res.rows)); |
| res.total_rows.should.equal(3); |
| done(); |
| }); |
| }); |
| }); |
| }); |
| }); |
| }); |
| |
| it("Test basic replication with migration + changes()", function (done) { |
| if (skip) { return done(); } |
| var docs = [ |
| {_id: "0", integer: 0, string: '0'}, |
| {_id: "1", integer: 1, string: '1'}, |
| {_id: "2", integer: 2, string: '2'}, |
| {_id: "3", integer: 3, string: '3', _deleted : true}, |
| {_id: "4", integer: 4, string: '4', _deleted : true} |
| ]; |
| |
| var oldPouch = new dbs.first.pouch(dbs.first.remote); |
| oldPouch.bulkDocs({docs: docs}, {}, function (err) { |
| should.not.exist(err, 'got error in bulkDocs: ' + |
| JSON.stringify(err)); |
| var oldLocalPouch = new dbs.first.pouch(dbs.first.local, |
| dbs.first.localOpts); |
| oldPouch.replicate.to(oldLocalPouch, function (err, result) { |
| should.not.exist(err, 'got error in replicate: ' + |
| JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| should.exist(result.ok, 'replication was ok'); |
| oldPouch.close(function (err) { |
| should.not.exist(err, 'got error in close: ' + |
| JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| should.not.exist(err, 'got error: ' + JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| oldLocalPouch.close(function (err) { |
| should.not.exist(err, 'got error in close: ' + |
| JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| var newPouch = new dbs.second.pouch(dbs.second.local); |
| newPouch.changes({include_docs: true, return_docs: true}) |
| .on('complete', function (complete) { |
| complete.results.should.have |
| .length(5, 'no _local docs in changes()'); |
| done(); |
| }).on('error', done); |
| }); |
| }); |
| }); |
| }); |
| }); |
| |
| if (post220) { |
| it("Test persistent views don't require update", function (done) { |
| if (skip) { return done(); } |
| var oldPouch = new dbs.first.pouch(dbs.first.local, dbs.first.localOpts); |
| var docs = origDocs.slice().concat([{ |
| _id: '_design/myview', |
| views: { |
| myview: { |
| map: function (doc) { |
| emit(doc.a); |
| }.toString() |
| } |
| } |
| }]); |
| var expectedRows = [ |
| { key: 1, id: '0', value: null }, |
| { key: 2, id: '1', value: null }, |
| { key: 3, id: '2', value: null }, |
| { key: 4, id: '3', value: null } |
| ]; |
| oldPouch.bulkDocs({docs: docs}, function (err) { |
| should.not.exist(err, 'bulkDocs'); |
| oldPouch.query('myview', function (err, res) { |
| should.not.exist(err, 'query'); |
| res.rows.should.deep.equal(expectedRows); |
| oldPouch.close(function (err) { |
| should.not.exist(err, 'close'); |
| var newPouch = new dbs.second.pouch(dbs.second.local); |
| newPouch.query('myview', {stale: 'ok'}).then(function (res) { |
| res.rows.should.deep.equal(expectedRows); |
| done(); |
| }).catch(function (err) { |
| should.not.exist(err, 'catch'); |
| done(); |
| }); |
| }); |
| }); |
| }); |
| }); |
| |
| it("Test persistent views don't require update, with a value", |
| function (done) { |
| if (skip) { return done(); } |
| var oldPouch = new dbs.first.pouch(dbs.first.local, dbs.first.localOpts); |
| var docs = origDocs.slice().concat([{ |
| _id: '_design/myview', |
| views: { |
| myview: { |
| map: function (doc) { |
| emit(doc.a, doc.b); |
| }.toString() |
| } |
| } |
| }]); |
| var expectedRows = [ |
| { key: 1, id: '0', value: 1 }, |
| { key: 2, id: '1', value: 4 }, |
| { key: 3, id: '2', value: 9 }, |
| { key: 4, id: '3', value: 16 } |
| ]; |
| oldPouch.bulkDocs({docs: docs}, function (err) { |
| should.not.exist(err, 'bulkDocs'); |
| oldPouch.query('myview', function (err, res) { |
| should.not.exist(err, 'query'); |
| res.rows.should.deep.equal(expectedRows); |
| oldPouch.close(function (err) { |
| should.not.exist(err, 'close'); |
| var newPouch = new dbs.second.pouch(dbs.second.local); |
| newPouch.query('myview', {stale: 'ok'}).then(function (res) { |
| res.rows.should.deep.equal(expectedRows); |
| done(); |
| }).catch(function (err) { |
| should.not.exist(err, 'catch'); |
| done(); |
| }); |
| }); |
| }); |
| }); |
| }); |
| |
| it('Returns ok for viewCleanup after modifying view', function (done) { |
| if (skip) { return done(); } |
| var oldPouch = |
| new dbs.first.pouch(dbs.first.local, dbs.first.localOpts, |
| function (err) { |
| should.not.exist(err, 'got error: ' + JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| }); |
| var ddoc = { |
| _id: '_design/myview', |
| views: { |
| myview: { |
| map: function (doc) { |
| emit(doc.firstName); |
| }.toString() |
| } |
| } |
| }; |
| var doc = { |
| _id: 'foo', |
| firstName: 'Foobar', |
| lastName: 'Bazman' |
| }; |
| oldPouch.bulkDocs({docs: [ddoc, doc]}).then(function (info) { |
| ddoc._rev = info[0].rev; |
| return oldPouch.query('myview'); |
| }).then(function (res) { |
| res.rows.should.deep.equal([ |
| {id: 'foo', key: 'Foobar', value: null} |
| ]); |
| ddoc.views.myview.map = function (doc) { |
| emit(doc.lastName); |
| }.toString(); |
| return oldPouch.put(ddoc); |
| }).then(function () { |
| return oldPouch.query('myview'); |
| }).then(function (res) { |
| res.rows.should.deep.equal([ |
| {id: 'foo', key: 'Bazman', value: null} |
| ]); |
| return oldPouch.close(); |
| }).then(function () { |
| var newPouch = new dbs.second.pouch(dbs.second.local); |
| newPouch.viewCleanup().then(function () { |
| done(); |
| }, done); |
| }, done); |
| }); |
| it('Remembers local docs', function (done) { |
| if (skip) { return done(); } |
| var oldPouch = |
| new dbs.first.pouch(dbs.first.local, dbs.first.localOpts, |
| function (err) { |
| should.not.exist(err, 'got error: ' + JSON.stringify(err)); |
| if (err) { |
| done(); |
| } |
| }); |
| var docs = [ |
| { _id: '_local/foo' }, |
| { _id: '_local/bar' } |
| ]; |
| oldPouch.bulkDocs({docs: docs}).then(function () { |
| return oldPouch.close(); |
| }).then(function () { |
| var newPouch = new dbs.second.pouch(dbs.second.local); |
| newPouch.get('_local/foo').then(function () { |
| return newPouch.get('_local/bar'); |
| }).then(function () { |
| done(); |
| }, done); |
| }, done); |
| }); |
| |
| it('Testing migration with weird doc ids', function (done) { |
| if (skip) { return done(); } |
| |
| var origDocs = [ |
| {_id: 'foo::bar::baz'}, |
| {_id: '\u0000foo\u0000'} |
| ]; |
| |
| var oldPouch = new dbs.first.pouch(dbs.first.local, dbs.first.localOpts); |
| oldPouch.bulkDocs({docs: origDocs}, function (err) { |
| should.not.exist(err, 'got error: ' + JSON.stringify(err)); |
| oldPouch.close(function (err) { |
| should.not.exist(err, 'got error: ' + JSON.stringify(err)); |
| var newPouch = new dbs.second.pouch(dbs.second.local); |
| newPouch.allDocs().then(function (res) { |
| res.total_rows.should.equal(2); |
| res.rows.should.have.length(2); |
| res.rows[1].id.should.equal(origDocs[0]._id); |
| res.rows[0].id.should.equal(origDocs[1]._id); |
| done(); |
| }); |
| }); |
| }); |
| }); |
| } |
| |
| if (post306) { |
| // attachments didn't really work until this release |
| it('#2818 Testing attachments with compaction of dups', function () { |
| if (skip) { return; } |
| |
| var docs = [ |
| { |
| _id: 'doc1', |
| _attachments: { |
| 'att.txt': { |
| data: 'Zm9vYmFy', // 'foobar' |
| content_type: 'text/plain' |
| } |
| } |
| }, |
| { |
| _id: 'doc2', |
| _attachments: { |
| 'att.txt': { |
| data: 'Zm9vYmFy', // 'foobar' |
| content_type: 'text/plain' |
| } |
| } |
| } |
| ]; |
| |
| var oldPouch = new dbs.first.pouch( |
| dbs.first.local, dbs.first.localOpts); |
| return oldPouch.bulkDocs(docs).then(function () { |
| return oldPouch.close(); |
| }).then(function () { |
| var newPouch = new dbs.second.pouch(dbs.second.local, |
| {auto_compaction: false}); |
| return newPouch.get('doc1').then(function (doc1) { |
| return newPouch.remove(doc1); |
| }).then(function () { |
| return newPouch.compact(); |
| }).then(function () { |
| return newPouch.get('doc2', {attachments: true}); |
| }).then(function (doc2) { |
| doc2._attachments['att.txt'].data.should.equal('Zm9vYmFy'); |
| }); |
| }); |
| }); |
| |
| it('#2818 Testing attachments with compaction of dups 2', function () { |
| if (skip) { return; } |
| |
| var docs = [ |
| { |
| _id: 'doc1', |
| _attachments: { |
| 'att.txt': { |
| data: 'Zm9vYmFy', // 'foobar' |
| content_type: 'text/plain' |
| } |
| } |
| } |
| ]; |
| |
| var oldPouch = new dbs.first.pouch( |
| dbs.first.local, dbs.first.localOpts); |
| return oldPouch.bulkDocs(docs).then(function () { |
| return oldPouch.close(); |
| }).then(function () { |
| var newPouch = new dbs.second.pouch(dbs.second.local, |
| {auto_compaction: false}); |
| return newPouch.put({ |
| _id: 'doc2', |
| _attachments: { |
| 'att.txt': { |
| data: 'Zm9vYmFy', // 'foobar' |
| content_type: 'text/plain' |
| } |
| } |
| }).then(function () { |
| return newPouch.get('doc2'); |
| }).then(function (doc2) { |
| return newPouch.remove(doc2); |
| }).then(function () { |
| return newPouch.compact(); |
| }).then(function () { |
| return newPouch.get('doc1', {attachments: true}); |
| }).then(function (doc1) { |
| doc1._attachments['att.txt'].data.should.equal('Zm9vYmFy'); |
| }); |
| }); |
| }); |
| |
| it('#2818 Testing attachments with compaction of dups 3', function () { |
| if (skip) { return; } |
| |
| var docs = [ |
| { |
| _id: 'doc1', |
| _attachments: { |
| 'att.txt': { |
| data: 'Zm9vYmFy', // 'foobar' |
| content_type: 'text/plain' |
| } |
| } |
| }, |
| { |
| _id: 'doc_deleted', |
| _deleted: true |
| }, |
| { |
| _id: 'doc_no_attachments' |
| } |
| ]; |
| |
| for (var i = 0; i < 25; i++) { |
| // test paging in the migration |
| docs.push({ |
| _id: 'some_other_doc_' + i |
| }); |
| } |
| |
| var oldPouch = new dbs.first.pouch( |
| dbs.first.local, dbs.first.localOpts); |
| return oldPouch.bulkDocs(docs).then(function () { |
| return oldPouch.close(); |
| }).then(function () { |
| var newPouch = new dbs.second.pouch(dbs.second.local, |
| {auto_compaction: false}); |
| return newPouch.put({ |
| _id: 'doc2', |
| _attachments: { |
| 'att.txt': { |
| data: 'Zm9vYmFy', // 'foobar' |
| content_type: 'text/plain' |
| } |
| } |
| }).then(function () { |
| return newPouch.get('doc2'); |
| }).then(function (doc2) { |
| return newPouch.remove(doc2); |
| }).then(function () { |
| return newPouch.compact(); |
| }).then(function () { |
| return newPouch.get('doc1', {attachments: true}); |
| }).then(function (doc1) { |
| doc1._attachments['att.txt'].data.should.equal('Zm9vYmFy'); |
| }); |
| }); |
| }); |
| |
| it('#2818 Testing attachments with compaction of dups 4', function () { |
| if (skip) { return; } |
| |
| var docs = [ |
| { |
| _id: 'doc1', |
| _attachments: { |
| 'att.txt': { |
| data: 'Zm9vYmFy', // 'foobar' |
| content_type: 'text/plain' |
| }, |
| 'att2.txt': { |
| data: 'Zm9vYmFy', // 'foobar' |
| content_type: 'text/plain' |
| }, |
| 'att3.txt': { |
| data: 'Zm9v', // 'foo' |
| content_type: 'text/plain' |
| } |
| } |
| } |
| ]; |
| |
| var oldPouch = new dbs.first.pouch( |
| dbs.first.local, dbs.first.localOpts); |
| return oldPouch.bulkDocs(docs).then(function () { |
| return oldPouch.close(); |
| }).then(function () { |
| var newPouch = new dbs.second.pouch(dbs.second.local, |
| {auto_compaction: false}); |
| return newPouch.put({ |
| _id: 'doc2', |
| _attachments: { |
| 'att.txt': { |
| data: 'Zm9vYmFy', // 'foobar' |
| content_type: 'text/plain' |
| } |
| } |
| }).then(function () { |
| return newPouch.get('doc2'); |
| }).then(function (doc2) { |
| return newPouch.remove(doc2); |
| }).then(function () { |
| return newPouch.compact(); |
| }).then(function () { |
| return newPouch.get('doc1', {attachments: true}); |
| }).then(function (doc1) { |
| doc1._attachments['att.txt'].data.should.equal('Zm9vYmFy'); |
| doc1._attachments['att2.txt'].data.should.equal('Zm9vYmFy'); |
| doc1._attachments['att3.txt'].data.should.equal('Zm9v'); |
| }); |
| }); |
| }); |
| |
| it('#2818 Testing attachments with compaction of dups 5', function () { |
| if (skip) { return; } |
| |
| var docs = [ |
| { |
| _id: 'doc1', |
| _attachments: { |
| 'att.txt': { |
| data: 'Zm9vYmFy', // 'foobar' |
| content_type: 'text/plain' |
| }, |
| 'att2.txt': { |
| data: 'Zm9vYmFy', // 'foobar' |
| content_type: 'text/plain' |
| }, |
| 'att3.txt': { |
| data: 'Zm9v', // 'foo' |
| content_type: 'text/plain' |
| } |
| } |
| }, { |
| _id: 'doc3', |
| _attachments: { |
| 'att-a.txt': { |
| data: 'Zm9vYmFy', // 'foobar' |
| content_type: 'text/plain' |
| }, |
| 'att-b.txt': { |
| data: 'Zm9v', // 'foo' |
| content_type: 'text/plain' |
| }, |
| 'att-c.txt': { |
| data: 'YmFy', // 'bar' |
| content_type: 'text/plain' |
| } |
| } |
| } |
| ]; |
| |
| var oldPouch = new dbs.first.pouch( |
| dbs.first.local, dbs.first.localOpts); |
| return oldPouch.bulkDocs(docs).then(function () { |
| return oldPouch.close(); |
| }).then(function () { |
| var newPouch = new dbs.second.pouch(dbs.second.local, |
| {auto_compaction: false}); |
| return newPouch.put({ |
| _id: 'doc2', |
| _attachments: { |
| 'att.txt': { |
| data: 'YmFy', // 'bar' |
| content_type: 'text/plain' |
| } |
| } |
| }).then(function () { |
| return newPouch.get('doc2'); |
| }).then(function (doc2) { |
| return newPouch.remove(doc2); |
| }).then(function () { |
| return newPouch.compact(); |
| }).then(function () { |
| return newPouch.get('doc1', {attachments: true}); |
| }).then(function (doc1) { |
| doc1._attachments['att.txt'].data.should.equal('Zm9vYmFy'); |
| doc1._attachments['att2.txt'].data.should.equal('Zm9vYmFy'); |
| doc1._attachments['att3.txt'].data.should.equal('Zm9v'); |
| return newPouch.get('doc3', {attachments: true}); |
| }).then(function (doc3) { |
| doc3._attachments['att-a.txt'].data.should.equal('Zm9vYmFy'); |
| doc3._attachments['att-b.txt'].data.should.equal('Zm9v'); |
| doc3._attachments['att-c.txt'].data.should.equal('YmFy'); |
| }); |
| }); |
| }); |
| |
| it('#2818 Testing attachments with compaction of dups 6', function () { |
| if (skip) { return; } |
| |
| var docs = []; |
| |
| for (var i = 0; i < 40; i++) { |
| docs.push({ |
| _id: 'doc' + i, |
| _attachments: { |
| 'att.txt' : { |
| data: testUtils.btoa(Math.random().toString()), |
| content_type: 'text/plain' |
| } |
| } |
| }); |
| } |
| docs.push({ |
| _id: 'doc_a', |
| _attachments: { |
| 'att.txt': { |
| data: 'Zm9vYmFy', // 'foobar' |
| content_type: 'text/plain' |
| }, |
| 'att2.txt': { |
| data: 'Zm9vYmFy', // 'foobar' |
| content_type: 'text/plain' |
| }, |
| 'att3.txt': { |
| data: 'Zm9v', // 'foo' |
| content_type: 'text/plain' |
| } |
| } |
| }); |
| var oldPouch = new dbs.first.pouch( |
| dbs.first.local, dbs.first.localOpts); |
| return oldPouch.bulkDocs(docs).then(function () { |
| return oldPouch.close(); |
| }).then(function () { |
| var newPouch = new dbs.second.pouch(dbs.second.local, |
| {auto_compaction: false}); |
| return newPouch.put({ |
| _id: 'doc_b', |
| _attachments: { |
| 'att.txt': { |
| data: 'Zm9v', // 'foo' |
| content_type: 'text/plain' |
| } |
| } |
| }).then(function () { |
| return newPouch.get('doc_b'); |
| }).then(function (doc) { |
| return newPouch.remove(doc); |
| }).then(function () { |
| return newPouch.compact(); |
| }).then(function () { |
| return newPouch.get('doc_a', {attachments: true}); |
| }).then(function (doc) { |
| doc._attachments['att.txt'].data.should.equal('Zm9vYmFy'); |
| doc._attachments['att2.txt'].data.should.equal('Zm9vYmFy'); |
| doc._attachments['att3.txt'].data.should.equal('Zm9v'); |
| }); |
| }); |
| }); |
| |
| it('#2818 compaction of atts after many revs', function () { |
| if (skip) { return; } |
| |
| var oldPouch = new dbs.first.pouch( |
| dbs.first.local, dbs.first.localOpts); |
| |
| return oldPouch.put({_id: 'foo'}).then(function (res) { |
| return oldPouch.putAttachment('foo', 'att', res.rev, 'Zm9v', |
| 'text/plain'); |
| }).then(function () { |
| return oldPouch.get('foo', {attachments: true}); |
| }).then(function (doc) { |
| doc._attachments['att'].content_type.should.equal('text/plain'); |
| should.exist(doc._attachments['att'].data); |
| return oldPouch.get('foo'); |
| }).then(function (doc) { |
| return oldPouch.put(doc); |
| }).then(function () { |
| var newPouch = new dbs.second.pouch(dbs.second.local, |
| {auto_compaction: false}); |
| return newPouch.compact().then(function () { |
| return newPouch.get('foo', {attachments: true}); |
| }).then(function (doc) { |
| doc._attachments['att'].content_type.should.equal('text/plain'); |
| doc._attachments['att'].data.length.should.be.above(0, |
| 'attachment exists'); |
| }); |
| }); |
| }); |
| |
| it('#2890 PNG content after migration', function () { |
| if (skip) { return; } |
| |
| var oldPouch = new dbs.first.pouch( |
| dbs.first.local, dbs.first.localOpts); |
| |
| var transparent1x1Png = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HA' + |
| 'wCAAAAC0lEQVR4nGP6zwAAAgcBApocMXEA' + |
| 'AAAASUVORK5CYII='; |
| var black1x1Png = |
| 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACkl' + |
| 'EQVR4nGNiAAAABgADNjd8qAAA' + |
| 'AABJRU5ErkJggg=='; |
| |
| return oldPouch.put({_id: 'foo'}).then(function (res) { |
| return oldPouch.putAttachment('foo', 'att', res.rev, |
| transparent1x1Png, 'image/png'); |
| }).then(function () { |
| return oldPouch.get('foo', {attachments: true}); |
| }).then(function (doc) { |
| doc._attachments['att'].content_type.should.equal('image/png'); |
| should.exist(doc._attachments['att'].data); |
| return oldPouch.get('foo'); |
| }).then(function (doc) { |
| return oldPouch.put(doc); |
| }).then(function () { |
| var newPouch = new dbs.second.pouch(dbs.second.local, |
| {auto_compaction: false}); |
| return newPouch.compact().then(function () { |
| return newPouch.get('foo', {attachments: true}); |
| }).then(function (doc) { |
| doc._attachments['att'].content_type.should.equal('image/png'); |
| doc._attachments['att'].data.should.equal(transparent1x1Png); |
| return newPouch.putAttachment('bar', 'att', null, |
| black1x1Png, 'image/png'); |
| }).then(function () { |
| return newPouch.get('bar', {attachments: true}); |
| }).then(function (doc) { |
| doc._attachments['att'].content_type.should.equal('image/png'); |
| doc._attachments['att'].data.should.equal(black1x1Png); |
| }); |
| }); |
| }); |
| } |
| |
| if (post320) { |
| it('#3136 Testing later winningSeqs', function () { |
| if (skip) { |
| return; |
| } |
| |
| var tree = [ |
| [ |
| { |
| _id: 'foo', |
| _rev: '1-a', |
| _revisions: {start: 1, ids: ['a']} |
| } |
| ], [ |
| { |
| _id: 'foo', |
| _rev: '2-b', |
| _revisions: {start: 2, ids: ['b', 'a']} |
| } |
| ], [ |
| { |
| _id: 'bar', |
| _rev: '1-x', |
| _revisions: {start: 1, ids: ['x']} |
| } |
| ], [ |
| { |
| _id: 'foo', |
| _rev: '2-c', |
| _deleted: true, |
| _revisions: {start: 2, ids: ['c', 'a']} |
| } |
| ] |
| ]; |
| |
| var oldPouch = new dbs.first.pouch( |
| dbs.first.local, dbs.first.localOpts); |
| var chain = testUtils.Promise.resolve(); |
| tree.forEach(function (docs) { |
| chain = chain.then(function () { |
| return oldPouch.bulkDocs(docs, {new_edits: false}); |
| }); |
| }); |
| |
| return chain.then(function () { |
| return oldPouch.close(); |
| }).then(function () { |
| var newPouch = new dbs.second.pouch(dbs.second.local, |
| {auto_compaction: false}); |
| return newPouch.changes({ |
| return_docs: true, |
| include_docs: true, |
| style: 'all_docs' |
| }); |
| }).then(function (result) { |
| // order don't matter |
| result.results.forEach(function (ch) { |
| ch.changes = ch.changes.sort(function (a, b) { |
| return a.rev < b.rev ? -1 : 1; |
| }); |
| }); |
| var expected = { |
| "results": [ |
| { |
| "seq": 3, |
| "id": "bar", |
| "changes": [{"rev": "1-x"}], |
| "doc": {"_id": "bar", "_rev": "1-x"} |
| }, |
| { |
| "seq": 4, |
| "id": "foo", |
| "changes": [{"rev": "2-b"}, {"rev": "2-c"}], |
| "doc": {"_id": "foo", "_rev": "2-b"} |
| } |
| ], |
| "last_seq": 4 |
| }; |
| result.should.deep.equal(expected); |
| }); |
| }); |
| } |
| |
| if (post360) { |
| it('#3646 - Should finish with 0 documents', function () { |
| if (skip) { |
| return; |
| } |
| |
| var data = [ |
| { |
| "docs": [ |
| { |
| "_revisions": { |
| "start": 2, |
| "ids": [ |
| "4e16ac64356d4358bf1bdb4857fc299f", |
| "aed67b17ea5ba6b78e704ad65d3fb5db" |
| ] |
| }, |
| "_rev": "2-4e16ac64356d4358bf1bdb4857fc299f", |
| "_id": "b74e3b45", |
| "_deleted": true |
| }, |
| { |
| "_revisions": { |
| "start": 2, |
| "ids": [ |
| "3757f03a178b34284361c89303cf8c35", |
| "0593f4c87b24f0f9b620526433929bb0" |
| ] |
| }, |
| "_rev": "2-3757f03a178b34284361c89303cf8c35", |
| "_id": "b74e3b45", |
| "_deleted": true |
| }, |
| { |
| "_revisions": { |
| "start": 3, |
| "ids": [ |
| "f28d17ab990dcadd20ad38860fde9f11", |
| "6cf4b9e2115d7e884292b97aa8765285", |
| "dcfdf66ab61873ee512a9ccf3e3731a1" |
| ] |
| }, |
| "_rev": "3-f28d17ab990dcadd20ad38860fde9f11", |
| "_id": "b74e3b45" |
| }, |
| { |
| "_revisions": { |
| "start": 3, |
| "ids": [ |
| "4d93920c00a4a7269095b22ff4329b3c", |
| "7190eca51acb2b302a89ed1204ac2813", |
| "017eba7ef1e4f529143f463779822627" |
| ] |
| }, |
| "_rev": "3-4d93920c00a4a7269095b22ff4329b3c", |
| "_id": "b74e3b45", |
| "_deleted": true |
| }, |
| { |
| "_revisions": { |
| "start": 3, |
| "ids": [ |
| "91b47d7b889feb36eaf9336c071f00cc", |
| "0e3379b8f9128e6062d13eeb98ec538e", |
| "1c006ce18b663e2a031ced4669797c28" |
| ] |
| }, |
| "_rev": "3-91b47d7b889feb36eaf9336c071f00cc", |
| "_id": "b74e3b45", |
| "_deleted": true |
| }, |
| { |
| "_revisions": { |
| "start": 4, |
| "ids": [ |
| "2c3c860d421fc9f6cc82e4fb811dc8e2", |
| "4473170dcffa850aca381b4f644b2947", |
| "3524a871600080f5e30e59a292b02a3f", |
| "89eb0b5131800963bb7caf1fc83b6242" |
| ] |
| }, |
| "_rev": "4-2c3c860d421fc9f6cc82e4fb811dc8e2", |
| "_id": "b74e3b45", |
| "_deleted": true |
| }, |
| { |
| "_revisions": { |
| "start": 6, |
| "ids": [ |
| "441f43a31c89dc68a7cc934ce5779bf8", |
| "4c7f8b00508144d049d18668d17e552a", |
| "e8431fb3b448f3457c5b2d77012fa8b4", |
| "f2e7dc8102123e13ca792a0a05ca6235", |
| "37a13a5c1e2ce5926a3ffcda7e669106", |
| "78739468c87b30f76d067a2d7f373803" |
| ] |
| }, |
| "_rev": "6-441f43a31c89dc68a7cc934ce5779bf8", |
| "_id": "b74e3b45", |
| "_deleted": true |
| } |
| ] |
| }, |
| { |
| "docs": [ |
| { |
| "_revisions": { |
| "start": 2, |
| "ids": [ |
| "3757f03a178b34284361c89303cf8c35", |
| "0593f4c87b24f0f9b620526433929bb0" |
| ] |
| }, |
| "_rev": "2-3757f03a178b34284361c89303cf8c35", |
| "_id": "b74e3b45", |
| "_deleted": true |
| }, |
| { |
| "_revisions": { |
| "start": 2, |
| "ids": [ |
| "4e16ac64356d4358bf1bdb4857fc299f", |
| "aed67b17ea5ba6b78e704ad65d3fb5db" |
| ] |
| }, |
| "_rev": "2-4e16ac64356d4358bf1bdb4857fc299f", |
| "_id": "b74e3b45", |
| "_deleted": true |
| }, |
| { |
| "_revisions": { |
| "start": 3, |
| "ids": [ |
| "91b47d7b889feb36eaf9336c071f00cc", |
| "0e3379b8f9128e6062d13eeb98ec538e", |
| "1c006ce18b663e2a031ced4669797c28" |
| ] |
| }, |
| "_rev": "3-91b47d7b889feb36eaf9336c071f00cc", |
| "_id": "b74e3b45", |
| "_deleted": true |
| }, |
| { |
| "_revisions": { |
| "start": 3, |
| "ids": [ |
| "4d93920c00a4a7269095b22ff4329b3c", |
| "7190eca51acb2b302a89ed1204ac2813", |
| "017eba7ef1e4f529143f463779822627" |
| ] |
| }, |
| "_rev": "3-4d93920c00a4a7269095b22ff4329b3c", |
| "_id": "b74e3b45", |
| "_deleted": true |
| }, |
| { |
| "_revisions": { |
| "start": 4, |
| "ids": [ |
| "2c3c860d421fc9f6cc82e4fb811dc8e2", |
| "4473170dcffa850aca381b4f644b2947", |
| "3524a871600080f5e30e59a292b02a3f", |
| "89eb0b5131800963bb7caf1fc83b6242" |
| ] |
| }, |
| "_rev": "4-2c3c860d421fc9f6cc82e4fb811dc8e2", |
| "_id": "b74e3b45", |
| "_deleted": true |
| }, |
| { |
| "_revisions": { |
| "start": 4, |
| "ids": [ |
| "dbaa7e6c02381c2c0ec5259572387d7c", |
| "f28d17ab990dcadd20ad38860fde9f11", |
| "6cf4b9e2115d7e884292b97aa8765285", |
| "dcfdf66ab61873ee512a9ccf3e3731a1" |
| ] |
| }, |
| "_rev": "4-dbaa7e6c02381c2c0ec5259572387d7c", |
| "_id": "b74e3b45", |
| "_deleted": true |
| }, |
| { |
| "_revisions": { |
| "start": 6, |
| "ids": [ |
| "441f43a31c89dc68a7cc934ce5779bf8", |
| "4c7f8b00508144d049d18668d17e552a", |
| "e8431fb3b448f3457c5b2d77012fa8b4", |
| "f2e7dc8102123e13ca792a0a05ca6235", |
| "37a13a5c1e2ce5926a3ffcda7e669106", |
| "78739468c87b30f76d067a2d7f373803" |
| ] |
| }, |
| "_rev": "6-441f43a31c89dc68a7cc934ce5779bf8", |
| "_id": "b74e3b45", |
| "_deleted": true |
| } |
| ] |
| } |
| ]; |
| |
| var oldPouch = new dbs.first.pouch( |
| dbs.first.local, dbs.first.localOpts); |
| var newPouch; |
| |
| return oldPouch.bulkDocs(data[0], { |
| new_edits: false |
| }).then(function () { |
| return oldPouch.bulkDocs(data[1], {new_edits: false}); |
| }).then(function () { |
| return oldPouch.close(); |
| }).then(function () { |
| newPouch = new dbs.second.pouch(dbs.second.local, |
| {auto_compaction: false}); |
| return newPouch.allDocs(); |
| }).then(function (res) { |
| res.rows.should.have.length(0, 'all docs length is 0'); |
| res.total_rows.should.equal(0); |
| return newPouch.allDocs({keys: ['b74e3b45'], include_docs: true}); |
| }).then(function (res) { |
| var first = res.rows[0]; |
| should.equal(first.value.deleted, true, 'all docs value.deleted'); |
| first.value.rev.should.equal('6-441f43a31c89dc68a7cc934ce5779bf8'); |
| res.total_rows.should.equal(0); |
| return newPouch.info(); |
| }).then(function (info) { |
| info.doc_count.should.equal(0, 'doc_count is 0'); |
| return newPouch.changes({include_docs: true, return_docs: true}); |
| }).then(function (changes) { |
| changes.results.should.have.length(1); |
| var first = changes.results[0]; |
| first.doc._rev.should.equal('6-441f43a31c89dc68a7cc934ce5779bf8'); |
| should.equal(first.deleted, true, 'changes metadata.deleted'); |
| should.equal(first.doc._deleted, true, 'changes doc._deleted'); |
| }); |
| }); |
| } |
| }); |
| }); |
| }); |