Commit c2386704 authored by Bryan Kaperick's avatar Bryan Kaperick

Added additional testing, fixed attachment methods, incorporated Romain's...

Added additional testing, fixed attachment methods, incorporated Romain's comments, and added more comments and simplified code structure.
parent f71fb6cb
/*jslint nomen: true*/ /*jslint nomen: true*/
/*global RSVP, jiodate*/ /*global RSVP*/
(function (jIO) { (function (jIO, RSVP) {
"use strict"; "use strict";
//local mod/frozen remote
//local del/remote mod
// Used to distinguish between operations done within the same millisecond // Used to distinguish between operations done within the same millisecond
var unique_timestamp = function () { var unique_timestamp = function () {
...@@ -15,7 +12,89 @@ ...@@ -15,7 +12,89 @@
.toString(16)).slice(-4), .toString(16)).slice(-4),
timestamp = Date.now().toString(); timestamp = Date.now().toString();
return timestamp + "-" + uuid; return timestamp + "-" + uuid;
}; },
// Helper function for getAttachment
findAttachment = function (substorage, name, metadata_query, steps) {
var options = {
query: metadata_query,
sort_on: [["timestamp", "descending"], ["op", "ascending"]],
select_list: ["op", "name"]
};
return substorage.allDocs(options)
.push(function (results) {
var ind,
id = metadata_query.value,
count = 0;
// At the least, a document needs to have been put and an attachment
// needs to have been put
if (results.data.rows.length > 1) {
for (ind = 0; ind < results.data.rows.length; ind += 1) {
// Cannot get the attachment of a removed document
if (results.data.rows[ind].value.op === "remove") {
throw new jIO.util.jIOError(
"HistoryStorage: cannot find attachment '" + name +
"' of object '" + id + "' (removed)",
404
);
}
// Make sure to get the correct revision of the attachment
// and throw 404 error if it was removed
if (results.data.rows[ind].value.name === name) {
if (count === steps) {
if (results.data.rows[ind].value.op === "removeAttachment") {
throw new jIO.util.jIOError(
"HistoryStorage: cannot find attachment '" + name +
"' of object '" + id + "' (removed)",
404
);
}
return substorage.getAttachment(
results.data.rows[ind].id,
name
);
}
count += 1;
}
}
}
throw new jIO.util.jIOError(
"HistoryStorage: cannot find attachment '" + name +
"' of object '" + id + "'",
404
);
});
},
findDoc = function (substorage, metadata_query, steps) {
var options = {
query: metadata_query,
sort_on: [["timestamp", "descending"]],
select_list: ["op"],
limit: [steps, 1]
};
return substorage.allDocs(options)
.push(function (results) {
var id_in = metadata_query.query_list[0].value;
if (results.data.rows.length > 0) {
if (results.data.rows[0].value.op === "put") {
return substorage.get(results.data.rows[0].id)
.push(function (result) {
return result.doc;
});
}
throw new jIO.util.jIOError(
"HistoryStorage: cannot find object '" + id_in + "' (removed)",
404
);
}
throw new jIO.util.jIOError(
"HistoryStorage: cannot find object '" + id_in + "'",
404
);
});
};
/** /**
* The jIO HistoryStorage extension * The jIO HistoryStorage extension
...@@ -24,92 +103,53 @@ ...@@ -24,92 +103,53 @@
* @constructor * @constructor
*/ */
function HistoryStorage(spec) { function HistoryStorage(spec) {
this._sub_storage = jIO.createJIO(spec.sub_storage);
this._sub_storage = jIO.createJIO({
type: "query",
sub_storage: spec.sub_storage
});
} }
HistoryStorage.prototype.get = function (id_in) { HistoryStorage.prototype.get = function (id_in) {
// Query to get the last edit made to this document // Query to get the last edit made to this document
var substorage = this._sub_storage, var substorage = this._sub_storage,
metadata_query = function (id) { metadata_query;
return "doc_id: " + id + " AND ((op: put) OR (op: remove))";
}, // Include id_in as value in query object for safety
options = { metadata_query = jIO.QueryFactory.create(
query: metadata_query(id_in), "(doc_id: undefined) AND ((op: put) OR (op: remove))"
sort_on: [["timestamp", "descending"]], );
limit: [0, 1] metadata_query.query_list[0].value = id_in;
};
return findDoc(substorage, metadata_query, 0)
return substorage.allDocs(options) .push(undefined,
.push(function (results) { // If no documents returned in first query, check if the id is encoding
if (results.data.rows.length > 0) { // revision information
return substorage.get(results.data.rows[0].id); function (error) {
}
throw new jIO.util.jIOError( if (!(error instanceof jIO.util.jIOError) ||
"HistoryStorage: cannot find object '" + id_in + "' (0)", (error.status_code !== 404) ||
404 (error.message !== "HistoryStorage: cannot find object '" +
); id_in + "'")) {
}) throw error;
.push(function (result) { }
if (result.op === "put") {
return result.doc;
}
throw new jIO.util.jIOError(
"HistoryStorage: cannot find object '" + id_in + "' (removed)",
404
);
// If no documents returned in first query, check if the id is encoding // "_-" is the revision signature used to indicate a previous revision
// revision information var steps,
}, function () { steps_loc = id_in.lastIndexOf("_-");
var steps,
steps_loc = id_in.lastIndexOf("_-");
// If revision signature is not in id_in, than return 404, since id
// is not found
if (steps_loc === -1) {
throw new jIO.util.jIOError(
"HistoryStorage: cannot find object '" + id_in + "' (1)",
404
);
}
// If revision signature is found, query storage based on this // If the revision signature '_-' is not contained in the id, then
steps = Number(id_in.slice(steps_loc + 2)); // the first findDoc call should have found the id if it exists
id_in = id_in.slice(0, steps_loc); if (steps_loc === -1) {
options = {
query: metadata_query(id_in),
sort_on: [["timestamp", "descending"]],
limit: [steps, 1]
};
return substorage.allDocs(options)
.push(function (results) {
if (results.data.rows.length > 0) {
return substorage.get(results.data.rows[0].id);
}
throw new jIO.util.jIOError(
"HistoryStorage: cannot find object '" + id_in + "' (2)",
404
);
})
.push(function (result) {
if (result.op === "put") {
return result.doc;
}
throw new jIO.util.jIOError( throw new jIO.util.jIOError(
"HistoryStorage: cannot find object '" + id_in + "HistoryStorage: cannot find object '" + id_in + "'",
"' (removed) (1)",
404 404
); );
}); }
});
};
HistoryStorage.prototype.post = function (metadata) { // If revision signature is found, query storage based on this
return this._sub_storage.post(metadata); steps = Number(id_in.slice(steps_loc + 2));
id_in = id_in.slice(0, steps_loc);
metadata_query.query_list[0].value = id_in;
return findDoc(substorage, metadata_query, steps);
});
}; };
HistoryStorage.prototype.put = function (id, data) { HistoryStorage.prototype.put = function (id, data) {
...@@ -136,12 +176,25 @@ ...@@ -136,12 +176,25 @@
}; };
HistoryStorage.prototype.allAttachments = function (id) { HistoryStorage.prototype.allAttachments = function (id) {
// XXX: Do we need to be able to retrieve older revisions with
// allAttachments?
var substorage = this._sub_storage, var substorage = this._sub_storage,
options = { query_obj,
query: "(doc_id: " + id + ") AND " + options;
"((op: putAttachment) OR (op: removeAttachment))",
sort_on: [["timestamp", "descending"]] // Include id as value in query object for safety (as opposed to string
}; // concatenation)
query_obj = jIO.QueryFactory.create(
"(doc_id: undefined) AND ((op: putAttachment) OR (op: removeAttachment))"
);
query_obj.query_list[0].value = id;
// Only query for attachment edits
options = {
query: query_obj,
sort_on: [["timestamp", "descending"]]
};
return this._sub_storage.allDocs(options) return this._sub_storage.allDocs(options)
.push(function (results) { .push(function (results) {
var promises = results.data.rows.map(function (data) { var promises = results.data.rows.map(function (data) {
...@@ -154,6 +207,8 @@ ...@@ -154,6 +207,8 @@
attachments = {}, attachments = {},
ind, ind,
doc; doc;
// Only include attachments whose most recent edit is a putAttachment
// (and not a removeAttachment)
for (ind = 0; ind < results.length; ind += 1) { for (ind = 0; ind < results.length; ind += 1) {
doc = results[ind]; doc = results[ind];
if (!seen.hasOwnProperty(doc.name)) { if (!seen.hasOwnProperty(doc.name)) {
...@@ -187,79 +242,45 @@ ...@@ -187,79 +242,45 @@
// Query to get the last edit made to this document // Query to get the last edit made to this document
var substorage = this._sub_storage, var substorage = this._sub_storage,
metadata_query = function (id) { metadata_query;
return "(doc_id: " + id +
") AND (name: " + name + // Include id_in as value in query object for safety
") AND ((op: putAttachment) OR (op: removeAttachment))"; metadata_query = jIO.QueryFactory.create(
}, "(doc_id: undefined)"
options = { );
query: metadata_query(id), metadata_query.value = id;
sort_on: [["timestamp", "descending"]], return findAttachment(substorage, name, metadata_query, 0)
limit: [0, 1] .push(undefined,
};
return substorage.allDocs(options) // If no documents returned in first query, check if the id is encoding
.push(function (results) { // revision information
if (results.data.rows.length > 0) { function (error) {
return substorage.get(results.data.rows[0].id);
} if (!(error instanceof jIO.util.jIOError) ||
throw new jIO.util.jIOError( (error.status_code !== 404) ||
"HistoryStorage: cannot find object '" + id + "' (0)", (error.message !== "HistoryStorage: cannot find attachment '" +
404 name + "' of object '" + id + "'")) {
); throw error;
}) }
.push(function (result) {
if (result.op === "putAttachment") {
return substorage.getAttachment(result.timestamp, result.name);
//return result.blob;
}
throw new jIO.util.jIOError(
"HistoryStorage: cannot find object '" + id + "' (removed)",
404
);
// If no documents returned in first query, check if the id is encoding var steps,
// revision information steps_loc = name.lastIndexOf("_-");
}, function () {
var steps,
steps_loc = id.lastIndexOf("_-");
// If revision signature is not in id_in, than return 404, since id
// is not found
if (steps_loc === -1) {
throw new jIO.util.jIOError(
"HistoryStorage: cannot find object '" + id + "' (1)",
404
);
}
// If revision signature is found, query storage based on this // If revision signature is not in id_in, than return 404, since id
steps = Number(id.slice(steps_loc + 2)); // is not found
id = id.slice(0, steps_loc); if (steps_loc === -1) {
options = {
query: metadata_query(id),
sort_on: [["timestamp", "descending"]],
limit: [steps, 1]
};
return substorage.allDocs(options)
.push(function (results) {
if (results.data.rows.length > 0) {
return substorage.get(results.data.rows[0].id);
}
throw new jIO.util.jIOError( throw new jIO.util.jIOError(
"HistoryStorage: cannot find object '" + id + "' (2)", "HistoryStorage: cannot find attachment '" + name +
"' of object '" + id + "'",
404 404
); );
}) }
.push(function (result) {
if (result.op === "putAttachment") { // If revision signature is found, query storage based on this
return substorage.getAttachment(result.timestamp, result.name); steps = Number(name.slice(steps_loc + 2));
//return result.blob; name = name.slice(0, steps_loc);
} return findAttachment(substorage, name, metadata_query, steps);
throw new jIO.util.jIOError( });
"HistoryStorage: cannot find object '" + id + "' (removed) (1)",
404
);
});
});
}; };
HistoryStorage.prototype.removeAttachment = function (id, name) { HistoryStorage.prototype.removeAttachment = function (id, name) {
...@@ -281,9 +302,7 @@ ...@@ -281,9 +302,7 @@
}; };
HistoryStorage.prototype.buildQuery = function (options) { HistoryStorage.prototype.buildQuery = function (options) {
if (options.message === "give all docs") { // Set default values
return this._sub_storage.allDocs(options.opts);
}
if (options === undefined) { if (options === undefined) {
options = {}; options = {};
} }
...@@ -298,17 +317,7 @@ ...@@ -298,17 +317,7 @@
} }
options.sort_on.push(["timestamp", "descending"]); options.sort_on.push(["timestamp", "descending"]);
options.query = jIO.QueryFactory.create(options.query); options.query = jIO.QueryFactory.create(options.query);
var meta_options = { var meta_options,
// XXX: I don't believe it's currently possible to query on
// sub-attributes so for now, we just use the inputted query, which
// obviously will fail
//query: "",//(op: put) OR (op: remove)",
// XXX: same here, we cannot sort correctly because we cannot access
// attributes of doc
query: "(op: remove) OR (op: put)",
sort_on: options.sort_on
},
substorage = this._sub_storage, substorage = this._sub_storage,
// Check if query involved _REVISION. If not, we will later place a // Check if query involved _REVISION. If not, we will later place a
...@@ -322,6 +331,8 @@ ...@@ -322,6 +331,8 @@
} else { } else {
rev_query = (query_obj.key === "_REVISION"); rev_query = (query_obj.key === "_REVISION");
} }
// Traverse through query tree to find mentions of _REVISION
// and stop as soon as it is found once
while (query_stack.length > 0 && (!rev_query)) { while (query_stack.length > 0 && (!rev_query)) {
query_obj = query_stack.pop(); query_obj = query_stack.pop();
for (ind = 0; ind < query_obj.query_list.length; ind += 1) { for (ind = 0; ind < query_obj.query_list.length; ind += 1) {
...@@ -334,18 +345,24 @@ ...@@ -334,18 +345,24 @@
} }
} }
// Query for all edits putting or removing documents (and nothing about
// attachments)
meta_options = {
query: "(op: remove) OR (op: put)",
sort_on: options.sort_on
};
return this._sub_storage.allDocs(meta_options) return this._sub_storage.allDocs(meta_options)
// Get all documents found in query // Get all documents found in query
// XXX: Once include_docs is implemented, this step can be simplified
.push(function (results) { .push(function (results) {
var promises = results.data.rows.map(function (data) { var promises = results.data.rows.map(function (data) {
return substorage.get(data.id); return substorage.get(data.id);
}); });
return RSVP.all(promises); return RSVP.all(promises);
}) })
.push(function (results) {
.push(function (results) {
// Label all documents with their current revision status // Label all documents with their current revision status
var docum, var docum,
revision_tracker = {}, revision_tracker = {},
...@@ -361,6 +378,9 @@ ...@@ -361,6 +378,9 @@
if (docum.op === "remove") { if (docum.op === "remove") {
docum.doc = {}; docum.doc = {};
} }
// Add op and _REVISION to the docum.doc (temporarily) so the
// document can be matched manually with the inputted query
results[ind].doc._REVISION = revision_tracker[docum.doc_id]; results[ind].doc._REVISION = revision_tracker[docum.doc_id];
results[ind].doc.op = docum.op; results[ind].doc.op = docum.op;
} }
...@@ -370,12 +390,16 @@ ...@@ -370,12 +390,16 @@
latest_rev_query = jIO.QueryFactory.create( latest_rev_query = jIO.QueryFactory.create(
"(_REVISION: >= 0) AND (op: put)" "(_REVISION: >= 0) AND (op: put)"
); );
// If query does not use _REVISION, then by default set _REVISION := 0
if (rev_query) { if (rev_query) {
latest_rev_query.query_list[0] = options.query; latest_rev_query.query_list[0] = options.query;
} else { } else {
latest_rev_query.query_list[0] = jIO.QueryFactory.create( latest_rev_query.query_list[0] = jIO.QueryFactory.create(
"(_REVISION: = 0)" "(_REVISION: = 0)"
); );
// Check if options.query is nonempty
if (options.query.type === "simple" || if (options.query.type === "simple" ||
options.query.type === "complex") { options.query.type === "complex") {
latest_rev_query.query_list.push(options.query); latest_rev_query.query_list.push(options.query);
...@@ -404,7 +428,8 @@ ...@@ -404,7 +428,8 @@
return true; return true;
}) })
// Format results to be expected output of allDocs // Return certain attributes in .val as specified by
// options.select_list
.map(function (current_doc) { .map(function (current_doc) {
var val = {}, var val = {},
ind, ind,
...@@ -415,6 +440,7 @@ ...@@ -415,6 +440,7 @@
val[key] = current_doc.doc[key]; val[key] = current_doc.doc[key];
} }
} }
// Format results to be expected output of allDocs
return { return {
doc: current_doc.doc, doc: current_doc.doc,
value: val, value: val,
...@@ -426,4 +452,4 @@ ...@@ -426,4 +452,4 @@
jIO.addStorage('history', HistoryStorage); jIO.addStorage('history', HistoryStorage);
}(jIO)); }(jIO, RSVP));
\ No newline at end of file \ No newline at end of file
/*jslint nomen: true*/ /*jslint nomen: true*/
/*global Blob, jiodate*/ /*global Blob*/
(function (jIO, QUnit) { (function (jIO, RSVP, Blob, QUnit) {
"use strict"; "use strict";
var test = QUnit.test, var test = QUnit.test,
stop = QUnit.stop, stop = QUnit.stop,
...@@ -37,11 +37,14 @@ ...@@ -37,11 +37,14 @@
jio = jIO.createJIO({ jio = jIO.createJIO({
type: "history", type: "history",
sub_storage: { sub_storage: {
type: "uuid", type: "query",
sub_storage: { sub_storage: {
//type: "memory" type: "uuid",
type: "indexeddb", sub_storage: {
database: dbname //type: "memory"
type: "indexeddb",
database: dbname
}
} }
} }
}), }),
...@@ -297,17 +300,20 @@ ...@@ -297,17 +300,20 @@
test("Testing proper adding/removing attachments", test("Testing proper adding/removing attachments",
function () { function () {
stop(); stop();
expect(9); expect(26);
// create storage of type "history" with memory as substorage // create storage of type "history" with memory as substorage
var jio = jIO.createJIO({ var dbname = "db_" + Date.now(),
jio = jIO.createJIO({
type: "history", type: "history",
sub_storage: { sub_storage: {
type: "uuid", type: "query",
sub_storage: { sub_storage: {
type: "memory" type: "uuid",
//type: "indexeddb", sub_storage: {
//database: dbname type: "indexeddb",
database: dbname
}
} }
} }
}), }),
...@@ -316,17 +322,20 @@ ...@@ -316,17 +322,20 @@
sub_storage: { sub_storage: {
type: "uuid", type: "uuid",
sub_storage: { sub_storage: {
type: "memory" type: "indexeddb",
//type: "indexeddb", database: dbname
//database: dbname
} }
} }
}), }),
blob1 = new Blob(['a']), blob1 = new Blob(['a']),
blob2 = new Blob(['b']), blob2 = new Blob(['b']),
blob3 = new Blob(['ccc']),
other_blob = new Blob(['1']); other_blob = new Blob(['1']);
jio.put("doc", {title: "foo0"}) jio.put("doc", {title: "foo0"})
.push(function () {
return jio.put("doc2", {key: "val"});
})
.push(function () { .push(function () {
return jio.putAttachment("doc", "attached", blob1); return jio.putAttachment("doc", "attached", blob1);
}) })
...@@ -342,7 +351,7 @@ ...@@ -342,7 +351,7 @@
.push(function (result) { .push(function (result) {
deepEqual(result, { deepEqual(result, {
title: "foo0" title: "foo0"
}, "Get does not return any attachment information"); }, "Get does not return any attachment/revision information");
return jio.getAttachment("doc", "attached"); return jio.getAttachment("doc", "attached");
}) })
.push(function (result) { .push(function (result) {
...@@ -355,26 +364,40 @@ ...@@ -355,26 +364,40 @@
.push(function (result) { .push(function (result) {
deepEqual(result, deepEqual(result,
blob2, blob2,
"Return the attachment information with getAttachment" "Return the attachment information with getAttachment for " +
"current revision"
); );
return jio.getAttachment("doc", "attached_-1"); return jio.getAttachment("doc", "attached_-1");
}, function (error) {
ok(false, error);
}) })
.push(function (result) { .push(function (result) {
deepEqual(result, deepEqual(result,
blob1, blob1,
"Return the attachment information with getAttachment" "Return the attachment information with getAttachment for " +
"previous revision"
); );
return jio.getAttachment("doc", "attached_-2"); return jio.getAttachment("doc", "attached_-2");
}, function (error) {
ok(false, error);
}) })
.push(function () { .push(function () {
ok(false, "This query should have thrown a 404 error"); ok(false, "This query should have thrown a 404 error");
}, },
function (error) { function (error) {
ok(error instanceof jIO.util.jIOError, "Correct type of error");
deepEqual(error.status_code, deepEqual(error.status_code,
404, 404,
"Error if you try to go back more revisions than what exists"); "Error if you try to go back more revisions than what exists");
return jio.allAttachments("doc"); return jio.getAttachment("doc", "other_attached");
}) })
.push(function (result) {
deepEqual(result,
other_blob,
"Other document successfully queried"
);
return jio.allAttachments("doc");
})
.push(function (results) { .push(function (results) {
deepEqual(results, { deepEqual(results, {
"attached": {}, "attached": {},
...@@ -388,13 +411,14 @@ ...@@ -388,13 +411,14 @@
.push(function (result) { .push(function (result) {
deepEqual(result, { deepEqual(result, {
title: "foo0" title: "foo0"
}, "Get does not return any attachment information"); }, "Get does not return any attachment information (9)");
return jio.getAttachment("doc", "attached"); return jio.getAttachment("doc", "attached");
}) })
.push(function () { .push(function () {
ok(false, "This query should have thrown a 404 error"); ok(false, "This query should have thrown a 404 error");
}, },
function (error) { function (error) {
ok(error instanceof jIO.util.jIOError, "Correct type of error");
deepEqual(error.status_code, deepEqual(error.status_code,
404, 404,
"Removed attachments cannot be queried"); "Removed attachments cannot be queried");
...@@ -404,18 +428,99 @@ ...@@ -404,18 +428,99 @@
deepEqual(results, { deepEqual(results, {
"other_attached": {} "other_attached": {}
}, "allAttachments works as expected with a removed attachment"); }, "allAttachments works as expected with a removed attachment");
return jio.putAttachment("doc", "attached", blob3);
}) })
.push(function () {
return not_history.allDocs();
})
.push(function (results) {
var promises = results.data.rows.map(function (data) {
return not_history.get(data.id);
});
return RSVP.all(promises);
})
.push(function (results) {
deepEqual(results, [
{timestamp: results[0].timestamp,
doc_id: "doc", doc: results[0].doc, op: "put"},
{timestamp: results[1].timestamp,
doc_id: "doc2", doc: results[1].doc, op: "put"},
{timestamp: results[2].timestamp,
doc_id: "doc", name: "attached", op: "putAttachment"},
{timestamp: results[3].timestamp,
doc_id: "doc", name: "attached", op: "putAttachment"},
{timestamp: results[4].timestamp,
doc_id: "doc", name: "other_attached", op: "putAttachment"},
{timestamp: results[5].timestamp,
doc_id: "doc", name: "attached", op: "removeAttachment"},
{timestamp: results[6].timestamp,
doc_id: "doc", name: "attached", op: "putAttachment"}
], "Other storage can access all document revisions."
);
})
.push(function () {
return jio.getAttachment("doc", "attached");
})
.push(function (result) {
deepEqual(result,
blob3,
"Return the attachment information with getAttachment"
);
return jio.getAttachment("doc", "attached_-0");
})
.push(function (result) {
deepEqual(result,
blob3,
"Return the attachment information with getAttachment"
);
return jio.getAttachment("doc", "attached_-1");
})
.push(function () {
ok(false, "This query should have thrown a 404 error");
},
function (error) {
ok(error instanceof jIO.util.jIOError, "Correct type of error");
deepEqual(error.status_code,
404,
"Error if you try to go back to a removed attachment state");
return jio.getAttachment("doc", "attached_-2");
})
.push(function (result) {
deepEqual(result,
blob2,
"Return the attachment information with getAttachment (17)"
);
return jio.getAttachment("doc", "attached_-3");
})
.push(function (result) {
deepEqual(result,
blob1,
"Return the attachment information with getAttachment"
);
return jio.getAttachment("doc", "attached_-4");
})
.push(function () {
ok(false, "This query should have thrown a 404 error");
},
function (error) {
ok(error instanceof jIO.util.jIOError, "Correct type of error");
deepEqual(error.status_code,
404,
"Error if you try to go back more revisions than what exists");
})
.push(function () { .push(function () {
return jio.allDocs(); return jio.allDocs();
}) })
.push(function (results) { .push(function (results) {
equal(results.data.rows.length, 1, "Only one document in storage"); equal(results.data.rows.length,
return jio.get(results.data.rows[0].id); 2,
"Two documents in accessible storage");
return jio.get(results.data.rows[1].id);
}) })
.push(function (result) { .push(function (result) {
deepEqual(result, { deepEqual(result, {
"title": "foo0" "title": "foo0"
}); }, "Get second document accessible from jio storage");
return not_history.allDocs(); return not_history.allDocs();
}) })
...@@ -424,6 +529,22 @@ ...@@ -424,6 +529,22 @@
return not_history.get(d.id); return not_history.get(d.id);
})); }));
}) })
.push(function (results) {
equal(results.length, 7, "Seven document revisions in storage (24)");
return jio.remove("doc");
})
.push(function () {
return jio.getAttachment("doc", "attached");
})
.push(function () {
ok(false, "This query should have thrown a 404 error");
},
function (error) {
ok(error instanceof jIO.util.jIOError, "Correct type of error");
deepEqual(error.status_code,
404,
"Cannot get the attachment of a removed document");
})
.fail(function (error) { .fail(function (error) {
//console.log(error); //console.log(error);
ok(false, error); ok(false, error);
...@@ -446,9 +567,12 @@ ...@@ -446,9 +567,12 @@
var jio = jIO.createJIO({ var jio = jIO.createJIO({
type: "history", type: "history",
sub_storage: { sub_storage: {
type: "uuid", type: "query",
sub_storage: { sub_storage: {
type: "memory" type: "uuid",
sub_storage: {
type: "memory"
}
} }
} }
}); });
...@@ -627,6 +751,7 @@ ...@@ -627,6 +751,7 @@
.always(function () {start(); }); .always(function () {start(); });
}); });
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// Querying older revisions // Querying older revisions
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
...@@ -641,9 +766,12 @@ ...@@ -641,9 +766,12 @@
var jio = jIO.createJIO({ var jio = jIO.createJIO({
type: "history", type: "history",
sub_storage: { sub_storage: {
type: "uuid", type: "query",
sub_storage: { sub_storage: {
type: "memory" type: "uuid",
sub_storage: {
type: "memory"
}
} }
} }
}); });
...@@ -854,7 +982,7 @@ ...@@ -854,7 +982,7 @@
}) })
.push(function (results) { .push(function (results) {
equal(results.data.rows.length, 4, equal(results.data.rows.length, 4,
"Correct number of results with optins.limit set"); "Correct number of results with options.limit set");
deepEqual(results.data.rows[0].doc, { deepEqual(results.data.rows[0].doc, {
"k2": "w0" "k2": "w0"
}, "Correct results with options.limit set"); }, "Correct results with options.limit set");
...@@ -907,9 +1035,12 @@ ...@@ -907,9 +1035,12 @@
var jio = jIO.createJIO({ var jio = jIO.createJIO({
type: "history", type: "history",
sub_storage: { sub_storage: {
type: "uuid", type: "query",
sub_storage: { sub_storage: {
type: "memory" type: "uuid",
sub_storage: {
type: "memory"
}
} }
} }
}), }),
...@@ -960,4 +1091,4 @@ ...@@ -960,4 +1091,4 @@
.always(function () {start(); }); .always(function () {start(); });
}); });
}(jIO, QUnit)); }(jIO, RSVP, Blob, QUnit));
\ No newline at end of file \ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment