michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: * http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: Cu.import("resource://services-common/storageservice.js"); michael@0: Cu.import("resource://testing-common/services-common/storageserver.js"); michael@0: michael@0: function run_test() { michael@0: initTestLogging("Trace"); michael@0: michael@0: run_next_test(); michael@0: } michael@0: michael@0: function getRandomUser() { michael@0: return "" + (Math.floor(Math.random() * 100000) + 1); michael@0: } michael@0: michael@0: function getEmptyServer(user=getRandomUser(), password="password") { michael@0: let users = {}; michael@0: users[user] = password; michael@0: michael@0: return storageServerForUsers(users, { michael@0: meta: {}, michael@0: clients: {}, michael@0: crypto: {}, michael@0: }); michael@0: } michael@0: michael@0: function getClient(server, user=getRandomUser(), password="password") { michael@0: let identity = server.server.identity; michael@0: let url = identity.primaryScheme + "://" + identity.primaryHost + ":" + michael@0: identity.primaryPort + "/2.0/" + user; michael@0: let client = new StorageServiceClient(url); michael@0: client.addListener({ michael@0: onDispatch: function onDispatch(request) { michael@0: let up = user + ":" + password; michael@0: request.request.setHeader("authorization", "Basic " + btoa(up)); michael@0: } michael@0: }); michael@0: michael@0: return client; michael@0: } michael@0: michael@0: function getServerAndClient(user=getRandomUser(), password="password") { michael@0: let server = getEmptyServer(user, password); michael@0: let client = getClient(server, user, password); michael@0: michael@0: return [server, client, user, password]; michael@0: } michael@0: michael@0: add_test(function test_auth_failure_listener() { michael@0: _("Ensure the onAuthFailure listener is invoked."); michael@0: michael@0: let server = getEmptyServer(); michael@0: let client = getClient(server, "324", "INVALID"); michael@0: client.addListener({ michael@0: onAuthFailure: function onAuthFailure(client, request) { michael@0: _("onAuthFailure"); michael@0: server.stop(run_next_test); michael@0: } michael@0: }); michael@0: michael@0: let request = client.getCollectionInfo(); michael@0: request.dispatch(); michael@0: }); michael@0: michael@0: add_test(function test_duplicate_listeners() { michael@0: _("Ensure that duplicate listeners aren't installed multiple times."); michael@0: michael@0: let server = getEmptyServer(); michael@0: let client = getClient(server, "1234567", "BAD_PASSWORD"); michael@0: michael@0: let invokeCount = 0; michael@0: let listener = { michael@0: onAuthFailure: function onAuthFailure() { michael@0: invokeCount++; michael@0: } michael@0: }; michael@0: michael@0: client.addListener(listener); michael@0: // No error expected. michael@0: client.addListener(listener); michael@0: michael@0: let request = client.getCollectionInfo(); michael@0: request.dispatch(function onComplete() { michael@0: do_check_eq(invokeCount, 1); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_handler_object() { michael@0: _("Ensure that installed handlers get their callbacks invoked."); michael@0: michael@0: let [server, client] = getServerAndClient(); michael@0: michael@0: let onCompleteCount = 0; michael@0: let onDispatchCount = 0; michael@0: michael@0: let handler = { michael@0: onComplete: function onComplete() { michael@0: onCompleteCount++; michael@0: michael@0: do_check_eq(onDispatchCount, 1); michael@0: do_check_eq(onCompleteCount, 1); michael@0: michael@0: server.stop(run_next_test); michael@0: }, michael@0: michael@0: onDispatch: function onDispatch() { michael@0: onDispatchCount++; michael@0: }, michael@0: }; michael@0: let request = client.getCollectionInfo(); michael@0: request.handler = handler; michael@0: request.dispatch(); michael@0: }); michael@0: michael@0: add_test(function test_info_collections() { michael@0: _("Ensure requests to /info/collections work as expected."); michael@0: michael@0: let [server, client] = getServerAndClient(); michael@0: michael@0: let request = client.getCollectionInfo(); michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: do_check_eq("object", typeof req.resultObj); michael@0: do_check_attribute_count(req.resultObj, 3); michael@0: do_check_true("meta" in req.resultObj); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_info_collections_conditional_not_modified() { michael@0: _("Ensure conditional getCollectionInfo requests work."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: let now = Date.now(); michael@0: michael@0: user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload", now) michael@0: }); michael@0: michael@0: let request = client.getCollectionInfo(); michael@0: request.locallyModifiedVersion = now + 10; michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: do_check_true(req.notModified); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_info_collections_conditional_modified() { michael@0: _("Ensure conditional getCollectionInfo requests work."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: let now = Date.now(); michael@0: michael@0: user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload", now) michael@0: }); michael@0: michael@0: let request = client.getCollectionInfo(); michael@0: request.locallyModifiedVersion = now - 10; michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: do_check_false(req.notModified); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_get_quota() { michael@0: _("Ensure quota requests work."); michael@0: michael@0: let [server, client] = getServerAndClient(); michael@0: michael@0: let request = client.getQuota(); michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: michael@0: do_check_eq(req.resultObj.quota, 1048576); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_get_quota_conditional_not_modified() { michael@0: _("Ensure conditional getQuota requests work."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: let now = Date.now(); michael@0: michael@0: user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload", now) michael@0: }); michael@0: michael@0: let request = client.getQuota(); michael@0: request.locallyModifiedVersion = now + 10; michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: do_check_true(req.notModified); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_get_quota_conditional_modified() { michael@0: _("Ensure conditional getQuota requests work."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: let now = Date.now(); michael@0: michael@0: user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload", now) michael@0: }); michael@0: michael@0: let request = client.getQuota(); michael@0: request.locallyModifiedVersion = now - 10; michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: do_check_false(req.notModified); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_get_collection_usage() { michael@0: _("Ensure info/collection_usage requests work."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: user.createCollection("testcoll", { michael@0: abc123: new ServerBSO("abc123", "payload", Date.now()) michael@0: }); michael@0: michael@0: let request = client.getCollectionUsage(); michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: michael@0: let usage = req.resultObj; michael@0: do_check_true("testcoll" in usage); michael@0: do_check_eq(usage.testcoll, "payload".length); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_get_usage_conditional_not_modified() { michael@0: _("Ensure conditional getCollectionUsage requests work."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: let now = Date.now(); michael@0: michael@0: user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload", now) michael@0: }); michael@0: michael@0: let request = client.getCollectionUsage(); michael@0: request.locallyModifiedVersion = now + 10; michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: do_check_true(req.notModified); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_get_usage_conditional_modified() { michael@0: _("Ensure conditional getCollectionUsage requests work."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: let now = Date.now(); michael@0: michael@0: user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload", now) michael@0: }); michael@0: michael@0: let request = client.getCollectionUsage(); michael@0: request.locallyModifiedVersion = now - 10; michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: do_check_false(req.notModified); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_get_collection_counts() { michael@0: _("Ensure info/collection_counts requests work."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload0", Date.now()), michael@0: bar: new ServerBSO("bar", "payload1", Date.now()) michael@0: }); michael@0: michael@0: let request = client.getCollectionCounts(); michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: michael@0: let counts = req.resultObj; michael@0: do_check_true("testcoll" in counts); michael@0: do_check_eq(counts.testcoll, 2); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_get_counts_conditional_not_modified() { michael@0: _("Ensure conditional getCollectionCounts requests work."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: let now = Date.now(); michael@0: michael@0: user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload", now) michael@0: }); michael@0: michael@0: let request = client.getCollectionCounts(); michael@0: request.locallyModifiedVersion = now + 10; michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: do_check_true(req.notModified); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_get_counts_conditional_modified() { michael@0: _("Ensure conditional getCollectionCounts requests work."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: let now = Date.now(); michael@0: michael@0: user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload", now) michael@0: }); michael@0: michael@0: let request = client.getCollectionCounts(); michael@0: request.locallyModifiedVersion = now - 10; michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: do_check_false(req.notModified); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_get_collection_simple() { michael@0: _("Ensure basic collection retrieval works."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload0", Date.now()), michael@0: bar: new ServerBSO("bar", "payload1", Date.now()) michael@0: }); michael@0: michael@0: let request = client.getCollection("testcoll"); michael@0: let bsos = []; michael@0: request.handler = { michael@0: onBSORecord: function onBSORecord(request, bso) { michael@0: bsos.push(bso); michael@0: }, michael@0: michael@0: onComplete: function onComplete(error, request) { michael@0: do_check_null(error); michael@0: michael@0: do_check_eq(bsos.length, 2); michael@0: do_check_eq(bsos[0], "foo"); michael@0: do_check_eq(bsos[1], "bar"); michael@0: michael@0: server.stop(run_next_test); michael@0: } michael@0: }; michael@0: request.dispatch(); michael@0: }); michael@0: michael@0: add_test(function test_get_collection_conditional_not_modified() { michael@0: _("Ensure conditional requests with no new data to getCollection work."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: let now = Date.now(); michael@0: michael@0: user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload0", now) michael@0: }); michael@0: michael@0: let request = client.getCollection("testcoll"); michael@0: request.locallyModifiedVersion = now + 1; michael@0: michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: michael@0: do_check_true(req.notModified); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_get_collection_conditional_modified() { michael@0: _("Ensure conditional requests with new data to getCollection work."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: let now = Date.now(); michael@0: michael@0: user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload0", now) michael@0: }); michael@0: michael@0: let request = client.getCollection("testcoll"); michael@0: request.locallyModifiedVersion = now - 1; michael@0: michael@0: let bsoCount = 0; michael@0: request.handler = { michael@0: onBSORecord: function onBSORecord() { michael@0: bsoCount++; michael@0: }, michael@0: michael@0: onComplete: function onComplete(error, req) { michael@0: do_check_null(error); michael@0: michael@0: do_check_false(req.notModified); michael@0: do_check_eq(bsoCount, 1); michael@0: michael@0: server.stop(run_next_test); michael@0: } michael@0: }; michael@0: request.dispatch(); michael@0: }); michael@0: michael@0: // This is effectively a sanity test for query string generation. michael@0: add_test(function test_get_collection_newer() { michael@0: _("Ensure query string for newer and full work together."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: michael@0: let date0 = Date.now(); michael@0: let date1 = date0 + 500; michael@0: michael@0: let user = server.user(username); michael@0: user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload0", date0), michael@0: bar: new ServerBSO("bar", "payload1", date1) michael@0: }); michael@0: michael@0: let request = client.getCollection("testcoll"); michael@0: request.full = true; michael@0: request.newer = date0; michael@0: michael@0: let bsos = []; michael@0: request.handler = { michael@0: onBSORecord: function onBSORecord(request, bso) { michael@0: bsos.push(bso); michael@0: }, michael@0: michael@0: onComplete: function onComplete(error, req) { michael@0: do_check_null(error); michael@0: michael@0: do_check_eq(bsos.length, 1); michael@0: let bso = bsos[0]; michael@0: michael@0: do_check_eq(bso.id, "bar"); michael@0: do_check_eq(bso.payload, "payload1"); michael@0: michael@0: server.stop(run_next_test); michael@0: } michael@0: }; michael@0: request.dispatch(); michael@0: }); michael@0: michael@0: add_test(function test_get_bso() { michael@0: _("Ensure that simple BSO fetches work."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: michael@0: server.createCollection(username, "testcoll", { michael@0: abc123: new ServerBSO("abc123", "payload", Date.now()) michael@0: }); michael@0: michael@0: let request = client.getBSO("testcoll", "abc123"); michael@0: request.dispatch(function(error, req) { michael@0: do_check_null(error); michael@0: do_check_true(req.resultObj instanceof BasicStorageObject); michael@0: michael@0: let bso = req.resultObj; michael@0: do_check_eq(bso.id, "abc123"); michael@0: do_check_eq(bso.payload, "payload"); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_bso_conditional() { michael@0: _("Ensure conditional requests for an individual BSO work."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: michael@0: let user = server.user(username); michael@0: let now = Date.now(); michael@0: user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload", now) michael@0: }); michael@0: michael@0: let request = client.getBSO("testcoll", "foo"); michael@0: request.locallyModifiedVersion = now; michael@0: michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: do_check_true(req.notModified); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_set_bso() { michael@0: _("Ensure simple BSO PUT works."); michael@0: michael@0: let [server, client] = getServerAndClient(); michael@0: michael@0: let id = "mnas08h3f3r2351"; michael@0: michael@0: let bso = new BasicStorageObject(id, "testcoll"); michael@0: bso.payload = "my test payload"; michael@0: michael@0: let request = client.setBSO(bso); michael@0: request.dispatch(function(error, req) { michael@0: do_check_eq(error, null); michael@0: do_check_eq(req.resultObj, null); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: michael@0: add_test(function test_set_bso_conditional() { michael@0: _("Ensure conditional setting a BSO is properly rejected."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: let now = Date.now(); michael@0: user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload0", now + 1000) michael@0: }); michael@0: michael@0: // Should get an mtime newer than server's. michael@0: let bso = new BasicStorageObject("foo", "testcoll"); michael@0: bso.payload = "payload1"; michael@0: michael@0: let request = client.setBSO(bso); michael@0: request.locallyModifiedVersion = now; michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_true(error instanceof StorageServiceRequestError); michael@0: do_check_true(error.serverModified); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_set_bso_argument_errors() { michael@0: _("Ensure BSO set detects invalid arguments."); michael@0: michael@0: let server = getEmptyServer(); michael@0: let bso = new BasicStorageObject(); michael@0: let client = getClient(server); michael@0: michael@0: let threw = false; michael@0: try { michael@0: client.setBSO(bso); michael@0: } catch (ex) { michael@0: threw = true; michael@0: do_check_eq(ex.name, "Error"); michael@0: do_check_neq(ex.message.indexOf("does not have collection defined"), -1); michael@0: } finally { michael@0: do_check_true(threw); michael@0: threw = false; michael@0: } michael@0: michael@0: bso = new BasicStorageObject("id"); michael@0: try { michael@0: client.setBSO(bso); michael@0: } catch (ex) { michael@0: threw = true; michael@0: do_check_eq(ex.name, "Error"); michael@0: do_check_neq(ex.message.indexOf("does not have collection defined"), -1); michael@0: } finally { michael@0: do_check_true(threw); michael@0: threw = false; michael@0: } michael@0: michael@0: bso = new BasicStorageObject(null, "coll"); michael@0: try { michael@0: client.setBSO(bso); michael@0: } catch (ex) { michael@0: threw = true; michael@0: do_check_eq(ex.name, "Error"); michael@0: do_check_neq(ex.message.indexOf("does not have ID defined"), -1); michael@0: } finally { michael@0: do_check_true(threw); michael@0: threw = false; michael@0: } michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: michael@0: add_test(function test_set_bsos_simple() { michael@0: _("Ensure setBSOs with basic options works."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: let bso0 = new BasicStorageObject("foo"); michael@0: bso0.payload = "payload0"; michael@0: michael@0: let bso1 = new BasicStorageObject("bar"); michael@0: bso1.payload = "payload1"; michael@0: michael@0: let request = client.setBSOs("testcollection"); michael@0: request.addBSO(bso0); michael@0: request.addBSO(bso1); michael@0: michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: michael@0: let successful = req.successfulIDs; michael@0: do_check_eq(successful.length, 2); michael@0: do_check_eq(successful.indexOf(bso0.id), 0); michael@0: do_check_true(successful.indexOf(bso1.id), 1); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_set_bsos_invalid_bso() { michael@0: _("Ensure that adding an invalid BSO throws."); michael@0: michael@0: let server = getEmptyServer(); michael@0: let client = getClient(server); michael@0: let request = client.setBSOs("testcoll"); michael@0: michael@0: let threw = false; michael@0: michael@0: // Empty argument is invalid. michael@0: try { michael@0: request.addBSO(null); michael@0: } catch (ex) { michael@0: threw = true; michael@0: } finally { michael@0: do_check_true(threw); michael@0: threw = false; michael@0: } michael@0: michael@0: try { michael@0: let bso = new BasicStorageObject(); michael@0: request.addBSO(bso); michael@0: } catch (ex) { michael@0: threw = true; michael@0: } finally { michael@0: do_check_true(threw); michael@0: threw = false; michael@0: } michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: michael@0: add_test(function test_set_bsos_newline() { michael@0: _("Ensure that newlines in BSO payloads are formatted properly."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: let request = client.setBSOs("testcoll"); michael@0: michael@0: let bso0 = new BasicStorageObject("bso0"); michael@0: bso0.payload = "hello\nworld"; michael@0: request.addBSO(bso0); michael@0: michael@0: let bso1 = new BasicStorageObject("bso1"); michael@0: bso1.payload = "foobar"; michael@0: request.addBSO(bso1); michael@0: michael@0: request.dispatch(function onComplete(error, request) { michael@0: do_check_null(error); michael@0: do_check_eq(request.successfulIDs.length, 2); michael@0: michael@0: let coll = user.collection("testcoll"); michael@0: do_check_eq(coll.bso("bso0").payload, bso0.payload); michael@0: do_check_eq(coll.bso("bso1").payload, bso1.payload); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_delete_bso_simple() { michael@0: _("Ensure deletion of individual BSOs works."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: michael@0: let user = server.user(username); michael@0: let coll = user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload0", Date.now()), michael@0: bar: new ServerBSO("bar", "payload1", Date.now()) michael@0: }); michael@0: michael@0: let request = client.deleteBSO("testcoll", "foo"); michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: do_check_eq(req.statusCode, 204); michael@0: michael@0: do_check_eq(coll.count(), 1); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_delete_bso_conditional_failed() { michael@0: _("Ensure deletion of an individual BSO with older modification fails."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: let now = Date.now(); michael@0: user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload0", now) michael@0: }); michael@0: michael@0: let request = client.deleteBSO("testcoll", "foo"); michael@0: request.locallyModifiedVersion = now - 10; michael@0: michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_true(error instanceof StorageServiceRequestError); michael@0: do_check_true(error.serverModified); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_delete_bso_conditional_success() { michael@0: _("Ensure deletion of an individual BSO with newer modification works."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: let now = Date.now(); michael@0: user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload0", now) michael@0: }); michael@0: michael@0: let request = client.deleteBSO("testcoll", "foo"); michael@0: request.locallyModifiedVersion = now; michael@0: michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: do_check_eq(req.statusCode, 204); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_delete_bsos_simple() { michael@0: _("Ensure deletion of multiple BSOs works."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: let coll = user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload0", Date.now()), michael@0: bar: new ServerBSO("bar", "payload1", Date.now()), michael@0: baz: new ServerBSO("baz", "payload2", Date.now()) michael@0: }); michael@0: michael@0: let request = client.deleteBSOs("testcoll", ["foo", "baz"]); michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: do_check_eq(req.statusCode, 204); michael@0: michael@0: do_check_eq(coll.count(), 1); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_delete_bsos_conditional_failed() { michael@0: _("Ensure deletion of BSOs with server modifications fails."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: let now = Date.now(); michael@0: let coll = user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload0", now) michael@0: }); michael@0: michael@0: let request = client.deleteBSOs("testcoll", ["foo"]); michael@0: request.locallyModifiedVersion = coll.timestamp - 1; michael@0: michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_true(error instanceof StorageServiceRequestError); michael@0: do_check_true(error.serverModified); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_delete_bsos_conditional_success() { michael@0: _("Ensure conditional deletion of BSOs without server modifications works."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: let now = Date.now(); michael@0: let coll = user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload0", now), michael@0: bar: new ServerBSO("bar", "payload1", now - 10) michael@0: }); michael@0: michael@0: let request = client.deleteBSOs("testcoll", ["bar"]); michael@0: request.locallyModifiedVersion = coll.timestamp; michael@0: michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: michael@0: do_check_eq(req.statusCode, 204); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_delete_collection() { michael@0: _("Ensure deleteCollection() works."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload0", Date.now()) michael@0: }); michael@0: michael@0: let request = client.deleteCollection("testcoll"); michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: michael@0: do_check_eq(user.collection("testcoll", undefined)); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_delete_collection_conditional_failed() { michael@0: _("Ensure conditional deletes with server modifications fail."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: let now = Date.now(); michael@0: michael@0: let coll = user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload0", now) michael@0: }); michael@0: michael@0: let request = client.deleteCollection("testcoll"); michael@0: request.locallyModifiedVersion = coll.timestamp - 1; michael@0: michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_true(error instanceof StorageServiceRequestError); michael@0: do_check_true(error.serverModified); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_delete_collection_conditional_success() { michael@0: _("Ensure conditional delete of collection works when it's supposed to."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: let now = Date.now(); michael@0: michael@0: let coll = user.createCollection("testcoll", { michael@0: foo: new ServerBSO("foo", "payload0", now) michael@0: }); michael@0: michael@0: let request = client.deleteCollection("testcoll"); michael@0: request.locallyModifiedVersion = coll.timestamp; michael@0: michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: michael@0: do_check_eq(user.collection("testcoll"), undefined); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_delete_collections() { michael@0: _("Ensure deleteCollections() works."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let user = server.user(username); michael@0: michael@0: user.createCollection("testColl", { michael@0: foo: new ServerBSO("foo", "payload0", Date.now()) michael@0: }); michael@0: michael@0: let request = client.deleteCollections(); michael@0: request.dispatch(function onComplete(error, req) { michael@0: do_check_null(error); michael@0: michael@0: do_check_eq(user.collection("testcoll"), undefined); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_network_error_captured() { michael@0: _("Ensure network errors are captured."); michael@0: michael@0: // Network errors should result in .networkError being set on request. michael@0: let client = new StorageServiceClient("http://rnewman-is-splendid.badtld/"); michael@0: michael@0: let request = client.getCollectionInfo(); michael@0: request.dispatch(function(error, req) { michael@0: do_check_neq(error, null); michael@0: do_check_neq(error.network, null); michael@0: michael@0: run_next_test(); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_network_error_listener() { michael@0: _("Ensure the onNetworkError listener is invoked on network errors."); michael@0: michael@0: let listenerCalled = false; michael@0: michael@0: let client = new StorageServiceClient("http://philikon-is-too.badtld/"); michael@0: client.addListener({ michael@0: onNetworkError: function(client, request) { michael@0: listenerCalled = true; michael@0: } michael@0: }); michael@0: let request = client.getCollectionInfo(); michael@0: request.dispatch(function() { michael@0: do_check_true(listenerCalled); michael@0: run_next_test(); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_batching_set_too_large() { michael@0: _("Ensure we throw when attempting to add a BSO that is too large to fit."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: michael@0: let request = client.setBSOsBatching("testcoll"); michael@0: let payload = ""; michael@0: michael@0: // The actual length of the payload is a little less. But, this ensures we michael@0: // exceed it. michael@0: for (let i = 0; i < client.REQUEST_SIZE_LIMIT; i++) { michael@0: payload += i; michael@0: } michael@0: michael@0: let bso = new BasicStorageObject("bso"); michael@0: bso.payload = payload; michael@0: do_check_throws(function add() { request.addBSO(bso); }); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: michael@0: add_test(function test_batching_set_basic() { michael@0: _("Ensure batching set works with single requests."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: michael@0: let request = client.setBSOsBatching("testcoll"); michael@0: for (let i = 0; i < 10; i++) { michael@0: let bso = new BasicStorageObject("bso" + i); michael@0: bso.payload = "payload" + i; michael@0: request.addBSO(bso); michael@0: } michael@0: michael@0: request.finish(function onFinish(request) { michael@0: do_check_eq(request.successfulIDs.length, 10); michael@0: michael@0: let collection = server.user(username).collection("testcoll"); michael@0: do_check_eq(collection.timestamp, request.serverModifiedVersion); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_batching_set_batch_count() { michael@0: _("Ensure multiple outgoing request batching works when count is exceeded."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let requestCount = 0; michael@0: server.callback.onRequest = function onRequest() { michael@0: requestCount++; michael@0: } michael@0: michael@0: let request = client.setBSOsBatching("testcoll"); michael@0: for (let i = 1; i <= 300; i++) { michael@0: let bso = new BasicStorageObject("bso" + i); michael@0: bso.payload = "XXXXXXX"; michael@0: request.addBSO(bso); michael@0: } michael@0: michael@0: request.finish(function onFinish(request) { michael@0: do_check_eq(request.successfulIDs.length, 300); michael@0: do_check_eq(requestCount, 3); michael@0: michael@0: let collection = server.user(username).collection("testcoll"); michael@0: do_check_eq(collection.timestamp, request.serverModifiedVersion); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_batching_set_batch_size() { michael@0: _("Ensure outgoing requests batch when size is exceeded."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let requestCount = 0; michael@0: server.callback.onRequest = function onRequest() { michael@0: requestCount++; michael@0: }; michael@0: michael@0: let limit = client.REQUEST_SIZE_LIMIT; michael@0: michael@0: let request = client.setBSOsBatching("testcoll"); michael@0: michael@0: // JavaScript: Y U NO EASY REPETITION FUNCTIONALITY? michael@0: let data = []; michael@0: for (let i = (limit / 2) - 100; i; i -= 1) { michael@0: data.push("X"); michael@0: } michael@0: michael@0: let payload = data.join(""); michael@0: michael@0: for (let i = 0; i < 4; i++) { michael@0: let bso = new BasicStorageObject("bso" + i); michael@0: bso.payload = payload; michael@0: request.addBSO(bso); michael@0: } michael@0: michael@0: request.finish(function onFinish(request) { michael@0: do_check_eq(request.successfulIDs.length, 4); michael@0: do_check_eq(requestCount, 2); michael@0: michael@0: let collection = server.user(username).collection("testcoll"); michael@0: do_check_eq(collection.timestamp, request.serverModifiedVersion); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_batching_set_flush() { michael@0: _("Ensure flushing batch sets works."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: michael@0: let requestCount = 0; michael@0: server.callback.onRequest = function onRequest() { michael@0: requestCount++; michael@0: } michael@0: michael@0: let request = client.setBSOsBatching("testcoll"); michael@0: for (let i = 1; i < 101; i++) { michael@0: let bso = new BasicStorageObject("bso" + i); michael@0: bso.payload = "foo"; michael@0: request.addBSO(bso); michael@0: michael@0: if (i % 10 == 0) { michael@0: request.flush(); michael@0: } michael@0: } michael@0: michael@0: request.finish(function onFinish(request) { michael@0: do_check_eq(request.successfulIDs.length, 100); michael@0: do_check_eq(requestCount, 10); michael@0: michael@0: let collection = server.user(username).collection("testcoll"); michael@0: do_check_eq(collection.timestamp, request.serverModifiedVersion); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_batching_set_conditional_success() { michael@0: _("Ensure conditional requests for batched sets work properly."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: michael@0: let collection = server.user(username).createCollection("testcoll"); michael@0: michael@0: let lastServerVersion = Date.now(); michael@0: collection.insertBSO(new ServerBSO("foo", "bar", lastServerVersion)); michael@0: collection.timestamp = lastServerVersion; michael@0: do_check_eq(collection.timestamp, lastServerVersion); michael@0: michael@0: let requestCount = 0; michael@0: server.callback.onRequest = function onRequest() { michael@0: requestCount++; michael@0: } michael@0: michael@0: let request = client.setBSOsBatching("testcoll"); michael@0: request.locallyModifiedVersion = collection.timestamp; michael@0: michael@0: for (let i = 1; i < 251; i++) { michael@0: let bso = new BasicStorageObject("bso" + i); michael@0: bso.payload = "foo" + i; michael@0: request.addBSO(bso); michael@0: } michael@0: michael@0: request.finish(function onFinish(request) { michael@0: do_check_eq(requestCount, 3); michael@0: michael@0: do_check_eq(collection.timestamp, request.serverModifiedVersion); michael@0: do_check_eq(collection.timestamp, request.locallyModifiedVersion); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_batching_set_initial_failure() { michael@0: _("Ensure that an initial request failure setting BSOs is handled properly."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: michael@0: let collection = server.user(username).createCollection("testcoll"); michael@0: collection.timestamp = Date.now(); michael@0: michael@0: let requestCount = 0; michael@0: server.callback.onRequest = function onRequest() { michael@0: requestCount++; michael@0: } michael@0: michael@0: let request = client.setBSOsBatching("testcoll"); michael@0: request.locallyModifiedVersion = collection.timestamp - 1; michael@0: michael@0: for (let i = 1; i < 250; i++) { michael@0: let bso = new BasicStorageObject("bso" + i); michael@0: bso.payload = "foo" + i; michael@0: request.addBSO(bso); michael@0: } michael@0: michael@0: request.finish(function onFinish(request) { michael@0: do_check_eq(requestCount, 1); michael@0: michael@0: do_check_eq(request.successfulIDs.length, 0); michael@0: do_check_eq(Object.keys(request.failures).length, 0); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_batching_set_subsequent_failure() { michael@0: _("Ensure a non-initial failure during batching set is handled properly."); michael@0: michael@0: let [server, client, username] = getServerAndClient(); michael@0: let collection = server.user(username).createCollection("testcoll"); michael@0: collection.timestamp = Date.now(); michael@0: michael@0: let requestCount = 0; michael@0: server.callback.onRequest = function onRequest() { michael@0: requestCount++; michael@0: michael@0: if (requestCount == 1) { michael@0: return; michael@0: } michael@0: michael@0: collection.timestamp++; michael@0: } michael@0: michael@0: let request = client.setBSOsBatching("testcoll"); michael@0: request.locallyModifiedVersion = collection.timestamp; michael@0: michael@0: for (let i = 0; i < 250; i++) { michael@0: let bso = new BasicStorageObject("bso" + i); michael@0: bso.payload = "foo" + i; michael@0: request.addBSO(bso); michael@0: } michael@0: michael@0: request.finish(function onFinish(request) { michael@0: do_check_eq(requestCount, 2); michael@0: do_check_eq(request.successfulIDs.length, 100); michael@0: do_check_eq(Object.keys(request.failures).length, 0); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: function getBatchedDeleteData(collection="testcoll") { michael@0: let [server, client, username] = getServerAndClient(); michael@0: michael@0: let serverBSOs = {}; michael@0: for (let i = 1000; i; i -= 1) { michael@0: serverBSOs["bso" + i] = new ServerBSO("bso" + i, "payload" + i); michael@0: } michael@0: michael@0: let user = server.user(username); michael@0: user.createCollection(collection, serverBSOs); michael@0: michael@0: return [server, client, username, collection]; michael@0: } michael@0: michael@0: add_test(function test_batched_delete_single() { michael@0: _("Ensure batched delete with single request works."); michael@0: michael@0: let [server, client, username, collection] = getBatchedDeleteData(); michael@0: michael@0: let requestCount = 0; michael@0: server.callback.onRequest = function onRequest() { michael@0: requestCount += 1; michael@0: } michael@0: michael@0: let request = client.deleteBSOsBatching(collection); michael@0: for (let i = 1; i < 51; i += 1) { michael@0: request.addID("bso" + i); michael@0: } michael@0: michael@0: request.finish(function onFinish(request) { michael@0: do_check_eq(requestCount, 1); michael@0: do_check_eq(request.errors.length, 0); michael@0: michael@0: let coll = server.user(username).collection(collection); michael@0: do_check_eq(coll.count(), 950); michael@0: michael@0: do_check_eq(request.serverModifiedVersion, coll.timestamp); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_batched_delete_multiple() { michael@0: _("Ensure batched delete splits requests properly."); michael@0: michael@0: let [server, client, username, collection] = getBatchedDeleteData(); michael@0: michael@0: let requestCount = 0; michael@0: server.callback.onRequest = function onRequest() { michael@0: requestCount += 1; michael@0: } michael@0: michael@0: let request = client.deleteBSOsBatching(collection); michael@0: for (let i = 1; i < 251; i += 1) { michael@0: request.addID("bso" + i); michael@0: } michael@0: michael@0: request.finish(function onFinish(request) { michael@0: do_check_eq(requestCount, 3); michael@0: do_check_eq(request.errors.length, 0); michael@0: michael@0: let coll = server.user(username).collection(collection); michael@0: do_check_eq(coll.count(), 750); michael@0: michael@0: do_check_eq(request.serverModifiedVersion, coll.timestamp); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_batched_delete_conditional_success() { michael@0: _("Ensure conditional batched delete all work."); michael@0: michael@0: let [server, client, username, collection] = getBatchedDeleteData(); michael@0: michael@0: let requestCount = 0; michael@0: server.callback.onRequest = function onRequest() { michael@0: requestCount++; michael@0: } michael@0: michael@0: let serverCollection = server.user(username).collection(collection); michael@0: let initialTimestamp = serverCollection.timestamp; michael@0: michael@0: let request = client.deleteBSOsBatching(collection); michael@0: request.locallyModifiedVersion = initialTimestamp; michael@0: michael@0: for (let i = 1; i < 251; i += 1) { michael@0: request.addID("bso" + 1); michael@0: } michael@0: michael@0: request.finish(function onFinish(request) { michael@0: do_check_eq(requestCount, 3); michael@0: do_check_eq(request.errors.length, 0); michael@0: michael@0: do_check_true(request.locallyModifiedVersion > initialTimestamp); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_batched_delete_conditional_initial_failure() { michael@0: _("Ensure conditional batched delete failure on initial request works."); michael@0: michael@0: // The client needs to issue multiple requests but the first one was michael@0: // rejected. The client should only issue that initial request. michael@0: let [server, client, username, collection] = getBatchedDeleteData(); michael@0: michael@0: let requestCount = 0; michael@0: server.callback.onRequest = function onRequest() { michael@0: requestCount++; michael@0: } michael@0: michael@0: let serverCollection = server.user(username).collection(collection); michael@0: let request = client.deleteBSOsBatching(collection); michael@0: request.locallyModifiedVersion = serverCollection.timestamp - 1; michael@0: michael@0: for (let i = 1; i < 251; i += 1) { michael@0: request.addID("bso" + i); michael@0: } michael@0: michael@0: request.finish(function onFinish(request) { michael@0: do_check_eq(requestCount, 1); michael@0: do_check_eq(request.errors.length, 1); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: }); michael@0: michael@0: add_test(function test_batched_delete_conditional_subsequent_failure() { michael@0: _("Ensure conditional batched delete failure on non-initial request."); michael@0: michael@0: let [server, client, username, collection] = getBatchedDeleteData(); michael@0: michael@0: let serverCollection = server.user(username).collection(collection); michael@0: michael@0: let requestCount = 0; michael@0: server.callback.onRequest = function onRequest() { michael@0: requestCount++; michael@0: michael@0: if (requestCount <= 1) { michael@0: return; michael@0: } michael@0: michael@0: // Advance collection's timestamp on subsequent requests so request is michael@0: // rejected. michael@0: serverCollection.timestamp++; michael@0: } michael@0: michael@0: let request = client.deleteBSOsBatching(collection); michael@0: request.locallyModifiedVersion = serverCollection.timestamp; michael@0: michael@0: for (let i = 1; i < 251; i += 1) { michael@0: request.addID("bso" + i); michael@0: } michael@0: michael@0: request.finish(function onFinish(request) { michael@0: do_check_eq(requestCount, 2); michael@0: do_check_eq(request.errors.length, 1); michael@0: michael@0: server.stop(run_next_test); michael@0: }); michael@0: });