From 697054c328cb63465199b732ed9954bbaef09751 Mon Sep 17 00:00:00 2001 From: Craig Beck Date: Mon, 24 Jan 2022 13:57:40 -0800 Subject: [PATCH 01/13] Add ignoreMissigops option when getting ops Default behavior should be unchanged, returning error for missing ops. When passing `{ignoreMissingOps: true}` via `options`, `getOps` and `getOpsToSnapshot` will not call `checkOpsFrom` to avoid erroring when using an incomplete set of ops --- index.js | 5 +- test/test_get_ops.js | 147 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+), 2 deletions(-) create mode 100644 test/test_get_ops.js diff --git a/index.js b/index.js index df8411d..8b02c3a 100644 --- a/index.js +++ b/index.js @@ -443,7 +443,7 @@ ShareDbMongo.prototype.getOpsToSnapshot = function(collectionName, id, from, sna this._getOps(collectionName, id, from, to, options, function(err, ops) { if (err) return callback(err); var filtered = getLinkedOps(ops, null, snapshot._opLink); - var err = checkOpsFrom(collectionName, id, filtered, from); + var err = (options || {}).ignoreMissingOps ? null : checkOpsFrom(collectionName, id, filtered, from); if (err) return callback(err); callback(null, filtered); }); @@ -464,10 +464,11 @@ ShareDbMongo.prototype.getOps = function(collectionName, id, from, to, options, if (err) return callback(err); if (self.getOpsWithoutStrictLinking) fetchOpsTo = opLink._v; } + self._getOps(collectionName, id, from, fetchOpsTo, options, function(err, ops) { if (err) return callback(err); var filtered = filterOps(ops, opLink, to); - var err = checkOpsFrom(collectionName, id, filtered, from); + var err = (options || {}).ignoreMissingOps ? null : checkOpsFrom(collectionName, id, filtered, from); if (err) return callback(err); callback(null, filtered); }); diff --git a/test/test_get_ops.js b/test/test_get_ops.js new file mode 100644 index 0000000..4083c7c --- /dev/null +++ b/test/test_get_ops.js @@ -0,0 +1,147 @@ +var expect = require('chai').expect; +var ShareDbMongo = require('..'); +var getQuery = require('sharedb-mingo-memory/get-query'); +var sinon = require('sinon'); + +var mongoUrl = process.env.TEST_MONGO_URL || 'mongodb://localhost:27017/test'; + +function create(callback) { + var db = new ShareDbMongo(mongoUrl, { + mongoOptions: {}, + getOpsWithoutStrictLinking: true + }); + db.getDbs(function(err, mongo) { + if (err) return callback(err); + mongo.dropDatabase(function(err) { + if (err) return callback(err); + callback(null, db, mongo); + }); + }); +}; + +require('sharedb/test/db')({create: create, getQuery: getQuery}); + +describe('getOps', function() { + beforeEach(function(done) { + var self = this; + create(function(err, db, mongo) { + if (err) return done(err); + self.db = db; + self.mongo = mongo; + done(); + }); + }); + + afterEach(function(done) { + this.db.close(done); + }); + + describe('a chain of ops', function() { + var db; + var mongo; + var id; + var collection; + + beforeEach(function(done) { + db = this.db; + mongo = this.mongo; + id = 'document1'; + collection = 'testcollection'; + + sinon.spy(db, '_getOps'); + sinon.spy(db, '_getSnapshotOpLink'); + + var ops = [ + {v: 0, create: {}}, + {v: 1, p: ['foo'], oi: 'bar'}, + {v: 2, p: ['foo'], oi: 'baz'}, + {v: 3, p: ['foo'], oi: 'qux'} + ]; + + commitOpChain(db, mongo, collection, id, ops, function(error) { + if (error) done(error); + callInSeries([ + function(next) { + mongo.collection('o_' + collection).deleteOne({v: 0}, next); + }, + function() { + mongo.collection('o_' + collection).deleteOne({v: 1}, done); + } + ]); + }); + }); + + it('fetches ops 2-3 without fetching all ops', function(done) { + db.getOps(collection, id, 2, 4, null, function(error, ops) { + if (error) return done(error); + expect(ops.length).to.equal(2); + expect(ops[0].v).to.equal(2); + expect(ops[1].v).to.equal(3); + done(); + }); + }); + + it('default option errors when missing ops', function(done) { + db.getOps(collection, id, 0, 4, null, function(error) { + expect(error.code).to.equal(5103); + expect(error.message).to.equal('Missing ops from requested version testcollection.document1 0'); + done(); + }); + }); + + it('ignoreMissingOps option returns available ops when missing ops', function(done) { + db.getOps(collection, id, 0, 4, {ignoreMissingOps: true}, function(error, ops) { + if (error) return done(error); + expect(ops.length).to.equal(2); + expect(ops[0].v).to.equal(2); + expect(ops[1].v).to.equal(3); + done(); + }); + }); + }); +}); + +function commitOpChain(db, mongo, collection, id, ops, previousOpId, version, callback) { + if (typeof previousOpId === 'function') { + callback = previousOpId; + previousOpId = undefined; + version = 0; + } + + ops = ops.slice(); + var op = ops.shift(); + + if (!op) { + return callback(); + } + + var snapshot = {id: id, v: version + 1, type: 'json0', data: {}, m: null, _opLink: previousOpId}; + db.commit(collection, id, op, snapshot, null, function(error) { + if (error) return callback(error); + mongo.collection('o_' + collection).find({d: id, v: version}).next(function(error, op) { + if (error) return callback(error); + commitOpChain(db, mongo, collection, id, ops, (op ? op._id : null), ++version, callback); + }); + }); +} + +function callInSeries(callbacks, args) { + if (!callbacks.length) return; + args = args || []; + var error = args.shift(); + + if (error) { + var finalCallback = callbacks[callbacks.length - 1]; + return finalCallback(error); + } + + var callback = callbacks.shift(); + if (callbacks.length) { + args.push(function() { + var args = Array.from(arguments); + callInSeries(callbacks, args); + }); + } + + callback.apply(callback, args); +} From 7192bc7c14357a8493bd768df7de149008a50b72 Mon Sep 17 00:00:00 2001 From: Craig Beck Date: Mon, 24 Jan 2022 14:57:45 -0800 Subject: [PATCH 02/13] add test for getOpsToSnapshop with incomplete set of ops --- test/test_get_ops.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/test_get_ops.js b/test/test_get_ops.js index 4083c7c..e2101eb 100644 --- a/test/test_get_ops.js +++ b/test/test_get_ops.js @@ -98,6 +98,19 @@ describe('getOps', function() { done(); }); }); + + it('getOpsToSnapshot ignoreMissingOps option returns available ops when missing ops', function(done) { + db.getSnapshot(collection, id, {$submit: true}, null, function(error, snapshot) { + if (error) done(error); + db.getOpsToSnapshot(collection, id, 0, snapshot, {ignoreMissingOps: true}, function(error, ops) { + if (error) return done(error); + expect(ops.length).to.equal(2); + expect(ops[0].v).to.equal(2); + expect(ops[1].v).to.equal(3); + done(); + }); + }); + }); }); }); From 5b1efbe1fa825e0400c84d9428738492f947b81f Mon Sep 17 00:00:00 2001 From: Craig Beck Date: Tue, 25 Jan 2022 11:05:15 -0800 Subject: [PATCH 03/13] only remove one ops to show behavior of fetching upto last missing op --- test/test_get_ops.js | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/test/test_get_ops.js b/test/test_get_ops.js index e2101eb..813f640 100644 --- a/test/test_get_ops.js +++ b/test/test_get_ops.js @@ -60,14 +60,7 @@ describe('getOps', function() { commitOpChain(db, mongo, collection, id, ops, function(error) { if (error) done(error); - callInSeries([ - function(next) { - mongo.collection('o_' + collection).deleteOne({v: 0}, next); - }, - function() { - mongo.collection('o_' + collection).deleteOne({v: 1}, done); - } - ]); + mongo.collection('o_' + collection).deleteOne({v: 1}, done); }); }); @@ -89,7 +82,7 @@ describe('getOps', function() { }); }); - it('ignoreMissingOps option returns available ops when missing ops', function(done) { + it('ignoreMissingOps option returns ops up to the first missing op', function(done) { db.getOps(collection, id, 0, 4, {ignoreMissingOps: true}, function(error, ops) { if (error) return done(error); expect(ops.length).to.equal(2); From da891a4df7e29a7ec2da019338225cc240cc315c Mon Sep 17 00:00:00 2001 From: Craig Beck Date: Tue, 25 Jan 2022 12:07:41 -0800 Subject: [PATCH 04/13] Update test description --- test/test_get_ops.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_get_ops.js b/test/test_get_ops.js index 813f640..358579f 100644 --- a/test/test_get_ops.js +++ b/test/test_get_ops.js @@ -92,7 +92,7 @@ describe('getOps', function() { }); }); - it('getOpsToSnapshot ignoreMissingOps option returns available ops when missing ops', function(done) { + it('getOpsToSnapshot ignoreMissingOps option returns ops up to the first missing op', function(done) { db.getSnapshot(collection, id, {$submit: true}, null, function(error, snapshot) { if (error) done(error); db.getOpsToSnapshot(collection, id, 0, snapshot, {ignoreMissingOps: true}, function(error, ops) { From fd2400958ecf2abc31f0c91c6b6e357fa29eca7e Mon Sep 17 00:00:00 2001 From: Craig Beck Date: Wed, 26 Jan 2022 11:29:43 -0800 Subject: [PATCH 05/13] remove unused funciton --- test/test_get_ops.js | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/test/test_get_ops.js b/test/test_get_ops.js index 358579f..12d717b 100644 --- a/test/test_get_ops.js +++ b/test/test_get_ops.js @@ -130,24 +130,3 @@ function commitOpChain(db, mongo, collection, id, ops, previousOpId, version, ca }); }); } - -function callInSeries(callbacks, args) { - if (!callbacks.length) return; - args = args || []; - var error = args.shift(); - - if (error) { - var finalCallback = callbacks[callbacks.length - 1]; - return finalCallback(error); - } - - var callback = callbacks.shift(); - if (callbacks.length) { - args.push(function() { - var args = Array.from(arguments); - callInSeries(callbacks, args); - }); - } - - callback.apply(callback, args); -} From e19d4889c9abb661a33e5d5d2498b8fe631eb131 Mon Sep 17 00:00:00 2001 From: Craig Beck Date: Wed, 26 Jan 2022 12:11:45 -0800 Subject: [PATCH 06/13] Pre-initalize options --- index.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 8b02c3a..c283685 100644 --- a/index.js +++ b/index.js @@ -439,11 +439,15 @@ ShareDbMongo.prototype.getOpsToSnapshot = function(collectionName, id, from, sna var err = ShareDbMongo.missingLastOperationError(collectionName, id); return callback(err); } + var options = Object.assign({}, options); var to = null; this._getOps(collectionName, id, from, to, options, function(err, ops) { if (err) return callback(err); var filtered = getLinkedOps(ops, null, snapshot._opLink); - var err = (options || {}).ignoreMissingOps ? null : checkOpsFrom(collectionName, id, filtered, from); + var err = null; + if (!options.ignoreMissingOps) { + err = checkOpsFrom(collectionName, id, filtered, from); + } if (err) return callback(err); callback(null, filtered); }); @@ -451,6 +455,7 @@ ShareDbMongo.prototype.getOpsToSnapshot = function(collectionName, id, from, sna ShareDbMongo.prototype.getOps = function(collectionName, id, from, to, options, callback) { var self = this; + var options = Object.assign({}, options); this._getOpLink(collectionName, id, to, options, function(err, opLink) { if (err) return callback(err); // We need to fetch slightly more ops than requested in order to work backwards along @@ -468,7 +473,10 @@ ShareDbMongo.prototype.getOps = function(collectionName, id, from, to, options, self._getOps(collectionName, id, from, fetchOpsTo, options, function(err, ops) { if (err) return callback(err); var filtered = filterOps(ops, opLink, to); - var err = (options || {}).ignoreMissingOps ? null : checkOpsFrom(collectionName, id, filtered, from); + var err = null; + if (!options.ignoreMissingOps) { + err = checkOpsFrom(collectionName, id, filtered, from); + } if (err) return callback(err); callback(null, filtered); }); From 1fb1b66f1a15727c14ff8e060051b474268cbb16 Mon Sep 17 00:00:00 2001 From: Craig Beck Date: Fri, 11 Feb 2022 13:33:08 -0800 Subject: [PATCH 07/13] remove require of duplicate tests --- test/test_get_ops.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/test_get_ops.js b/test/test_get_ops.js index 12d717b..e1f6ae8 100644 --- a/test/test_get_ops.js +++ b/test/test_get_ops.js @@ -1,6 +1,5 @@ var expect = require('chai').expect; var ShareDbMongo = require('..'); -var getQuery = require('sharedb-mingo-memory/get-query'); var sinon = require('sinon'); var mongoUrl = process.env.TEST_MONGO_URL || 'mongodb://localhost:27017/test'; @@ -19,8 +18,6 @@ function create(callback) { }); }; -require('sharedb/test/db')({create: create, getQuery: getQuery}); - describe('getOps', function() { beforeEach(function(done) { var self = this; From d025a8b35094cc252b461892d32e99b192d4951f Mon Sep 17 00:00:00 2001 From: Craig Beck Date: Fri, 11 Feb 2022 13:51:41 -0800 Subject: [PATCH 08/13] tests ensuring behaviour for getOpts with strict linking on or off --- test/test_get_ops.js | 97 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 92 insertions(+), 5 deletions(-) diff --git a/test/test_get_ops.js b/test/test_get_ops.js index e1f6ae8..c0fb475 100644 --- a/test/test_get_ops.js +++ b/test/test_get_ops.js @@ -4,11 +4,12 @@ var sinon = require('sinon'); var mongoUrl = process.env.TEST_MONGO_URL || 'mongodb://localhost:27017/test'; -function create(callback) { - var db = new ShareDbMongo(mongoUrl, { +function create(options, callback) { + const opts = Object.assign({ mongoOptions: {}, getOpsWithoutStrictLinking: true - }); + }, options); + const db = new ShareDbMongo(mongoUrl, opts); db.getDbs(function(err, mongo) { if (err) return callback(err); mongo.dropDatabase(function(err) { @@ -18,10 +19,96 @@ function create(callback) { }); }; -describe('getOps', function() { +describe('getOps with strict linking', function() { + beforeEach(function(done) { + var self = this; + create({ getOpsWithoutStrictLinking: true }, function(err, db, mongo) { + if (err) return done(err); + self.db = db; + self.mongo = mongo; + done(); + }); + }); + + afterEach(function(done) { + this.db.close(done); + }); + + describe('a chain of ops', function() { + var db; + var mongo; + var id; + var collection; + + beforeEach(function(done) { + db = this.db; + mongo = this.mongo; + id = 'document1'; + collection = 'testcollection'; + + sinon.spy(db, '_getOps'); + sinon.spy(db, '_getSnapshotOpLink'); + + var ops = [ + {v: 0, create: {}}, + {v: 1, p: ['foo'], oi: 'bar'}, + {v: 2, p: ['foo'], oi: 'baz'}, + {v: 3, p: ['foo'], oi: 'qux'} + ]; + + commitOpChain(db, mongo, collection, id, ops, function(error) { + if (error) done(error); + mongo.collection('o_' + collection).deleteOne({v: 1}, done); + }); + }); + + it('fetches ops 2-3 without fetching all ops', function(done) { + db.getOps(collection, id, 2, 4, null, function(error, ops) { + if (error) return done(error); + expect(ops.length).to.equal(2); + expect(ops[0].v).to.equal(2); + expect(ops[1].v).to.equal(3); + done(); + }); + }); + + it('default option errors when missing ops', function(done) { + db.getOps(collection, id, 0, 4, null, function(error) { + expect(error.code).to.equal(5103); + expect(error.message).to.equal('Missing ops from requested version testcollection.document1 0'); + done(); + }); + }); + + it('ignoreMissingOps option returns ops up to the first missing op', function(done) { + db.getOps(collection, id, 0, 4, {ignoreMissingOps: true}, function(error, ops) { + if (error) return done(error); + expect(ops.length).to.equal(2); + expect(ops[0].v).to.equal(2); + expect(ops[1].v).to.equal(3); + done(); + }); + }); + + it('getOpsToSnapshot ignoreMissingOps option returns ops up to the first missing op', function(done) { + db.getSnapshot(collection, id, {$submit: true}, null, function(error, snapshot) { + if (error) done(error); + db.getOpsToSnapshot(collection, id, 0, snapshot, {ignoreMissingOps: true}, function(error, ops) { + if (error) return done(error); + expect(ops.length).to.equal(2); + expect(ops[0].v).to.equal(2); + expect(ops[1].v).to.equal(3); + done(); + }); + }); + }); + }); +}); + +describe('getOps without strict linking', function() { beforeEach(function(done) { var self = this; - create(function(err, db, mongo) { + create({ getOpsWithoutStrictLinking: false }, function(err, db, mongo) { if (err) return done(err); self.db = db; self.mongo = mongo; From 5a6f48f3d8c9c9d9cc0ec501edee59363f39ea83 Mon Sep 17 00:00:00 2001 From: Craig Beck Date: Tue, 15 Feb 2022 09:06:47 -0800 Subject: [PATCH 09/13] mollify linter --- test/test_get_ops.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_get_ops.js b/test/test_get_ops.js index c0fb475..dc21dc9 100644 --- a/test/test_get_ops.js +++ b/test/test_get_ops.js @@ -5,11 +5,11 @@ var sinon = require('sinon'); var mongoUrl = process.env.TEST_MONGO_URL || 'mongodb://localhost:27017/test'; function create(options, callback) { - const opts = Object.assign({ + var opts = Object.assign({ mongoOptions: {}, getOpsWithoutStrictLinking: true }, options); - const db = new ShareDbMongo(mongoUrl, opts); + var db = new ShareDbMongo(mongoUrl, opts); db.getDbs(function(err, mongo) { if (err) return callback(err); mongo.dropDatabase(function(err) { @@ -22,7 +22,7 @@ function create(options, callback) { describe('getOps with strict linking', function() { beforeEach(function(done) { var self = this; - create({ getOpsWithoutStrictLinking: true }, function(err, db, mongo) { + create({getOpsWithoutStrictLinking: true}, function(err, db, mongo) { if (err) return done(err); self.db = db; self.mongo = mongo; @@ -108,7 +108,7 @@ describe('getOps with strict linking', function() { describe('getOps without strict linking', function() { beforeEach(function(done) { var self = this; - create({ getOpsWithoutStrictLinking: false }, function(err, db, mongo) { + create({getOpsWithoutStrictLinking: false}, function(err, db, mongo) { if (err) return done(err); self.db = db; self.mongo = mongo; From f331a0ecf52b8084b30eaad537db16ade59f9bc6 Mon Sep 17 00:00:00 2001 From: Craig Beck Date: Tue, 15 Feb 2022 09:35:17 -0800 Subject: [PATCH 10/13] de-duplicate tests passig strickt linking option --- test/test_get_ops.js | 137 ++++++++++++++++++++++--------------------- 1 file changed, 71 insertions(+), 66 deletions(-) diff --git a/test/test_get_ops.js b/test/test_get_ops.js index dc21dc9..f9773ba 100644 --- a/test/test_get_ops.js +++ b/test/test_get_ops.js @@ -19,81 +19,73 @@ function create(options, callback) { }); }; -describe('getOps with strict linking', function() { - beforeEach(function(done) { - var self = this; - create({getOpsWithoutStrictLinking: true}, function(err, db, mongo) { - if (err) return done(err); - self.db = db; - self.mongo = mongo; - done(); - }); - }); - - afterEach(function(done) { - this.db.close(done); - }); - - describe('a chain of ops', function() { - var db; - var mongo; - var id; - var collection; - +// loop thru strict linking options +for (strictLinkingOption in [true, false]) { + describe('getOps with strict linking ' + strictLinkingOption, function() { beforeEach(function(done) { - db = this.db; - mongo = this.mongo; - id = 'document1'; - collection = 'testcollection'; - - sinon.spy(db, '_getOps'); - sinon.spy(db, '_getSnapshotOpLink'); - - var ops = [ - {v: 0, create: {}}, - {v: 1, p: ['foo'], oi: 'bar'}, - {v: 2, p: ['foo'], oi: 'baz'}, - {v: 3, p: ['foo'], oi: 'qux'} - ]; + var self = this; + create( + {getOpsWithoutStrictLinking: strictLinkingOption}, + function(err, db, mongo) { + if (err) return done(err); + self.db = db; + self.mongo = mongo; + done(); + }); + }); - commitOpChain(db, mongo, collection, id, ops, function(error) { - if (error) done(error); - mongo.collection('o_' + collection).deleteOne({v: 1}, done); - }); + afterEach(function(done) { + this.db.close(done); }); - it('fetches ops 2-3 without fetching all ops', function(done) { - db.getOps(collection, id, 2, 4, null, function(error, ops) { - if (error) return done(error); - expect(ops.length).to.equal(2); - expect(ops[0].v).to.equal(2); - expect(ops[1].v).to.equal(3); - done(); + describe('a chain of ops', function() { + var db; + var mongo; + var id; + var collection; + + beforeEach(function(done) { + db = this.db; + mongo = this.mongo; + id = 'document1'; + collection = 'testcollection'; + + sinon.spy(db, '_getOps'); + sinon.spy(db, '_getSnapshotOpLink'); + + var ops = [ + {v: 0, create: {}}, + {v: 1, p: ['foo'], oi: 'bar'}, + {v: 2, p: ['foo'], oi: 'baz'}, + {v: 3, p: ['foo'], oi: 'qux'} + ]; + + commitOpChain(db, mongo, collection, id, ops, function(error) { + if (error) done(error); + mongo.collection('o_' + collection).deleteOne({v: 1}, done); + }); }); - }); - it('default option errors when missing ops', function(done) { - db.getOps(collection, id, 0, 4, null, function(error) { - expect(error.code).to.equal(5103); - expect(error.message).to.equal('Missing ops from requested version testcollection.document1 0'); - done(); + it('fetches ops 2-3 without fetching all ops', function(done) { + db.getOps(collection, id, 2, 4, null, function(error, ops) { + if (error) return done(error); + expect(ops.length).to.equal(2); + expect(ops[0].v).to.equal(2); + expect(ops[1].v).to.equal(3); + done(); + }); }); - }); - it('ignoreMissingOps option returns ops up to the first missing op', function(done) { - db.getOps(collection, id, 0, 4, {ignoreMissingOps: true}, function(error, ops) { - if (error) return done(error); - expect(ops.length).to.equal(2); - expect(ops[0].v).to.equal(2); - expect(ops[1].v).to.equal(3); - done(); + it('default option errors when missing ops', function(done) { + db.getOps(collection, id, 0, 4, null, function(error) { + expect(error.code).to.equal(5103); + expect(error.message).to.equal('Missing ops from requested version testcollection.document1 0'); + done(); + }); }); - }); - it('getOpsToSnapshot ignoreMissingOps option returns ops up to the first missing op', function(done) { - db.getSnapshot(collection, id, {$submit: true}, null, function(error, snapshot) { - if (error) done(error); - db.getOpsToSnapshot(collection, id, 0, snapshot, {ignoreMissingOps: true}, function(error, ops) { + it('ignoreMissingOps option returns ops up to the first missing op', function(done) { + db.getOps(collection, id, 0, 4, {ignoreMissingOps: true}, function(error, ops) { if (error) return done(error); expect(ops.length).to.equal(2); expect(ops[0].v).to.equal(2); @@ -101,9 +93,22 @@ describe('getOps with strict linking', function() { done(); }); }); + + it('getOpsToSnapshot ignoreMissingOps option returns ops up to the first missing op', function(done) { + db.getSnapshot(collection, id, {$submit: true}, null, function(error, snapshot) { + if (error) done(error); + db.getOpsToSnapshot(collection, id, 0, snapshot, {ignoreMissingOps: true}, function(error, ops) { + if (error) return done(error); + expect(ops.length).to.equal(2); + expect(ops[0].v).to.equal(2); + expect(ops[1].v).to.equal(3); + done(); + }); + }); + }); }); }); -}); +} describe('getOps without strict linking', function() { beforeEach(function(done) { From a77e103a0bd6a0df678625635909f1e98beab448 Mon Sep 17 00:00:00 2001 From: Craig Beck Date: Tue, 15 Feb 2022 09:39:14 -0800 Subject: [PATCH 11/13] use Array.froEach over for-in --- test/test_get_ops.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_get_ops.js b/test/test_get_ops.js index f9773ba..616b4ec 100644 --- a/test/test_get_ops.js +++ b/test/test_get_ops.js @@ -20,7 +20,7 @@ function create(options, callback) { }; // loop thru strict linking options -for (strictLinkingOption in [true, false]) { +[true, false].forEach(function (strictLinkingOption) { describe('getOps with strict linking ' + strictLinkingOption, function() { beforeEach(function(done) { var self = this; From d3e1732fd8df1d0007a190284686597568a8a74d Mon Sep 17 00:00:00 2001 From: Craig Beck Date: Tue, 15 Feb 2022 09:40:41 -0800 Subject: [PATCH 12/13] add missing paren --- test/test_get_ops.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_get_ops.js b/test/test_get_ops.js index 616b4ec..2b23a60 100644 --- a/test/test_get_ops.js +++ b/test/test_get_ops.js @@ -20,7 +20,7 @@ function create(options, callback) { }; // loop thru strict linking options -[true, false].forEach(function (strictLinkingOption) { +[true, false].forEach(function(strictLinkingOption) { describe('getOps with strict linking ' + strictLinkingOption, function() { beforeEach(function(done) { var self = this; @@ -108,7 +108,7 @@ function create(options, callback) { }); }); }); -} +}); describe('getOps without strict linking', function() { beforeEach(function(done) { From 107d1a1784d685d788719053cf11299829a77e95 Mon Sep 17 00:00:00 2001 From: Craig Beck Date: Tue, 15 Feb 2022 09:43:19 -0800 Subject: [PATCH 13/13] remove extra tests --- test/test_get_ops.js | 86 -------------------------------------------- 1 file changed, 86 deletions(-) diff --git a/test/test_get_ops.js b/test/test_get_ops.js index 2b23a60..7510a9d 100644 --- a/test/test_get_ops.js +++ b/test/test_get_ops.js @@ -110,92 +110,6 @@ function create(options, callback) { }); }); -describe('getOps without strict linking', function() { - beforeEach(function(done) { - var self = this; - create({getOpsWithoutStrictLinking: false}, function(err, db, mongo) { - if (err) return done(err); - self.db = db; - self.mongo = mongo; - done(); - }); - }); - - afterEach(function(done) { - this.db.close(done); - }); - - describe('a chain of ops', function() { - var db; - var mongo; - var id; - var collection; - - beforeEach(function(done) { - db = this.db; - mongo = this.mongo; - id = 'document1'; - collection = 'testcollection'; - - sinon.spy(db, '_getOps'); - sinon.spy(db, '_getSnapshotOpLink'); - - var ops = [ - {v: 0, create: {}}, - {v: 1, p: ['foo'], oi: 'bar'}, - {v: 2, p: ['foo'], oi: 'baz'}, - {v: 3, p: ['foo'], oi: 'qux'} - ]; - - commitOpChain(db, mongo, collection, id, ops, function(error) { - if (error) done(error); - mongo.collection('o_' + collection).deleteOne({v: 1}, done); - }); - }); - - it('fetches ops 2-3 without fetching all ops', function(done) { - db.getOps(collection, id, 2, 4, null, function(error, ops) { - if (error) return done(error); - expect(ops.length).to.equal(2); - expect(ops[0].v).to.equal(2); - expect(ops[1].v).to.equal(3); - done(); - }); - }); - - it('default option errors when missing ops', function(done) { - db.getOps(collection, id, 0, 4, null, function(error) { - expect(error.code).to.equal(5103); - expect(error.message).to.equal('Missing ops from requested version testcollection.document1 0'); - done(); - }); - }); - - it('ignoreMissingOps option returns ops up to the first missing op', function(done) { - db.getOps(collection, id, 0, 4, {ignoreMissingOps: true}, function(error, ops) { - if (error) return done(error); - expect(ops.length).to.equal(2); - expect(ops[0].v).to.equal(2); - expect(ops[1].v).to.equal(3); - done(); - }); - }); - - it('getOpsToSnapshot ignoreMissingOps option returns ops up to the first missing op', function(done) { - db.getSnapshot(collection, id, {$submit: true}, null, function(error, snapshot) { - if (error) done(error); - db.getOpsToSnapshot(collection, id, 0, snapshot, {ignoreMissingOps: true}, function(error, ops) { - if (error) return done(error); - expect(ops.length).to.equal(2); - expect(ops[0].v).to.equal(2); - expect(ops[1].v).to.equal(3); - done(); - }); - }); - }); - }); -}); - function commitOpChain(db, mongo, collection, id, ops, previousOpId, version, callback) { if (typeof previousOpId === 'function') { callback = previousOpId;