Commit d42fadc0 authored by Marco Mariani's avatar Marco Mariani

Merge remote-tracking branch 'origin/master' into keys-jiodate-async

parents 98cf075d cadb268e
......@@ -20,7 +20,7 @@
}
window.complex_queries = {};
module(window.complex_queries, RSVP);
}(['exports'], function (to_export, RSVP) {
}(['exports', 'rsvp'], function (to_export, RSVP) {
"use strict";
/**
......
......@@ -15,12 +15,12 @@
<body>
<table>
<tr>
<td>Query (String):<br /><textarea id="str">1:abc AND 2:def</textarea></td>
<td>Query (Object):<br /><textarea id="obj">{&quot;type&quot;:&quot;complex&quot;,&quot;operator&quot;:&quot;AND&quot;,&quot;query_list&quot;:[{&quot;type&quot;:&quot;simple&quot;,&quot;operator&quot;:&quot;=&quot;,&quot;key&quot;:&quot;1&quot;,&quot;value&quot;:&quot;abc&quot;},{&quot;type&quot;:&quot;simple&quot;,&quot;operator&quot;:&quot;=&quot;,&quot;key&quot;:&quot;2&quot;,&quot;value&quot;:&quot;def&quot;}]}</textarea></td>
<td>Query (String):<br /><textarea id="str">title:abc AND format:def</textarea></td>
<td>Query (Object):<br /><textarea id="obj">{&quot;type&quot;:&quot;complex&quot;,&quot;operator&quot;:&quot;AND&quot;,&quot;query_list&quot;:[{&quot;type&quot;:&quot;simple&quot;,&quot;operator&quot;:&quot;=&quot;,&quot;key&quot;:&quot;title&quot;,&quot;value&quot;:&quot;abc&quot;},{&quot;type&quot;:&quot;simple&quot;,&quot;operator&quot;:&quot;=&quot;,&quot;key&quot;:&quot;format&quot;,&quot;value&quot;:&quot;def&quot;}]}</textarea></td>
</tr>
<tr>
<td>Item list (to filter, from 'Query (Object)'):<br /><textarea id="list">[{&quot;1&quot;:&quot;abc&quot;,&quot;2&quot;:&quot;def&quot;},{&quot;1&quot;:&quot;def&quot;,&quot;2&quot;:&quot;abc&quot;}]</textarea></td>
<td>Result list:<br /><textarea id="result">[{&quot;1&quot;:&quot;abc&quot;,&quot;2&quot;:&quot;def&quot;}]</textarea></td>
<td>Item list (to filter, from 'Query (Object)'):<br /><textarea id="list">[{&quot;title&quot;:&quot;abc&quot;,&quot;format&quot;:&quot;def&quot;},{&quot;title&quot;:&quot;def&quot;,&quot;format&quot;:&quot;abc&quot;}]</textarea></td>
<td>Result list:<br /><textarea id="result"></textarea></td>
</tr>
<tr>
<td><label for="wildcard">Wildcard char: </label></td>
......@@ -28,11 +28,11 @@
</tr>
<tr>
<td><label for="sort_on">Sort on: </label></td>
<td><input type="text" id="sort_on" name="sort_on" value="[[&quot;1&quot;,&quot;ascending&quot;],[&quot;2&quot;,&quot;descending&quot;]]" /></td>
<td><input type="text" id="sort_on" name="sort_on" value="[[&quot;title&quot;,&quot;ascending&quot;],[&quot;format&quot;,&quot;descending&quot;]]" /></td>
</tr>
<tr>
<td><label for="select_list">Select_list: </label></td>
<td><input type="text" id="select_list" name="select_list" value="[&quot;1&quot;,&quot;2&quot;]" /></td>
<td><input type="text" id="select_list" name="select_list" value="[&quot;title&quot;,&quot;format&quot;]" /></td>
</tr>
<tr>
<td><label for="limit">Limit: </label></td>
......@@ -42,24 +42,39 @@
<button onclick="searchTextToJson()">Search text to JSON</button>
<button onclick="jsonToSearchText()">JSON to Search text</button>
<button onclick="query()">Query</button>
<script type="text/javascript" src="../lib/md5/md5.js"></script>
<script type="text/javascript" src="../lib/jsSha2/sha2.js"></script>
<script type="text/javascript" src="../lib/sjcl/sjcl.min.js"></script>
<script type="text/javascript" src="../jio.min.js"></script>
<script type="text/javascript" src="../complex_queries.min.js"></script>
<script type="text/javascript" src="../lib/rsvp/rsvp-custom.js"></script>
<script type="text/javascript" src="../complex_queries.js"></script>
<script type="text/javascript"
src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script type="text/javascript">
<!--
var searchTextToJson = function () {
$("#obj").attr("value", JSON.stringify(complex_queries.Query.parseStringToObject($("#str").attr("value"))));
};
var jsonToSearchText = function () {
$("#str").attr("value", complex_queries.QueryFactory.create(JSON.parse($("#obj").attr("value"))).toString());
};
var query = function () {
function searchTextToJson() {
$("#obj").attr(
"value",
JSON.stringify(
complex_queries.QueryFactory.create(
$("#str").attr("value")
).serialized()
)
);
}
function jsonToSearchText() {
$("#str").attr(
"value",
complex_queries.QueryFactory.create(
JSON.parse(
$("#obj").attr("value")
)
).toString()
);
}
function query() {
var list = JSON.parse($("#list").attr("value"));
$("#str").attr("value", complex_queries.QueryFactory.create(JSON.parse($("#obj").attr("value"))).exec(
complex_queries.QueryFactory.create(
JSON.parse(
$("#obj").attr("value")
)
).exec(
list,
{
"wildcard_character": $('#wildcard').attr('value'),
......@@ -67,9 +82,10 @@ var query = function () {
"limit": JSON.parse($("#limit").attr("value")),
"select_list": JSON.parse($("#select_list").attr("value"))
}
));
$("#result").attr("value", JSON.stringify(list));
};
).then(function (list) {
$("#result").attr("value", JSON.stringify(list));
});
}
// -->
</script>
</body>
......
......@@ -17,6 +17,7 @@ var log = function (o) {
<div id="log">
</div>
<script src="../src/sha256.amd.js"></script>
<script src="../lib/rsvp/rsvp-custom.js"></script>
<script src="../jio.js"></script>
<script src="../complex_queries.js"></script>
<script src="../src/jio.storage/localstorage.js"></script>
......@@ -34,6 +35,11 @@ jio_instance = jIO.createJIO({
});
// Careful! These are asynchronous methods!
// And they use promises with a custom version of RSVP.js
// For more information, see
// RSVP https://github.com/tildeio/rsvp.js#rsvpjs--
// Promises A+ http://promisesaplus.com/
// CommonJS http://wiki.commonjs.org/wiki/Promises
log('-> post "video" document metadata to localStorage');
jio_instance.post({
......@@ -86,11 +92,11 @@ jio_instance.post({
}).then(function (response) {
return jIO.util.blobAsBinaryString(response.data);
return jIO.util.readBlobAsBinaryString(response.data);
}).then(function (binary_string) {
}).then(function (event) {
log('Video content is: ' + binary_string);
log('Video content is: ' + event.target.result);
log('-> remove "video" document from localStorage');
return jio_instance.remove({"_id":'video'});
......
......@@ -197,6 +197,24 @@
*/
that._database = spec.database || [];
/**
* True if it has been modified
*
* @property modified
* @type Boolean
* @default false
*/
that.modified = false;
/**
* Updates the modified date
*
* @method touch
*/
that.touch = function () {
that.modified = true;
};
/**
* Adds a metadata object in the database, replace if already exist
*
......@@ -232,10 +250,11 @@
that._database.push(needed_meta);
that._location[meta._id] = that._database.length - 1;
}
that.modified = true;
return true;
}
if (typeof that._location[meta._id] === "number") {
that.remove(meta);
return that.remove(meta);
}
return false;
};
......@@ -245,6 +264,7 @@
*
* @method remove
* @param {Object} meta The metadata to remove
* @return {Boolean} true if removed else false
*/
that.remove = function (meta) {
if (typeof meta._id !== "string") {
......@@ -252,11 +272,13 @@
}
if (typeof that._location[meta._id] !== "number") {
// throw new ReferenceError("Not Found");
return;
return false;
}
that._database[that._location[meta._id]] = null;
that._free.push(that._location[meta._id]);
delete that._location[meta._id];
that.modified = true;
return true;
};
/**
......@@ -354,6 +376,8 @@
that._database.splice(i, 1);
}
}
that.modified = true;
return true;
};
/**
......@@ -454,11 +478,13 @@
IndexStorage.prototype.getIndexDatabase = function (command, index) {
index = this._indices[index];
function makeNewIndex() {
return new JSONIndex({
var json_index = new JSONIndex({
"_id": index.id,
"_attachment": index.attachment || "body",
"indexing": index.index
});
json_index.touch();
return json_index;
}
return command.storage(
index.sub_storage || this._sub_storage
......@@ -497,6 +523,9 @@
IndexStorage.prototype.storeIndexDatabase = function (command, database,
index) {
var that = this;
if (!database.modified) {
return RSVP.resolve({"result": "success"});
}
index = this._indices[index];
function putAttachment() {
return command.storage(
......
......@@ -364,7 +364,7 @@
*/
LocalStorage.prototype.removeAttachment = function (command, param) {
var doc = this._storage.getItem(this._localpath + "/" + param._id);
if (typeof doc !== 'object') {
if (typeof doc !== 'object' || doc === null) {
return command.error(
"not_found",
"missing document",
......@@ -539,7 +539,7 @@
}
// check document type
if (typeof doc !== 'object') {
if (typeof doc !== 'object' || doc === null) {
// wrong document
if (!repair) {
return {"error": true, "answers": [
......
......@@ -5,7 +5,7 @@
*/
/*jslint indent:2, maxlen: 80, nomen: true */
/*global jIO, define */
/*global jIO, define, Blob */
/**
* Provides a split storage for JIO. This storage splits data
......@@ -329,9 +329,9 @@
if (err) {
err.message = "Unable to " + method + " document";
delete err.index;
return that.error(err);
return command.error(err);
}
that.success({"id": doc_underscores._id});
command.success({"id": doc_underscores._id});
});
};
......@@ -368,10 +368,10 @@
var i, attachment_list = [], data = param._blob;
for (i = 0; i < priv.storage_list.length; i += 1) {
attachment_list[i] = jIO.util.deepClone(param);
attachment_list[i]._data = data.slice(
(data.length / priv.storage_list.length) * i,
(data.length / priv.storage_list.length) * (i + 1),
"application/octet-stream"
attachment_list[i]._blob = data.slice(
data.size * i / priv.storage_list.length,
data.size * (i + 1) / priv.storage_list.length,
data.type
);
}
priv.send(
......@@ -447,7 +447,7 @@
}
}
}
that.success({"data": doc});
command.success({"data": doc});
});
};
......@@ -462,17 +462,15 @@
err,
response
) {
var i, doc;
if (err) {
err.message = "Unable to get attachment";
delete err.index;
return command.error(err);
}
doc = '';
for (i = 0; i < response.length; i += 1) {
doc += response[i].data;
}
that.success({"data": doc}); // XXX get mimetype
command.success({"data": new Blob(response.map(function (answer) {
return answer.data;
}), {"type": response[0].data.type})});
});
};
......
......@@ -20,7 +20,7 @@
}
window.complex_queries = {};
module(window.complex_queries, RSVP);
}(['exports'], function (to_export, RSVP) {
}(['exports', 'rsvp'], function (to_export, RSVP) {
"use strict";
/**
......
......@@ -263,6 +263,43 @@
(/\bPhantomJS\b/i).test(navigator.userAgent)) {
window.Blob = Blob;
window.FileReader = FileReader;
//console.warn("Blob and FileReader have been replaced!");
}
if (!Function.prototype.bind) {
//////////////////////////////////////////////////////////////////////
// https://github.com/TristanCavelier/notesntools/blob/master/javascript/\
// bind.js
/**
* Creates a new function that, when called, has its `this` keyword set to
* the provided value, with a given sequence of arguments preceding any
* provided when the new function is called. See Mozilla Developer Network:
* Function.prototype.bind
*
* In PhantomJS, their is a bug with `Function.prototype.bind`. You can
* reproduce this bug by testing this code:
*
* function a(str) { console.log(this, str); }
* var b = a.bind({"a": "b"}, "test");
* b();
*
* @param {Object} thisArg The value to be passed as the `this` parameter to
* the target function when the bound function is called. The value is
* ignored if the bound function is constructed using the `new` operator.
*
* @param {Any} [arg]* Arguments to prepend to arguments provided to the
* bound function when invoking the target function.
*
* @return {Function} The bound function.
*/
Function.prototype.bind = function (thisArg) {
var fun = this, args = [].slice.call(arguments, 1);
return function () {
args.push.apply(args, arguments);
return fun.apply(thisArg, args);
};
};
//console.warn("Function.prototype.bind has been replaced!");
}
}());
/*jslint indent: 2, maxlen: 80, nomen: true */
/*global define, jIO, jio_tests, test, ok, deepEqual, sinon, module */
/*global define, jIO, test_util, RSVP, test, ok, deepEqual, module, stop,
start, hex_sha256 */
// define([module_name], [dependencies], module);
(function (dependencies, module) {
......@@ -7,519 +8,957 @@
if (typeof define === 'function' && define.amd) {
return define(dependencies, module);
}
module(jIO, jio_tests);
}(['jio', 'jio_tests', 'localstorage', 'splitstorage'], function (jIO, util) {
module(jIO, test_util, RSVP);
}([
'jio',
'test_util',
'rsvp',
'localstorage',
'splitstorage'
], function (jIO, util, RSVP) {
"use strict";
function generateTools() {
return {
clock: sinon.useFakeTimers(),
spy: util.ospy,
tick: util.otick
};
var tool = {
"readBlobAsBinaryString": jIO.util.readBlobAsBinaryString
};
function reverse(promise) {
return new RSVP.Promise(function (resolve, reject, notify) {
promise.then(reject, resolve, notify);
}, function () {
promise.cancel();
});
}
/**
* sequence(thens): Promise
*
* Executes a sequence of *then* callbacks. It acts like
* `smth().then(callback).then(callback)...`. The first callback is called
* with no parameter.
*
* Elements of `thens` array can be a function or an array contaning at most
* three *then* callbacks: *onFulfilled*, *onRejected*, *onNotified*.
*
* When `cancel()` is executed, each then promises are cancelled at the same
* time.
*
* @param {Array} thens An array of *then* callbacks
* @return {Promise} A new promise
*/
function sequence(thens) {
var promises = [];
return new RSVP.Promise(function (resolve, reject, notify) {
var i;
promises[0] = new RSVP.Promise(function (resolve) {
resolve();
});
for (i = 0; i < thens.length; i += 1) {
if (Array.isArray(thens[i])) {
promises[i + 1] = promises[i].
then(thens[i][0], thens[i][1], thens[i][2]);
} else {
promises[i + 1] = promises[i].then(thens[i]);
}
}
promises[i].then(resolve, reject, notify);
}, function () {
var i;
for (i = 0; i < promises.length; i += 1) {
promises[i].cancel();
}
});
}
function unexpectedError(error) {
if (error instanceof Error) {
deepEqual([
error.name + ": " + error.message,
error
], "UNEXPECTED ERROR", "Unexpected error");
} else {
deepEqual(error, "UNEXPECTED ERROR", "Unexpected error");
}
}
module("SplitStorage + LocalStorage");
test("Post", function () {
var o = generateTools();
o.jio = jIO.newJio({
var shared = {}, jio, jio_local_list = [];
shared.workspace = {};
shared.local_storage_description1 = {
"type": "local",
"username": "splitstorage",
"application_name": "post1",
"mode": "memory"
};
shared.local_storage_description2 = {
"type": "local",
"username": "splitstorage",
"application_name": "post2",
"mode": "memory"
};
jio = jIO.createJIO({
"type": "split",
"storage_list": [{
"type": "local",
"username": "splitstorage",
"application_name": "post1"
}, {
"type": "local",
"username": "splitstorage",
"application_name": "post2"
}]
"storage_list": [
shared.local_storage_description1,
shared.local_storage_description2
]
}, {"workspace": shared.workspace});
jio_local_list[0] = jIO.createJIO(shared.local_storage_description1, {
"workspace": shared.workspace
});
jio_local_list[1] = jIO.createJIO(shared.local_storage_description2, {
"workspace": shared.workspace
});
jio_local_list.run = function (method, argument) {
var i, promises = [];
for (i = 0; i < this.length; i += 1) {
promises[i] = this[i][method].apply(this[i], argument);
}
return RSVP.all(promises);
};
jio_local_list.get = function () {
return this.run("get", arguments);
};
stop();
// post without id
o.spy(o, "jobstatus", "done", "Post document without id");
o.jio.post({
jio.post({
"_underscored_meta": "uvalue",
"meta": "data"
}, function (err, response) {
o.f(err, response);
o.uuid = (err || response).id;
ok(util.isUuid(o.uuid), "Uuid should look like " +
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx : " + o.uuid);
});
o.tick(o);
// check uploaded documents
deepEqual(util.jsonlocalstorage.getItem(
'jio/localstorage/splitstorage/post1/' + o.uuid
), {
"_id": o.uuid,
"_underscored_meta": "uvalue",
"data": "{\"meta\""
}, "Check uploaded document in sub storage 1");
deepEqual(util.jsonlocalstorage.getItem(
'jio/localstorage/splitstorage/post2/' + o.uuid
), {
"_id": o.uuid,
"_underscored_meta": "uvalue",
"data": ":\"data\"}"
}, "Check uploaded document in sub storage 2");
// post with id
o.spy(o, "value", {"ok": true, "id": "one"}, "Post document with id");
o.jio.post({
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data",
"hello": "world"
}, o.f);
o.tick(o);
// check uploaded documents
deepEqual(util.jsonlocalstorage.getItem(
'jio/localstorage/splitstorage/post1/one'
), {
"_id": "one",
"_underscored_meta": "uvalue",
"data": "{\"meta\":\"data\","
}, "Check uploaded document in sub storage 1");
}).then(function (answer) {
shared.uuid = answer.id;
answer.id = "<uuid>";
ok(util.isUuid(shared.uuid), "Uuid should look like " +
"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx : " + shared.uuid);
deepEqual(answer, {
"id": "<uuid>",
"method": "post",
"result": "success",
"status": 201,
"statusText": "Created"
}, "Post document without id");
// check uploaded documents
return jio_local_list.get({"_id": shared.uuid});
}).then(function (answers) {
var i;
for (i = 0; i < answers.length; i += 1) {
deepEqual(answers[i].data, {
"_id": shared.uuid,
"_underscored_meta": "uvalue",
"data": i === 0 ? "{\"meta\"" : ":\"data\"}"
}, "Check uploaded document in sub storage " + (i + 1));
}
deepEqual(util.jsonlocalstorage.getItem(
'jio/localstorage/splitstorage/post2/one'
), {
"_id": "one",
"_underscored_meta": "uvalue",
"data": "\"hello\":\"world\"}"
}, "Check uploaded document in sub storage 2");
// post with id
return jio.post({
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data",
"hello": "world"
});
// post with id
o.spy(o, "status", 409, "Post document with same id");
o.jio.post({
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data",
"hello": "world"
}, o.f);
o.tick(o);
}).then(function (answer) {
deepEqual(answer, {
"id": "one",
"method": "post",
"result": "success",
"status": 201,
"statusText": "Created"
}, "Post document with id");
// check uploaded documents
return jio_local_list.get({"_id": "one"});
}).then(function (answers) {
deepEqual(answers[0].data, {
"_id": "one",
"_underscored_meta": "uvalue",
"data": "{\"meta\":\"data\","
}, "Check uploaded document in sub storage 1");
deepEqual(answers[1].data, {
"_id": "one",
"_underscored_meta": "uvalue",
"data": "\"hello\":\"world\"}"
}, "Check uploaded document in sub storage 2");
// post with id
return reverse(jio.post({
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data",
"hello": "world"
}));
}).then(function (answer) {
deepEqual(answer, {
"error": "conflict",
"id": "one",
"message": "Unable to post document",
"method": "post",
"reason": "document exists",
"result": "error",
"status": 409,
"statusText": "Conflict"
}, "Post document with same id -> 409 Conflict");
}).fail(unexpectedError).always(start);
util.closeAndcleanUpJio(o.jio);
});
test("PutAttachment", function () {
var o = generateTools();
o.jio = jIO.newJio({
var shared = {}, jio, jio_local_list = [];
shared.workspace = {};
shared.local_storage_description1 = {
"type": "local",
"username": "splitstorage",
"application_name": "putAttachment1",
"mode": "memory"
};
shared.local_storage_description2 = {
"type": "local",
"username": "splitstorage",
"application_name": "putAttachment2",
"mode": "memory"
};
jio = jIO.createJIO({
"type": "split",
"storage_list": [{
"type": "local",
"username": "splitstorage",
"application_name": "putAttachment1"
}, {
"type": "local",
"username": "splitstorage",
"application_name": "putAttachment2"
}]
"storage_list": [
shared.local_storage_description1,
shared.local_storage_description2
]
}, {"workspace": shared.workspace});
jio_local_list[0] = jIO.createJIO(shared.local_storage_description1, {
"workspace": shared.workspace
});
jio_local_list[1] = jIO.createJIO(shared.local_storage_description2, {
"workspace": shared.workspace
});
jio_local_list.run = function (method, argument) {
var i, promises = [];
for (i = 0; i < this.length; i += 1) {
promises[i] = this[i][method].apply(this[i], argument);
}
return RSVP.all(promises);
};
jio_local_list.get = function () {
return this.run("get", arguments);
};
jio_local_list.getAttachmentAsBinaryString = function () {
return this.run("getAttachment", arguments).then(function (answers) {
var i, promises = [];
for (i = 0; i < answers.length; i += 1) {
promises[i] = tool.readBlobAsBinaryString(answers[i].data);
}
return RSVP.all(promises);
});
};
o.spy(o, "status", 404, "Put attachment on a inexistent document");
o.jio.putAttachment({
"_id": "one",
"_attachment": "my_attachment",
"_data": "My Data",
"_mimetype": "text/plain"
}, o.f);
o.tick(o);
o.jio.post({"_id": "one", "_underscored_meta": "uvalue", "meta": "data"});
o.clock.tick(1000);
o.spy(o, "value", {
"ok": true,
"id": "one",
"attachment": "my_attachment"
}, "Put attachment");
o.jio.putAttachment({
stop();
return reverse(jio.putAttachment({
"_id": "one",
"_attachment": "my_attachment",
"_data": "My Data",
"_mimetype": "text/plain"
}, o.f);
o.tick(o);
// check uploaded documents
deepEqual(util.jsonlocalstorage.getItem(
'jio/localstorage/splitstorage/putAttachment1/one'
), {
"_id": "one",
"_underscored_meta": "uvalue",
"data": "{\"meta\"",
"_attachments": {
"my_attachment": {
"length": 3,
"digest": "md5-1b4686bc8ca15befdccb1da1dcb8c271", // md5("My ")
"content_type": "text/plain"
}
}
}, "Check uploaded document in sub storage 1");
"_content_type": "text/plain"
})).then(function (answer) {
deepEqual(answer, {
"attachment": "my_attachment",
"error": "not_found",
"id": "one",
"message": "Unable to put attachment",
"method": "putAttachment",
"reason": "missing",
"result": "error",
"status": 404,
"statusText": "Not Found"
}, "Put attachment on a inexistent document -> 404 Not Found");
return jio.post({
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data"
});
deepEqual(util.jsonlocalstorage.getItem(
'jio/localstorage/splitstorage/putAttachment2/one'
), {
"_id": "one",
"_underscored_meta": "uvalue",
"data": ":\"data\"}",
"_attachments": {
"my_attachment": {
"length": 4,
"digest": "md5-f6068daa29dbb05a7ead1e3b5a48bbee", // md5("Data")
"content_type": "text/plain"
}
}
}, "Check uploaded document in sub storage 2");
}).then(function () {
return jio.putAttachment({
"_id": "one",
"_attachment": "my_attachment",
"_data": "My Data",
"_mimetype": "text/plain"
});
deepEqual(util.jsonlocalstorage.getItem(
'jio/localstorage/splitstorage/putAttachment1/one/my_attachment'
), "My ", "Check uploaded document in sub storage 1");
}).then(function (answer) {
deepEqual(answer, {
"attachment": "my_attachment",
"id": "one",
"method": "putAttachment",
"result": "success",
"status": 204,
"statusText": "No Content"
}, "Put attachment on a document");
// check uploaded documents
return jio_local_list.get({"_id": "one"});
}).then(function (answers) {
deepEqual(answers[0].data, {
"_attachments": {
"my_attachment": {
"content_type": "text/plain",
"digest": "sha256-ebf2d770a6a2dfa135f6c81431f22fc3cbcde9ae" +
"e52759ca9e520d4d964c1322", // sha256("My ")
"length": 3
}
},
"_id": "one",
"_underscored_meta": "uvalue",
"data": "{\"meta\""
}, "Check uploaded document in sub storage 1");
deepEqual(answers[1].data, {
"_attachments": {
"my_attachment": {
"content_type": "text/plain",
"digest": "sha256-cec3a9b89b2e391393d0f68e4bc12a9fa6cf358b" +
"3cdf79496dc442d52b8dd528", // sha256("Data")
"length": 4
}
},
"_id": "one",
"_underscored_meta": "uvalue",
"data": ":\"data\"}"
}, "Check uploaded document in sub storage 2");
return jio_local_list.getAttachmentAsBinaryString({
"_id": "one",
"_attachment": "my_attachment"
});
deepEqual(util.jsonlocalstorage.getItem(
'jio/localstorage/splitstorage/putAttachment2/one/my_attachment'
), "Data", "Check uploaded document in sub storage 2");
}).then(function (events) {
deepEqual(events[0].target.result, "My ",
"Check uploaded document in sub storage 1");
deepEqual(events[1].target.result, "Data",
"Check uploaded document in sub storage 1");
}).fail(unexpectedError).always(start);
util.closeAndcleanUpJio(o.jio);
});
test("Get", function () {
var o = generateTools();
o.jio = jIO.newJio({
var shared = {}, jio;
shared.workspace = {};
shared.local_storage_description1 = {
"type": "local",
"username": "splitstorage",
"application_name": "get1",
"mode": "memory"
};
shared.local_storage_description2 = {
"type": "local",
"username": "splitstorage",
"application_name": "get2",
"mode": "memory"
};
jio = jIO.createJIO({
"type": "split",
"storage_list": [{
"type": "local",
"username": "splitstorage",
"application_name": "get1"
}, {
"type": "local",
"username": "splitstorage",
"application_name": "get2"
}]
});
"storage_list": [
shared.local_storage_description1,
shared.local_storage_description2
]
}, {"workspace": shared.workspace});
stop();
reverse(jio.get({"_id": "one"})).then(function (answer) {
deepEqual(answer, {
"error": "not_found",
"id": "one",
"message": "Unable to get document",
"method": "get",
"reason": "missing",
"result": "error",
"status": 404,
"statusText": "Not Found"
}, "Get missing document");
return jio.post({
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data"
});
o.spy(o, "status", 404, "Get missing document");
o.jio.get({"_id": "one"}, o.f);
o.tick(o);
}).then(function () {
o.jio.post({"_id": "one", "_underscored_meta": "uvalue", "meta": "data"});
o.clock.tick(1000);
return jio.get({"_id": "one"});
o.spy(o, "value", {
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data"
}, "Get posted document");
o.jio.get({"_id": "one"}, o.f);
o.tick(o);
}).then(function (answer) {
o.jio.putAttachment({
"_id": "one",
"_attachment": "my_attachment",
"_data": "My Data",
"_mimetype": "text/plain"
});
o.clock.tick(1000);
deepEqual(answer.data, {
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data"
}, "Get posted document");
o.spy(o, "value", {
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data",
"_attachments": {
"my_attachment": {
"length": 7,
"content_type": "text/plain"
return jio.putAttachment({
"_id": "one",
"_attachment": "my_attachment",
"_data": "My Data",
"_content_type": "text/plain"
});
}).then(function () {
return jio.get({"_id": "one"});
}).then(function (answer) {
deepEqual(answer.data, {
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data",
"_attachments": {
"my_attachment": {
"length": 7,
"content_type": "text/plain"
}
}
}
}, "Get document with attachment informations");
o.jio.get({"_id": "one"}, o.f);
o.tick(o);
}, "Get document with attachment informations");
}).fail(unexpectedError).always(start);
util.closeAndcleanUpJio(o.jio);
});
test("GetAttachment", function () {
var o = generateTools();
o.jio = jIO.newJio({
var shared = {}, jio;
shared.workspace = {};
shared.local_storage_description1 = {
"type": "local",
"username": "splitstorage",
"application_name": "getAttachment1",
"mode": "memory"
};
shared.local_storage_description2 = {
"type": "local",
"username": "splitstorage",
"application_name": "getAttachment2",
"mode": "memory"
};
jio = jIO.createJIO({
"type": "split",
"storage_list": [{
"type": "local",
"username": "splitstorage",
"application_name": "getAttachment1"
}, {
"type": "local",
"username": "splitstorage",
"application_name": "getAttachment2"
}]
});
"storage_list": [
shared.local_storage_description1,
shared.local_storage_description2
]
}, {"workspace": shared.workspace});
stop();
o.spy(o, "status", 404, "Get attachment from missing document");
o.jio.getAttachment({"_id": "one", "_attachment": "my_attachment"}, o.f);
o.tick(o);
reverse(jio.getAttachment({
"_id": "one",
"_attachment": "my_attachment"
})).then(function (answer) {
deepEqual(answer, {
"attachment": "my_attachment",
"error": "not_found",
"id": "one",
"message": "Unable to get attachment",
"method": "getAttachment",
"reason": "missing document",
"result": "error",
"status": 404,
"statusText": "Not Found"
}, "Get attachment from missing document -> 404 Not Found");
return jio.post({
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data"
});
o.jio.post({"_id": "one", "_underscored_meta": "uvalue", "meta": "data"});
o.clock.tick(1000);
}).then(function () {
return reverse(jio.getAttachment({
"_id": "one",
"_attachment": "my_attachment"
}));
}).then(function (answer) {
deepEqual(answer, {
"attachment": "my_attachment",
"error": "not_found",
"id": "one",
"message": "Unable to get attachment",
"method": "getAttachment",
"reason": "missing attachment",
"result": "error",
"status": 404,
"statusText": "Not Found"
}, "Get missing attachment from document");
return jio.putAttachment({
"_id": "one",
"_attachment": "my_attachment",
"_data": "My Data",
"_mimetype": "text/plain"
});
o.spy(o, "status", 404, "Get missing attachment from document");
o.jio.getAttachment({"_id": "one", "_attachment": "my_attachment"}, o.f);
o.tick(o);
}).then(function () {
o.jio.putAttachment({
"_id": "one",
"_attachment": "my_attachment",
"_data": "My Data",
"_mimetype": "text/plain"
});
o.clock.tick(1000);
return jio.getAttachment({"_id": "one", "_attachment": "my_attachment"});
}).then(function (answer) {
return tool.readBlobAsBinaryString(answer.data);
}).then(function (event) {
o.spy(o, "value", "My Data", "Get attachment");
o.jio.getAttachment({"_id": "one", "_attachment": "my_attachment"}, o.f);
o.tick(o);
deepEqual(event.target.result, "My Data", "Get attachment");
}).fail(unexpectedError).always(start);
util.closeAndcleanUpJio(o.jio);
});
test("removeAttachment", function () {
var o = generateTools();
test("RemoveAttachment", function () {
var shared = {}, jio;
o.jio = jIO.newJio({
shared.workspace = {};
shared.local_storage_description1 = {
"type": "local",
"username": "splitstorage",
"application_name": "removeAttachment1",
"mode": "memory"
};
shared.local_storage_description2 = {
"type": "local",
"username": "splitstorage",
"application_name": "removeAttachment2",
"mode": "memory"
};
jio = jIO.createJIO({
"type": "split",
"storage_list": [{
"type": "local",
"username": "splitstorage",
"application_name": "removeAttachment1"
}, {
"type": "local",
"username": "splitstorage",
"application_name": "removeAttachment2"
}]
});
"storage_list": [
shared.local_storage_description1,
shared.local_storage_description2
]
}, {"workspace": shared.workspace});
o.spy(o, "status", 404, "Remove attachment from inexistent document");
o.jio.removeAttachment({"_id": "one", "_attachment": "my_attachment"}, o.f);
o.tick(o);
stop();
o.jio.post({"_id": "one", "_underscored_meta": "uvalue", "meta": "data"});
o.clock.tick(1000);
reverse(jio.removeAttachment({
"_id": "one",
"_attachment": "my_attachment"
})).then(function (answer) {
deepEqual(answer, {
"attachment": "my_attachment",
"error": "not_found",
"id": "one",
"message": "Unable to remove attachment",
"method": "removeAttachment",
"reason": "missing document",
"result": "error",
"status": 404,
"statusText": "Not Found"
}, "Remove attachment from inexistent document -> 404 Not Found");
return jio.post({
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data"
});
o.spy(o, "status", 404, "Remove inexistent attachment");
o.jio.removeAttachment({"_id": "one", "_attachment": "my_attachment"}, o.f);
o.tick(o);
}).then(function () {
return reverse(jio.removeAttachment({
"_id": "one",
"_attachment": "my_attachment"
}));
}).then(function (answer) {
deepEqual(answer, {
"attachment": "my_attachment",
"error": "not_found",
"id": "one",
"message": "Unable to remove attachment",
"method": "removeAttachment",
"reason": "missing attachment",
"result": "error",
"status": 404,
"statusText": "Not Found"
}, "Remove inexistent attachment -> 404 Not Found");
return jio.putAttachment({
"_id": "one",
"_attachment": "my_attachment",
"_data": "My Data",
"_mimetype": "text/plain"
});
o.jio.putAttachment({
"_id": "one",
"_attachment": "my_attachment",
"_data": "My Data",
"_mimetype": "text/plain"
});
o.clock.tick(1000);
}).then(function () {
return jio.removeAttachment({
"_id": "one",
"_attachment": "my_attachment"
});
o.spy(o, "value", {
"ok": true,
"id": "one",
"attachment": "my_attachment"
}, "Remove attachment");
o.jio.removeAttachment({"_id": "one", "_attachment": "my_attachment"}, o.f);
o.tick(o);
}).then(function (answer) {
o.spy(o, "value", {
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data"
}, "Get document for check");
o.jio.get({"_id": "one"}, o.f);
o.tick(o);
deepEqual(answer, {
"attachment": "my_attachment",
"id": "one",
"method": "removeAttachment",
"result": "success",
"status": 204,
"statusText": "No Content"
}, "Remove attachment");
return jio.get({"_id": "one"});
}).then(function (answer) {
o.spy(o, "status", 404, "Get attachment for check");
o.jio.getAttachment({"_id": "one", "_attachment": "my_attachment"}, o.f);
o.tick(o);
deepEqual(answer.data, {
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data"
}, "Check document");
return reverse(jio.getAttachment({
"_id": "one",
"_attachment": "my_attachment"
}));
}).then(function (answer) {
deepEqual(answer, {
"attachment": "my_attachment",
"error": "not_found",
"id": "one",
"message": "Unable to get attachment",
"method": "getAttachment",
"reason": "missing attachment",
"result": "error",
"status": 404,
"statusText": "Not Found"
}, "Check attachment -> 404 Not Found");
}).fail(unexpectedError).always(start);
util.closeAndcleanUpJio(o.jio);
});
test("remove", function () {
var o = generateTools();
o.jio = jIO.newJio({
test("Remove", function () {
var shared = {}, jio;
shared.workspace = {};
shared.local_storage_description1 = {
"type": "local",
"username": "splitstorage",
"application_name": "remove1",
"mode": "memory"
};
shared.local_storage_description2 = {
"type": "local",
"username": "splitstorage",
"application_name": "remove2",
"mode": "memory"
};
jio = jIO.createJIO({
"type": "split",
"storage_list": [{
"type": "local",
"username": "splitstorage",
"application_name": "remove1"
}, {
"type": "local",
"username": "splitstorage",
"application_name": "remove2"
}]
});
"storage_list": [
shared.local_storage_description1,
shared.local_storage_description2
]
}, {"workspace": shared.workspace});
stop();
reverse(jio.remove({"_id": "one"})).then(function (answer) {
deepEqual(answer, {
"error": "not_found",
"id": "one",
"message": "Unable to remove document",
"method": "remove",
"reason": "missing",
"result": "error",
"status": 404,
"statusText": "Not Found"
}, "Remove missing document -> 404 Not Found");
return jio.post({
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data"
});
o.spy(o, "status", 404, "Remove missing document");
o.jio.remove({"_id": "one"}, o.f);
o.tick(o);
}).then(function () {
o.jio.post({"_id": "one", "_underscored_meta": "uvalue", "meta": "data"});
o.clock.tick(1000);
return jio.putAttachment({
"_id": "one",
"_attachment": "my_attachment",
"_data": "My Data",
"_mimetype": "text/plain"
});
o.jio.putAttachment({
"_id": "one",
"_attachment": "my_attachment",
"_data": "My Data",
"_mimetype": "text/plain"
});
o.clock.tick(1000);
}).then(function () {
return jio.remove({"_id": "one"});
o.spy(o, "value", {"ok": true, "id": "one"}, "Remove document");
o.jio.remove({"_id": "one"}, o.f);
o.tick(o);
}).then(function (answer) {
o.spy(o, "status", 404, "Get attachment for check");
o.jio.getAttachment({"_id": "one", "_attachment": "my_attachment"}, o.f);
o.tick(o);
deepEqual(answer, {
"id": "one",
"method": "remove",
"result": "success",
"status": 204,
"statusText": "No Content"
}, "Remove document");
o.spy(o, "status", 404, "Get document for check");
o.jio.get({"_id": "one"}, o.f);
o.tick(o);
return reverse(jio.getAttachment({
"_id": "one",
"_attachment": "my_attachment"
}));
}).then(function (answer) {
deepEqual(answer, {
"attachment": "my_attachment",
"error": "not_found",
"id": "one",
"message": "Unable to get attachment",
"method": "getAttachment",
"reason": "missing document",
"result": "error",
"status": 404,
"statusText": "Not Found"
}, "Check attachment -> 404 Not Found");
return reverse(jio.get({"_id": "one"}));
}).then(function (answer) {
deepEqual(answer, {
"error": "not_found",
"id": "one",
"message": "Unable to get document",
"method": "get",
"reason": "missing",
"result": "error",
"status": 404,
"statusText": "Not Found"
}, "Check document -> 404 Not Found");
}).fail(unexpectedError).always(start);
util.closeAndcleanUpJio(o.jio);
});
test("Put", function () {
var o = generateTools();
o.jio = jIO.newJio({
var shared = {}, jio;
shared.workspace = {};
shared.local_storage_description1 = {
"type": "local",
"username": "splitstorage",
"application_name": "put1",
"mode": "memory"
};
shared.local_storage_description2 = {
"type": "local",
"username": "splitstorage",
"application_name": "put2",
"mode": "memory"
};
jio = jIO.createJIO({
"type": "split",
"storage_list": [{
"type": "local",
"username": "splitstorage",
"application_name": "put1"
}, {
"type": "local",
"username": "splitstorage",
"application_name": "put2"
}]
});
"storage_list": [
shared.local_storage_description1,
shared.local_storage_description2
]
}, {"workspace": shared.workspace});
o.spy(o, "value", {"ok": true, "id": "one"}, "Put document");
o.jio.put({
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data"
}, o.f);
o.tick(o);
stop();
o.spy(o, "value", {
jio.put({
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data"
}, "Get document for check");
o.jio.get({"_id": "one"}, o.f);
o.tick(o);
}).then(function (answer) {
deepEqual(answer, {
"id": "one",
"method": "put",
"result": "success",
"status": 204,
"statusText": "No Content"
}, "Put new document");
return jio.get({"_id": "one"});
}).then(function (answer) {
deepEqual(answer.data, {
"_id": "one",
"_underscored_meta": "uvalue",
"meta": "data"
}, "Check document");
return jio.put({
"_id": "one",
"_underscored_meta": "uvalue",
"meow": "dog"
});
o.spy(o, "value", {"ok": true, "id": "one"}, "Put document again");
o.jio.put({
"_id": "one",
"_underscored_meta": "uvalue",
"meow": "dog"
}, o.f);
o.tick(o);
}).then(function (answer) {
o.spy(o, "value", {
"_id": "one",
"_underscored_meta": "uvalue",
"meow": "dog"
}, "Get document for check");
o.jio.get({"_id": "one"}, o.f);
o.tick(o);
deepEqual(answer, {
"id": "one",
"method": "put",
"result": "success",
"status": 204,
"statusText": "No Content"
}, "Put same document again");
return jio.get({"_id": "one"});
}).then(function (answer) {
deepEqual(answer.data, {
"_id": "one",
"_underscored_meta": "uvalue",
"meow": "dog"
}, "Get document for check");
}).fail(unexpectedError).always(start);
util.closeAndcleanUpJio(o.jio);
});
test("AllDocs", function () {
var o = generateTools();
o.jio = jIO.newJio({
var shared = {}, jio;
shared.workspace = {};
shared.local_storage_description1 = {
"type": "local",
"username": "splitstorage",
"application_name": "alldocs1",
"mode": "memory"
};
shared.local_storage_description2 = {
"type": "local",
"username": "splitstorage",
"application_name": "alldocs2",
"mode": "memory"
};
jio = jIO.createJIO({
"type": "split",
"storage_list": [{
"type": "local",
"username": "splitstorage",
"application_name": "alldocs1"
}, {
"type": "local",
"username": "splitstorage",
"application_name": "alldocs2"
}]
});
for (o.i = 0; o.i < 5; o.i += 1) {
o.jio.post({
"_id": "doc" + o.i,
"_underscored_meta": "uvalue" + o.i,
"meta": "data" + o.i
});
o.clock.tick(1000);
"storage_list": [
shared.local_storage_description1,
shared.local_storage_description2
]
}, {"workspace": shared.workspace});
stop();
function prepareDatabase() {
var i, do_list = [];
function post(i) {
return function () {
return jio.post({
"_id": "doc" + i,
"_underscored_meta": "uvalue" + i,
"meta": "data" + i
});
};
}
function putAttachment(i) {
return function () {
return jio.putAttachment({
"_id": "doc" + i,
"_attachment": "my_attachment" + i,
"_data": "My Data" + i,
"_content_type": "text/plain"
});
};
}
for (i = 0; i < 5; i += 1) {
do_list.push(post(i));
}
for (i = 0; i < 2; i += 1) {
do_list.push(putAttachment(i));
}
return sequence(do_list);
}
for (o.i = 0; o.i < 2; o.i += 1) {
o.jio.putAttachment({
"_id": "doc" + o.i,
"_attachment": "my_attachment" + o.i,
"_data": "My Data" + o.i,
"_mimetype": "text/plain"
});
o.clock.tick(1000);
}
prepareDatabase().then(function () {
o.spy(o, "value", {
"_id": "doc1",
"_underscored_meta": "uvalue1",
"meta": "data1",
"_attachments": {
"my_attachment1": {
"length": 8,
"content_type": "text/plain"
return jio.get({"_id": "doc1"});
}).then(function (answer) {
deepEqual(answer.data, {
"_id": "doc1",
"_underscored_meta": "uvalue1",
"meta": "data1",
"_attachments": {
"my_attachment1": {
"length": 8,
"content_type": "text/plain"
}
}
}
}, "Get document for check");
o.jio.get({"_id": "doc1"}, o.f);
o.tick(o);
o.spy(o, "value", {
"total_rows": 5,
"rows": [{
"id": "doc0",
"key": "doc0",
"value": {}
}, {
"id": "doc1",
"key": "doc1",
"value": {}
}, {
"id": "doc2",
"key": "doc2",
"value": {}
}, {
"id": "doc3",
"key": "doc3",
"value": {}
}, {
"id": "doc4",
"key": "doc4",
"value": {}
}]
}, "AllDocs with document ids only");
o.jio.allDocs(function (err, response) {
if (response && Array.isArray(response.rows)) {
response.rows.sort(function (a, b) {
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
});
}
o.f(err, response);
});
o.tick(o);
}, "Check document");
return jio.allDocs();
}).then(function (answer) {
answer.data.rows.sort(function (a, b) {
return a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
});
deepEqual(answer.data, {
"total_rows": 5,
"rows": [{
"id": "doc0",
"key": "doc0",
"value": {}
}, {
"id": "doc1",
"key": "doc1",
"value": {}
}, {
"id": "doc2",
"key": "doc2",
"value": {}
}, {
"id": "doc3",
"key": "doc3",
"value": {}
}, {
"id": "doc4",
"key": "doc4",
"value": {}
}]
}, "AllDocs with document ids only");
}).fail(unexpectedError).always(start);
util.closeAndcleanUpJio(o.jio);
});
}));
......@@ -47,5 +47,8 @@
<script src="../src/jio.storage/replicaterevisionstorage.js"></script>
<script src="../test/jio.storage/replicaterevisionstorage.tests.js"></script>
<script src="../src/jio.storage/splitstorage.js"></script>
<script src="../test/jio.storage/splitstorage.tests.js"></script>
</body>
</html>
......@@ -37,6 +37,9 @@
"replicaterevisionstorage_tests":
"jio.storage/replicaterevisionstorage.tests",
"splitstorage": "../src/jio.storage/splitstorage",
"splitstorage_tests": "jio.storage/splitstorage.tests",
"qunit": "../lib/qunit/qunit",
"sinon": "../lib/sinon/sinon",
"sinon_qunit": "../lib/sinon/sinon-qunit"
......@@ -56,6 +59,7 @@
"indexstorage_tests",
"gidstorage_tests",
"revisionstorage_tests",
"replicaterevisionstorage_tests"
"replicaterevisionstorage_tests",
"splitstorage_tests"
]);
}());
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