diff --git a/test/jio.storage/replicatestorage.tests.js b/test/jio.storage/replicatestorage.tests.js index bdae9e08208fcd9226f475e2cc9e3ca04d129745..cf57cd5be7a6e916ea74601cb86c39f7f056de44 100644 --- a/test/jio.storage/replicatestorage.tests.js +++ b/test/jio.storage/replicatestorage.tests.js @@ -1,6 +1,6 @@ /*jslint nomen: true*/ -/*global Blob, console, RSVP*/ -(function (jIO, QUnit, Blob, RSVP) { +/*global Blob*/ +(function (jIO, QUnit, Blob) { "use strict"; var test = QUnit.test, stop = QUnit.stop, @@ -36,39 +36,6 @@ } jIO.addStorage('signaturestorage2713', Storage2713); - function StorageEmptyAllAttachments(spec) { - this._sub_storage = jIO.createJIO(spec.sub_storage); - return this; - } - jIO.addStorage('signaturestorageallattachments', StorageEmptyAllAttachments); - StorageEmptyAllAttachments.prototype.allAttachments = function () { - return this._sub_storage.allAttachments.apply(this._sub_storage, - arguments); - }; - StorageEmptyAllAttachments.prototype.getAttachment = function () { - return this._sub_storage.getAttachment.apply(this._sub_storage, - arguments); - }; - StorageEmptyAllAttachments.prototype.putAttachment = function () { - return this._sub_storage.putAttachment.apply(this._sub_storage, - arguments); - }; - StorageEmptyAllAttachments.prototype.buildQuery = function () { - return this._sub_storage.buildQuery.apply(this._sub_storage, - arguments); - }; - StorageEmptyAllAttachments.prototype.put = function () { - return this._sub_storage.put.apply(this._sub_storage, - arguments); - }; - StorageEmptyAllAttachments.prototype.get = function () { - return this._sub_storage.get.apply(this._sub_storage, - arguments); - }; - StorageEmptyAllAttachments.prototype.hasCapacity = function (name) { - return (name !== 'bulk_get'); - }; - ///////////////////////////////////////////////////////////////// // replicateStorage.constructor ///////////////////////////////////////////////////////////////// @@ -734,7254 +701,4 @@ }); }); - ///////////////////////////////////////////////////////////////// - // replicateStorage.repair use cases - ///////////////////////////////////////////////////////////////// - module("replicateStorage.repair.document", { - setup: function () { - // Uses memory substorage, so that it is flushed after each run - this.jio = jIO.createJIO({ - type: "replicate", - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - } - }); - - ///////////////////////////////////////////////////////////////// - // document replication - ///////////////////////////////////////////////////////////////// - - test("local document creation", function () { - stop(); - expect(2); - - var id, - context = this; - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local document creation not checked", function () { - stop(); - expect(6); - - this.jio = jIO.createJIO({ - type: "replicate", - check_local_creation: false, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - var id, - context = this; - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return context.jio.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - }) - .always(function () { - start(); - }); - }); - - test("local document creation and use remote post", function () { - stop(); - expect(13); - - var id, - post_id, - context = this, - blob = new Blob([big_string]); - - this.jio = jIO.createJIO({ - type: "replicate", - use_remote_post: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, 'foo', blob); - }) - .then(function () { - return context.jio.repair(); - }) - // Document 'id' has been deleted in both storages - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._local_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function () { - ok(false, "Signature should have been deleted"); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - }) - - // But another document should have been created - .then(function () { - return context.jio.__storage._remote_sub_storage.allDocs(); - }) - .then(function (result) { - equal(result.data.total_rows, 1); - post_id = result.data.rows[0].id; - return context.jio.__storage._remote_sub_storage.get(post_id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - }) - .then(function () { - return context.jio.__storage._local_sub_storage.get(post_id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - // Attachment should be kept - return context.jio.__storage._local_sub_storage - .getAttachment(post_id, 'foo', {format: 'text'}); - }) - .then(function (result) { - equal(result, big_string); - return context.jio.__storage._signature_sub_storage.get(post_id); - }) - .then(function (result) { - deepEqual(result, { - hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local document creation, remote post and delayed allDocs", function () { - stop(); - expect(11); - - var id, - post_id = "_foobar", - context = this; - - function Storage200DelayedAllDocs(spec) { - this._sub_storage = jIO.createJIO(spec.sub_storage); - } - Storage200DelayedAllDocs.prototype.get = function () { - return this._sub_storage.get.apply(this._sub_storage, arguments); - }; - Storage200DelayedAllDocs.prototype.post = function (param) { - return this.put(post_id, param); - }; - Storage200DelayedAllDocs.prototype.put = function () { - return this._sub_storage.put.apply(this._sub_storage, arguments); - }; - Storage200DelayedAllDocs.prototype.hasCapacity = function () { - return true; - }; - Storage200DelayedAllDocs.prototype.buildQuery = function () { - return []; - }; - jIO.addStorage( - 'replicatestorage200delayedalldocs', - Storage200DelayedAllDocs - ); - - this.jio = jIO.createJIO({ - type: "replicate", - use_remote_post: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "replicatestorage200delayedalldocs", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - // Document 'id' has been deleted in both storages - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._local_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - }) - - // But another document should have been created - .then(function () { - return context.jio.__storage._remote_sub_storage.get(post_id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - }) - .then(function () { - return context.jio.__storage._local_sub_storage.get(post_id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(post_id); - }) - .then(function (result) { - deepEqual(result, { - hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("remote document creation", function () { - stop(); - expect(2); - - var id, - context = this; - - context.jio.__storage._remote_sub_storage.post({"title": "bar"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return context.jio.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "bar" - }); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "6799f3ea80e325b89f19589282a343c376c1f1af" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("remote document creation not checked", function () { - stop(); - expect(6); - - var id, - context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - check_remote_creation: false, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.__storage._remote_sub_storage.post({"title": "bar"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "bar" - }); - }) - .then(function () { - return context.jio.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote document creations", function () { - stop(); - expect(5); - - var context = this; - - RSVP.all([ - context.jio.put("conflict", {"title": "foo"}), - context.jio.__storage._remote_sub_storage.put("conflict", - {"title": "bar"}) - ]) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - ok(false); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Conflict on 'conflict': " + - "{\"title\":\"foo\"} !== {\"title\":\"bar\"}"); - equal(error.status_code, 409); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get("conflict"); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); -// equal(error.message, "Cannot find document: conflict"); - equal(error.status_code, 404); - }) - .always(function () { - start(); - }); - }); - - test("local and remote document creations: keep local", function () { - stop(); - expect(3); - - var context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - conflict_handling: 1 - }); - - RSVP.all([ - context.jio.put("conflict", {"title": "foo"}), - context.jio.__storage._remote_sub_storage.put("conflict", - {"title": "bar"}) - ]) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" - }); - }) - .then(function () { - return context.jio.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote document creations: keep local, remote post", - function () { - stop(); - expect(3); - - var context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - use_remote_post: 1, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - conflict_handling: 1 - }); - - RSVP.all([ - context.jio.put("conflict", {"title": "foo"}), - context.jio.__storage._remote_sub_storage.put("conflict", - {"title": "bar"}) - ]) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" - }); - }) - .then(function () { - return context.jio.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote document creations: keep local, " + - "local not matching query", function () { - stop(); - expect(3); - - var context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - local_sub_storage: { - type: "query", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "query", - sub_storage: { - type: "memory" - } - }, - query: {query: 'type: "foobar"'}, - conflict_handling: 1 - }); - - RSVP.all([ - context.jio.put("conflict", {"title": "foo"}), - context.jio.__storage._remote_sub_storage.put("conflict", - {"title": "bar", - "type": "foobar"}) - ]) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" - }); - }) - .then(function () { - return context.jio.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote document creations: keep local, " + - "remote not matching query", function () { - stop(); - expect(3); - - var context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - local_sub_storage: { - type: "query", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "query", - sub_storage: { - type: "memory" - } - }, - query: {query: 'type: "foobar"'}, - conflict_handling: 1 - }); - - RSVP.all([ - context.jio.put("conflict", {"title": "foo", "type": "foobar"}), - context.jio.__storage._remote_sub_storage.put("conflict", - {"title": "bar"}) - ]) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - hash: "a0a1b37cee3709101b752c56e59b9d66cce09961" - }); - }) - .then(function () { - return context.jio.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - title: "foo", - type: "foobar" - }); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - title: "foo", - type: "foobar" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote document creations: keep remote", function () { - stop(); - expect(3); - - var context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - conflict_handling: 2 - }); - - RSVP.all([ - context.jio.put("conflict", {"title": "foo"}), - context.jio.__storage._remote_sub_storage.put("conflict", - {"title": "bar"}) - ]) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - hash: "6799f3ea80e325b89f19589282a343c376c1f1af" - }); - }) - .then(function () { - return context.jio.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - title: "bar" - }); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - title: "bar" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote document creations: keep remote, remote post", - function () { - stop(); - expect(3); - - var context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - use_remote_post: 1, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - conflict_handling: 2 - }); - - RSVP.all([ - context.jio.put("conflict", {"title": "foo"}), - context.jio.__storage._remote_sub_storage.put("conflict", - {"title": "bar"}) - ]) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - hash: "6799f3ea80e325b89f19589282a343c376c1f1af" - }); - }) - .then(function () { - return context.jio.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - title: "bar" - }); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - title: "bar" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote document creations: keep remote, " + - "local not matching query", function () { - stop(); - expect(3); - - var context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - local_sub_storage: { - type: "query", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "query", - sub_storage: { - type: "memory" - } - }, - query: {query: 'type: "foobar"'}, - conflict_handling: 2 - }); - - RSVP.all([ - context.jio.put("conflict", {"title": "foo"}), - context.jio.__storage._remote_sub_storage.put("conflict", - {"title": "bar", - "type": "foobar"}) - ]) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - hash: "45efa2292d54cc4ce1f726ea197bc0b9721fc1dc" - }); - }) - .then(function () { - return context.jio.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - title: "bar", - type: "foobar" - }); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - title: "bar", - type: "foobar" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote document creations: keep remote, " + - "remote not matching query", function () { - stop(); - expect(3); - - var context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - local_sub_storage: { - type: "query", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "query", - sub_storage: { - type: "memory" - } - }, - query: {query: 'type: "foobar"'}, - conflict_handling: 2 - }); - - RSVP.all([ - context.jio.put("conflict", {"title": "foo", "type": "foobar"}), - context.jio.__storage._remote_sub_storage.put("conflict", - {"title": "bar"}) - ]) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - hash: "6799f3ea80e325b89f19589282a343c376c1f1af" - }); - }) - .then(function () { - return context.jio.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - title: "bar" - }); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - title: "bar" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote document creations: continue", function () { - stop(); - expect(4); - - var context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - conflict_handling: 3 - }); - - RSVP.all([ - context.jio.put("conflict", {"title": "foo"}), - context.jio.__storage._remote_sub_storage.put("conflict", - {"title": "bar"}) - ]) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get("conflict"); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); -// equal(error.message, "Cannot find document: conflict"); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - title: "bar" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote document creations: continue, remote post", - function () { - stop(); - expect(4); - - var context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - use_remote_post: 1, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - conflict_handling: 3 - }); - - RSVP.all([ - context.jio.put("conflict", {"title": "foo"}), - context.jio.__storage._remote_sub_storage.put("conflict", - {"title": "bar"}) - ]) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get("conflict"); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - // equal(error.message, "Cannot find document: conflict"); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - title: "bar" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote same document creations", function () { - stop(); - expect(1); - - var context = this; - - RSVP.all([ - context.jio.put("conflict", {"title": "foo"}), - context.jio.__storage._remote_sub_storage.put("conflict", - {"title": "foo"}) - ]) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get("conflict"); - }) - .then(function (result) { - deepEqual(result, { - hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("no modification", function () { - stop(); - expect(2); - - var id, - context = this; - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local document modification", function () { - stop(); - expect(2); - - var id, - context = this; - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return context.jio.put(id, {"title": "foo2"}); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo2" - }); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "9819187e39531fdc9bcfd40dbc6a7d3c78fe8dab" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - - test("local document modification: use remote post", function () { - stop(); - expect(2); - - var id, - context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - use_remote_post: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.__storage._remote_sub_storage.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return context.jio.put(id, {"title": "foo2"}); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo2" - }); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "9819187e39531fdc9bcfd40dbc6a7d3c78fe8dab" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local document modification not checked", function () { - stop(); - expect(3); - - var id, - context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - check_local_modification: false, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return context.jio.put(id, {"title": "foo2"}); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo2" - }); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("remote document modification", function () { - stop(); - expect(2); - - var id, - context = this; - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.put( - id, - {"title": "foo3"} - ); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo3" - }); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "4b1dde0f80ac38514771a9d25b5278e38f560e0f" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("remote document modification not checked", function () { - stop(); - expect(3); - - var id, - context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - check_remote_modification: false, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.put( - id, - {"title": "foo3"} - ); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo3" - }); - }) - .then(function () { - return context.jio.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote document modifications", function () { - stop(); - expect(4); - - var id, - context = this; - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.put(id, {"title": "foo4"}), - context.jio.__storage._remote_sub_storage.put(id, {"title": "foo5"}) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - ok(false); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Conflict on '" + id + "': " + - "{\"title\":\"foo4\"} !== {\"title\":\"foo5\"}"); - equal(error.status_code, 409); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" - }); - }) - .always(function () { - start(); - }); - }); - - test("local and remote document modifications: keep local", function () { - stop(); - expect(3); - - var id, - context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - conflict_handling: 1 - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.put(id, {"title": "foo4"}), - context.jio.__storage._remote_sub_storage.put(id, {"title": "foo5"}) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "6f700e813022233a785692585484c21cb5a412fd" - }); - }) - .then(function () { - return context.jio.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo4" - }); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo4" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote document modifications: keep remote", function () { - stop(); - expect(3); - - var id, - context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - conflict_handling: 2 - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.put(id, {"title": "foo4"}), - context.jio.__storage._remote_sub_storage.put(id, {"title": "foo5"}) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "7bea6f87fd1dda14e340e5b14836cc8578fd615f" - }); - }) - .then(function () { - return context.jio.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo5" - }); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo5" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote document modifications: continue", function () { - stop(); - expect(3); - - var id, - context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - conflict_handling: 3 - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.put(id, {"title": "foo4"}), - context.jio.__storage._remote_sub_storage.put(id, {"title": "foo5"}) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" - }); - }) - .then(function () { - return context.jio.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo4" - }); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo5" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote document same modifications", function () { - stop(); - expect(1); - - var id, - context = this; - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.put(id, {"title": "foo99"}), - context.jio.__storage._remote_sub_storage.put(id, {"title": "foo99"}) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "8ed3a474128b6e0c0c7d3dd51b1a06ebfbf6722f" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local document deletion", function () { - stop(); - expect(6); - - var id, - context = this; - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return context.jio.remove(id); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - ok(true, "Removal correctly synced"); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id) - .then(function () { - ok(false, "Signature should be deleted"); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); -// equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }); - }) - .always(function () { - start(); - }); - }); - - test("local document deletion not checked", function () { - stop(); - expect(6); - - var id, - context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - check_local_deletion: false, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return context.jio.remove(id); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - ok(true, "Removal correctly synced"); - }) - .then(function () { - return context.jio.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" - }); - }) - .always(function () { - start(); - }); - }); - - test("local document deletion with attachment", function () { - stop(); - expect(7); - - var id, - context = this, - blob = new Blob([big_string]); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return context.jio.remove(id); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage - .putAttachment(id, 'foo', blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - ok(true, "Removal correctly synced"); - }) - .then(function () { - return context.jio.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage - .getAttachment(id, 'foo', {format: 'text'}); - }) - .then(function (result) { - equal(result, big_string); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" - }); - }) - .always(function () { - start(); - }); - }); - - test("remote document deletion", function () { - stop(); - expect(6); - - var id, - context = this; - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.remove(id); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - ok(true, "Removal correctly synced"); - }) - .then(function () { - return context.jio.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id) - .then(function () { - ok(false, "Signature should be deleted"); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); -// equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }); - }) - .always(function () { - start(); - }); - }); - - test("remote document deletion not checked", function () { - stop(); - expect(6); - - var id, - context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - check_remote_deletion: false, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.remove(id); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - ok(true, "Removal correctly synced"); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" - }); - }) - .always(function () { - start(); - }); - }); - - test("remote document deletion with attachment", function () { - stop(); - expect(7); - - var id, - context = this, - blob = new Blob([big_string]); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.remove(id); - }) - .then(function () { - return context.jio.putAttachment(id, 'foo', blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - ok(true, "Removal correctly synced"); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo" - }); - }) - .then(function () { - return context.jio.getAttachment(id, 'foo', {format: 'text'}); - }) - .then(function (result) { - equal(result, big_string); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" - }); - }) - .always(function () { - start(); - }); - }); - - test("local and remote document deletions", function () { - stop(); - expect(8); - - var id, - context = this; - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.remove(id), - context.jio.__storage._remote_sub_storage.remove(id) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.get(id) - .then(function () { - ok(false, "Document should be locally deleted"); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id) - .then(function () { - ok(false, "Document should be remotely deleted"); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id) - .then(function () { - ok(false, "Signature should be deleted"); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); -// equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local deletion and remote modifications", function () { - stop(); - expect(2); - - var id, - context = this; - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.remove(id), - context.jio.__storage._remote_sub_storage.put(id, {"title": "foo99"}) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo99" - }); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "8ed3a474128b6e0c0c7d3dd51b1a06ebfbf6722f" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local deletion and remote modifications: keep local", function () { - stop(); - expect(9); - - var id, - context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 1, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.remove(id), - context.jio.__storage._remote_sub_storage.put(id, {"title": "foo99"}) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal( - error.message.indexOf( - "Cannot find attachment: " + - "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + - "jio_document/" - ), - 0 - ); - equal(error.status_code, 404); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local deletion and remote modifications: keep remote", function () { - stop(); - expect(3); - - var id, - context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 2, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.remove(id), - context.jio.__storage._remote_sub_storage.put(id, {"title": "foo99"}) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo99" - }); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo99" - }); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "8ed3a474128b6e0c0c7d3dd51b1a06ebfbf6722f" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local deletion and remote modifications: ignore", function () { - stop(); - expect(5); - - var id, - context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 3, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.remove(id), - context.jio.__storage._remote_sub_storage.put(id, {"title": "foo99"}) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo99" - }); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local modifications and remote deletion", function () { - stop(); - expect(2); - - var id, - context = this; - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.put(id, {"title": "foo99"}), - context.jio.__storage._remote_sub_storage.remove(id) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - title: "foo99" - }); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "8ed3a474128b6e0c0c7d3dd51b1a06ebfbf6722f" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local modifications and remote deletion: use remote post", function () { - stop(); - expect(13); - - var id, - context = this, - post_id; - - this.jio = jIO.createJIO({ - type: "replicate", - use_remote_post: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.__storage._remote_sub_storage.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.put(id, {"title": "foo99"}), - context.jio.__storage._remote_sub_storage.remove(id) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - // Old id deleted - .then(function () { - return context.jio.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal( - error.message.indexOf( - "Cannot find attachment: " + - "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + - "jio_document/" - ), - 0 - ); - equal(error.status_code, 404); - }) - // Check new id - .then(function () { - return context.jio.allDocs({include_docs: true}); - }) - .then(function (result) { - equal(result.data.total_rows, 1); - post_id = result.data.rows[0].id; - return context.jio.__storage._remote_sub_storage.get(post_id); - }) - .then(function (result) { - deepEqual(result, { - "title": "foo99" - }); - }) - .then(function () { - return context.jio.__storage._local_sub_storage.get(post_id); - }) - .then(function (result) { - deepEqual(result, { - "title": "foo99" - }); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(post_id); - }) - .then(function (result) { - deepEqual(result, { - hash: "8ed3a474128b6e0c0c7d3dd51b1a06ebfbf6722f" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - - test("local modif, remote del: remote post, no check loc mod", function () { - stop(); - expect(13); - - var id, - context = this, - post_id; - - this.jio = jIO.createJIO({ - type: "replicate", - use_remote_post: true, - check_local_modification: false, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.__storage._remote_sub_storage.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.put(id, {"title": "foo99"}), - context.jio.__storage._remote_sub_storage.remove(id) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - // Old id deleted - .then(function () { - return context.jio.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal( - error.message.indexOf( - "Cannot find attachment: " + - "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + - "jio_document/" - ), - 0 - ); - equal(error.status_code, 404); - }) - // Check new id - .then(function () { - return context.jio.allDocs({include_docs: true}); - }) - .then(function (result) { - equal(result.data.total_rows, 1); - post_id = result.data.rows[0].id; - return context.jio.__storage._remote_sub_storage.get(post_id); - }) - .then(function (result) { - deepEqual(result, { - "title": "foo99" - }); - }) - .then(function () { - return context.jio.__storage._local_sub_storage.get(post_id); - }) - .then(function (result) { - deepEqual(result, { - "title": "foo99" - }); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(post_id); - }) - .then(function (result) { - deepEqual(result, { - hash: "8ed3a474128b6e0c0c7d3dd51b1a06ebfbf6722f" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local modifications and remote deletion: keep local", function () { - stop(); - expect(3); - - var id, - context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 1, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.put(id, {"title": "foo99"}), - context.jio.__storage._remote_sub_storage.remove(id) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - // Old id deleted - .then(function () { - return context.jio.get(id); - }) - .then(function (result) { - deepEqual(result, { - "title": "foo99" - }); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - "title": "foo99" - }); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "8ed3a474128b6e0c0c7d3dd51b1a06ebfbf6722f" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local modif and remote del: keep local, use remote post", function () { - stop(); - expect(13); - - var id, - context = this, - post_id; - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 1, - use_remote_post: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.__storage._remote_sub_storage.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.put(id, {"title": "foo99"}), - context.jio.__storage._remote_sub_storage.remove(id) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - // Old id deleted - .then(function () { - return context.jio.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal( - error.message.indexOf( - "Cannot find attachment: " + - "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + - "jio_document/" - ), - 0 - ); - equal(error.status_code, 404); - }) - // Check new id - .then(function () { - return context.jio.allDocs({include_docs: true}); - }) - .then(function (result) { - equal(result.data.total_rows, 1); - post_id = result.data.rows[0].id; - return context.jio.__storage._remote_sub_storage.get(post_id); - }) - .then(function (result) { - deepEqual(result, { - "title": "foo99" - }); - }) - .then(function () { - return context.jio.__storage._local_sub_storage.get(post_id); - }) - .then(function (result) { - deepEqual(result, { - "title": "foo99" - }); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(post_id); - }) - .then(function (result) { - deepEqual(result, { - hash: "8ed3a474128b6e0c0c7d3dd51b1a06ebfbf6722f" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local modifications and remote deletion: keep remote", function () { - stop(); - expect(9); - - var id, - context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 2, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.put(id, {"title": "foo99"}), - context.jio.__storage._remote_sub_storage.remove(id) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - // id deleted - .then(function () { - return context.jio.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal( - error.message.indexOf( - "Cannot find attachment: " + - "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + - "jio_document/" - ), - 0 - ); - equal(error.status_code, 404); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local modif and remote del: keep remote, not check modif", function () { - stop(); - expect(9); - - var id, - context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 2, - check_local_modification: false, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.put(id, {"title": "foo99"}), - context.jio.__storage._remote_sub_storage.remove(id) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - // id deleted - .then(function () { - return context.jio.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal( - error.message.indexOf( - "Cannot find attachment: " + - "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + - "jio_document/" - ), - 0 - ); - equal(error.status_code, 404); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local modifications and remote deletion: ignore", function () { - stop(); - expect(5); - - var id, - context = this; - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 3, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.put(id, {"title": "foo99"}), - context.jio.__storage._remote_sub_storage.remove(id) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - // id deleted - .then(function () { - return context.jio.get(id); - }) - .then(function (result) { - deepEqual(result, { - "title": "foo99" - }); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + id); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.get(id); - }) - .then(function (result) { - deepEqual(result, { - hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("signature document is not synced", function () { - stop(); - expect(6); - - var context = this; - - // Uses sessionstorage substorage, so that signature are stored - // in the same local sub storage - this.jio = jIO.createJIO({ - type: "replicate", - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "document", - document_id: "/", - sub_storage: { - type: "local", - sessiononly: true - } - } - }, - remote_sub_storage: { - type: "memory" - } - }); - - context.jio.post({"title": "foo"}) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get( - context.jio.__storage._signature_hash - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + - "_replicate_8662994dcefb3a2ceec61e86953efda8ec6520d6"); - equal(error.status_code, 404); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.get( - context.jio.__storage._signature_hash - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Cannot find document: " + - "_replicate_8662994dcefb3a2ceec61e86953efda8ec6520d6"); - equal(error.status_code, 404); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("substorages are repaired too", function () { - stop(); - expect(8); - - var context = this, - first_call = true, - options = {foo: "bar"}; - - function Storage200CheckRepair() { - return this; - } - Storage200CheckRepair.prototype.get = function () { - ok(true, "get 200 check repair called"); - return {}; - }; - Storage200CheckRepair.prototype.hasCapacity = function () { - return true; - }; - Storage200CheckRepair.prototype.buildQuery = function () { - ok(true, "buildQuery 200 check repair called"); - return []; - }; - Storage200CheckRepair.prototype.allAttachments = function () { - ok(true, "allAttachments 200 check repair called"); - return {}; - }; - Storage200CheckRepair.prototype.repair = function (kw) { - if (first_call) { - deepEqual( - this, - context.jio.__storage._local_sub_storage.__storage, - "local substorage repair" - ); - first_call = false; - } else { - deepEqual( - this, - context.jio.__storage._remote_sub_storage.__storage, - "remote substorage repair" - ); - } - deepEqual(kw, options, "substorage repair parameters provided"); - }; - - jIO.addStorage( - 'replicatestorage200chechrepair', - Storage200CheckRepair - ); - - - this.jio = jIO.createJIO({ - type: "replicate", - local_sub_storage: { - type: "replicatestorage200chechrepair" - }, - remote_sub_storage: { - type: "replicatestorage200chechrepair" - } - }); - - context.jio.repair(options) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("sync all documents by default", function () { - stop(); - expect(4); - - var context = this; - - function Storage200DefaultQuery() { - return this; - } - Storage200DefaultQuery.prototype.get = function () { - ok(true, "get 200 check repair called"); - return {}; - }; - Storage200DefaultQuery.prototype.hasCapacity = function () { - return true; - }; - Storage200DefaultQuery.prototype.buildQuery = function (query) { - deepEqual(query, {}); - return []; - }; - Storage200DefaultQuery.prototype.allAttachments = function () { - ok(true, "allAttachments 200 check repair called"); - return {}; - }; - jIO.addStorage( - 'replicatestorage200defaultquery', - Storage200DefaultQuery - ); - - this.jio = jIO.createJIO({ - type: "replicate", - local_sub_storage: { - type: "replicatestorage200defaultquery" - }, - remote_sub_storage: { - type: "replicatestorage200defaultquery" - } - }); - - return context.jio.repair() - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("sync can be restricted to some documents", function () { - stop(); - expect(4); - - var context = this, - query = {query: 'portal_type: "Foo"', limit: [0, 1234567890]}; - - function Storage200CustomQuery() { - return this; - } - Storage200CustomQuery.prototype.get = function () { - ok(true, "get 200 check repair called"); - return {}; - }; - Storage200CustomQuery.prototype.hasCapacity = function () { - return true; - }; - Storage200CustomQuery.prototype.buildQuery = function (options) { - deepEqual(options, query); - return []; - }; - Storage200CustomQuery.prototype.allAttachments = function () { - ok(true, "allAttachments 200 check repair called"); - return {}; - }; - jIO.addStorage( - 'replicatestorage200customquery', - Storage200CustomQuery - ); - - this.jio = jIO.createJIO({ - type: "replicate", - local_sub_storage: { - type: "replicatestorage200customquery" - }, - remote_sub_storage: { - type: "replicatestorage200customquery" - }, - query: {query: 'portal_type: "Foo"', limit: [0, 1234567890]} - }); - - return context.jio.repair() - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("use 1 parallel operation", function () { - stop(); - expect(16); - - var context = this, - order_number = 0, - expected_order_list = [ - 'start get 0', - 'stop get 0', - 'start put 0', - 'stop put 0', - 'start get 1', - 'stop get 1', - 'start put 1', - 'stop put 1', - 'start get 2', - 'stop get 2', - 'start put 2', - 'stop put 2', - 'start get 3', - 'stop get 3', - 'start put 3', - 'stop put 3' - ]; - - function assertExecutionOrder(text) { - equal(text, expected_order_list[order_number], - expected_order_list[order_number]); - order_number += 1; - } - - function StorageOneParallelOperation() { - this._sub_storage = jIO.createJIO({type: "memory"}); - return this; - } - - StorageOneParallelOperation.prototype.put = function (id, doc) { - assertExecutionOrder('start put ' + id); - var storage = this; - return storage._sub_storage.put(id, doc) - .push(function (result) { - assertExecutionOrder('stop put ' + id); - return result; - }); - }; - - StorageOneParallelOperation.prototype.get = function (id) { - assertExecutionOrder('start get ' + id); - var storage = this; - return storage._sub_storage.get(id) - .push(undefined, function (error) { - assertExecutionOrder('stop get ' + id); - throw error; - }); - }; - StorageOneParallelOperation.prototype.buildQuery = function () { - return this._sub_storage.buildQuery.apply(this._sub_storage, arguments); - }; - - StorageOneParallelOperation.prototype.hasCapacity = function () { - return this._sub_storage.hasCapacity.apply(this._sub_storage, arguments); - }; - - jIO.addStorage( - 'one_parallel', - StorageOneParallelOperation - ); - - this.jio = jIO.createJIO({ - type: "replicate", - local_sub_storage: { - type: "memory" - }, - remote_sub_storage: { - type: "one_parallel" - } - }); - - return RSVP.all([ - context.jio.put("0", {"title": "foo"}), - context.jio.put("1", {"title": "foo1"}), - context.jio.put("2", {"title": "foo2"}), - context.jio.put("3", {"title": "foo3"}) - ]) - .then(function () { - return context.jio.repair(); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("use 2 parallel operations", function () { - stop(); - expect(16); - - var context = this, - order_number = 0, - expected_order_list = [ - 'start get 0', - - 'start get 1', - 'stop get 1', - 'start put 1', - 'stop put 1', - 'start get 2', - 'stop get 2', - 'start put 2', - - 'stop get 0', - 'start put 0', - 'stop put 0', - 'start get 3', - 'stop get 3', - 'start put 3', - 'stop put 3', - - 'stop put 2' - ], - defer0, - defer2; - - function assertExecutionOrder(text) { - equal(text, expected_order_list[order_number], - expected_order_list[order_number]); - order_number += 1; - } - - function StorageTwoParallelOperation() { - this._sub_storage = jIO.createJIO({type: "memory"}); - return this; - } - - StorageTwoParallelOperation.prototype.put = function (id, doc) { - var storage = this; - assertExecutionOrder('start put ' + id); - return new RSVP.Queue() - .push(function () { - if (id === "2") { - defer0.resolve(); - defer2 = RSVP.defer(); - return defer2.promise; - } - }) - .push(function () { - return storage._sub_storage.put(id, doc); - }) - .push(function (result) { - if (id === "3") { - defer2.resolve(); - } - assertExecutionOrder('stop put ' + id); - return result; - }); - }; - - StorageTwoParallelOperation.prototype.get = function (id) { - var storage = this; - assertExecutionOrder('start get ' + id); - return new RSVP.Queue() - .push(function () { - if (id === "0") { - defer0 = RSVP.defer(); - return defer0.promise; - } - }) - .push(function () { - return storage._sub_storage.get(id); - }) - .push(undefined, function (error) { - assertExecutionOrder('stop get ' + id); - throw error; - }); - }; - StorageTwoParallelOperation.prototype.buildQuery = function () { - return this._sub_storage.buildQuery.apply(this._sub_storage, arguments); - }; - - StorageTwoParallelOperation.prototype.hasCapacity = function () { - return this._sub_storage.hasCapacity.apply(this._sub_storage, arguments); - }; - - jIO.addStorage( - 'two_parallel', - StorageTwoParallelOperation - ); - - this.jio = jIO.createJIO({ - type: "replicate", - parallel_operation_amount: 2, - local_sub_storage: { - type: "memory" - }, - remote_sub_storage: { - type: "two_parallel" - } - }); - - return RSVP.all([ - context.jio.put("0", {"title": "foo"}), - context.jio.put("1", {"title": "foo1"}), - context.jio.put("2", {"title": "foo2"}), - context.jio.put("3", {"title": "foo3"}) - ]) - .then(function () { - return context.jio.repair(); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - - test("use 4 parallel operations", function () { - stop(); - expect(16); - - var context = this, - order_number = 0, - expected_order_list = [ - 'start get 0', - 'start get 1', - 'start get 2', - 'start get 3', - 'stop get 0', - 'stop get 1', - 'stop get 2', - 'stop get 3', - 'start put 0', - 'start put 1', - 'start put 2', - 'start put 3', - 'stop put 0', - 'stop put 1', - 'stop put 2', - 'stop put 3' - ]; - - function assertExecutionOrder(text) { - equal(text, expected_order_list[order_number], - expected_order_list[order_number]); - order_number += 1; - } - - function StorageFourParallelOperation() { - this._sub_storage = jIO.createJIO({type: "memory"}); - return this; - } - - StorageFourParallelOperation.prototype.put = function (id, doc) { - assertExecutionOrder('start put ' + id); - var storage = this; - return storage._sub_storage.put(id, doc) - .push(function (result) { - assertExecutionOrder('stop put ' + id); - return result; - }); - }; - - StorageFourParallelOperation.prototype.get = function (id) { - assertExecutionOrder('start get ' + id); - var storage = this; - return storage._sub_storage.get(id) - .push(undefined, function (error) { - assertExecutionOrder('stop get ' + id); - throw error; - }); - }; - StorageFourParallelOperation.prototype.buildQuery = function () { - return this._sub_storage.buildQuery.apply(this._sub_storage, arguments); - }; - - StorageFourParallelOperation.prototype.hasCapacity = function () { - return this._sub_storage.hasCapacity.apply(this._sub_storage, arguments); - }; - - jIO.addStorage( - 'four_parallel', - StorageFourParallelOperation - ); - - this.jio = jIO.createJIO({ - type: "replicate", - parallel_operation_amount: 4, - local_sub_storage: { - type: "memory" - }, - remote_sub_storage: { - type: "four_parallel" - } - }); - - return RSVP.all([ - context.jio.put("0", {"title": "foo"}), - context.jio.put("1", {"title": "foo1"}), - context.jio.put("2", {"title": "foo2"}), - context.jio.put("3", {"title": "foo3"}) - ]) - .then(function () { - return context.jio.repair(); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - ///////////////////////////////////////////////////////////////// - // attachment replication - ///////////////////////////////////////////////////////////////// - module("replicateStorage.repair.attachment", { - setup: function () { - // Uses memory substorage, so that it is flushed after each run - this.jio = jIO.createJIO({ - type: "replicate", - check_local_attachment_creation: true, - check_local_attachment_modification: true, - check_local_attachment_deletion: true, - check_remote_attachment_creation: true, - check_remote_attachment_modification: true, - check_remote_attachment_deletion: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - } - }); - - test("local attachment creation", function () { - stop(); - expect(2); - - var id, - context = this, - blob = new Blob([big_string]); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "cd762363c1c11ecb48611583520bba111f0034d4" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local attachment creation, local document creation not checked", - function () { - stop(); - expect(6); - - var id, - context = this, - blob = new Blob([big_string]); - - this.jio = jIO.createJIO({ - type: "replicate", - check_local_creation: false, - check_local_attachment_creation: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - var error_message = "Cannot find attachment: " + - "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + - "jio_attachment/"; - equal( - error.message.substring(0, error_message.length), - error_message - ); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local attachment creation not checked", function () { - stop(); - expect(6); - - var id, - context = this, - blob = new Blob([big_string]); - - this.jio = jIO.createJIO({ - type: "replicate", - check_local_attachment_creation: false, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - var error_message = "Cannot find attachment: " + - "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + - "jio_attachment/"; - equal( - error.message.substring(0, error_message.length), - error_message - ); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local attachment creation, local document creation and use remote post", - function () { - stop(); - expect(4); - - var id, - context = this, - post_id, - blob = new Blob([big_string]); - - this.jio = jIO.createJIO({ - type: "replicate", - use_remote_post: true, - check_local_attachment_creation: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - // Another document should have been created - .then(function () { - return context.jio.__storage._remote_sub_storage.allDocs(); - }) - .then(function (result) { - equal(result.data.total_rows, 1); - post_id = result.data.rows[0].id; - return context.jio.getAttachment( - post_id, - "foo", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string); - return context.jio.__storage._remote_sub_storage.getAttachment( - post_id, - "foo", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string); - return context.jio.__storage._signature_sub_storage - .getAttachment(post_id, "foo", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "cd762363c1c11ecb48611583520bba111f0034d4" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("remote attachment creation", function () { - stop(); - expect(2); - - var id, - context = this, - blob = new Blob([big_string]); - - context.jio.__storage._remote_sub_storage.post({"title": "bar"}) - .then(function (result) { - id = result; - return context.jio.__storage._remote_sub_storage - .putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "cd762363c1c11ecb48611583520bba111f0034d4" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("remote attachment creation, remote document creation not checked", - function () { - stop(); - expect(6); - - var id, - context = this, - blob = new Blob([big_string]); - - this.jio = jIO.createJIO({ - type: "replicate", - check_remote_creation: false, - check_local_attachment_creation: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.__storage._remote_sub_storage.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.__storage._remote_sub_storage - .putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - var error_message = "Cannot find attachment: " + - "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + - "jio_attachment/"; - equal( - error.message.substring(0, error_message.length), - error_message - ); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - - test("remote attachment creation not checked", function () { - stop(); - expect(6); - - var id, - context = this, - blob = new Blob([big_string]); - - this.jio = jIO.createJIO({ - type: "replicate", - check_remote_attachment_creation: false, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.__storage._remote_sub_storage.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.__storage._remote_sub_storage - .putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - var error_message = "Cannot find attachment: " + - "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + - "jio_attachment/"; - equal( - error.message.substring(0, error_message.length), - error_message - ); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote attachment creations", function () { - stop(); - expect(5); - - var context = this, - id = 'foobar', - blob = new Blob([big_string]), - blob2 = new Blob([big_string + "a"]); - - context.jio.put(id, {"title": "foo"}) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return RSVP.all([ - context.jio.putAttachment(id, "conflict", blob), - context.jio.__storage._remote_sub_storage.putAttachment(id, - "conflict", - blob2) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - ok(false); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Conflict on 'foobar' with attachment 'conflict'"); - equal(error.status_code, 409); - }) - .then(function () { - return context.jio.__storage._signature_sub_storage.getAttachment( - id, - "conflict" - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); -// equal(error.message, "Cannot find document: conflict"); - equal(error.status_code, 404); - }) - .always(function () { - start(); - }); - }); - - test("local and remote attachment creations: keep local", function () { - stop(); - expect(3); - - var context = this, - id = 'foobar', - blob = new Blob([big_string]), - blob2 = new Blob([big_string + "a"]); - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 1, - check_local_attachment_creation: true, - check_remote_attachment_creation: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.put(id, {"title": "foo"}) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return RSVP.all([ - context.jio.putAttachment(id, "conflict", blob), - context.jio.__storage._remote_sub_storage.putAttachment(id, - "conflict", - blob2) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "conflict", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "cd762363c1c11ecb48611583520bba111f0034d4" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote attachment creations: keep local, " + - "local not matching allAttachments", function () { - stop(); - expect(3); - - var context = this, - id = 'foobar', - blob = new Blob([big_string]), - blob2 = new Blob([big_string + "a"]); - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 1, - check_local_attachment_creation: true, - check_remote_attachment_creation: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "signaturestorageallattachments", - sub_storage: { - type: "memory" - } - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.put(id, {"title": "foo"}) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return RSVP.all([ - context.jio.putAttachment(id, "conflict", blob), - context.jio.__storage._remote_sub_storage.putAttachment(id, - "conflict", - blob2) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "conflict", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "cd762363c1c11ecb48611583520bba111f0034d4" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote attachment creations: keep local, " + - "remote not matching allAttachments", function () { - stop(); - expect(3); - - var context = this, - id = 'foobar', - blob = new Blob([big_string]), - blob2 = new Blob([big_string + "a"]); - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 1, - check_local_attachment_creation: true, - check_remote_attachment_creation: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "signaturestorageallattachments", - sub_storage: { - type: "memory" - } - } - } - }); - - context.jio.put(id, {"title": "foo"}) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return RSVP.all([ - context.jio.putAttachment(id, "conflict", blob), - context.jio.__storage._remote_sub_storage.putAttachment(id, - "conflict", - blob2) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "conflict", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "cd762363c1c11ecb48611583520bba111f0034d4" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote attachment creations: keep remote", function () { - stop(); - expect(3); - - var context = this, - id = 'foobar', - blob = new Blob([big_string]), - blob2 = new Blob([big_string + "a"]); - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 2, - check_local_attachment_creation: true, - check_remote_attachment_creation: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.put(id, {"title": "foo"}) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return RSVP.all([ - context.jio.putAttachment(id, "conflict", blob), - context.jio.__storage._remote_sub_storage.putAttachment(id, - "conflict", - blob2) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "a"); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "a"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "conflict", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "65cf771ad2cc0b1e8f89361e3b7bec2365b3ad24" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote attachment creations: keep remote, " + - "local not matching allAttachments", function () { - stop(); - expect(3); - - var context = this, - id = 'foobar', - blob = new Blob([big_string]), - blob2 = new Blob([big_string + "a"]); - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 2, - check_local_attachment_creation: true, - check_remote_attachment_creation: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "signaturestorageallattachments", - sub_storage: { - type: "memory" - } - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.put(id, {"title": "foo"}) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return RSVP.all([ - context.jio.putAttachment(id, "conflict", blob), - context.jio.__storage._remote_sub_storage.putAttachment(id, - "conflict", - blob2) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "a"); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "a"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "conflict", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "65cf771ad2cc0b1e8f89361e3b7bec2365b3ad24" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote attachment creations: keep remote, " + - "remote not matching allAttachments", function () { - stop(); - expect(3); - - var context = this, - id = 'foobar', - blob = new Blob([big_string]), - blob2 = new Blob([big_string + "a"]); - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 2, - check_local_attachment_creation: true, - check_remote_attachment_creation: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "signaturestorageallattachments", - sub_storage: { - type: "memory" - } - } - } - }); - - context.jio.put(id, {"title": "foo"}) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return RSVP.all([ - context.jio.putAttachment(id, "conflict", blob), - context.jio.__storage._remote_sub_storage.putAttachment(id, - "conflict", - blob2) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "a"); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "a"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "conflict", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "65cf771ad2cc0b1e8f89361e3b7bec2365b3ad24" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote attachment creations: continue", function () { - stop(); - expect(4); - - var context = this, - id = 'foobar', - blob = new Blob([big_string]), - blob2 = new Blob([big_string + "a"]); - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 3, - check_local_attachment_creation: true, - check_remote_attachment_creation: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.put(id, {"title": "foo"}) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return RSVP.all([ - context.jio.putAttachment(id, "conflict", blob), - context.jio.__storage._remote_sub_storage.putAttachment(id, - "conflict", - blob2) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "a"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "conflict", {format: "json"}); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); -// equal(error.message, "Cannot find document: conflict"); - equal(error.status_code, 404); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote same attachment creations", function () { - stop(); - expect(3); - - var context = this, - id = 'foobar', - blob = new Blob([big_string]), - blob2 = new Blob([big_string]); - - context.jio.put(id, {"title": "foo"}) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return RSVP.all([ - context.jio.putAttachment(id, "conflict", blob), - context.jio.__storage._remote_sub_storage.putAttachment(id, - "conflict", - blob2) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "conflict", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "cd762363c1c11ecb48611583520bba111f0034d4" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("no attachment modification", function () { - stop(); - expect(3); - - var context = this, - id = 'foobar', - blob = new Blob([big_string]); - - context.jio.put(id, {"title": "foo"}) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return context.jio.putAttachment(id, "conflict", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "conflict", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "cd762363c1c11ecb48611583520bba111f0034d4" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local attachment modification", function () { - stop(); - expect(3); - - var context = this, - id = 'foobar', - blob = new Blob([big_string]), - blob2 = new Blob([big_string + "a"]); - - context.jio.put(id, {"title": "foo"}) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return context.jio.putAttachment(id, "conflict", blob); - }) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return context.jio.putAttachment(id, "conflict", blob2); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "a"); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "a"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "conflict", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "65cf771ad2cc0b1e8f89361e3b7bec2365b3ad24" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local attachment modification not checked", function () { - stop(); - expect(3); - - var context = this, - id = 'foobar', - blob = new Blob([big_string]), - blob2 = new Blob([big_string + "a"]); - - this.jio = jIO.createJIO({ - type: "replicate", - check_local_attachment_creation: true, - check_local_attachment_modification: false, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.put(id, {"title": "foo"}) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return context.jio.putAttachment(id, "conflict", blob); - }) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return context.jio.putAttachment(id, "conflict", blob2); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "a"); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "conflict", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "cd762363c1c11ecb48611583520bba111f0034d4" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("remote attachment modification", function () { - stop(); - expect(3); - - var context = this, - id = 'foobar', - blob = new Blob([big_string]), - blob2 = new Blob([big_string + "a"]); - - context.jio.put(id, {"title": "foo"}) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return context.jio.putAttachment(id, "conflict", blob); - }) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return context.jio.__storage._remote_sub_storage - .putAttachment(id, "conflict", blob2); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "a"); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "a"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "conflict", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "65cf771ad2cc0b1e8f89361e3b7bec2365b3ad24" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("remote attachment modification not checked", function () { - stop(); - expect(3); - - var context = this, - id = 'foobar', - blob = new Blob([big_string]), - blob2 = new Blob([big_string + "a"]); - - this.jio = jIO.createJIO({ - type: "replicate", - check_local_attachment_creation: true, - check_remote_attachment_modification: false, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.put(id, {"title": "foo"}) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return context.jio.putAttachment(id, "conflict", blob); - }) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return context.jio.__storage._remote_sub_storage - .putAttachment(id, "conflict", blob2); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "a"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "conflict", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "cd762363c1c11ecb48611583520bba111f0034d4" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote attachment modifications", function () { - stop(); - expect(6); - - var context = this, - id = 'foobar', - blob = new Blob([big_string]), - blob2 = new Blob([big_string + "a"]), - blob3 = new Blob([big_string + "b"]); - - context.jio.put(id, {"title": "foo"}) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return context.jio.putAttachment(id, "conflict", blob); - }) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return RSVP.all([ - context.jio.putAttachment(id, "conflict", blob2), - context.jio.__storage._remote_sub_storage - .putAttachment(id, "conflict", blob3) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - ok(false); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.message, "Conflict on 'foobar' " + - "with attachment 'conflict'"); - equal(error.status_code, 409); - }) - .then(function () { - return context.jio.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "a"); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "b"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "conflict", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "cd762363c1c11ecb48611583520bba111f0034d4" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote attachment modifications: keep local", function () { - stop(); - expect(3); - - var context = this, - id = 'foobar', - blob = new Blob([big_string]), - blob2 = new Blob([big_string + "a"]), - blob3 = new Blob([big_string + "b"]); - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 1, - check_local_attachment_creation: true, - check_remote_attachment_creation: true, - check_local_attachment_modification: true, - check_remote_attachment_modification: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.put(id, {"title": "foo"}) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return context.jio.putAttachment(id, "conflict", blob); - }) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return RSVP.all([ - context.jio.putAttachment(id, "conflict", blob2), - context.jio.__storage._remote_sub_storage - .putAttachment(id, "conflict", blob3) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "a"); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "a"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "conflict", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "65cf771ad2cc0b1e8f89361e3b7bec2365b3ad24" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote attachment modifications: keep remote", function () { - stop(); - expect(3); - - var context = this, - id = 'foobar', - blob = new Blob([big_string]), - blob2 = new Blob([big_string + "a"]), - blob3 = new Blob([big_string + "b"]); - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 2, - check_local_attachment_creation: true, - check_remote_attachment_creation: true, - check_local_attachment_modification: true, - check_remote_attachment_modification: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.put(id, {"title": "foo"}) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return context.jio.putAttachment(id, "conflict", blob); - }) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return RSVP.all([ - context.jio.putAttachment(id, "conflict", blob2), - context.jio.__storage._remote_sub_storage - .putAttachment(id, "conflict", blob3) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "b"); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "b"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "conflict", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "9a73ce4f16b7fa5d2b4d8f723a754fef048fb9f8" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote attachment modifications: continue", function () { - stop(); - expect(3); - - var context = this, - id = 'foobar', - blob = new Blob([big_string]), - blob2 = new Blob([big_string + "a"]), - blob3 = new Blob([big_string + "b"]); - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 3, - check_local_attachment_creation: true, - check_remote_attachment_creation: true, - check_local_attachment_modification: true, - check_remote_attachment_modification: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.put(id, {"title": "foo"}) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return context.jio.putAttachment(id, "conflict", blob); - }) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return RSVP.all([ - context.jio.putAttachment(id, "conflict", blob2), - context.jio.__storage._remote_sub_storage - .putAttachment(id, "conflict", blob3) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "a"); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "b"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "conflict", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "cd762363c1c11ecb48611583520bba111f0034d4" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote attachment same modifications", function () { - stop(); - expect(3); - - var context = this, - id = 'foobar', - blob = new Blob([big_string]), - blob2 = new Blob([big_string + "a"]); - - context.jio.put(id, {"title": "foo"}) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return context.jio.putAttachment(id, "conflict", blob); - }) - .push(function () { - return context.jio.repair(); - }) - .push(function () { - return RSVP.all([ - context.jio.putAttachment(id, "conflict", blob2), - context.jio.__storage._remote_sub_storage - .putAttachment(id, "conflict", blob2) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "a"); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "conflict", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string + "a"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "conflict", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "65cf771ad2cc0b1e8f89361e3b7bec2365b3ad24" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local attachment deletion", function () { - stop(); - expect(9); - - var id, - context = this, - blob = new Blob([big_string]); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.removeAttachment(id, "foo"); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - var error_message = "Cannot find attachment: " + - "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + - "jio_attachment/"; - equal( - error.message.substring(0, error_message.length), - error_message - ); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local attachment deletion not checked", function () { - - stop(); - expect(5); - - var id, - context = this, - blob = new Blob([big_string]); - - this.jio = jIO.createJIO({ - type: "replicate", - check_local_attachment_creation: true, - check_local_attachment_deletion: false, - check_local_attachment_modification: true, - check_remote_attachment_creation: true, - check_remote_attachment_deletion: true, - check_remote_attachment_modification: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.removeAttachment(id, "foo"); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "cd762363c1c11ecb48611583520bba111f0034d4" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("remote attachment deletion", function () { - stop(); - expect(9); - - var id, - context = this, - blob = new Blob([big_string]); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage - .removeAttachment(id, "foo"); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - var error_message = "Cannot find attachment: " + - "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + - "jio_attachment/"; - equal( - error.message.substring(0, error_message.length), - error_message - ); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("remote attachment deletion not checked", function () { - - stop(); - expect(5); - - var id, - context = this, - blob = new Blob([big_string]); - - this.jio = jIO.createJIO({ - type: "replicate", - check_local_attachment_creation: true, - check_local_attachment_deletion: true, - check_local_attachment_modification: true, - check_remote_attachment_creation: true, - check_remote_attachment_deletion: false, - check_remote_attachment_modification: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage - .removeAttachment(id, "foo"); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .then(function (result) { - equal(result, big_string); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "cd762363c1c11ecb48611583520bba111f0034d4" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local and remote attachment deletions", function () { - stop(); - expect(9); - - var id, - context = this, - blob = new Blob([big_string]); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.removeAttachment(id, "foo"), - context.jio.__storage._remote_sub_storage - .removeAttachment(id, "foo") - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - var error_message = "Cannot find attachment: " + - "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + - "jio_attachment/"; - equal( - error.message.substring(0, error_message.length), - error_message - ); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local deletion and remote modifications", function () { - stop(); - expect(3); - - var id, - context = this, - blob = new Blob([big_string + "a"]), - blob2 = new Blob([big_string]); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.removeAttachment(id, "foo"), - context.jio.__storage._remote_sub_storage - .putAttachment(id, "foo", blob2) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .then(function (result) { - equal(true, big_string === result); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .then(function (result) { - equal(true, big_string === result); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "cd762363c1c11ecb48611583520bba111f0034d4" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local deletion and remote modifications: keep local", function () { - stop(); - expect(9); - - var id, - context = this, - blob = new Blob([big_string + "a"]), - blob2 = new Blob([big_string]); - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 1, - check_local_attachment_creation: true, - check_local_attachment_deletion: true, - check_local_attachment_modification: true, - check_remote_attachment_creation: true, - check_remote_attachment_deletion: true, - check_remote_attachment_modification: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.removeAttachment(id, "foo"), - context.jio.__storage._remote_sub_storage - .putAttachment(id, "foo", blob2) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - var error_message = "Cannot find attachment: " + - "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + - "jio_attachment/"; - equal( - error.message.substring(0, error_message.length), - error_message - ); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local deletion and remote modifications: keep local, dont check local", - function () { - stop(); - expect(9); - - var id, - context = this, - blob = new Blob([big_string + "a"]), - blob2 = new Blob([big_string]); - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 1, - check_local_attachment_creation: true, - check_local_attachment_deletion: false, - check_local_attachment_modification: true, - check_remote_attachment_creation: true, - check_remote_attachment_deletion: true, - check_remote_attachment_modification: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.removeAttachment(id, "foo"), - context.jio.__storage._remote_sub_storage - .putAttachment(id, "foo", blob2) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - var error_message = "Cannot find attachment: " + - "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + - "jio_attachment/"; - equal( - error.message.substring(0, error_message.length), - error_message - ); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local deletion and remote modifications: keep remote", function () { - stop(); - expect(3); - - var id, - context = this, - blob = new Blob([big_string + "a"]), - blob2 = new Blob([big_string]); - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 2, - check_local_attachment_creation: true, - check_local_attachment_deletion: true, - check_local_attachment_modification: true, - check_remote_attachment_creation: true, - check_remote_attachment_deletion: true, - check_remote_attachment_modification: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.removeAttachment(id, "foo"), - context.jio.__storage._remote_sub_storage - .putAttachment(id, "foo", blob2) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .then(function (result) { - equal(true, big_string === result); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .then(function (result) { - equal(true, big_string === result); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "cd762363c1c11ecb48611583520bba111f0034d4" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local deletion and remote modifications: ignore", function () { - stop(); - expect(5); - - var id, - context = this, - blob = new Blob([big_string + "a"]), - blob2 = new Blob([big_string]); - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 3, - check_local_attachment_creation: true, - check_local_attachment_deletion: true, - check_local_attachment_modification: true, - check_remote_attachment_creation: true, - check_remote_attachment_deletion: true, - check_remote_attachment_modification: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.removeAttachment(id, "foo"), - context.jio.__storage._remote_sub_storage - .putAttachment(id, "foo", blob2) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .then(function (result) { - equal(true, big_string === result); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "65cf771ad2cc0b1e8f89361e3b7bec2365b3ad24" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local modifications and remote deletion", function () { - stop(); - expect(3); - - var id, - context = this, - blob = new Blob([big_string + "a"]), - blob2 = new Blob([big_string]); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.putAttachment(id, "foo", blob2), - context.jio.__storage._remote_sub_storage - .removeAttachment(id, "foo") - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .then(function (result) { - equal(true, big_string === result); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .then(function (result) { - equal(true, big_string === result); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "cd762363c1c11ecb48611583520bba111f0034d4" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local modifications and remote deletion: keep remote", function () { - stop(); - expect(9); - - var id, - context = this, - blob = new Blob([big_string + "a"]), - blob2 = new Blob([big_string]); - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 2, - check_local_attachment_creation: true, - check_local_attachment_deletion: true, - check_local_attachment_modification: true, - check_remote_attachment_creation: true, - check_remote_attachment_deletion: true, - check_remote_attachment_modification: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.putAttachment(id, "foo", blob2), - context.jio.__storage._remote_sub_storage.removeAttachment(id, "foo") - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - var error_message = "Cannot find attachment: " + - "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + - "jio_attachment/"; - equal( - error.message.substring(0, error_message.length), - error_message - ); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local modifications and remote deletion: keep local", function () { - stop(); - expect(3); - - var id, - context = this, - blob = new Blob([big_string + "a"]), - blob2 = new Blob([big_string]); - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 1, - check_local_attachment_creation: true, - check_local_attachment_deletion: true, - check_local_attachment_modification: true, - check_remote_attachment_creation: true, - check_remote_attachment_deletion: true, - check_remote_attachment_modification: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.putAttachment(id, "foo", blob2), - context.jio.__storage._remote_sub_storage.removeAttachment(id, "foo") - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .then(function (result) { - equal(true, big_string === result); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .then(function (result) { - equal(true, big_string === result); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "cd762363c1c11ecb48611583520bba111f0034d4" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local modif and remote del: keep remote, not check modif", function () { - stop(); - expect(9); - - var id, - context = this, - blob = new Blob([big_string + "a"]), - blob2 = new Blob([big_string]); - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 2, - check_local_attachment_creation: true, - check_local_attachment_deletion: true, - check_local_attachment_modification: false, - check_remote_attachment_creation: true, - check_remote_attachment_deletion: true, - check_remote_attachment_modification: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.putAttachment(id, "foo", blob2), - context.jio.__storage._remote_sub_storage.removeAttachment(id, "foo") - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - var error_message = "Cannot find attachment: " + - "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + - "jio_attachment/"; - equal( - error.message.substring(0, error_message.length), - error_message - ); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("local modifications and remote deletion: ignore", function () { - stop(); - expect(5); - - var id, - context = this, - blob = new Blob([big_string + "a"]), - blob2 = new Blob([big_string]); - - this.jio = jIO.createJIO({ - type: "replicate", - conflict_handling: 3, - check_local_attachment_creation: true, - check_local_attachment_deletion: true, - check_local_attachment_modification: true, - check_remote_attachment_creation: true, - check_remote_attachment_deletion: true, - check_remote_attachment_modification: true, - local_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - }, - remote_sub_storage: { - type: "uuid", - sub_storage: { - type: "memory" - } - } - }); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return RSVP.all([ - context.jio.putAttachment(id, "foo", blob2), - context.jio.__storage._remote_sub_storage.removeAttachment(id, "foo") - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .then(function (result) { - equal(true, big_string === result); - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .then(function (result) { - deepEqual(result, { - hash: "65cf771ad2cc0b1e8f89361e3b7bec2365b3ad24" - }); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - ///////////////////////////////////////////////////////////////// - // attachment replication performance - ///////////////////////////////////////////////////////////////// - test("document and attachment deletion performance", function () { - stop(); - expect(12); - - var id, - context = this, - blob = new Blob([big_string]); - - context.jio.post({"title": "foo"}) - .then(function (result) { - id = result; - return context.jio.putAttachment(id, "foo", blob); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.remove(id); - }) - .then(function () { - return context.jio.repair(); - }) - .then(function () { - return context.jio.__storage._remote_sub_storage.getAttachment( - id, - "foo", - {format: "text"} - ); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find attachment: " + id + " , foo"); - return context.jio.__storage._remote_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - equal(error.message, "Cannot find document: " + id); - return context.jio.__storage._signature_sub_storage - .getAttachment(id, "foo", {format: "json"}); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - var error_message = "Cannot find attachment: " + - "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + - "jio_attachment/"; - equal( - error.message.substring(0, error_message.length), - error_message - ); - return context.jio.__storage._signature_sub_storage.get(id); - }) - .fail(function (error) { - ok(error instanceof jIO.util.jIOError); - equal(error.status_code, 404); - var error_message = "Cannot find attachment: " + - "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + - "jio_document/"; - equal( - error.message.substring(0, error_message.length), - error_message - ); - }) - .always(function () { - start(); - }); - }); - - test("use 1 parallel operation", function () { - stop(); - expect(40); - - var context = this, - order_number = 0, - expected_order_list = [ - 'start get 0', - 'stop get 0', - 'start put 0', - 'stop put 0', - 'start get 1', - 'stop get 1', - 'start put 1', - 'stop put 1', - 'start getAttachment 00', - 'stop getAttachment 00', - 'start putAttachment 00', - 'stop putAttachment 00', - 'start getAttachment 01', - 'stop getAttachment 01', - 'start putAttachment 01', - 'stop putAttachment 01', - 'start getAttachment 02', - 'stop getAttachment 02', - 'start putAttachment 02', - 'stop putAttachment 02', - 'start getAttachment 03', - 'stop getAttachment 03', - 'start putAttachment 03', - 'stop putAttachment 03', - 'start getAttachment 10', - 'stop getAttachment 10', - 'start putAttachment 10', - 'stop putAttachment 10', - 'start getAttachment 11', - 'stop getAttachment 11', - 'start putAttachment 11', - 'stop putAttachment 11', - 'start getAttachment 12', - 'stop getAttachment 12', - 'start putAttachment 12', - 'stop putAttachment 12', - 'start getAttachment 13', - 'stop getAttachment 13', - 'start putAttachment 13', - 'stop putAttachment 13' - ]; - - function assertExecutionOrder(text) { - equal(text, expected_order_list[order_number], - expected_order_list[order_number]); - order_number += 1; - } - - function StorageOneParallelOperation() { - this._sub_storage = jIO.createJIO({type: "memory"}); - return this; - } - - StorageOneParallelOperation.prototype.put = function (id, doc) { - assertExecutionOrder('start put ' + id); - var storage = this; - return storage._sub_storage.put(id, doc) - .push(function (result) { - assertExecutionOrder('stop put ' + id); - return result; - }); - }; - - StorageOneParallelOperation.prototype.get = function (id) { - assertExecutionOrder('start get ' + id); - var storage = this; - return storage._sub_storage.get(id) - .push(undefined, function (error) { - assertExecutionOrder('stop get ' + id); - throw error; - }); - }; - - StorageOneParallelOperation.prototype.getAttachment = function (id, name) { - assertExecutionOrder('start getAttachment ' + name); - var storage = this; - return storage._sub_storage.getAttachment(id, name) - .push(undefined, function (error) { - assertExecutionOrder('stop getAttachment ' + name); - throw error; - }); - }; - - StorageOneParallelOperation.prototype.putAttachment = function (id, name, - blob) { - assertExecutionOrder('start putAttachment ' + name); - var storage = this; - return storage._sub_storage.putAttachment(id, name, blob) - .push(function (result) { - assertExecutionOrder('stop putAttachment ' + name); - return result; - }); - }; - - StorageOneParallelOperation.prototype.buildQuery = function () { - return this._sub_storage.buildQuery.apply(this._sub_storage, arguments); - }; - StorageOneParallelOperation.prototype.allAttachments = function () { - return this._sub_storage.allAttachments.apply(this._sub_storage, - arguments); - }; - - StorageOneParallelOperation.prototype.hasCapacity = function () { - return this._sub_storage.hasCapacity.apply(this._sub_storage, arguments); - }; - - jIO.addStorage( - 'one_parallel_attachment', - StorageOneParallelOperation - ); - - this.jio = jIO.createJIO({ - type: "replicate", - check_local_attachment_creation: true, - local_sub_storage: { - type: "memory" - }, - remote_sub_storage: { - type: "one_parallel_attachment" - } - }); - - return RSVP.all([ - context.jio.put("0", {}), - context.jio.put("1", {}) - ]) - .then(function () { - return RSVP.all([ - context.jio.putAttachment("0", "00", new Blob(["0"])), - context.jio.putAttachment("0", "01", new Blob(["1"])), - context.jio.putAttachment("0", "02", new Blob(["2"])), - context.jio.putAttachment("0", "03", new Blob(["3"])), - context.jio.putAttachment("1", "10", new Blob(["0"])), - context.jio.putAttachment("1", "11", new Blob(["1"])), - context.jio.putAttachment("1", "12", new Blob(["2"])), - context.jio.putAttachment("1", "13", new Blob(["3"])) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("use 2 parallel operation", function () { - stop(); - expect(40); - - var context = this, - order_number = 0, - expected_order_list = [ - 'start get 0', - 'stop get 0', - 'start put 0', - 'stop put 0', - 'start get 1', - 'stop get 1', - 'start put 1', - 'stop put 1', - - 'start getAttachment 00', - - 'start getAttachment 01', - 'stop getAttachment 01', - 'start putAttachment 01', - 'stop putAttachment 01', - 'start getAttachment 02', - 'stop getAttachment 02', - 'start putAttachment 02', - - 'stop getAttachment 00', - 'start putAttachment 00', - 'stop putAttachment 00', - 'start getAttachment 03', - 'stop getAttachment 03', - 'start putAttachment 03', - 'stop putAttachment 03', - - 'stop putAttachment 02', - - 'start getAttachment 10', - - 'start getAttachment 11', - 'stop getAttachment 11', - 'start putAttachment 11', - 'stop putAttachment 11', - 'start getAttachment 12', - 'stop getAttachment 12', - 'start putAttachment 12', - - 'stop getAttachment 10', - 'start putAttachment 10', - 'stop putAttachment 10', - 'start getAttachment 13', - 'stop getAttachment 13', - 'start putAttachment 13', - 'stop putAttachment 13', - - 'stop putAttachment 12' - ], - defer0, - defer2; - - function assertExecutionOrder(text) { - equal(text, expected_order_list[order_number], - expected_order_list[order_number]); - order_number += 1; - } - - function StorageTwoParallelOperation() { - this._sub_storage = jIO.createJIO({type: "memory"}); - return this; - } - - StorageTwoParallelOperation.prototype.put = function (id, doc) { - assertExecutionOrder('start put ' + id); - var storage = this; - return storage._sub_storage.put(id, doc) - .push(function (result) { - assertExecutionOrder('stop put ' + id); - return result; - }); - }; - - StorageTwoParallelOperation.prototype.get = function (id) { - assertExecutionOrder('start get ' + id); - var storage = this; - return storage._sub_storage.get(id) - .push(undefined, function (error) { - assertExecutionOrder('stop get ' + id); - throw error; - }); - }; - - - StorageTwoParallelOperation.prototype.getAttachment = function (id, - name) { - assertExecutionOrder('start getAttachment ' + name); - var storage = this; - return new RSVP.Queue() - .push(function () { - if (name[1] === "0") { - defer0 = RSVP.defer(); - return defer0.promise; - } - }) - .push(function () { - return storage._sub_storage.getAttachment(id, name); - }) - .push(undefined, function (error) { - assertExecutionOrder('stop getAttachment ' + name); - throw error; - }); - }; - - StorageTwoParallelOperation.prototype.putAttachment = function (id, name, - blob) { - assertExecutionOrder('start putAttachment ' + name); - var storage = this; - return new RSVP.Queue() - .push(function () { - if (name[1] === "2") { - defer0.resolve(); - defer2 = RSVP.defer(); - return defer2.promise; - } - }) - .push(function () { - return storage._sub_storage.putAttachment(id, name, blob); - }) - .push(function (result) { - if (name[1] === "3") { - defer2.resolve(); - } - assertExecutionOrder('stop putAttachment ' + name); - return result; - }); - }; - - - StorageTwoParallelOperation.prototype.buildQuery = function () { - return this._sub_storage.buildQuery.apply(this._sub_storage, arguments); - }; - StorageTwoParallelOperation.prototype.allAttachments = function () { - return this._sub_storage.allAttachments.apply(this._sub_storage, - arguments); - }; - - StorageTwoParallelOperation.prototype.hasCapacity = function () { - return this._sub_storage.hasCapacity.apply(this._sub_storage, arguments); - }; - - jIO.addStorage( - 'two_parallel_attachment', - StorageTwoParallelOperation - ); - - this.jio = jIO.createJIO({ - type: "replicate", - check_local_attachment_creation: true, - parallel_operation_attachment_amount: 2, - local_sub_storage: { - type: "memory" - }, - remote_sub_storage: { - type: "two_parallel_attachment" - } - }); - - return RSVP.all([ - context.jio.put("0", {}), - context.jio.put("1", {}) - ]) - .then(function () { - return RSVP.all([ - context.jio.putAttachment("0", "00", new Blob(["0"])), - context.jio.putAttachment("0", "01", new Blob(["1"])), - context.jio.putAttachment("0", "02", new Blob(["2"])), - context.jio.putAttachment("0", "03", new Blob(["3"])), - context.jio.putAttachment("1", "10", new Blob(["0"])), - context.jio.putAttachment("1", "11", new Blob(["1"])), - context.jio.putAttachment("1", "12", new Blob(["2"])), - context.jio.putAttachment("1", "13", new Blob(["3"])) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - - test("use 4 parallel operation", function () { - stop(); - expect(40); - - var context = this, - order_number = 0, - expected_order_list = [ - 'start get 0', - 'stop get 0', - 'start put 0', - 'stop put 0', - 'start get 1', - 'stop get 1', - 'start put 1', - 'stop put 1', - - 'start getAttachment 00', - 'stop getAttachment 00', - 'start putAttachment 00', - - 'start getAttachment 01', - 'stop getAttachment 01', - 'start putAttachment 01', - - 'start getAttachment 02', - 'stop getAttachment 02', - 'start putAttachment 02', - - 'start getAttachment 03', - 'stop getAttachment 03', - 'start putAttachment 03', - - 'stop putAttachment 00', - 'stop putAttachment 01', - 'stop putAttachment 02', - 'stop putAttachment 03', - - 'start getAttachment 10', - 'stop getAttachment 10', - 'start putAttachment 10', - - 'start getAttachment 11', - 'stop getAttachment 11', - 'start putAttachment 11', - - 'start getAttachment 12', - 'stop getAttachment 12', - 'start putAttachment 12', - - 'start getAttachment 13', - 'stop getAttachment 13', - 'start putAttachment 13', - - 'stop putAttachment 10', - 'stop putAttachment 11', - 'stop putAttachment 12', - 'stop putAttachment 13' - - ]; - - function assertExecutionOrder(text) { - equal(text, expected_order_list[order_number], - expected_order_list[order_number]); - order_number += 1; - } - - function StorageFourParallelOperation() { - this._sub_storage = jIO.createJIO({type: "memory"}); - return this; - } - - StorageFourParallelOperation.prototype.put = function (id, doc) { - assertExecutionOrder('start put ' + id); - var storage = this; - return storage._sub_storage.put(id, doc) - .push(function (result) { - assertExecutionOrder('stop put ' + id); - return result; - }); - }; - - StorageFourParallelOperation.prototype.get = function (id) { - assertExecutionOrder('start get ' + id); - var storage = this; - return storage._sub_storage.get(id) - .push(undefined, function (error) { - assertExecutionOrder('stop get ' + id); - throw error; - }); - }; - - StorageFourParallelOperation.prototype.getAttachment = function (id, - name) { - assertExecutionOrder('start getAttachment ' + name); - var storage = this; - return storage._sub_storage.getAttachment(id, name) - .push(undefined, function (error) { - assertExecutionOrder('stop getAttachment ' + name); - throw error; - }); - }; - - StorageFourParallelOperation.prototype.putAttachment = function (id, name, - blob) { - assertExecutionOrder('start putAttachment ' + name); - var storage = this; - return storage._sub_storage.putAttachment(id, name, blob) - .push(function (result) { - assertExecutionOrder('stop putAttachment ' + name); - return result; - }); - }; - - StorageFourParallelOperation.prototype.buildQuery = function () { - return this._sub_storage.buildQuery.apply(this._sub_storage, arguments); - }; - StorageFourParallelOperation.prototype.allAttachments = function () { - return this._sub_storage.allAttachments.apply(this._sub_storage, - arguments); - }; - - StorageFourParallelOperation.prototype.hasCapacity = function () { - return this._sub_storage.hasCapacity.apply(this._sub_storage, arguments); - }; - - jIO.addStorage( - 'four_parallel_attachment', - StorageFourParallelOperation - ); - - this.jio = jIO.createJIO({ - type: "replicate", - check_local_attachment_creation: true, - parallel_operation_attachment_amount: 4, - local_sub_storage: { - type: "memory" - }, - remote_sub_storage: { - type: "four_parallel_attachment" - } - }); - - return RSVP.all([ - context.jio.put("0", {}), - context.jio.put("1", {}) - ]) - .then(function () { - return RSVP.all([ - context.jio.putAttachment("0", "00", new Blob(["0"])), - context.jio.putAttachment("0", "01", new Blob(["1"])), - context.jio.putAttachment("0", "02", new Blob(["2"])), - context.jio.putAttachment("0", "03", new Blob(["3"])), - context.jio.putAttachment("1", "10", new Blob(["0"])), - context.jio.putAttachment("1", "11", new Blob(["1"])), - context.jio.putAttachment("1", "12", new Blob(["2"])), - context.jio.putAttachment("1", "13", new Blob(["3"])) - ]); - }) - .then(function () { - return context.jio.repair(); - }) - .fail(function (error) { - ok(false, error); - }) - .always(function () { - start(); - }); - }); - -}(jIO, QUnit, Blob, RSVP)); \ No newline at end of file +}(jIO, QUnit, Blob)); \ No newline at end of file diff --git a/test/jio.storage/replicatestorage_repair.tests.js b/test/jio.storage/replicatestorage_repair.tests.js new file mode 100644 index 0000000000000000000000000000000000000000..45afa3a9ec3393f25925d627445298e1511349f4 --- /dev/null +++ b/test/jio.storage/replicatestorage_repair.tests.js @@ -0,0 +1,3672 @@ +/*jslint nomen: true*/ +/*global Blob, RSVP*/ +(function (jIO, QUnit, Blob, RSVP) { + "use strict"; + var test = QUnit.test, + stop = QUnit.stop, + start = QUnit.start, + ok = QUnit.ok, + expect = QUnit.expect, + deepEqual = QUnit.deepEqual, + equal = QUnit.equal, + module = QUnit.module, + big_string = "", + j; + + for (j = 0; j < 30; j += 1) { + big_string += "a"; + } + + ///////////////////////////////////////////////////////////////// + // replicateStorage.repair use cases + ///////////////////////////////////////////////////////////////// + module("replicateStorage.repair.document", { + setup: function () { + // Uses memory substorage, so that it is flushed after each run + this.jio = jIO.createJIO({ + type: "replicate", + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + } + }); + + ///////////////////////////////////////////////////////////////// + // document replication + ///////////////////////////////////////////////////////////////// + + test("local document creation", function () { + stop(); + expect(2); + + var id, + context = this; + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local document creation not checked", function () { + stop(); + expect(6); + + this.jio = jIO.createJIO({ + type: "replicate", + check_local_creation: false, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + var id, + context = this; + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return context.jio.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + }) + .always(function () { + start(); + }); + }); + + test("local document creation and use remote post", function () { + stop(); + expect(13); + + var id, + post_id, + context = this, + blob = new Blob([big_string]); + + this.jio = jIO.createJIO({ + type: "replicate", + use_remote_post: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, 'foo', blob); + }) + .then(function () { + return context.jio.repair(); + }) + // Document 'id' has been deleted in both storages + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._local_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function () { + ok(false, "Signature should have been deleted"); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + }) + + // But another document should have been created + .then(function () { + return context.jio.__storage._remote_sub_storage.allDocs(); + }) + .then(function (result) { + equal(result.data.total_rows, 1); + post_id = result.data.rows[0].id; + return context.jio.__storage._remote_sub_storage.get(post_id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + }) + .then(function () { + return context.jio.__storage._local_sub_storage.get(post_id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + // Attachment should be kept + return context.jio.__storage._local_sub_storage + .getAttachment(post_id, 'foo', {format: 'text'}); + }) + .then(function (result) { + equal(result, big_string); + return context.jio.__storage._signature_sub_storage.get(post_id); + }) + .then(function (result) { + deepEqual(result, { + hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local document creation, remote post and delayed allDocs", function () { + stop(); + expect(11); + + var id, + post_id = "_foobar", + context = this; + + function Storage200DelayedAllDocs(spec) { + this._sub_storage = jIO.createJIO(spec.sub_storage); + } + Storage200DelayedAllDocs.prototype.get = function () { + return this._sub_storage.get.apply(this._sub_storage, arguments); + }; + Storage200DelayedAllDocs.prototype.post = function (param) { + return this.put(post_id, param); + }; + Storage200DelayedAllDocs.prototype.put = function () { + return this._sub_storage.put.apply(this._sub_storage, arguments); + }; + Storage200DelayedAllDocs.prototype.hasCapacity = function () { + return true; + }; + Storage200DelayedAllDocs.prototype.buildQuery = function () { + return []; + }; + jIO.addStorage( + 'replicatestorage200delayedalldocs', + Storage200DelayedAllDocs + ); + + this.jio = jIO.createJIO({ + type: "replicate", + use_remote_post: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "replicatestorage200delayedalldocs", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + // Document 'id' has been deleted in both storages + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._local_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + }) + + // But another document should have been created + .then(function () { + return context.jio.__storage._remote_sub_storage.get(post_id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + }) + .then(function () { + return context.jio.__storage._local_sub_storage.get(post_id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(post_id); + }) + .then(function (result) { + deepEqual(result, { + hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("remote document creation", function () { + stop(); + expect(2); + + var id, + context = this; + + context.jio.__storage._remote_sub_storage.post({"title": "bar"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return context.jio.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "bar" + }); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "6799f3ea80e325b89f19589282a343c376c1f1af" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("remote document creation not checked", function () { + stop(); + expect(6); + + var id, + context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + check_remote_creation: false, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.__storage._remote_sub_storage.post({"title": "bar"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "bar" + }); + }) + .then(function () { + return context.jio.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote document creations", function () { + stop(); + expect(5); + + var context = this; + + RSVP.all([ + context.jio.put("conflict", {"title": "foo"}), + context.jio.__storage._remote_sub_storage.put("conflict", + {"title": "bar"}) + ]) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + ok(false); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Conflict on 'conflict': " + + "{\"title\":\"foo\"} !== {\"title\":\"bar\"}"); + equal(error.status_code, 409); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get("conflict"); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); +// equal(error.message, "Cannot find document: conflict"); + equal(error.status_code, 404); + }) + .always(function () { + start(); + }); + }); + + test("local and remote document creations: keep local", function () { + stop(); + expect(3); + + var context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + conflict_handling: 1 + }); + + RSVP.all([ + context.jio.put("conflict", {"title": "foo"}), + context.jio.__storage._remote_sub_storage.put("conflict", + {"title": "bar"}) + ]) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" + }); + }) + .then(function () { + return context.jio.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote document creations: keep local, remote post", + function () { + stop(); + expect(3); + + var context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + use_remote_post: 1, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + conflict_handling: 1 + }); + + RSVP.all([ + context.jio.put("conflict", {"title": "foo"}), + context.jio.__storage._remote_sub_storage.put("conflict", + {"title": "bar"}) + ]) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" + }); + }) + .then(function () { + return context.jio.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote document creations: keep local, " + + "local not matching query", function () { + stop(); + expect(3); + + var context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + local_sub_storage: { + type: "query", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "query", + sub_storage: { + type: "memory" + } + }, + query: {query: 'type: "foobar"'}, + conflict_handling: 1 + }); + + RSVP.all([ + context.jio.put("conflict", {"title": "foo"}), + context.jio.__storage._remote_sub_storage.put("conflict", + {"title": "bar", + "type": "foobar"}) + ]) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" + }); + }) + .then(function () { + return context.jio.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote document creations: keep local, " + + "remote not matching query", function () { + stop(); + expect(3); + + var context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + local_sub_storage: { + type: "query", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "query", + sub_storage: { + type: "memory" + } + }, + query: {query: 'type: "foobar"'}, + conflict_handling: 1 + }); + + RSVP.all([ + context.jio.put("conflict", {"title": "foo", "type": "foobar"}), + context.jio.__storage._remote_sub_storage.put("conflict", + {"title": "bar"}) + ]) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + hash: "a0a1b37cee3709101b752c56e59b9d66cce09961" + }); + }) + .then(function () { + return context.jio.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + title: "foo", + type: "foobar" + }); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + title: "foo", + type: "foobar" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote document creations: keep remote", function () { + stop(); + expect(3); + + var context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + conflict_handling: 2 + }); + + RSVP.all([ + context.jio.put("conflict", {"title": "foo"}), + context.jio.__storage._remote_sub_storage.put("conflict", + {"title": "bar"}) + ]) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + hash: "6799f3ea80e325b89f19589282a343c376c1f1af" + }); + }) + .then(function () { + return context.jio.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + title: "bar" + }); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + title: "bar" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote document creations: keep remote, remote post", + function () { + stop(); + expect(3); + + var context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + use_remote_post: 1, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + conflict_handling: 2 + }); + + RSVP.all([ + context.jio.put("conflict", {"title": "foo"}), + context.jio.__storage._remote_sub_storage.put("conflict", + {"title": "bar"}) + ]) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + hash: "6799f3ea80e325b89f19589282a343c376c1f1af" + }); + }) + .then(function () { + return context.jio.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + title: "bar" + }); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + title: "bar" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote document creations: keep remote, " + + "local not matching query", function () { + stop(); + expect(3); + + var context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + local_sub_storage: { + type: "query", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "query", + sub_storage: { + type: "memory" + } + }, + query: {query: 'type: "foobar"'}, + conflict_handling: 2 + }); + + RSVP.all([ + context.jio.put("conflict", {"title": "foo"}), + context.jio.__storage._remote_sub_storage.put("conflict", + {"title": "bar", + "type": "foobar"}) + ]) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + hash: "45efa2292d54cc4ce1f726ea197bc0b9721fc1dc" + }); + }) + .then(function () { + return context.jio.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + title: "bar", + type: "foobar" + }); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + title: "bar", + type: "foobar" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote document creations: keep remote, " + + "remote not matching query", function () { + stop(); + expect(3); + + var context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + local_sub_storage: { + type: "query", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "query", + sub_storage: { + type: "memory" + } + }, + query: {query: 'type: "foobar"'}, + conflict_handling: 2 + }); + + RSVP.all([ + context.jio.put("conflict", {"title": "foo", "type": "foobar"}), + context.jio.__storage._remote_sub_storage.put("conflict", + {"title": "bar"}) + ]) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + hash: "6799f3ea80e325b89f19589282a343c376c1f1af" + }); + }) + .then(function () { + return context.jio.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + title: "bar" + }); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + title: "bar" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote document creations: continue", function () { + stop(); + expect(4); + + var context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + conflict_handling: 3 + }); + + RSVP.all([ + context.jio.put("conflict", {"title": "foo"}), + context.jio.__storage._remote_sub_storage.put("conflict", + {"title": "bar"}) + ]) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get("conflict"); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); +// equal(error.message, "Cannot find document: conflict"); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + title: "bar" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote document creations: continue, remote post", + function () { + stop(); + expect(4); + + var context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + use_remote_post: 1, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + conflict_handling: 3 + }); + + RSVP.all([ + context.jio.put("conflict", {"title": "foo"}), + context.jio.__storage._remote_sub_storage.put("conflict", + {"title": "bar"}) + ]) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get("conflict"); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + // equal(error.message, "Cannot find document: conflict"); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + title: "bar" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote same document creations", function () { + stop(); + expect(1); + + var context = this; + + RSVP.all([ + context.jio.put("conflict", {"title": "foo"}), + context.jio.__storage._remote_sub_storage.put("conflict", + {"title": "foo"}) + ]) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get("conflict"); + }) + .then(function (result) { + deepEqual(result, { + hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("no modification", function () { + stop(); + expect(2); + + var id, + context = this; + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local document modification", function () { + stop(); + expect(2); + + var id, + context = this; + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return context.jio.put(id, {"title": "foo2"}); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo2" + }); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "9819187e39531fdc9bcfd40dbc6a7d3c78fe8dab" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + + test("local document modification: use remote post", function () { + stop(); + expect(2); + + var id, + context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + use_remote_post: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.__storage._remote_sub_storage.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return context.jio.put(id, {"title": "foo2"}); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo2" + }); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "9819187e39531fdc9bcfd40dbc6a7d3c78fe8dab" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local document modification not checked", function () { + stop(); + expect(3); + + var id, + context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + check_local_modification: false, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return context.jio.put(id, {"title": "foo2"}); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo2" + }); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("remote document modification", function () { + stop(); + expect(2); + + var id, + context = this; + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.put( + id, + {"title": "foo3"} + ); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo3" + }); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "4b1dde0f80ac38514771a9d25b5278e38f560e0f" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("remote document modification not checked", function () { + stop(); + expect(3); + + var id, + context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + check_remote_modification: false, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.put( + id, + {"title": "foo3"} + ); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo3" + }); + }) + .then(function () { + return context.jio.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote document modifications", function () { + stop(); + expect(4); + + var id, + context = this; + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.put(id, {"title": "foo4"}), + context.jio.__storage._remote_sub_storage.put(id, {"title": "foo5"}) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + ok(false); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Conflict on '" + id + "': " + + "{\"title\":\"foo4\"} !== {\"title\":\"foo5\"}"); + equal(error.status_code, 409); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" + }); + }) + .always(function () { + start(); + }); + }); + + test("local and remote document modifications: keep local", function () { + stop(); + expect(3); + + var id, + context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + conflict_handling: 1 + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.put(id, {"title": "foo4"}), + context.jio.__storage._remote_sub_storage.put(id, {"title": "foo5"}) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "6f700e813022233a785692585484c21cb5a412fd" + }); + }) + .then(function () { + return context.jio.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo4" + }); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo4" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote document modifications: keep remote", function () { + stop(); + expect(3); + + var id, + context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + conflict_handling: 2 + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.put(id, {"title": "foo4"}), + context.jio.__storage._remote_sub_storage.put(id, {"title": "foo5"}) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "7bea6f87fd1dda14e340e5b14836cc8578fd615f" + }); + }) + .then(function () { + return context.jio.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo5" + }); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo5" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote document modifications: continue", function () { + stop(); + expect(3); + + var id, + context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + conflict_handling: 3 + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.put(id, {"title": "foo4"}), + context.jio.__storage._remote_sub_storage.put(id, {"title": "foo5"}) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" + }); + }) + .then(function () { + return context.jio.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo4" + }); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo5" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote document same modifications", function () { + stop(); + expect(1); + + var id, + context = this; + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.put(id, {"title": "foo99"}), + context.jio.__storage._remote_sub_storage.put(id, {"title": "foo99"}) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "8ed3a474128b6e0c0c7d3dd51b1a06ebfbf6722f" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local document deletion", function () { + stop(); + expect(6); + + var id, + context = this; + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return context.jio.remove(id); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + ok(true, "Removal correctly synced"); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id) + .then(function () { + ok(false, "Signature should be deleted"); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); +// equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }); + }) + .always(function () { + start(); + }); + }); + + test("local document deletion not checked", function () { + stop(); + expect(6); + + var id, + context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + check_local_deletion: false, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return context.jio.remove(id); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + ok(true, "Removal correctly synced"); + }) + .then(function () { + return context.jio.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" + }); + }) + .always(function () { + start(); + }); + }); + + test("local document deletion with attachment", function () { + stop(); + expect(7); + + var id, + context = this, + blob = new Blob([big_string]); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return context.jio.remove(id); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage + .putAttachment(id, 'foo', blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + ok(true, "Removal correctly synced"); + }) + .then(function () { + return context.jio.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage + .getAttachment(id, 'foo', {format: 'text'}); + }) + .then(function (result) { + equal(result, big_string); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" + }); + }) + .always(function () { + start(); + }); + }); + + test("remote document deletion", function () { + stop(); + expect(6); + + var id, + context = this; + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.remove(id); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + ok(true, "Removal correctly synced"); + }) + .then(function () { + return context.jio.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id) + .then(function () { + ok(false, "Signature should be deleted"); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); +// equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }); + }) + .always(function () { + start(); + }); + }); + + test("remote document deletion not checked", function () { + stop(); + expect(6); + + var id, + context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + check_remote_deletion: false, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.remove(id); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + ok(true, "Removal correctly synced"); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" + }); + }) + .always(function () { + start(); + }); + }); + + test("remote document deletion with attachment", function () { + stop(); + expect(7); + + var id, + context = this, + blob = new Blob([big_string]); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.remove(id); + }) + .then(function () { + return context.jio.putAttachment(id, 'foo', blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + ok(true, "Removal correctly synced"); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo" + }); + }) + .then(function () { + return context.jio.getAttachment(id, 'foo', {format: 'text'}); + }) + .then(function (result) { + equal(result, big_string); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" + }); + }) + .always(function () { + start(); + }); + }); + + test("local and remote document deletions", function () { + stop(); + expect(8); + + var id, + context = this; + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.remove(id), + context.jio.__storage._remote_sub_storage.remove(id) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.get(id) + .then(function () { + ok(false, "Document should be locally deleted"); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id) + .then(function () { + ok(false, "Document should be remotely deleted"); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id) + .then(function () { + ok(false, "Signature should be deleted"); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); +// equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local deletion and remote modifications", function () { + stop(); + expect(2); + + var id, + context = this; + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.remove(id), + context.jio.__storage._remote_sub_storage.put(id, {"title": "foo99"}) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo99" + }); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "8ed3a474128b6e0c0c7d3dd51b1a06ebfbf6722f" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local deletion and remote modifications: keep local", function () { + stop(); + expect(9); + + var id, + context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 1, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.remove(id), + context.jio.__storage._remote_sub_storage.put(id, {"title": "foo99"}) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal( + error.message.indexOf( + "Cannot find attachment: " + + "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + + "jio_document/" + ), + 0 + ); + equal(error.status_code, 404); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local deletion and remote modifications: keep remote", function () { + stop(); + expect(3); + + var id, + context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 2, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.remove(id), + context.jio.__storage._remote_sub_storage.put(id, {"title": "foo99"}) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo99" + }); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo99" + }); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "8ed3a474128b6e0c0c7d3dd51b1a06ebfbf6722f" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local deletion and remote modifications: ignore", function () { + stop(); + expect(5); + + var id, + context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 3, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.remove(id), + context.jio.__storage._remote_sub_storage.put(id, {"title": "foo99"}) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo99" + }); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local modifications and remote deletion", function () { + stop(); + expect(2); + + var id, + context = this; + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.put(id, {"title": "foo99"}), + context.jio.__storage._remote_sub_storage.remove(id) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + title: "foo99" + }); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "8ed3a474128b6e0c0c7d3dd51b1a06ebfbf6722f" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local modifications and remote deletion: use remote post", function () { + stop(); + expect(13); + + var id, + context = this, + post_id; + + this.jio = jIO.createJIO({ + type: "replicate", + use_remote_post: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.__storage._remote_sub_storage.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.put(id, {"title": "foo99"}), + context.jio.__storage._remote_sub_storage.remove(id) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + // Old id deleted + .then(function () { + return context.jio.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal( + error.message.indexOf( + "Cannot find attachment: " + + "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + + "jio_document/" + ), + 0 + ); + equal(error.status_code, 404); + }) + // Check new id + .then(function () { + return context.jio.allDocs({include_docs: true}); + }) + .then(function (result) { + equal(result.data.total_rows, 1); + post_id = result.data.rows[0].id; + return context.jio.__storage._remote_sub_storage.get(post_id); + }) + .then(function (result) { + deepEqual(result, { + "title": "foo99" + }); + }) + .then(function () { + return context.jio.__storage._local_sub_storage.get(post_id); + }) + .then(function (result) { + deepEqual(result, { + "title": "foo99" + }); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(post_id); + }) + .then(function (result) { + deepEqual(result, { + hash: "8ed3a474128b6e0c0c7d3dd51b1a06ebfbf6722f" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + + test("local modif, remote del: remote post, no check loc mod", function () { + stop(); + expect(13); + + var id, + context = this, + post_id; + + this.jio = jIO.createJIO({ + type: "replicate", + use_remote_post: true, + check_local_modification: false, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.__storage._remote_sub_storage.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.put(id, {"title": "foo99"}), + context.jio.__storage._remote_sub_storage.remove(id) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + // Old id deleted + .then(function () { + return context.jio.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal( + error.message.indexOf( + "Cannot find attachment: " + + "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + + "jio_document/" + ), + 0 + ); + equal(error.status_code, 404); + }) + // Check new id + .then(function () { + return context.jio.allDocs({include_docs: true}); + }) + .then(function (result) { + equal(result.data.total_rows, 1); + post_id = result.data.rows[0].id; + return context.jio.__storage._remote_sub_storage.get(post_id); + }) + .then(function (result) { + deepEqual(result, { + "title": "foo99" + }); + }) + .then(function () { + return context.jio.__storage._local_sub_storage.get(post_id); + }) + .then(function (result) { + deepEqual(result, { + "title": "foo99" + }); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(post_id); + }) + .then(function (result) { + deepEqual(result, { + hash: "8ed3a474128b6e0c0c7d3dd51b1a06ebfbf6722f" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local modifications and remote deletion: keep local", function () { + stop(); + expect(3); + + var id, + context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 1, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.put(id, {"title": "foo99"}), + context.jio.__storage._remote_sub_storage.remove(id) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + // Old id deleted + .then(function () { + return context.jio.get(id); + }) + .then(function (result) { + deepEqual(result, { + "title": "foo99" + }); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + "title": "foo99" + }); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "8ed3a474128b6e0c0c7d3dd51b1a06ebfbf6722f" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local modif and remote del: keep local, use remote post", function () { + stop(); + expect(13); + + var id, + context = this, + post_id; + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 1, + use_remote_post: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.__storage._remote_sub_storage.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.put(id, {"title": "foo99"}), + context.jio.__storage._remote_sub_storage.remove(id) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + // Old id deleted + .then(function () { + return context.jio.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal( + error.message.indexOf( + "Cannot find attachment: " + + "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + + "jio_document/" + ), + 0 + ); + equal(error.status_code, 404); + }) + // Check new id + .then(function () { + return context.jio.allDocs({include_docs: true}); + }) + .then(function (result) { + equal(result.data.total_rows, 1); + post_id = result.data.rows[0].id; + return context.jio.__storage._remote_sub_storage.get(post_id); + }) + .then(function (result) { + deepEqual(result, { + "title": "foo99" + }); + }) + .then(function () { + return context.jio.__storage._local_sub_storage.get(post_id); + }) + .then(function (result) { + deepEqual(result, { + "title": "foo99" + }); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(post_id); + }) + .then(function (result) { + deepEqual(result, { + hash: "8ed3a474128b6e0c0c7d3dd51b1a06ebfbf6722f" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local modifications and remote deletion: keep remote", function () { + stop(); + expect(9); + + var id, + context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 2, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.put(id, {"title": "foo99"}), + context.jio.__storage._remote_sub_storage.remove(id) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + // id deleted + .then(function () { + return context.jio.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal( + error.message.indexOf( + "Cannot find attachment: " + + "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + + "jio_document/" + ), + 0 + ); + equal(error.status_code, 404); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local modif and remote del: keep remote, not check modif", function () { + stop(); + expect(9); + + var id, + context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 2, + check_local_modification: false, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.put(id, {"title": "foo99"}), + context.jio.__storage._remote_sub_storage.remove(id) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + // id deleted + .then(function () { + return context.jio.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal( + error.message.indexOf( + "Cannot find attachment: " + + "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + + "jio_document/" + ), + 0 + ); + equal(error.status_code, 404); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local modifications and remote deletion: ignore", function () { + stop(); + expect(5); + + var id, + context = this; + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 3, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.put(id, {"title": "foo99"}), + context.jio.__storage._remote_sub_storage.remove(id) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + // id deleted + .then(function () { + return context.jio.get(id); + }) + .then(function (result) { + deepEqual(result, { + "title": "foo99" + }); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + id); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.get(id); + }) + .then(function (result) { + deepEqual(result, { + hash: "5ea9013447539ad65de308cbd75b5826a2ae30e5" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("signature document is not synced", function () { + stop(); + expect(6); + + var context = this; + + // Uses sessionstorage substorage, so that signature are stored + // in the same local sub storage + this.jio = jIO.createJIO({ + type: "replicate", + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "document", + document_id: "/", + sub_storage: { + type: "local", + sessiononly: true + } + } + }, + remote_sub_storage: { + type: "memory" + } + }); + + context.jio.post({"title": "foo"}) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get( + context.jio.__storage._signature_hash + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + + "_replicate_8662994dcefb3a2ceec61e86953efda8ec6520d6"); + equal(error.status_code, 404); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.get( + context.jio.__storage._signature_hash + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find document: " + + "_replicate_8662994dcefb3a2ceec61e86953efda8ec6520d6"); + equal(error.status_code, 404); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("substorages are repaired too", function () { + stop(); + expect(8); + + var context = this, + first_call = true, + options = {foo: "bar"}; + + function Storage200CheckRepair() { + return this; + } + Storage200CheckRepair.prototype.get = function () { + ok(true, "get 200 check repair called"); + return {}; + }; + Storage200CheckRepair.prototype.hasCapacity = function () { + return true; + }; + Storage200CheckRepair.prototype.buildQuery = function () { + ok(true, "buildQuery 200 check repair called"); + return []; + }; + Storage200CheckRepair.prototype.allAttachments = function () { + ok(true, "allAttachments 200 check repair called"); + return {}; + }; + Storage200CheckRepair.prototype.repair = function (kw) { + if (first_call) { + deepEqual( + this, + context.jio.__storage._local_sub_storage.__storage, + "local substorage repair" + ); + first_call = false; + } else { + deepEqual( + this, + context.jio.__storage._remote_sub_storage.__storage, + "remote substorage repair" + ); + } + deepEqual(kw, options, "substorage repair parameters provided"); + }; + + jIO.addStorage( + 'replicatestorage200chechrepair', + Storage200CheckRepair + ); + + + this.jio = jIO.createJIO({ + type: "replicate", + local_sub_storage: { + type: "replicatestorage200chechrepair" + }, + remote_sub_storage: { + type: "replicatestorage200chechrepair" + } + }); + + context.jio.repair(options) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("sync all documents by default", function () { + stop(); + expect(4); + + var context = this; + + function Storage200DefaultQuery() { + return this; + } + Storage200DefaultQuery.prototype.get = function () { + ok(true, "get 200 check repair called"); + return {}; + }; + Storage200DefaultQuery.prototype.hasCapacity = function () { + return true; + }; + Storage200DefaultQuery.prototype.buildQuery = function (query) { + deepEqual(query, {}); + return []; + }; + Storage200DefaultQuery.prototype.allAttachments = function () { + ok(true, "allAttachments 200 check repair called"); + return {}; + }; + jIO.addStorage( + 'replicatestorage200defaultquery', + Storage200DefaultQuery + ); + + this.jio = jIO.createJIO({ + type: "replicate", + local_sub_storage: { + type: "replicatestorage200defaultquery" + }, + remote_sub_storage: { + type: "replicatestorage200defaultquery" + } + }); + + return context.jio.repair() + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("sync can be restricted to some documents", function () { + stop(); + expect(4); + + var context = this, + query = {query: 'portal_type: "Foo"', limit: [0, 1234567890]}; + + function Storage200CustomQuery() { + return this; + } + Storage200CustomQuery.prototype.get = function () { + ok(true, "get 200 check repair called"); + return {}; + }; + Storage200CustomQuery.prototype.hasCapacity = function () { + return true; + }; + Storage200CustomQuery.prototype.buildQuery = function (options) { + deepEqual(options, query); + return []; + }; + Storage200CustomQuery.prototype.allAttachments = function () { + ok(true, "allAttachments 200 check repair called"); + return {}; + }; + jIO.addStorage( + 'replicatestorage200customquery', + Storage200CustomQuery + ); + + this.jio = jIO.createJIO({ + type: "replicate", + local_sub_storage: { + type: "replicatestorage200customquery" + }, + remote_sub_storage: { + type: "replicatestorage200customquery" + }, + query: {query: 'portal_type: "Foo"', limit: [0, 1234567890]} + }); + + return context.jio.repair() + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("use 1 parallel operation", function () { + stop(); + expect(16); + + var context = this, + order_number = 0, + expected_order_list = [ + 'start get 0', + 'stop get 0', + 'start put 0', + 'stop put 0', + 'start get 1', + 'stop get 1', + 'start put 1', + 'stop put 1', + 'start get 2', + 'stop get 2', + 'start put 2', + 'stop put 2', + 'start get 3', + 'stop get 3', + 'start put 3', + 'stop put 3' + ]; + + function assertExecutionOrder(text) { + equal(text, expected_order_list[order_number], + expected_order_list[order_number]); + order_number += 1; + } + + function StorageOneParallelOperation() { + this._sub_storage = jIO.createJIO({type: "memory"}); + return this; + } + + StorageOneParallelOperation.prototype.put = function (id, doc) { + assertExecutionOrder('start put ' + id); + var storage = this; + return storage._sub_storage.put(id, doc) + .push(function (result) { + assertExecutionOrder('stop put ' + id); + return result; + }); + }; + + StorageOneParallelOperation.prototype.get = function (id) { + assertExecutionOrder('start get ' + id); + var storage = this; + return storage._sub_storage.get(id) + .push(undefined, function (error) { + assertExecutionOrder('stop get ' + id); + throw error; + }); + }; + StorageOneParallelOperation.prototype.buildQuery = function () { + return this._sub_storage.buildQuery.apply(this._sub_storage, arguments); + }; + + StorageOneParallelOperation.prototype.hasCapacity = function () { + return this._sub_storage.hasCapacity.apply(this._sub_storage, arguments); + }; + + jIO.addStorage( + 'one_parallel', + StorageOneParallelOperation + ); + + this.jio = jIO.createJIO({ + type: "replicate", + local_sub_storage: { + type: "memory" + }, + remote_sub_storage: { + type: "one_parallel" + } + }); + + return RSVP.all([ + context.jio.put("0", {"title": "foo"}), + context.jio.put("1", {"title": "foo1"}), + context.jio.put("2", {"title": "foo2"}), + context.jio.put("3", {"title": "foo3"}) + ]) + .then(function () { + return context.jio.repair(); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("use 2 parallel operations", function () { + stop(); + expect(16); + + var context = this, + order_number = 0, + expected_order_list = [ + 'start get 0', + + 'start get 1', + 'stop get 1', + 'start put 1', + 'stop put 1', + 'start get 2', + 'stop get 2', + 'start put 2', + + 'stop get 0', + 'start put 0', + 'stop put 0', + 'start get 3', + 'stop get 3', + 'start put 3', + 'stop put 3', + + 'stop put 2' + ], + defer0, + defer2; + + function assertExecutionOrder(text) { + equal(text, expected_order_list[order_number], + expected_order_list[order_number]); + order_number += 1; + } + + function StorageTwoParallelOperation() { + this._sub_storage = jIO.createJIO({type: "memory"}); + return this; + } + + StorageTwoParallelOperation.prototype.put = function (id, doc) { + var storage = this; + assertExecutionOrder('start put ' + id); + return new RSVP.Queue() + .push(function () { + if (id === "2") { + defer0.resolve(); + defer2 = RSVP.defer(); + return defer2.promise; + } + }) + .push(function () { + return storage._sub_storage.put(id, doc); + }) + .push(function (result) { + if (id === "3") { + defer2.resolve(); + } + assertExecutionOrder('stop put ' + id); + return result; + }); + }; + + StorageTwoParallelOperation.prototype.get = function (id) { + var storage = this; + assertExecutionOrder('start get ' + id); + return new RSVP.Queue() + .push(function () { + if (id === "0") { + defer0 = RSVP.defer(); + return defer0.promise; + } + }) + .push(function () { + return storage._sub_storage.get(id); + }) + .push(undefined, function (error) { + assertExecutionOrder('stop get ' + id); + throw error; + }); + }; + StorageTwoParallelOperation.prototype.buildQuery = function () { + return this._sub_storage.buildQuery.apply(this._sub_storage, arguments); + }; + + StorageTwoParallelOperation.prototype.hasCapacity = function () { + return this._sub_storage.hasCapacity.apply(this._sub_storage, arguments); + }; + + jIO.addStorage( + 'two_parallel', + StorageTwoParallelOperation + ); + + this.jio = jIO.createJIO({ + type: "replicate", + parallel_operation_amount: 2, + local_sub_storage: { + type: "memory" + }, + remote_sub_storage: { + type: "two_parallel" + } + }); + + return RSVP.all([ + context.jio.put("0", {"title": "foo"}), + context.jio.put("1", {"title": "foo1"}), + context.jio.put("2", {"title": "foo2"}), + context.jio.put("3", {"title": "foo3"}) + ]) + .then(function () { + return context.jio.repair(); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + + test("use 4 parallel operations", function () { + stop(); + expect(16); + + var context = this, + order_number = 0, + expected_order_list = [ + 'start get 0', + 'start get 1', + 'start get 2', + 'start get 3', + 'stop get 0', + 'stop get 1', + 'stop get 2', + 'stop get 3', + 'start put 0', + 'start put 1', + 'start put 2', + 'start put 3', + 'stop put 0', + 'stop put 1', + 'stop put 2', + 'stop put 3' + ]; + + function assertExecutionOrder(text) { + equal(text, expected_order_list[order_number], + expected_order_list[order_number]); + order_number += 1; + } + + function StorageFourParallelOperation() { + this._sub_storage = jIO.createJIO({type: "memory"}); + return this; + } + + StorageFourParallelOperation.prototype.put = function (id, doc) { + assertExecutionOrder('start put ' + id); + var storage = this; + return storage._sub_storage.put(id, doc) + .push(function (result) { + assertExecutionOrder('stop put ' + id); + return result; + }); + }; + + StorageFourParallelOperation.prototype.get = function (id) { + assertExecutionOrder('start get ' + id); + var storage = this; + return storage._sub_storage.get(id) + .push(undefined, function (error) { + assertExecutionOrder('stop get ' + id); + throw error; + }); + }; + StorageFourParallelOperation.prototype.buildQuery = function () { + return this._sub_storage.buildQuery.apply(this._sub_storage, arguments); + }; + + StorageFourParallelOperation.prototype.hasCapacity = function () { + return this._sub_storage.hasCapacity.apply(this._sub_storage, arguments); + }; + + jIO.addStorage( + 'four_parallel', + StorageFourParallelOperation + ); + + this.jio = jIO.createJIO({ + type: "replicate", + parallel_operation_amount: 4, + local_sub_storage: { + type: "memory" + }, + remote_sub_storage: { + type: "four_parallel" + } + }); + + return RSVP.all([ + context.jio.put("0", {"title": "foo"}), + context.jio.put("1", {"title": "foo1"}), + context.jio.put("2", {"title": "foo2"}), + context.jio.put("3", {"title": "foo3"}) + ]) + .then(function () { + return context.jio.repair(); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + +}(jIO, QUnit, Blob, RSVP)); \ No newline at end of file diff --git a/test/jio.storage/replicatestorage_repairattachment.tests.js b/test/jio.storage/replicatestorage_repairattachment.tests.js new file mode 100644 index 0000000000000000000000000000000000000000..589618b390121340ecd0ec4f72bf06c9d195f325 --- /dev/null +++ b/test/jio.storage/replicatestorage_repairattachment.tests.js @@ -0,0 +1,3653 @@ +/*jslint nomen: true*/ +/*global Blob, RSVP*/ +(function (jIO, QUnit, Blob, RSVP) { + "use strict"; + var test = QUnit.test, + stop = QUnit.stop, + start = QUnit.start, + ok = QUnit.ok, + expect = QUnit.expect, + deepEqual = QUnit.deepEqual, + equal = QUnit.equal, + module = QUnit.module, + big_string = "", + j; + + for (j = 0; j < 30; j += 1) { + big_string += "a"; + } + + function StorageEmptyAllAttachments(spec) { + this._sub_storage = jIO.createJIO(spec.sub_storage); + return this; + } + jIO.addStorage('signaturestorageallattachments', StorageEmptyAllAttachments); + StorageEmptyAllAttachments.prototype.allAttachments = function () { + return this._sub_storage.allAttachments.apply(this._sub_storage, + arguments); + }; + StorageEmptyAllAttachments.prototype.getAttachment = function () { + return this._sub_storage.getAttachment.apply(this._sub_storage, + arguments); + }; + StorageEmptyAllAttachments.prototype.putAttachment = function () { + return this._sub_storage.putAttachment.apply(this._sub_storage, + arguments); + }; + StorageEmptyAllAttachments.prototype.buildQuery = function () { + return this._sub_storage.buildQuery.apply(this._sub_storage, + arguments); + }; + StorageEmptyAllAttachments.prototype.put = function () { + return this._sub_storage.put.apply(this._sub_storage, + arguments); + }; + StorageEmptyAllAttachments.prototype.get = function () { + return this._sub_storage.get.apply(this._sub_storage, + arguments); + }; + StorageEmptyAllAttachments.prototype.hasCapacity = function (name) { + return (name !== 'bulk_get'); + }; + + ///////////////////////////////////////////////////////////////// + // attachment replication + ///////////////////////////////////////////////////////////////// + module("replicateStorage.repair.attachment", { + setup: function () { + // Uses memory substorage, so that it is flushed after each run + this.jio = jIO.createJIO({ + type: "replicate", + check_local_attachment_creation: true, + check_local_attachment_modification: true, + check_local_attachment_deletion: true, + check_remote_attachment_creation: true, + check_remote_attachment_modification: true, + check_remote_attachment_deletion: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + } + }); + + test("local attachment creation", function () { + stop(); + expect(2); + + var id, + context = this, + blob = new Blob([big_string]); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "cd762363c1c11ecb48611583520bba111f0034d4" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local attachment creation, local document creation not checked", + function () { + stop(); + expect(6); + + var id, + context = this, + blob = new Blob([big_string]); + + this.jio = jIO.createJIO({ + type: "replicate", + check_local_creation: false, + check_local_attachment_creation: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + var error_message = "Cannot find attachment: " + + "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + + "jio_attachment/"; + equal( + error.message.substring(0, error_message.length), + error_message + ); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local attachment creation not checked", function () { + stop(); + expect(6); + + var id, + context = this, + blob = new Blob([big_string]); + + this.jio = jIO.createJIO({ + type: "replicate", + check_local_attachment_creation: false, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + var error_message = "Cannot find attachment: " + + "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + + "jio_attachment/"; + equal( + error.message.substring(0, error_message.length), + error_message + ); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local attachment creation, local document creation and use remote post", + function () { + stop(); + expect(4); + + var id, + context = this, + post_id, + blob = new Blob([big_string]); + + this.jio = jIO.createJIO({ + type: "replicate", + use_remote_post: true, + check_local_attachment_creation: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + // Another document should have been created + .then(function () { + return context.jio.__storage._remote_sub_storage.allDocs(); + }) + .then(function (result) { + equal(result.data.total_rows, 1); + post_id = result.data.rows[0].id; + return context.jio.getAttachment( + post_id, + "foo", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string); + return context.jio.__storage._remote_sub_storage.getAttachment( + post_id, + "foo", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string); + return context.jio.__storage._signature_sub_storage + .getAttachment(post_id, "foo", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "cd762363c1c11ecb48611583520bba111f0034d4" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("remote attachment creation", function () { + stop(); + expect(2); + + var id, + context = this, + blob = new Blob([big_string]); + + context.jio.__storage._remote_sub_storage.post({"title": "bar"}) + .then(function (result) { + id = result; + return context.jio.__storage._remote_sub_storage + .putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "cd762363c1c11ecb48611583520bba111f0034d4" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("remote attachment creation, remote document creation not checked", + function () { + stop(); + expect(6); + + var id, + context = this, + blob = new Blob([big_string]); + + this.jio = jIO.createJIO({ + type: "replicate", + check_remote_creation: false, + check_local_attachment_creation: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.__storage._remote_sub_storage.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.__storage._remote_sub_storage + .putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + var error_message = "Cannot find attachment: " + + "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + + "jio_attachment/"; + equal( + error.message.substring(0, error_message.length), + error_message + ); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + + test("remote attachment creation not checked", function () { + stop(); + expect(6); + + var id, + context = this, + blob = new Blob([big_string]); + + this.jio = jIO.createJIO({ + type: "replicate", + check_remote_attachment_creation: false, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.__storage._remote_sub_storage.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.__storage._remote_sub_storage + .putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + var error_message = "Cannot find attachment: " + + "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + + "jio_attachment/"; + equal( + error.message.substring(0, error_message.length), + error_message + ); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote attachment creations", function () { + stop(); + expect(5); + + var context = this, + id = 'foobar', + blob = new Blob([big_string]), + blob2 = new Blob([big_string + "a"]); + + context.jio.put(id, {"title": "foo"}) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return RSVP.all([ + context.jio.putAttachment(id, "conflict", blob), + context.jio.__storage._remote_sub_storage.putAttachment(id, + "conflict", + blob2) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + ok(false); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Conflict on 'foobar' with attachment 'conflict'"); + equal(error.status_code, 409); + }) + .then(function () { + return context.jio.__storage._signature_sub_storage.getAttachment( + id, + "conflict" + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); +// equal(error.message, "Cannot find document: conflict"); + equal(error.status_code, 404); + }) + .always(function () { + start(); + }); + }); + + test("local and remote attachment creations: keep local", function () { + stop(); + expect(3); + + var context = this, + id = 'foobar', + blob = new Blob([big_string]), + blob2 = new Blob([big_string + "a"]); + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 1, + check_local_attachment_creation: true, + check_remote_attachment_creation: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.put(id, {"title": "foo"}) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return RSVP.all([ + context.jio.putAttachment(id, "conflict", blob), + context.jio.__storage._remote_sub_storage.putAttachment(id, + "conflict", + blob2) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "conflict", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "cd762363c1c11ecb48611583520bba111f0034d4" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote attachment creations: keep local, " + + "local not matching allAttachments", function () { + stop(); + expect(3); + + var context = this, + id = 'foobar', + blob = new Blob([big_string]), + blob2 = new Blob([big_string + "a"]); + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 1, + check_local_attachment_creation: true, + check_remote_attachment_creation: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "signaturestorageallattachments", + sub_storage: { + type: "memory" + } + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.put(id, {"title": "foo"}) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return RSVP.all([ + context.jio.putAttachment(id, "conflict", blob), + context.jio.__storage._remote_sub_storage.putAttachment(id, + "conflict", + blob2) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "conflict", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "cd762363c1c11ecb48611583520bba111f0034d4" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote attachment creations: keep local, " + + "remote not matching allAttachments", function () { + stop(); + expect(3); + + var context = this, + id = 'foobar', + blob = new Blob([big_string]), + blob2 = new Blob([big_string + "a"]); + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 1, + check_local_attachment_creation: true, + check_remote_attachment_creation: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "signaturestorageallattachments", + sub_storage: { + type: "memory" + } + } + } + }); + + context.jio.put(id, {"title": "foo"}) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return RSVP.all([ + context.jio.putAttachment(id, "conflict", blob), + context.jio.__storage._remote_sub_storage.putAttachment(id, + "conflict", + blob2) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "conflict", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "cd762363c1c11ecb48611583520bba111f0034d4" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote attachment creations: keep remote", function () { + stop(); + expect(3); + + var context = this, + id = 'foobar', + blob = new Blob([big_string]), + blob2 = new Blob([big_string + "a"]); + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 2, + check_local_attachment_creation: true, + check_remote_attachment_creation: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.put(id, {"title": "foo"}) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return RSVP.all([ + context.jio.putAttachment(id, "conflict", blob), + context.jio.__storage._remote_sub_storage.putAttachment(id, + "conflict", + blob2) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "a"); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "a"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "conflict", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "65cf771ad2cc0b1e8f89361e3b7bec2365b3ad24" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote attachment creations: keep remote, " + + "local not matching allAttachments", function () { + stop(); + expect(3); + + var context = this, + id = 'foobar', + blob = new Blob([big_string]), + blob2 = new Blob([big_string + "a"]); + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 2, + check_local_attachment_creation: true, + check_remote_attachment_creation: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "signaturestorageallattachments", + sub_storage: { + type: "memory" + } + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.put(id, {"title": "foo"}) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return RSVP.all([ + context.jio.putAttachment(id, "conflict", blob), + context.jio.__storage._remote_sub_storage.putAttachment(id, + "conflict", + blob2) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "a"); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "a"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "conflict", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "65cf771ad2cc0b1e8f89361e3b7bec2365b3ad24" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote attachment creations: keep remote, " + + "remote not matching allAttachments", function () { + stop(); + expect(3); + + var context = this, + id = 'foobar', + blob = new Blob([big_string]), + blob2 = new Blob([big_string + "a"]); + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 2, + check_local_attachment_creation: true, + check_remote_attachment_creation: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "signaturestorageallattachments", + sub_storage: { + type: "memory" + } + } + } + }); + + context.jio.put(id, {"title": "foo"}) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return RSVP.all([ + context.jio.putAttachment(id, "conflict", blob), + context.jio.__storage._remote_sub_storage.putAttachment(id, + "conflict", + blob2) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "a"); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "a"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "conflict", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "65cf771ad2cc0b1e8f89361e3b7bec2365b3ad24" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote attachment creations: continue", function () { + stop(); + expect(4); + + var context = this, + id = 'foobar', + blob = new Blob([big_string]), + blob2 = new Blob([big_string + "a"]); + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 3, + check_local_attachment_creation: true, + check_remote_attachment_creation: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.put(id, {"title": "foo"}) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return RSVP.all([ + context.jio.putAttachment(id, "conflict", blob), + context.jio.__storage._remote_sub_storage.putAttachment(id, + "conflict", + blob2) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "a"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "conflict", {format: "json"}); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); +// equal(error.message, "Cannot find document: conflict"); + equal(error.status_code, 404); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote same attachment creations", function () { + stop(); + expect(3); + + var context = this, + id = 'foobar', + blob = new Blob([big_string]), + blob2 = new Blob([big_string]); + + context.jio.put(id, {"title": "foo"}) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return RSVP.all([ + context.jio.putAttachment(id, "conflict", blob), + context.jio.__storage._remote_sub_storage.putAttachment(id, + "conflict", + blob2) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "conflict", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "cd762363c1c11ecb48611583520bba111f0034d4" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("no attachment modification", function () { + stop(); + expect(3); + + var context = this, + id = 'foobar', + blob = new Blob([big_string]); + + context.jio.put(id, {"title": "foo"}) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return context.jio.putAttachment(id, "conflict", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "conflict", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "cd762363c1c11ecb48611583520bba111f0034d4" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local attachment modification", function () { + stop(); + expect(3); + + var context = this, + id = 'foobar', + blob = new Blob([big_string]), + blob2 = new Blob([big_string + "a"]); + + context.jio.put(id, {"title": "foo"}) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return context.jio.putAttachment(id, "conflict", blob); + }) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return context.jio.putAttachment(id, "conflict", blob2); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "a"); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "a"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "conflict", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "65cf771ad2cc0b1e8f89361e3b7bec2365b3ad24" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local attachment modification not checked", function () { + stop(); + expect(3); + + var context = this, + id = 'foobar', + blob = new Blob([big_string]), + blob2 = new Blob([big_string + "a"]); + + this.jio = jIO.createJIO({ + type: "replicate", + check_local_attachment_creation: true, + check_local_attachment_modification: false, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.put(id, {"title": "foo"}) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return context.jio.putAttachment(id, "conflict", blob); + }) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return context.jio.putAttachment(id, "conflict", blob2); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "a"); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "conflict", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "cd762363c1c11ecb48611583520bba111f0034d4" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("remote attachment modification", function () { + stop(); + expect(3); + + var context = this, + id = 'foobar', + blob = new Blob([big_string]), + blob2 = new Blob([big_string + "a"]); + + context.jio.put(id, {"title": "foo"}) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return context.jio.putAttachment(id, "conflict", blob); + }) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return context.jio.__storage._remote_sub_storage + .putAttachment(id, "conflict", blob2); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "a"); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "a"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "conflict", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "65cf771ad2cc0b1e8f89361e3b7bec2365b3ad24" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("remote attachment modification not checked", function () { + stop(); + expect(3); + + var context = this, + id = 'foobar', + blob = new Blob([big_string]), + blob2 = new Blob([big_string + "a"]); + + this.jio = jIO.createJIO({ + type: "replicate", + check_local_attachment_creation: true, + check_remote_attachment_modification: false, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.put(id, {"title": "foo"}) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return context.jio.putAttachment(id, "conflict", blob); + }) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return context.jio.__storage._remote_sub_storage + .putAttachment(id, "conflict", blob2); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "a"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "conflict", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "cd762363c1c11ecb48611583520bba111f0034d4" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote attachment modifications", function () { + stop(); + expect(6); + + var context = this, + id = 'foobar', + blob = new Blob([big_string]), + blob2 = new Blob([big_string + "a"]), + blob3 = new Blob([big_string + "b"]); + + context.jio.put(id, {"title": "foo"}) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return context.jio.putAttachment(id, "conflict", blob); + }) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return RSVP.all([ + context.jio.putAttachment(id, "conflict", blob2), + context.jio.__storage._remote_sub_storage + .putAttachment(id, "conflict", blob3) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + ok(false); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Conflict on 'foobar' " + + "with attachment 'conflict'"); + equal(error.status_code, 409); + }) + .then(function () { + return context.jio.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "a"); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "b"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "conflict", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "cd762363c1c11ecb48611583520bba111f0034d4" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote attachment modifications: keep local", function () { + stop(); + expect(3); + + var context = this, + id = 'foobar', + blob = new Blob([big_string]), + blob2 = new Blob([big_string + "a"]), + blob3 = new Blob([big_string + "b"]); + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 1, + check_local_attachment_creation: true, + check_remote_attachment_creation: true, + check_local_attachment_modification: true, + check_remote_attachment_modification: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.put(id, {"title": "foo"}) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return context.jio.putAttachment(id, "conflict", blob); + }) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return RSVP.all([ + context.jio.putAttachment(id, "conflict", blob2), + context.jio.__storage._remote_sub_storage + .putAttachment(id, "conflict", blob3) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "a"); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "a"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "conflict", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "65cf771ad2cc0b1e8f89361e3b7bec2365b3ad24" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote attachment modifications: keep remote", function () { + stop(); + expect(3); + + var context = this, + id = 'foobar', + blob = new Blob([big_string]), + blob2 = new Blob([big_string + "a"]), + blob3 = new Blob([big_string + "b"]); + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 2, + check_local_attachment_creation: true, + check_remote_attachment_creation: true, + check_local_attachment_modification: true, + check_remote_attachment_modification: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.put(id, {"title": "foo"}) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return context.jio.putAttachment(id, "conflict", blob); + }) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return RSVP.all([ + context.jio.putAttachment(id, "conflict", blob2), + context.jio.__storage._remote_sub_storage + .putAttachment(id, "conflict", blob3) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "b"); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "b"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "conflict", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "9a73ce4f16b7fa5d2b4d8f723a754fef048fb9f8" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote attachment modifications: continue", function () { + stop(); + expect(3); + + var context = this, + id = 'foobar', + blob = new Blob([big_string]), + blob2 = new Blob([big_string + "a"]), + blob3 = new Blob([big_string + "b"]); + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 3, + check_local_attachment_creation: true, + check_remote_attachment_creation: true, + check_local_attachment_modification: true, + check_remote_attachment_modification: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.put(id, {"title": "foo"}) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return context.jio.putAttachment(id, "conflict", blob); + }) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return RSVP.all([ + context.jio.putAttachment(id, "conflict", blob2), + context.jio.__storage._remote_sub_storage + .putAttachment(id, "conflict", blob3) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "a"); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "b"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "conflict", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "cd762363c1c11ecb48611583520bba111f0034d4" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote attachment same modifications", function () { + stop(); + expect(3); + + var context = this, + id = 'foobar', + blob = new Blob([big_string]), + blob2 = new Blob([big_string + "a"]); + + context.jio.put(id, {"title": "foo"}) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return context.jio.putAttachment(id, "conflict", blob); + }) + .push(function () { + return context.jio.repair(); + }) + .push(function () { + return RSVP.all([ + context.jio.putAttachment(id, "conflict", blob2), + context.jio.__storage._remote_sub_storage + .putAttachment(id, "conflict", blob2) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "a"); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "conflict", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string + "a"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "conflict", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "65cf771ad2cc0b1e8f89361e3b7bec2365b3ad24" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local attachment deletion", function () { + stop(); + expect(9); + + var id, + context = this, + blob = new Blob([big_string]); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.removeAttachment(id, "foo"); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + var error_message = "Cannot find attachment: " + + "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + + "jio_attachment/"; + equal( + error.message.substring(0, error_message.length), + error_message + ); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local attachment deletion not checked", function () { + + stop(); + expect(5); + + var id, + context = this, + blob = new Blob([big_string]); + + this.jio = jIO.createJIO({ + type: "replicate", + check_local_attachment_creation: true, + check_local_attachment_deletion: false, + check_local_attachment_modification: true, + check_remote_attachment_creation: true, + check_remote_attachment_deletion: true, + check_remote_attachment_modification: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.removeAttachment(id, "foo"); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "cd762363c1c11ecb48611583520bba111f0034d4" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("remote attachment deletion", function () { + stop(); + expect(9); + + var id, + context = this, + blob = new Blob([big_string]); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage + .removeAttachment(id, "foo"); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + var error_message = "Cannot find attachment: " + + "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + + "jio_attachment/"; + equal( + error.message.substring(0, error_message.length), + error_message + ); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("remote attachment deletion not checked", function () { + + stop(); + expect(5); + + var id, + context = this, + blob = new Blob([big_string]); + + this.jio = jIO.createJIO({ + type: "replicate", + check_local_attachment_creation: true, + check_local_attachment_deletion: true, + check_local_attachment_modification: true, + check_remote_attachment_creation: true, + check_remote_attachment_deletion: false, + check_remote_attachment_modification: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage + .removeAttachment(id, "foo"); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .then(function (result) { + equal(result, big_string); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "cd762363c1c11ecb48611583520bba111f0034d4" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local and remote attachment deletions", function () { + stop(); + expect(9); + + var id, + context = this, + blob = new Blob([big_string]); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.removeAttachment(id, "foo"), + context.jio.__storage._remote_sub_storage + .removeAttachment(id, "foo") + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + var error_message = "Cannot find attachment: " + + "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + + "jio_attachment/"; + equal( + error.message.substring(0, error_message.length), + error_message + ); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local deletion and remote modifications", function () { + stop(); + expect(3); + + var id, + context = this, + blob = new Blob([big_string + "a"]), + blob2 = new Blob([big_string]); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.removeAttachment(id, "foo"), + context.jio.__storage._remote_sub_storage + .putAttachment(id, "foo", blob2) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .then(function (result) { + equal(true, big_string === result); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .then(function (result) { + equal(true, big_string === result); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "cd762363c1c11ecb48611583520bba111f0034d4" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local deletion and remote modifications: keep local", function () { + stop(); + expect(9); + + var id, + context = this, + blob = new Blob([big_string + "a"]), + blob2 = new Blob([big_string]); + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 1, + check_local_attachment_creation: true, + check_local_attachment_deletion: true, + check_local_attachment_modification: true, + check_remote_attachment_creation: true, + check_remote_attachment_deletion: true, + check_remote_attachment_modification: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.removeAttachment(id, "foo"), + context.jio.__storage._remote_sub_storage + .putAttachment(id, "foo", blob2) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + var error_message = "Cannot find attachment: " + + "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + + "jio_attachment/"; + equal( + error.message.substring(0, error_message.length), + error_message + ); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local deletion and remote modifications: keep local, dont check local", + function () { + stop(); + expect(9); + + var id, + context = this, + blob = new Blob([big_string + "a"]), + blob2 = new Blob([big_string]); + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 1, + check_local_attachment_creation: true, + check_local_attachment_deletion: false, + check_local_attachment_modification: true, + check_remote_attachment_creation: true, + check_remote_attachment_deletion: true, + check_remote_attachment_modification: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.removeAttachment(id, "foo"), + context.jio.__storage._remote_sub_storage + .putAttachment(id, "foo", blob2) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + var error_message = "Cannot find attachment: " + + "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + + "jio_attachment/"; + equal( + error.message.substring(0, error_message.length), + error_message + ); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local deletion and remote modifications: keep remote", function () { + stop(); + expect(3); + + var id, + context = this, + blob = new Blob([big_string + "a"]), + blob2 = new Blob([big_string]); + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 2, + check_local_attachment_creation: true, + check_local_attachment_deletion: true, + check_local_attachment_modification: true, + check_remote_attachment_creation: true, + check_remote_attachment_deletion: true, + check_remote_attachment_modification: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.removeAttachment(id, "foo"), + context.jio.__storage._remote_sub_storage + .putAttachment(id, "foo", blob2) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .then(function (result) { + equal(true, big_string === result); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .then(function (result) { + equal(true, big_string === result); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "cd762363c1c11ecb48611583520bba111f0034d4" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local deletion and remote modifications: ignore", function () { + stop(); + expect(5); + + var id, + context = this, + blob = new Blob([big_string + "a"]), + blob2 = new Blob([big_string]); + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 3, + check_local_attachment_creation: true, + check_local_attachment_deletion: true, + check_local_attachment_modification: true, + check_remote_attachment_creation: true, + check_remote_attachment_deletion: true, + check_remote_attachment_modification: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.removeAttachment(id, "foo"), + context.jio.__storage._remote_sub_storage + .putAttachment(id, "foo", blob2) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .then(function (result) { + equal(true, big_string === result); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "65cf771ad2cc0b1e8f89361e3b7bec2365b3ad24" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local modifications and remote deletion", function () { + stop(); + expect(3); + + var id, + context = this, + blob = new Blob([big_string + "a"]), + blob2 = new Blob([big_string]); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.putAttachment(id, "foo", blob2), + context.jio.__storage._remote_sub_storage + .removeAttachment(id, "foo") + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .then(function (result) { + equal(true, big_string === result); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .then(function (result) { + equal(true, big_string === result); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "cd762363c1c11ecb48611583520bba111f0034d4" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local modifications and remote deletion: keep remote", function () { + stop(); + expect(9); + + var id, + context = this, + blob = new Blob([big_string + "a"]), + blob2 = new Blob([big_string]); + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 2, + check_local_attachment_creation: true, + check_local_attachment_deletion: true, + check_local_attachment_modification: true, + check_remote_attachment_creation: true, + check_remote_attachment_deletion: true, + check_remote_attachment_modification: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.putAttachment(id, "foo", blob2), + context.jio.__storage._remote_sub_storage.removeAttachment(id, "foo") + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + var error_message = "Cannot find attachment: " + + "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + + "jio_attachment/"; + equal( + error.message.substring(0, error_message.length), + error_message + ); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local modifications and remote deletion: keep local", function () { + stop(); + expect(3); + + var id, + context = this, + blob = new Blob([big_string + "a"]), + blob2 = new Blob([big_string]); + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 1, + check_local_attachment_creation: true, + check_local_attachment_deletion: true, + check_local_attachment_modification: true, + check_remote_attachment_creation: true, + check_remote_attachment_deletion: true, + check_remote_attachment_modification: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.putAttachment(id, "foo", blob2), + context.jio.__storage._remote_sub_storage.removeAttachment(id, "foo") + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .then(function (result) { + equal(true, big_string === result); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .then(function (result) { + equal(true, big_string === result); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "cd762363c1c11ecb48611583520bba111f0034d4" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local modif and remote del: keep remote, not check modif", function () { + stop(); + expect(9); + + var id, + context = this, + blob = new Blob([big_string + "a"]), + blob2 = new Blob([big_string]); + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 2, + check_local_attachment_creation: true, + check_local_attachment_deletion: true, + check_local_attachment_modification: false, + check_remote_attachment_creation: true, + check_remote_attachment_deletion: true, + check_remote_attachment_modification: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.putAttachment(id, "foo", blob2), + context.jio.__storage._remote_sub_storage.removeAttachment(id, "foo") + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + var error_message = "Cannot find attachment: " + + "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + + "jio_attachment/"; + equal( + error.message.substring(0, error_message.length), + error_message + ); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("local modifications and remote deletion: ignore", function () { + stop(); + expect(5); + + var id, + context = this, + blob = new Blob([big_string + "a"]), + blob2 = new Blob([big_string]); + + this.jio = jIO.createJIO({ + type: "replicate", + conflict_handling: 3, + check_local_attachment_creation: true, + check_local_attachment_deletion: true, + check_local_attachment_modification: true, + check_remote_attachment_creation: true, + check_remote_attachment_deletion: true, + check_remote_attachment_modification: true, + local_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + }, + remote_sub_storage: { + type: "uuid", + sub_storage: { + type: "memory" + } + } + }); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return RSVP.all([ + context.jio.putAttachment(id, "foo", blob2), + context.jio.__storage._remote_sub_storage.removeAttachment(id, "foo") + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .then(function (result) { + equal(true, big_string === result); + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .then(function (result) { + deepEqual(result, { + hash: "65cf771ad2cc0b1e8f89361e3b7bec2365b3ad24" + }); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + ///////////////////////////////////////////////////////////////// + // attachment replication performance + ///////////////////////////////////////////////////////////////// + test("document and attachment deletion performance", function () { + stop(); + expect(12); + + var id, + context = this, + blob = new Blob([big_string]); + + context.jio.post({"title": "foo"}) + .then(function (result) { + id = result; + return context.jio.putAttachment(id, "foo", blob); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.remove(id); + }) + .then(function () { + return context.jio.repair(); + }) + .then(function () { + return context.jio.__storage._remote_sub_storage.getAttachment( + id, + "foo", + {format: "text"} + ); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find attachment: " + id + " , foo"); + return context.jio.__storage._remote_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + equal(error.message, "Cannot find document: " + id); + return context.jio.__storage._signature_sub_storage + .getAttachment(id, "foo", {format: "json"}); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + var error_message = "Cannot find attachment: " + + "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + + "jio_attachment/"; + equal( + error.message.substring(0, error_message.length), + error_message + ); + return context.jio.__storage._signature_sub_storage.get(id); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.status_code, 404); + var error_message = "Cannot find attachment: " + + "_replicate_b9296354cdf1dbe0046de11f57a5a24f8f6a78a8 , " + + "jio_document/"; + equal( + error.message.substring(0, error_message.length), + error_message + ); + }) + .always(function () { + start(); + }); + }); + + test("use 1 parallel operation", function () { + stop(); + expect(40); + + var context = this, + order_number = 0, + expected_order_list = [ + 'start get 0', + 'stop get 0', + 'start put 0', + 'stop put 0', + 'start get 1', + 'stop get 1', + 'start put 1', + 'stop put 1', + 'start getAttachment 00', + 'stop getAttachment 00', + 'start putAttachment 00', + 'stop putAttachment 00', + 'start getAttachment 01', + 'stop getAttachment 01', + 'start putAttachment 01', + 'stop putAttachment 01', + 'start getAttachment 02', + 'stop getAttachment 02', + 'start putAttachment 02', + 'stop putAttachment 02', + 'start getAttachment 03', + 'stop getAttachment 03', + 'start putAttachment 03', + 'stop putAttachment 03', + 'start getAttachment 10', + 'stop getAttachment 10', + 'start putAttachment 10', + 'stop putAttachment 10', + 'start getAttachment 11', + 'stop getAttachment 11', + 'start putAttachment 11', + 'stop putAttachment 11', + 'start getAttachment 12', + 'stop getAttachment 12', + 'start putAttachment 12', + 'stop putAttachment 12', + 'start getAttachment 13', + 'stop getAttachment 13', + 'start putAttachment 13', + 'stop putAttachment 13' + ]; + + function assertExecutionOrder(text) { + equal(text, expected_order_list[order_number], + expected_order_list[order_number]); + order_number += 1; + } + + function StorageOneParallelOperation() { + this._sub_storage = jIO.createJIO({type: "memory"}); + return this; + } + + StorageOneParallelOperation.prototype.put = function (id, doc) { + assertExecutionOrder('start put ' + id); + var storage = this; + return storage._sub_storage.put(id, doc) + .push(function (result) { + assertExecutionOrder('stop put ' + id); + return result; + }); + }; + + StorageOneParallelOperation.prototype.get = function (id) { + assertExecutionOrder('start get ' + id); + var storage = this; + return storage._sub_storage.get(id) + .push(undefined, function (error) { + assertExecutionOrder('stop get ' + id); + throw error; + }); + }; + + StorageOneParallelOperation.prototype.getAttachment = function (id, name) { + assertExecutionOrder('start getAttachment ' + name); + var storage = this; + return storage._sub_storage.getAttachment(id, name) + .push(undefined, function (error) { + assertExecutionOrder('stop getAttachment ' + name); + throw error; + }); + }; + + StorageOneParallelOperation.prototype.putAttachment = function (id, name, + blob) { + assertExecutionOrder('start putAttachment ' + name); + var storage = this; + return storage._sub_storage.putAttachment(id, name, blob) + .push(function (result) { + assertExecutionOrder('stop putAttachment ' + name); + return result; + }); + }; + + StorageOneParallelOperation.prototype.buildQuery = function () { + return this._sub_storage.buildQuery.apply(this._sub_storage, arguments); + }; + StorageOneParallelOperation.prototype.allAttachments = function () { + return this._sub_storage.allAttachments.apply(this._sub_storage, + arguments); + }; + + StorageOneParallelOperation.prototype.hasCapacity = function () { + return this._sub_storage.hasCapacity.apply(this._sub_storage, arguments); + }; + + jIO.addStorage( + 'one_parallel_attachment', + StorageOneParallelOperation + ); + + this.jio = jIO.createJIO({ + type: "replicate", + check_local_attachment_creation: true, + local_sub_storage: { + type: "memory" + }, + remote_sub_storage: { + type: "one_parallel_attachment" + } + }); + + return RSVP.all([ + context.jio.put("0", {}), + context.jio.put("1", {}) + ]) + .then(function () { + return RSVP.all([ + context.jio.putAttachment("0", "00", new Blob(["0"])), + context.jio.putAttachment("0", "01", new Blob(["1"])), + context.jio.putAttachment("0", "02", new Blob(["2"])), + context.jio.putAttachment("0", "03", new Blob(["3"])), + context.jio.putAttachment("1", "10", new Blob(["0"])), + context.jio.putAttachment("1", "11", new Blob(["1"])), + context.jio.putAttachment("1", "12", new Blob(["2"])), + context.jio.putAttachment("1", "13", new Blob(["3"])) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("use 2 parallel operation", function () { + stop(); + expect(40); + + var context = this, + order_number = 0, + expected_order_list = [ + 'start get 0', + 'stop get 0', + 'start put 0', + 'stop put 0', + 'start get 1', + 'stop get 1', + 'start put 1', + 'stop put 1', + + 'start getAttachment 00', + + 'start getAttachment 01', + 'stop getAttachment 01', + 'start putAttachment 01', + 'stop putAttachment 01', + 'start getAttachment 02', + 'stop getAttachment 02', + 'start putAttachment 02', + + 'stop getAttachment 00', + 'start putAttachment 00', + 'stop putAttachment 00', + 'start getAttachment 03', + 'stop getAttachment 03', + 'start putAttachment 03', + 'stop putAttachment 03', + + 'stop putAttachment 02', + + 'start getAttachment 10', + + 'start getAttachment 11', + 'stop getAttachment 11', + 'start putAttachment 11', + 'stop putAttachment 11', + 'start getAttachment 12', + 'stop getAttachment 12', + 'start putAttachment 12', + + 'stop getAttachment 10', + 'start putAttachment 10', + 'stop putAttachment 10', + 'start getAttachment 13', + 'stop getAttachment 13', + 'start putAttachment 13', + 'stop putAttachment 13', + + 'stop putAttachment 12' + ], + defer0, + defer2; + + function assertExecutionOrder(text) { + equal(text, expected_order_list[order_number], + expected_order_list[order_number]); + order_number += 1; + } + + function StorageTwoParallelOperation() { + this._sub_storage = jIO.createJIO({type: "memory"}); + return this; + } + + StorageTwoParallelOperation.prototype.put = function (id, doc) { + assertExecutionOrder('start put ' + id); + var storage = this; + return storage._sub_storage.put(id, doc) + .push(function (result) { + assertExecutionOrder('stop put ' + id); + return result; + }); + }; + + StorageTwoParallelOperation.prototype.get = function (id) { + assertExecutionOrder('start get ' + id); + var storage = this; + return storage._sub_storage.get(id) + .push(undefined, function (error) { + assertExecutionOrder('stop get ' + id); + throw error; + }); + }; + + + StorageTwoParallelOperation.prototype.getAttachment = function (id, + name) { + assertExecutionOrder('start getAttachment ' + name); + var storage = this; + return new RSVP.Queue() + .push(function () { + if (name[1] === "0") { + defer0 = RSVP.defer(); + return defer0.promise; + } + }) + .push(function () { + return storage._sub_storage.getAttachment(id, name); + }) + .push(undefined, function (error) { + assertExecutionOrder('stop getAttachment ' + name); + throw error; + }); + }; + + StorageTwoParallelOperation.prototype.putAttachment = function (id, name, + blob) { + assertExecutionOrder('start putAttachment ' + name); + var storage = this; + return new RSVP.Queue() + .push(function () { + if (name[1] === "2") { + defer0.resolve(); + defer2 = RSVP.defer(); + return defer2.promise; + } + }) + .push(function () { + return storage._sub_storage.putAttachment(id, name, blob); + }) + .push(function (result) { + if (name[1] === "3") { + defer2.resolve(); + } + assertExecutionOrder('stop putAttachment ' + name); + return result; + }); + }; + + + StorageTwoParallelOperation.prototype.buildQuery = function () { + return this._sub_storage.buildQuery.apply(this._sub_storage, arguments); + }; + StorageTwoParallelOperation.prototype.allAttachments = function () { + return this._sub_storage.allAttachments.apply(this._sub_storage, + arguments); + }; + + StorageTwoParallelOperation.prototype.hasCapacity = function () { + return this._sub_storage.hasCapacity.apply(this._sub_storage, arguments); + }; + + jIO.addStorage( + 'two_parallel_attachment', + StorageTwoParallelOperation + ); + + this.jio = jIO.createJIO({ + type: "replicate", + check_local_attachment_creation: true, + parallel_operation_attachment_amount: 2, + local_sub_storage: { + type: "memory" + }, + remote_sub_storage: { + type: "two_parallel_attachment" + } + }); + + return RSVP.all([ + context.jio.put("0", {}), + context.jio.put("1", {}) + ]) + .then(function () { + return RSVP.all([ + context.jio.putAttachment("0", "00", new Blob(["0"])), + context.jio.putAttachment("0", "01", new Blob(["1"])), + context.jio.putAttachment("0", "02", new Blob(["2"])), + context.jio.putAttachment("0", "03", new Blob(["3"])), + context.jio.putAttachment("1", "10", new Blob(["0"])), + context.jio.putAttachment("1", "11", new Blob(["1"])), + context.jio.putAttachment("1", "12", new Blob(["2"])), + context.jio.putAttachment("1", "13", new Blob(["3"])) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("use 4 parallel operation", function () { + stop(); + expect(40); + + var context = this, + order_number = 0, + expected_order_list = [ + 'start get 0', + 'stop get 0', + 'start put 0', + 'stop put 0', + 'start get 1', + 'stop get 1', + 'start put 1', + 'stop put 1', + + 'start getAttachment 00', + 'stop getAttachment 00', + 'start putAttachment 00', + + 'start getAttachment 01', + 'stop getAttachment 01', + 'start putAttachment 01', + + 'start getAttachment 02', + 'stop getAttachment 02', + 'start putAttachment 02', + + 'start getAttachment 03', + 'stop getAttachment 03', + 'start putAttachment 03', + + 'stop putAttachment 00', + 'stop putAttachment 01', + 'stop putAttachment 02', + 'stop putAttachment 03', + + 'start getAttachment 10', + 'stop getAttachment 10', + 'start putAttachment 10', + + 'start getAttachment 11', + 'stop getAttachment 11', + 'start putAttachment 11', + + 'start getAttachment 12', + 'stop getAttachment 12', + 'start putAttachment 12', + + 'start getAttachment 13', + 'stop getAttachment 13', + 'start putAttachment 13', + + 'stop putAttachment 10', + 'stop putAttachment 11', + 'stop putAttachment 12', + 'stop putAttachment 13' + + ]; + + function assertExecutionOrder(text) { + equal(text, expected_order_list[order_number], + expected_order_list[order_number]); + order_number += 1; + } + + function StorageFourParallelOperation() { + this._sub_storage = jIO.createJIO({type: "memory"}); + return this; + } + + StorageFourParallelOperation.prototype.put = function (id, doc) { + assertExecutionOrder('start put ' + id); + var storage = this; + return storage._sub_storage.put(id, doc) + .push(function (result) { + assertExecutionOrder('stop put ' + id); + return result; + }); + }; + + StorageFourParallelOperation.prototype.get = function (id) { + assertExecutionOrder('start get ' + id); + var storage = this; + return storage._sub_storage.get(id) + .push(undefined, function (error) { + assertExecutionOrder('stop get ' + id); + throw error; + }); + }; + + StorageFourParallelOperation.prototype.getAttachment = function (id, + name) { + assertExecutionOrder('start getAttachment ' + name); + var storage = this; + return storage._sub_storage.getAttachment(id, name) + .push(undefined, function (error) { + assertExecutionOrder('stop getAttachment ' + name); + throw error; + }); + }; + + StorageFourParallelOperation.prototype.putAttachment = function (id, name, + blob) { + assertExecutionOrder('start putAttachment ' + name); + var storage = this; + return storage._sub_storage.putAttachment(id, name, blob) + .push(function (result) { + assertExecutionOrder('stop putAttachment ' + name); + return result; + }); + }; + + StorageFourParallelOperation.prototype.buildQuery = function () { + return this._sub_storage.buildQuery.apply(this._sub_storage, arguments); + }; + StorageFourParallelOperation.prototype.allAttachments = function () { + return this._sub_storage.allAttachments.apply(this._sub_storage, + arguments); + }; + + StorageFourParallelOperation.prototype.hasCapacity = function () { + return this._sub_storage.hasCapacity.apply(this._sub_storage, arguments); + }; + + jIO.addStorage( + 'four_parallel_attachment', + StorageFourParallelOperation + ); + + this.jio = jIO.createJIO({ + type: "replicate", + check_local_attachment_creation: true, + parallel_operation_attachment_amount: 4, + local_sub_storage: { + type: "memory" + }, + remote_sub_storage: { + type: "four_parallel_attachment" + } + }); + + return RSVP.all([ + context.jio.put("0", {}), + context.jio.put("1", {}) + ]) + .then(function () { + return RSVP.all([ + context.jio.putAttachment("0", "00", new Blob(["0"])), + context.jio.putAttachment("0", "01", new Blob(["1"])), + context.jio.putAttachment("0", "02", new Blob(["2"])), + context.jio.putAttachment("0", "03", new Blob(["3"])), + context.jio.putAttachment("1", "10", new Blob(["0"])), + context.jio.putAttachment("1", "11", new Blob(["1"])), + context.jio.putAttachment("1", "12", new Blob(["2"])), + context.jio.putAttachment("1", "13", new Blob(["3"])) + ]); + }) + .then(function () { + return context.jio.repair(); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + +}(jIO, QUnit, Blob, RSVP)); \ No newline at end of file diff --git a/test/tests.html b/test/tests.html index a1b4b765b6a5af4f746f6274b8d36b23a40de4e7..5712c9c3e117dc50e03ddf71badb86ceb763917c 100644 --- a/test/tests.html +++ b/test/tests.html @@ -40,6 +40,8 @@ <script src="jio.storage/indexeddbstorage.tests.js"></script> <script src="jio.storage/uuidstorage.tests.js"></script> <script src="jio.storage/replicatestorage.tests.js"></script> + <script src="jio.storage/replicatestorage_repair.tests.js"></script> + <script src="jio.storage/replicatestorage_repairattachment.tests.js"></script> <script src="jio.storage/shastorage.tests.js"></script> <!--script src="jio.storage/qiniustorage.tests.js"></script-->