--- a/services/sync/modules/bookmark_repair.js
+++ b/services/sync/modules/bookmark_repair.js
@@ -552,17 +552,17 @@ class BookmarkRepairRequestor extends Co
arrayOfClientIDs.push(clientID);
this.prefs.set(PREF.REPAIR_PREVIOUS_CLIENTS, arrayOfClientIDs.join(" "));
}
/* Used for test mocks.
*/
_now() {
// We use the server time, which is SECONDS
- return AsyncResource.serverTime;
+ return Resource.serverTime;
}
}
/* An object that responds to repair requests initiated by some other device.
*/
class BookmarkRepairResponder extends CollectionRepairResponder {
async repair(request, rawCommand) {
if (request.request != "upload") {
--- a/services/sync/modules/doctor.js
+++ b/services/sync/modules/doctor.js
@@ -242,17 +242,17 @@ this.Doctor = {
set lastRepairAdvance(value) {
Svc.Prefs.set("doctor.lastRepairAdvance", value);
},
// functions used so tests can mock them
_now() {
// We use the server time, which is SECONDS
- return AsyncResource.serverTime;
+ return Resource.serverTime;
},
_getRepairRequestor(name) {
return getRepairRequestor(name);
},
_getAllRepairRequestors() {
return getAllRepairRequestors();
--- a/services/sync/modules/engines.js
+++ b/services/sync/modules/engines.js
@@ -1437,17 +1437,17 @@ SyncEngine.prototype = {
// We start reconciling by collecting a bunch of state. We do this here
// because some state may change during the course of this function and we
// need to operate on the original values.
let existsLocally = await this._store.itemExists(item.id);
let locallyModified = this._modified.has(item.id);
// TODO Handle clock drift better. Tracked in bug 721181.
- let remoteAge = AsyncResource.serverTime - item.modified;
+ let remoteAge = Resource.serverTime - item.modified;
let localAge = locallyModified ?
(Date.now() / 1000 - this._modified.getModifiedTimestamp(item.id)) : null;
let remoteIsNewer = remoteAge < localAge;
this._log.trace("Reconciling " + item.id + ". exists=" +
existsLocally + "; modified=" + locallyModified +
"; local age=" + localAge + "; incoming age=" +
remoteAge);
--- a/services/sync/modules/engines/clients.js
+++ b/services/sync/modules/engines/clients.js
@@ -427,17 +427,17 @@ ClientEngine.prototype = {
}
if (!names.has(record.name)) {
if (record.fxaDeviceId) {
seenDeviceIds.add(record.fxaDeviceId);
}
names.add(record.name);
continue;
}
- let remoteAge = AsyncResource.serverTime - this._incomingClients[id];
+ let remoteAge = Resource.serverTime - this._incomingClients[id];
if (remoteAge > STALE_CLIENT_REMOTE_AGE) {
this._log.info(`Hiding stale client ${id} with age ${remoteAge}`);
record.stale = true;
continue;
}
if (record.fxaDeviceId && seenDeviceIds.has(record.fxaDeviceId)) {
this._log.info(`Hiding stale client ${record.id}` +
` - duplicate device id ${record.fxaDeviceId}`);
--- a/services/sync/modules/record.js
+++ b/services/sync/modules/record.js
@@ -716,17 +716,17 @@ Collection.prototype = {
if (batchSize <= 0 || batchSize >= totalLimit) {
throw new Error("Invalid batch size");
}
if (!this.full) {
throw new Error("getBatched is unimplemented for guid-only GETs");
}
- // _onComplete and _onProgress are reset after each `get` by AsyncResource.
+ // _onComplete and _onProgress are reset after each `get` by Resource.
let { _onComplete, _onProgress } = this;
let recordBuffer = [];
let resp;
try {
let lastModifiedTime;
this.limit = batchSize;
do {
--- a/services/sync/modules/resource.js
+++ b/services/sync/modules/resource.js
@@ -1,21 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-this.EXPORTED_SYMBOLS = [
- "AsyncResource",
- "Resource"
-];
+this.EXPORTED_SYMBOLS = ["Resource"];
-var Cc = Components.classes;
-var Ci = Components.interfaces;
-var Cr = Components.results;
-var Cu = Components.utils;
+const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-common/observers.js");
Cu.import("resource://services-common/utils.js");
Cu.import("resource://services-sync/constants.js");
@@ -24,20 +18,20 @@ Cu.import("resource://services-sync/util
const DEFAULT_LOAD_FLAGS =
// Always validate the cache:
Ci.nsIRequest.LOAD_BYPASS_CACHE |
Ci.nsIRequest.INHIBIT_CACHING |
// Don't send user cookies over the wire (Bug 644734).
Ci.nsIRequest.LOAD_ANONYMOUS;
/*
- * AsyncResource represents a remote network resource, identified by a URI.
+ * Resource represents a remote network resource, identified by a URI.
* Create an instance like so:
*
- * let resource = new AsyncResource("http://foobar.com/path/to/resource");
+ * let resource = new Resource("http://foobar.com/path/to/resource");
*
* The 'resource' object has the following methods to issue HTTP requests
* of the corresponding HTTP methods:
*
* get(callback)
* put(data, callback)
* post(data, callback)
* delete(callback)
@@ -45,44 +39,44 @@ const DEFAULT_LOAD_FLAGS =
* 'callback' is a function with the following signature:
*
* function callback(error, result) {...}
*
* 'error' will be null on successful requests. Likewise, result will not be
* passed (=undefined) when an error occurs. Note that this is independent of
* the status of the HTTP response.
*/
-this.AsyncResource = function AsyncResource(uri) {
+this.Resource = function Resource(uri) {
this._log = Log.repository.getLogger(this._logName);
this._log.level =
Log.Level[Svc.Prefs.get("log.logger.network.resources")];
this.uri = uri;
this._headers = {};
this._onComplete = Utils.bind2(this, this._onComplete);
};
-AsyncResource.prototype = {
- _logName: "Sync.AsyncResource",
+Resource.prototype = {
+ _logName: "Sync.Resource",
- // ** {{{ AsyncResource.serverTime }}} **
+ // ** {{{ Resource.serverTime }}} **
//
// Caches the latest server timestamp (X-Weave-Timestamp header).
serverTime: null,
/**
* Callback to be invoked at request time to add authentication details.
*
* By default, a global authenticator is provided. If this is set, it will
* be used instead of the global one.
*/
authenticator: null,
// Wait 5 minutes before killing a request.
ABORT_TIMEOUT: 300000,
- // ** {{{ AsyncResource.headers }}} **
+ // ** {{{ Resource.headers }}} **
//
// Headers to be included when making a request for the resource.
// Note: Header names should be all lower case, there's no explicit
// check for duplicates due to case!
get headers() {
return this._headers;
},
set headers(value) {
@@ -90,50 +84,50 @@ AsyncResource.prototype = {
},
setHeader: function Res_setHeader(header, value) {
this._headers[header.toLowerCase()] = value;
},
get headerNames() {
return Object.keys(this.headers);
},
- // ** {{{ AsyncResource.uri }}} **
+ // ** {{{ Resource.uri }}} **
//
// URI representing this resource.
get uri() {
return this._uri;
},
set uri(value) {
if (typeof value == "string")
this._uri = CommonUtils.makeURI(value);
else
this._uri = value;
},
- // ** {{{ AsyncResource.spec }}} **
+ // ** {{{ Resource.spec }}} **
//
// Get the string representation of the URI.
get spec() {
if (this._uri)
return this._uri.spec;
return null;
},
- // ** {{{ AsyncResource.data }}} **
+ // ** {{{ Resource.data }}} **
//
// Get and set the data encapulated in the resource.
_data: null,
get data() {
return this._data;
},
set data(value) {
this._data = value;
},
- // ** {{{ AsyncResource._createRequest }}} **
+ // ** {{{ Resource._createRequest }}} **
//
// This method returns a new IO Channel for requests to be made
// through. It is never called directly, only {{{_doRequest}}} uses it
// to obtain a request channel.
//
_createRequest(method) {
this.method = method;
let channel = NetUtil.newChannel({uri: this.spec, loadUsingSystemPrincipal: true})
@@ -343,20 +337,16 @@ AsyncResource.prototype = {
return this._doRequest("POST", data);
},
delete() {
return this._doRequest("DELETE", undefined);
}
};
-// TODO: We still export both "Resource" and "AsyncRecourse" as the same
-// object, but we should decide on one and unify all references.
-this.Resource = AsyncResource;
-
// = ChannelListener =
//
// This object implements the {{{nsIStreamListener}}} interface
// and is called as the network operation proceeds.
function ChannelListener(onComplete, onProgress, logger, timeout) {
this._onComplete = onComplete;
this._onProgress = onProgress;
this._log = logger;
@@ -373,17 +363,17 @@ ChannelListener.prototype = {
} catch (ex) {
this._log.error("Unexpected error: channel is not a nsIHttpChannel!");
channel.cancel(Cr.NS_BINDING_ABORTED);
return;
}
// Save the latest server timestamp when possible.
try {
- AsyncResource.serverTime = channel.getResponseHeader("X-Weave-Timestamp") - 0;
+ Resource.serverTime = channel.getResponseHeader("X-Weave-Timestamp") - 0;
} catch (ex) {}
this._log.trace("onStartRequest: " + channel.requestMethod + " " +
channel.URI.spec);
this._data = "";
this.delayAbort();
},
--- a/services/sync/modules/telemetry.js
+++ b/services/sync/modules/telemetry.js
@@ -569,18 +569,18 @@ class SyncTelemetryImpl {
if (!validateTelemetryEvent(eventDetails)) {
// we've already logged what the problem is...
return;
}
log.debug("recording event", eventDetails);
let { object, method, value, extra } = eventDetails;
- if (extra && AsyncResource.serverTime && !extra.serverTime) {
- extra.serverTime = String(AsyncResource.serverTime);
+ if (extra && Resource.serverTime && !extra.serverTime) {
+ extra.serverTime = String(Resource.serverTime);
}
let category = "sync";
let ts = Math.floor(tryGetMonotonicTimestamp());
// An event record is a simple array with at least 4 items.
let event = [ts, category, method, object];
// It may have up to 6 elements if |extra| is defined
if (value) {
--- a/services/sync/tests/unit/test_fxa_node_reassignment.js
+++ b/services/sync/tests/unit/test_fxa_node_reassignment.js
@@ -15,17 +15,16 @@ Cu.import("resource://services-sync/serv
Cu.import("resource://services-sync/status.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://testing-common/services/sync/rotaryengine.js");
Cu.import("resource://services-sync/browserid_identity.js");
Cu.import("resource://testing-common/services/sync/utils.js");
Cu.import("resource://gre/modules/PromiseUtils.jsm");
add_task(async function setup() {
- Log.repository.getLogger("Sync.AsyncResource").level = Log.Level.Trace;
Log.repository.getLogger("Sync.ErrorHandler").level = Log.Level.Trace;
Log.repository.getLogger("Sync.Resource").level = Log.Level.Trace;
Log.repository.getLogger("Sync.RESTRequest").level = Log.Level.Trace;
Log.repository.getLogger("Sync.Service").level = Log.Level.Trace;
Log.repository.getLogger("Sync.SyncScheduler").level = Log.Level.Trace;
initTestLogging();
// Disables all built-in engines. Important for avoiding errors thrown by the
--- a/services/sync/tests/unit/test_node_reassignment.js
+++ b/services/sync/tests/unit/test_node_reassignment.js
@@ -11,17 +11,16 @@ Cu.import("resource://services-sync/serv
Cu.import("resource://services-sync/status.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://testing-common/services/sync/rotaryengine.js");
Cu.import("resource://testing-common/services/sync/utils.js");
Cu.import("resource://gre/modules/PromiseUtils.jsm");
add_task(async function setup() {
- Log.repository.getLogger("Sync.AsyncResource").level = Log.Level.Trace;
Log.repository.getLogger("Sync.ErrorHandler").level = Log.Level.Trace;
Log.repository.getLogger("Sync.Resource").level = Log.Level.Trace;
Log.repository.getLogger("Sync.RESTRequest").level = Log.Level.Trace;
Log.repository.getLogger("Sync.Service").level = Log.Level.Trace;
Log.repository.getLogger("Sync.SyncScheduler").level = Log.Level.Trace;
initTestLogging();
validate_all_future_pings();
--- a/services/sync/tests/unit/test_resource.js
+++ b/services/sync/tests/unit/test_resource.js
@@ -1,20 +1,21 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://gre/modules/Log.jsm");
Cu.import("resource://services-common/observers.js");
Cu.import("resource://services-common/utils.js");
Cu.import("resource://services-sync/resource.js");
-Cu.import("resource://services-sync/status.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/browserid_identity.js");
Cu.import("resource://testing-common/services/sync/utils.js");
+var logger;
+
var fetched = false;
function server_open(metadata, response) {
let body;
if (metadata.method == "GET") {
fetched = true;
body = "This path exists";
response.setStatusLine(metadata.httpVersion, 200, "OK");
} else {
@@ -43,24 +44,24 @@ function server_protected(metadata, resp
function server_404(metadata, response) {
let body = "File not found";
response.setStatusLine(metadata.httpVersion, 404, "Not Found");
response.bodyOutputStream.write(body, body.length);
}
var pacFetched = false;
function server_pac(metadata, response) {
+ _("Invoked PAC handler.");
pacFetched = true;
let body = 'function FindProxyForURL(url, host) { return "DIRECT"; }';
response.setStatusLine(metadata.httpVersion, 200, "OK");
response.setHeader("Content-Type", "application/x-ns-proxy-autoconfig", false);
response.bodyOutputStream.write(body, body.length);
}
-
var sample_data = {
some: "sample_data",
injson: "format",
number: 42
};
function server_upload(metadata, response) {
let body;
@@ -144,355 +145,484 @@ function server_headers(metadata, respon
for (let header of header_names) {
headers[header] = metadata.getHeader(header);
}
let body = JSON.stringify(headers);
response.setStatusLine(metadata.httpVersion, 200, "OK");
response.bodyOutputStream.write(body, body.length);
}
-add_task(async function test() {
- initTestLogging("Trace");
+var quotaValue;
+Observers.add("weave:service:quota:remaining",
+ function(subject) { quotaValue = subject; });
- let logger = Log.repository.getLogger("Test");
+function run_test() {
+ logger = Log.repository.getLogger("Test");
Log.repository.rootLogger.addAppender(new Log.DumpAppender());
+ Svc.Prefs.set("network.numRetries", 1); // speed up test
+ run_next_test();
+}
+
+// This apparently has to come first in order for our PAC URL to be hit.
+// Don't put any other HTTP requests earlier in the file!
+add_task(async function test_proxy_auth_redirect() {
+ _("Ensure that a proxy auth redirect (which switches out our channel) " +
+ "doesn't break Resource.");
let server = httpd_setup({
"/open": server_open,
+ "/pac2": server_pac
+ });
+
+ PACSystemSettings.PACURI = server.baseURI + "/pac2";
+ installFakePAC();
+ let res = new Resource(server.baseURI + "/open");
+ let result = await res.get();
+ do_check_true(pacFetched);
+ do_check_true(fetched);
+ do_check_eq("This path exists", result);
+ pacFetched = fetched = false;
+ uninstallFakePAC();
+ await promiseStopServer(server);
+});
+
+add_task(async function test_new_channel() {
+ _("Ensure a redirect to a new channel is handled properly.");
+
+ let resourceRequested = false;
+ function resourceHandler(metadata, response) {
+ resourceRequested = true;
+
+ let body = "Test";
+ response.setHeader("Content-Type", "text/plain");
+ response.bodyOutputStream.write(body, body.length);
+ }
+
+ let locationURL;
+ function redirectHandler(metadata, response) {
+ let body = "Redirecting";
+ response.setStatusLine(metadata.httpVersion, 307, "TEMPORARY REDIRECT");
+ response.setHeader("Location", locationURL);
+ response.bodyOutputStream.write(body, body.length);
+ }
+
+ let server = httpd_setup({"/resource": resourceHandler,
+ "/redirect": redirectHandler});
+ locationURL = server.baseURI + "/resource";
+
+ let request = new Resource(server.baseURI + "/redirect");
+ let content = await request.get();
+ do_check_true(resourceRequested);
+ do_check_eq(200, content.status);
+ do_check_true("content-type" in content.headers);
+ do_check_eq("text/plain", content.headers["content-type"]);
+
+ await promiseStopServer(server);
+});
+
+
+var server;
+
+add_test(function setup() {
+ server = httpd_setup({
+ "/open": server_open,
"/protected": server_protected,
"/404": server_404,
"/upload": server_upload,
"/delete": server_delete,
"/json": server_json,
"/timestamp": server_timestamp,
"/headers": server_headers,
"/backoff": server_backoff,
- "/pac1": server_pac,
+ "/pac2": server_pac,
"/quota-notice": server_quota_notice,
"/quota-error": server_quota_error
});
- Svc.Prefs.set("network.numRetries", 1); // speed up test
+ run_next_test();
+});
- // This apparently has to come first in order for our PAC URL to be hit.
- // Don't put any other HTTP requests earlier in the file!
- _("Testing handling of proxy auth redirection.");
- PACSystemSettings.PACURI = server.baseURI + "/pac1";
- installFakePAC();
- let proxiedRes = new Resource(server.baseURI + "/open");
- let content = await proxiedRes.get();
- do_check_true(pacFetched);
- do_check_true(fetched);
- do_check_eq(content, "This path exists");
- pacFetched = fetched = false;
- uninstallFakePAC();
-
+add_test(function test_members() {
_("Resource object members");
- let res = new Resource(server.baseURI + "/open");
+ let uri = server.baseURI + "/open";
+ let res = new Resource(uri);
do_check_true(res.uri instanceof Ci.nsIURI);
- do_check_eq(res.uri.spec, server.baseURI + "/open");
- do_check_eq(res.spec, server.baseURI + "/open");
+ do_check_eq(res.uri.spec, uri);
+ do_check_eq(res.spec, uri);
do_check_eq(typeof res.headers, "object");
do_check_eq(typeof res.authenticator, "object");
// Initially res.data is null since we haven't performed a GET or
// PUT/POST request yet.
do_check_eq(res.data, null);
+ run_next_test();
+});
+
+add_task(async function test_get() {
_("GET a non-password-protected resource");
- content = await res.get();
+ let res = new Resource(server.baseURI + "/open");
+ let content = await res.get();
do_check_eq(content, "This path exists");
do_check_eq(content.status, 200);
do_check_true(content.success);
// res.data has been updated with the result from the request
do_check_eq(res.data, content);
// Observe logging messages.
- logger = res._log;
- let dbg = logger.debug;
+ let resLogger = res._log;
+ let dbg = resLogger.debug;
let debugMessages = [];
- logger.debug = function(msg) {
+ resLogger.debug = function(msg) {
debugMessages.push(msg);
dbg.call(this, msg);
};
// Since we didn't receive proper JSON data, accessing content.obj
- // will result in a SyntaxError from JSON.parse.
- // Furthermore, we'll have logged.
+ // will result in a SyntaxError from JSON.parse
let didThrow = false;
try {
content.obj;
} catch (ex) {
didThrow = true;
}
do_check_true(didThrow);
do_check_eq(debugMessages.length, 1);
do_check_eq(debugMessages[0],
"Parse fail: Response body starts: \"\"This path exists\"\".");
- logger.debug = dbg;
+ resLogger.debug = dbg;
+});
+add_test(function test_basicauth() {
+ _("Test that the BasicAuthenticator doesn't screw up header case.");
+ let res1 = new Resource(server.baseURI + "/foo");
+ res1.setHeader("Authorization", "Basic foobar");
+ do_check_eq(res1._headers.authorization, "Basic foobar");
+ do_check_eq(res1.headers.authorization, "Basic foobar");
+
+ run_next_test();
+});
+
+add_task(async function test_get_protected_fail() {
_("GET a password protected resource (test that it'll fail w/o pass, no throw)");
let res2 = new Resource(server.baseURI + "/protected");
- content = await res2.get();
+ let content = await res2.get();
do_check_eq(content, "This path exists and is protected - failed");
do_check_eq(content.status, 401);
do_check_false(content.success);
+});
+add_task(async function test_get_protected_success() {
_("GET a password protected resource");
- let res3 = new Resource(server.baseURI + "/protected");
let identityConfig = makeIdentityConfig();
- let browseridManager = Status._authManager;
+ let browseridManager = new BrowserIDManager();
configureFxAccountIdentity(browseridManager, identityConfig);
let auth = browseridManager.getResourceAuthenticator();
+ let res3 = new Resource(server.baseURI + "/protected");
res3.authenticator = auth;
do_check_eq(res3.authenticator, auth);
- content = await res3.get();
+ let content = await res3.get();
do_check_eq(content, "This path exists and is protected");
do_check_eq(content.status, 200);
do_check_true(content.success);
+});
+add_task(async function test_get_404() {
_("GET a non-existent resource (test that it'll fail, but not throw)");
let res4 = new Resource(server.baseURI + "/404");
- content = await res4.get();
+ let content = await res4.get();
do_check_eq(content, "File not found");
do_check_eq(content.status, 404);
do_check_false(content.success);
// Check some headers of the 404 response
do_check_eq(content.headers.connection, "close");
do_check_eq(content.headers.server, "httpd.js");
do_check_eq(content.headers["content-length"], 14);
+});
+add_task(async function test_put_string() {
_("PUT to a resource (string)");
- let res5 = new Resource(server.baseURI + "/upload");
- content = await res5.put(JSON.stringify(sample_data));
+ let res_upload = new Resource(server.baseURI + "/upload");
+ let content = await res_upload.put(JSON.stringify(sample_data));
do_check_eq(content, "Valid data upload via PUT");
do_check_eq(content.status, 200);
- do_check_eq(res5.data, content);
+ do_check_eq(res_upload.data, content);
+});
+add_task(async function test_put_object() {
_("PUT to a resource (object)");
- content = await res5.put(sample_data);
+ let res_upload = new Resource(server.baseURI + "/upload");
+ let content = await res_upload.put(sample_data);
do_check_eq(content, "Valid data upload via PUT");
do_check_eq(content.status, 200);
- do_check_eq(res5.data, content);
+ do_check_eq(res_upload.data, content);
+});
+add_task(async function test_put_data_string() {
_("PUT without data arg (uses resource.data) (string)");
- res5.data = JSON.stringify(sample_data);
- content = await res5.put();
+ let res_upload = new Resource(server.baseURI + "/upload");
+ res_upload.data = JSON.stringify(sample_data);
+ let content = await res_upload.put();
do_check_eq(content, "Valid data upload via PUT");
do_check_eq(content.status, 200);
- do_check_eq(res5.data, content);
+ do_check_eq(res_upload.data, content);
+});
+add_task(async function test_put_data_object() {
_("PUT without data arg (uses resource.data) (object)");
- res5.data = sample_data;
- content = await res5.put();
+ let res_upload = new Resource(server.baseURI + "/upload");
+ res_upload.data = sample_data;
+ let content = await res_upload.put();
do_check_eq(content, "Valid data upload via PUT");
do_check_eq(content.status, 200);
- do_check_eq(res5.data, content);
+ do_check_eq(res_upload.data, content);
+});
+add_task(async function test_post_string() {
_("POST to a resource (string)");
- content = await res5.post(JSON.stringify(sample_data));
+ let res_upload = new Resource(server.baseURI + "/upload");
+ let content = await res_upload.post(JSON.stringify(sample_data));
do_check_eq(content, "Valid data upload via POST");
do_check_eq(content.status, 200);
- do_check_eq(res5.data, content);
+ do_check_eq(res_upload.data, content);
+});
+add_task(async function test_post_object() {
_("POST to a resource (object)");
- content = await res5.post(sample_data);
+ let res_upload = new Resource(server.baseURI + "/upload");
+ let content = await res_upload.post(sample_data);
do_check_eq(content, "Valid data upload via POST");
do_check_eq(content.status, 200);
- do_check_eq(res5.data, content);
+ do_check_eq(res_upload.data, content);
+});
+add_task(async function test_post_data_string() {
_("POST without data arg (uses resource.data) (string)");
- res5.data = JSON.stringify(sample_data);
- content = await res5.post();
+ let res_upload = new Resource(server.baseURI + "/upload");
+ res_upload.data = JSON.stringify(sample_data);
+ let content = await res_upload.post();
do_check_eq(content, "Valid data upload via POST");
do_check_eq(content.status, 200);
- do_check_eq(res5.data, content);
+ do_check_eq(res_upload.data, content);
+});
+add_task(async function test_post_data_object() {
_("POST without data arg (uses resource.data) (object)");
- res5.data = sample_data;
- content = await res5.post();
+ let res_upload = new Resource(server.baseURI + "/upload");
+ res_upload.data = sample_data;
+ let content = await res_upload.post();
do_check_eq(content, "Valid data upload via POST");
do_check_eq(content.status, 200);
- do_check_eq(res5.data, content);
+ do_check_eq(res_upload.data, content);
+});
+add_task(async function test_delete() {
_("DELETE a resource");
let res6 = new Resource(server.baseURI + "/delete");
- content = await res6.delete();
+ let content = await res6.delete();
do_check_eq(content, "This resource has been deleted");
do_check_eq(content.status, 200);
+});
+add_task(async function test_json_body() {
_("JSON conversion of response body");
let res7 = new Resource(server.baseURI + "/json");
- content = await res7.get();
+ let content = await res7.get();
do_check_eq(content, JSON.stringify(sample_data));
do_check_eq(content.status, 200);
do_check_eq(JSON.stringify(content.obj), JSON.stringify(sample_data));
+});
- _("X-Weave-Timestamp header updates AsyncResource.serverTime");
+add_task(async function test_weave_timestamp() {
+ _("X-Weave-Timestamp header updates Resource.serverTime");
// Before having received any response containing the
- // X-Weave-Timestamp header, AsyncResource.serverTime is null.
- do_check_eq(AsyncResource.serverTime, null);
+ // X-Weave-Timestamp header, Resource.serverTime is null.
+ do_check_eq(Resource.serverTime, null);
let res8 = new Resource(server.baseURI + "/timestamp");
- content = await res8.get();
- do_check_eq(AsyncResource.serverTime, TIMESTAMP);
+ await res8.get();
+ do_check_eq(Resource.serverTime, TIMESTAMP);
+});
+add_task(async function test_get_no_headers() {
_("GET: no special request headers");
- let res9 = new Resource(server.baseURI + "/headers");
- content = await res9.get();
+ let res_headers = new Resource(server.baseURI + "/headers");
+ let content = await res_headers.get();
do_check_eq(content, "{}");
+});
+add_task(async function test_put_default_content_type() {
_("PUT: Content-Type defaults to text/plain");
- content = await res9.put("data");
+ let res_headers = new Resource(server.baseURI + "/headers");
+ let content = await res_headers.put("data");
do_check_eq(content, JSON.stringify({"content-type": "text/plain"}));
+});
+add_task(async function test_post_default_content_type() {
_("POST: Content-Type defaults to text/plain");
- content = await res9.post("data");
+ let res_headers = new Resource(server.baseURI + "/headers");
+ let content = await res_headers.post("data");
do_check_eq(content, JSON.stringify({"content-type": "text/plain"}));
+});
+add_task(async function test_setHeader() {
_("setHeader(): setting simple header");
- res9.setHeader("X-What-Is-Weave", "awesome");
- do_check_eq(res9.headers["x-what-is-weave"], "awesome");
- content = await res9.get();
+ let res_headers = new Resource(server.baseURI + "/headers");
+ res_headers.setHeader("X-What-Is-Weave", "awesome");
+ do_check_eq(res_headers.headers["x-what-is-weave"], "awesome");
+ let content = await res_headers.get();
do_check_eq(content, JSON.stringify({"x-what-is-weave": "awesome"}));
+});
+add_task(async function test_setHeader_overwrite() {
_("setHeader(): setting multiple headers, overwriting existing header");
- res9.setHeader("X-WHAT-is-Weave", "more awesomer");
- res9.setHeader("X-Another-Header", "hello world");
- do_check_eq(res9.headers["x-what-is-weave"], "more awesomer");
- do_check_eq(res9.headers["x-another-header"], "hello world");
- content = await res9.get();
+ let res_headers = new Resource(server.baseURI + "/headers");
+ res_headers.setHeader("X-WHAT-is-Weave", "more awesomer");
+ res_headers.setHeader("X-Another-Header", "hello world");
+ do_check_eq(res_headers.headers["x-what-is-weave"], "more awesomer");
+ do_check_eq(res_headers.headers["x-another-header"], "hello world");
+ let content = await res_headers.get();
do_check_eq(content, JSON.stringify({"x-another-header": "hello world",
"x-what-is-weave": "more awesomer"}));
+});
+add_task(async function test_headers_object() {
_("Setting headers object");
- res9.headers = {};
- content = await res9.get();
+ let res_headers = new Resource(server.baseURI + "/headers");
+ res_headers.headers = {};
+ let content = await res_headers.get();
do_check_eq(content, "{}");
+});
- _("PUT/POST: override default Content-Type");
- res9.setHeader("Content-Type", "application/foobar");
- do_check_eq(res9.headers["content-type"], "application/foobar");
- content = await res9.put("data");
+add_task(async function test_put_override_content_type() {
+ _("PUT: override default Content-Type");
+ let res_headers = new Resource(server.baseURI + "/headers");
+ res_headers.setHeader("Content-Type", "application/foobar");
+ do_check_eq(res_headers.headers["content-type"], "application/foobar");
+ let content = await res_headers.put("data");
do_check_eq(content, JSON.stringify({"content-type": "application/foobar"}));
- content = await res9.post("data");
+});
+
+add_task(async function test_post_override_content_type() {
+ _("POST: override default Content-Type");
+ let res_headers = new Resource(server.baseURI + "/headers");
+ res_headers.setHeader("Content-Type", "application/foobar");
+ let content = await res_headers.post("data");
do_check_eq(content, JSON.stringify({"content-type": "application/foobar"}));
+});
-
+add_task(async function test_weave_backoff() {
_("X-Weave-Backoff header notifies observer");
let backoffInterval;
function onBackoff(subject, data) {
backoffInterval = subject;
}
Observers.add("weave:service:backoff:interval", onBackoff);
let res10 = new Resource(server.baseURI + "/backoff");
- content = await res10.get();
+ await res10.get();
do_check_eq(backoffInterval, 600);
+});
-
+add_task(async function test_quota_error() {
_("X-Weave-Quota-Remaining header notifies observer on successful requests.");
- let quotaValue;
- function onQuota(subject, data) {
- quotaValue = subject;
- }
- Observers.add("weave:service:quota:remaining", onQuota);
-
- res10 = new Resource(server.baseURI + "/quota-error");
- content = await res10.get();
+ let res10 = new Resource(server.baseURI + "/quota-error");
+ let content = await res10.get();
do_check_eq(content.status, 400);
do_check_eq(quotaValue, undefined); // HTTP 400, so no observer notification.
+});
- res10 = new Resource(server.baseURI + "/quota-notice");
- content = await res10.get();
+add_task(async function test_quota_notice() {
+ let res10 = new Resource(server.baseURI + "/quota-notice");
+ let content = await res10.get();
do_check_eq(content.status, 200);
do_check_eq(quotaValue, 1048576);
-
+});
- _("Error handling in _request() preserves exception information");
- let error;
+add_task(async function test_preserve_exceptions() {
+ _("Error handling in ChannelListener etc. preserves exception information");
let res11 = new Resource("http://localhost:12345/does/not/exist");
- try {
- content = await res11.get();
- } catch (ex) {
- error = ex;
- }
- do_check_eq(error.result, Cr.NS_ERROR_CONNECTION_REFUSED);
- do_check_eq(error.message, "NS_ERROR_CONNECTION_REFUSED");
- do_check_eq(typeof error.stack, "string");
+ await Assert.rejects(res11.get(), error => {
+ do_check_neq(error, null);
+ do_check_eq(error.result, Cr.NS_ERROR_CONNECTION_REFUSED);
+ do_check_eq(error.message, "NS_ERROR_CONNECTION_REFUSED");
+ return true;
+ });
+});
- _("Checking handling of errors in onProgress.");
- let res18 = new Resource(server.baseURI + "/json");
- let onProgress = function(rec) {
+add_task(async function test_xpc_exception_handling() {
+ _("Exception handling inside fetches.");
+ let res14 = new Resource(server.baseURI + "/json");
+ res14._onProgress = function(rec) {
// Provoke an XPC exception without a Javascript wrapper.
Services.io.newURI("::::::::");
};
- res18._onProgress = onProgress;
let warnings = [];
- res18._log.warn = function(msg) { warnings.push(msg); };
- error = undefined;
- try {
- content = await res18.get();
- } catch (ex) {
- error = ex;
- }
+ res14._log.warn = function(msg) { warnings.push(msg); };
- // It throws and logs.
- do_check_eq(error.result, Cr.NS_ERROR_MALFORMED_URI);
- do_check_eq(error.message, "NS_ERROR_MALFORMED_URI");
- // Note the strings haven't been formatted yet, but that's OK for this test.
- do_check_eq(warnings.pop(), "${action} request to ${url} failed: ${ex}");
+ await Assert.rejects(res14.get(), error => {
+ do_check_eq(error.result, Cr.NS_ERROR_MALFORMED_URI);
+ do_check_eq(error.message, "NS_ERROR_MALFORMED_URI");
+ return true;
+ });
+ do_check_eq(warnings.pop(),
+ "${action} request to ${url} failed: ${ex}");
do_check_eq(warnings.pop(),
"Got exception calling onProgress handler during fetch of " +
server.baseURI + "/json");
+});
- // And this is what happens if JS throws an exception.
- res18 = new Resource(server.baseURI + "/json");
- onProgress = function(rec) {
+add_task(async function test_js_exception_handling() {
+ _("JS exception handling inside fetches.");
+ let res15 = new Resource(server.baseURI + "/json");
+ res15._onProgress = function(rec) {
throw new Error("BOO!");
};
- res18._onProgress = onProgress;
- let oldWarn = res18._log.warn;
- warnings = [];
- res18._log.warn = function(msg) { warnings.push(msg); };
- error = undefined;
- try {
- content = await res18.get();
- } catch (ex) {
- error = ex;
- }
+ let warnings = [];
+ res15._log.warn = function(msg) { warnings.push(msg); };
- // It throws and logs.
- do_check_eq(error.result, Cr.NS_ERROR_XPC_JAVASCRIPT_ERROR_WITH_DETAILS);
- do_check_eq(error.message, "NS_ERROR_XPC_JAVASCRIPT_ERROR_WITH_DETAILS");
- do_check_eq(warnings.pop(), "${action} request to ${url} failed: ${ex}");
+ await Assert.rejects(res15.get(), error => {
+ do_check_eq(error.result, Cr.NS_ERROR_XPC_JAVASCRIPT_ERROR_WITH_DETAILS);
+ do_check_eq(error.message, "NS_ERROR_XPC_JAVASCRIPT_ERROR_WITH_DETAILS");
+ return true;
+ });
+ do_check_eq(warnings.pop(),
+ "${action} request to ${url} failed: ${ex}");
do_check_eq(warnings.pop(),
"Got exception calling onProgress handler during fetch of " +
server.baseURI + "/json");
+});
- res18._log.warn = oldWarn;
-
+add_task(async function test_timeout() {
_("Ensure channel timeouts are thrown appropriately.");
let res19 = new Resource(server.baseURI + "/json");
res19.ABORT_TIMEOUT = 0;
- error = undefined;
- try {
- content = await res19.get();
- } catch (ex) {
- error = ex;
- }
- do_check_eq(error.result, Cr.NS_ERROR_NET_TIMEOUT);
+ await Assert.rejects(res19.get(), error => {
+ do_check_eq(error.result, Cr.NS_ERROR_NET_TIMEOUT);
+ return true;
+ });
+});
+add_test(function test_uri_construction() {
_("Testing URI construction.");
let args = [];
args.push("newer=" + 1234);
args.push("limit=" + 1234);
args.push("sort=" + 1234);
let query = "?" + args.join("&");
let uri1 = CommonUtils.makeURI("http://foo/" + query)
.QueryInterface(Ci.nsIURL);
let uri2 = CommonUtils.makeURI("http://foo/")
.QueryInterface(Ci.nsIURL);
uri2.query = query;
do_check_eq(uri1.query, uri2.query);
- server.stop(do_test_finished);
+
+ run_next_test();
});
+
+/**
+ * End of tests that rely on a single HTTP server.
+ * All tests after this point must begin and end their own.
+ */
+add_test(function eliminate_server() {
+ server.stop(run_next_test);
+});
deleted file mode 100644
--- a/services/sync/tests/unit/test_resource_async.js
+++ /dev/null
@@ -1,628 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-Cu.import("resource://gre/modules/Log.jsm");
-Cu.import("resource://services-common/observers.js");
-Cu.import("resource://services-common/utils.js");
-Cu.import("resource://services-sync/resource.js");
-Cu.import("resource://services-sync/util.js");
-Cu.import("resource://services-sync/browserid_identity.js");
-Cu.import("resource://testing-common/services/sync/utils.js");
-
-var logger;
-
-var fetched = false;
-function server_open(metadata, response) {
- let body;
- if (metadata.method == "GET") {
- fetched = true;
- body = "This path exists";
- response.setStatusLine(metadata.httpVersion, 200, "OK");
- } else {
- body = "Wrong request method";
- response.setStatusLine(metadata.httpVersion, 405, "Method Not Allowed");
- }
- response.bodyOutputStream.write(body, body.length);
-}
-
-function server_protected(metadata, response) {
- let body;
-
- if (has_hawk_header(metadata, "guest", "guest")) {
- body = "This path exists and is protected";
- response.setStatusLine(metadata.httpVersion, 200, "OK, authorized");
- response.setHeader("WWW-Authenticate", 'Basic realm="secret"', false);
- } else {
- body = "This path exists and is protected - failed";
- response.setStatusLine(metadata.httpVersion, 401, "Unauthorized");
- response.setHeader("WWW-Authenticate", 'Basic realm="secret"', false);
- }
-
- response.bodyOutputStream.write(body, body.length);
-}
-
-function server_404(metadata, response) {
- let body = "File not found";
- response.setStatusLine(metadata.httpVersion, 404, "Not Found");
- response.bodyOutputStream.write(body, body.length);
-}
-
-var pacFetched = false;
-function server_pac(metadata, response) {
- _("Invoked PAC handler.");
- pacFetched = true;
- let body = 'function FindProxyForURL(url, host) { return "DIRECT"; }';
- response.setStatusLine(metadata.httpVersion, 200, "OK");
- response.setHeader("Content-Type", "application/x-ns-proxy-autoconfig", false);
- response.bodyOutputStream.write(body, body.length);
-}
-
-var sample_data = {
- some: "sample_data",
- injson: "format",
- number: 42
-};
-
-function server_upload(metadata, response) {
- let body;
-
- let input = readBytesFromInputStream(metadata.bodyInputStream);
- if (input == JSON.stringify(sample_data)) {
- body = "Valid data upload via " + metadata.method;
- response.setStatusLine(metadata.httpVersion, 200, "OK");
- } else {
- body = "Invalid data upload via " + metadata.method + ": " + input;
- response.setStatusLine(metadata.httpVersion, 500, "Internal Server Error");
- }
-
- response.bodyOutputStream.write(body, body.length);
-}
-
-function server_delete(metadata, response) {
- let body;
- if (metadata.method == "DELETE") {
- body = "This resource has been deleted";
- response.setStatusLine(metadata.httpVersion, 200, "OK");
- } else {
- body = "Wrong request method";
- response.setStatusLine(metadata.httpVersion, 405, "Method Not Allowed");
- }
- response.bodyOutputStream.write(body, body.length);
-}
-
-function server_json(metadata, response) {
- let body = JSON.stringify(sample_data);
- response.setStatusLine(metadata.httpVersion, 200, "OK");
- response.bodyOutputStream.write(body, body.length);
-}
-
-const TIMESTAMP = 1274380461;
-
-function server_timestamp(metadata, response) {
- let body = "Thank you for your request";
- response.setHeader("X-Weave-Timestamp", "" + TIMESTAMP, false);
- response.setStatusLine(metadata.httpVersion, 200, "OK");
- response.bodyOutputStream.write(body, body.length);
-}
-
-function server_backoff(metadata, response) {
- let body = "Hey, back off!";
- response.setHeader("X-Weave-Backoff", "600", false);
- response.setStatusLine(metadata.httpVersion, 200, "OK");
- response.bodyOutputStream.write(body, body.length);
-}
-
-function server_quota_notice(request, response) {
- let body = "You're approaching quota.";
- response.setHeader("X-Weave-Quota-Remaining", "1048576", false);
- response.setStatusLine(request.httpVersion, 200, "OK");
- response.bodyOutputStream.write(body, body.length);
-}
-
-function server_quota_error(request, response) {
- let body = "14";
- response.setHeader("X-Weave-Quota-Remaining", "-1024", false);
- response.setStatusLine(request.httpVersion, 400, "OK");
- response.bodyOutputStream.write(body, body.length);
-}
-
-function server_headers(metadata, response) {
- let ignore_headers = ["host", "user-agent", "accept", "accept-language",
- "accept-encoding", "accept-charset", "keep-alive",
- "connection", "pragma", "cache-control",
- "content-length"];
- let headers = metadata.headers;
- let header_names = [];
- while (headers.hasMoreElements()) {
- let header = headers.getNext().toString();
- if (ignore_headers.indexOf(header) == -1) {
- header_names.push(header);
- }
- }
- header_names = header_names.sort();
-
- headers = {};
- for (let header of header_names) {
- headers[header] = metadata.getHeader(header);
- }
- let body = JSON.stringify(headers);
- response.setStatusLine(metadata.httpVersion, 200, "OK");
- response.bodyOutputStream.write(body, body.length);
-}
-
-var quotaValue;
-Observers.add("weave:service:quota:remaining",
- function(subject) { quotaValue = subject; });
-
-function run_test() {
- logger = Log.repository.getLogger("Test");
- Log.repository.rootLogger.addAppender(new Log.DumpAppender());
-
- Svc.Prefs.set("network.numRetries", 1); // speed up test
- run_next_test();
-}
-
-// This apparently has to come first in order for our PAC URL to be hit.
-// Don't put any other HTTP requests earlier in the file!
-add_task(async function test_proxy_auth_redirect() {
- _("Ensure that a proxy auth redirect (which switches out our channel) " +
- "doesn't break AsyncResource.");
- let server = httpd_setup({
- "/open": server_open,
- "/pac2": server_pac
- });
-
- PACSystemSettings.PACURI = server.baseURI + "/pac2";
- installFakePAC();
- let res = new AsyncResource(server.baseURI + "/open");
- let result = await res.get();
- do_check_true(pacFetched);
- do_check_true(fetched);
- do_check_eq("This path exists", result);
- pacFetched = fetched = false;
- uninstallFakePAC();
- await promiseStopServer(server);
-});
-
-add_task(async function test_new_channel() {
- _("Ensure a redirect to a new channel is handled properly.");
-
- let resourceRequested = false;
- function resourceHandler(metadata, response) {
- resourceRequested = true;
-
- let body = "Test";
- response.setHeader("Content-Type", "text/plain");
- response.bodyOutputStream.write(body, body.length);
- }
-
- let locationURL;
- function redirectHandler(metadata, response) {
- let body = "Redirecting";
- response.setStatusLine(metadata.httpVersion, 307, "TEMPORARY REDIRECT");
- response.setHeader("Location", locationURL);
- response.bodyOutputStream.write(body, body.length);
- }
-
- let server = httpd_setup({"/resource": resourceHandler,
- "/redirect": redirectHandler});
- locationURL = server.baseURI + "/resource";
-
- let request = new AsyncResource(server.baseURI + "/redirect");
- let content = await request.get();
- do_check_true(resourceRequested);
- do_check_eq(200, content.status);
- do_check_true("content-type" in content.headers);
- do_check_eq("text/plain", content.headers["content-type"]);
-
- await promiseStopServer(server);
-});
-
-
-var server;
-
-add_test(function setup() {
- server = httpd_setup({
- "/open": server_open,
- "/protected": server_protected,
- "/404": server_404,
- "/upload": server_upload,
- "/delete": server_delete,
- "/json": server_json,
- "/timestamp": server_timestamp,
- "/headers": server_headers,
- "/backoff": server_backoff,
- "/pac2": server_pac,
- "/quota-notice": server_quota_notice,
- "/quota-error": server_quota_error
- });
-
- run_next_test();
-});
-
-add_test(function test_members() {
- _("Resource object members");
- let uri = server.baseURI + "/open";
- let res = new AsyncResource(uri);
- do_check_true(res.uri instanceof Ci.nsIURI);
- do_check_eq(res.uri.spec, uri);
- do_check_eq(res.spec, uri);
- do_check_eq(typeof res.headers, "object");
- do_check_eq(typeof res.authenticator, "object");
- // Initially res.data is null since we haven't performed a GET or
- // PUT/POST request yet.
- do_check_eq(res.data, null);
-
- run_next_test();
-});
-
-add_task(async function test_get() {
- _("GET a non-password-protected resource");
- let res = new AsyncResource(server.baseURI + "/open");
- let content = await res.get();
- do_check_eq(content, "This path exists");
- do_check_eq(content.status, 200);
- do_check_true(content.success);
- // res.data has been updated with the result from the request
- do_check_eq(res.data, content);
-
- // Observe logging messages.
- let resLogger = res._log;
- let dbg = resLogger.debug;
- let debugMessages = [];
- resLogger.debug = function(msg) {
- debugMessages.push(msg);
- dbg.call(this, msg);
- };
-
- // Since we didn't receive proper JSON data, accessing content.obj
- // will result in a SyntaxError from JSON.parse
- let didThrow = false;
- try {
- content.obj;
- } catch (ex) {
- didThrow = true;
- }
- do_check_true(didThrow);
- do_check_eq(debugMessages.length, 1);
- do_check_eq(debugMessages[0],
- "Parse fail: Response body starts: \"\"This path exists\"\".");
- resLogger.debug = dbg;
-});
-
-add_test(function test_basicauth() {
- _("Test that the BasicAuthenticator doesn't screw up header case.");
- let res1 = new AsyncResource(server.baseURI + "/foo");
- res1.setHeader("Authorization", "Basic foobar");
- do_check_eq(res1._headers.authorization, "Basic foobar");
- do_check_eq(res1.headers.authorization, "Basic foobar");
-
- run_next_test();
-});
-
-add_task(async function test_get_protected_fail() {
- _("GET a password protected resource (test that it'll fail w/o pass, no throw)");
- let res2 = new AsyncResource(server.baseURI + "/protected");
- let content = await res2.get();
- do_check_eq(content, "This path exists and is protected - failed");
- do_check_eq(content.status, 401);
- do_check_false(content.success);
-});
-
-add_task(async function test_get_protected_success() {
- _("GET a password protected resource");
- let identityConfig = makeIdentityConfig();
- let browseridManager = new BrowserIDManager();
- configureFxAccountIdentity(browseridManager, identityConfig);
- let auth = browseridManager.getResourceAuthenticator();
- let res3 = new AsyncResource(server.baseURI + "/protected");
- res3.authenticator = auth;
- do_check_eq(res3.authenticator, auth);
- let content = await res3.get();
- do_check_eq(content, "This path exists and is protected");
- do_check_eq(content.status, 200);
- do_check_true(content.success);
-});
-
-add_task(async function test_get_404() {
- _("GET a non-existent resource (test that it'll fail, but not throw)");
- let res4 = new AsyncResource(server.baseURI + "/404");
- let content = await res4.get();
- do_check_eq(content, "File not found");
- do_check_eq(content.status, 404);
- do_check_false(content.success);
-
- // Check some headers of the 404 response
- do_check_eq(content.headers.connection, "close");
- do_check_eq(content.headers.server, "httpd.js");
- do_check_eq(content.headers["content-length"], 14);
-});
-
-add_task(async function test_put_string() {
- _("PUT to a resource (string)");
- let res_upload = new AsyncResource(server.baseURI + "/upload");
- let content = await res_upload.put(JSON.stringify(sample_data));
- do_check_eq(content, "Valid data upload via PUT");
- do_check_eq(content.status, 200);
- do_check_eq(res_upload.data, content);
-});
-
-add_task(async function test_put_object() {
- _("PUT to a resource (object)");
- let res_upload = new AsyncResource(server.baseURI + "/upload");
- let content = await res_upload.put(sample_data);
- do_check_eq(content, "Valid data upload via PUT");
- do_check_eq(content.status, 200);
- do_check_eq(res_upload.data, content);
-});
-
-add_task(async function test_put_data_string() {
- _("PUT without data arg (uses resource.data) (string)");
- let res_upload = new AsyncResource(server.baseURI + "/upload");
- res_upload.data = JSON.stringify(sample_data);
- let content = await res_upload.put();
- do_check_eq(content, "Valid data upload via PUT");
- do_check_eq(content.status, 200);
- do_check_eq(res_upload.data, content);
-});
-
-add_task(async function test_put_data_object() {
- _("PUT without data arg (uses resource.data) (object)");
- let res_upload = new AsyncResource(server.baseURI + "/upload");
- res_upload.data = sample_data;
- let content = await res_upload.put();
- do_check_eq(content, "Valid data upload via PUT");
- do_check_eq(content.status, 200);
- do_check_eq(res_upload.data, content);
-});
-
-add_task(async function test_post_string() {
- _("POST to a resource (string)");
- let res_upload = new AsyncResource(server.baseURI + "/upload");
- let content = await res_upload.post(JSON.stringify(sample_data));
- do_check_eq(content, "Valid data upload via POST");
- do_check_eq(content.status, 200);
- do_check_eq(res_upload.data, content);
-});
-
-add_task(async function test_post_object() {
- _("POST to a resource (object)");
- let res_upload = new AsyncResource(server.baseURI + "/upload");
- let content = await res_upload.post(sample_data);
- do_check_eq(content, "Valid data upload via POST");
- do_check_eq(content.status, 200);
- do_check_eq(res_upload.data, content);
-});
-
-add_task(async function test_post_data_string() {
- _("POST without data arg (uses resource.data) (string)");
- let res_upload = new AsyncResource(server.baseURI + "/upload");
- res_upload.data = JSON.stringify(sample_data);
- let content = await res_upload.post();
- do_check_eq(content, "Valid data upload via POST");
- do_check_eq(content.status, 200);
- do_check_eq(res_upload.data, content);
-});
-
-add_task(async function test_post_data_object() {
- _("POST without data arg (uses resource.data) (object)");
- let res_upload = new AsyncResource(server.baseURI + "/upload");
- res_upload.data = sample_data;
- let content = await res_upload.post();
- do_check_eq(content, "Valid data upload via POST");
- do_check_eq(content.status, 200);
- do_check_eq(res_upload.data, content);
-});
-
-add_task(async function test_delete() {
- _("DELETE a resource");
- let res6 = new AsyncResource(server.baseURI + "/delete");
- let content = await res6.delete();
- do_check_eq(content, "This resource has been deleted");
- do_check_eq(content.status, 200);
-});
-
-add_task(async function test_json_body() {
- _("JSON conversion of response body");
- let res7 = new AsyncResource(server.baseURI + "/json");
- let content = await res7.get();
- do_check_eq(content, JSON.stringify(sample_data));
- do_check_eq(content.status, 200);
- do_check_eq(JSON.stringify(content.obj), JSON.stringify(sample_data));
-});
-
-add_task(async function test_weave_timestamp() {
- _("X-Weave-Timestamp header updates AsyncResource.serverTime");
- // Before having received any response containing the
- // X-Weave-Timestamp header, AsyncResource.serverTime is null.
- do_check_eq(AsyncResource.serverTime, null);
- let res8 = new AsyncResource(server.baseURI + "/timestamp");
- await res8.get();
- do_check_eq(AsyncResource.serverTime, TIMESTAMP);
-});
-
-add_task(async function test_get_no_headers() {
- _("GET: no special request headers");
- let res_headers = new AsyncResource(server.baseURI + "/headers");
- let content = await res_headers.get();
- do_check_eq(content, "{}");
-});
-
-add_task(async function test_put_default_content_type() {
- _("PUT: Content-Type defaults to text/plain");
- let res_headers = new AsyncResource(server.baseURI + "/headers");
- let content = await res_headers.put("data");
- do_check_eq(content, JSON.stringify({"content-type": "text/plain"}));
-});
-
-add_task(async function test_post_default_content_type() {
- _("POST: Content-Type defaults to text/plain");
- let res_headers = new AsyncResource(server.baseURI + "/headers");
- let content = await res_headers.post("data");
- do_check_eq(content, JSON.stringify({"content-type": "text/plain"}));
-});
-
-add_task(async function test_setHeader() {
- _("setHeader(): setting simple header");
- let res_headers = new AsyncResource(server.baseURI + "/headers");
- res_headers.setHeader("X-What-Is-Weave", "awesome");
- do_check_eq(res_headers.headers["x-what-is-weave"], "awesome");
- let content = await res_headers.get();
- do_check_eq(content, JSON.stringify({"x-what-is-weave": "awesome"}));
-});
-
-add_task(async function test_setHeader_overwrite() {
- _("setHeader(): setting multiple headers, overwriting existing header");
- let res_headers = new AsyncResource(server.baseURI + "/headers");
- res_headers.setHeader("X-WHAT-is-Weave", "more awesomer");
- res_headers.setHeader("X-Another-Header", "hello world");
- do_check_eq(res_headers.headers["x-what-is-weave"], "more awesomer");
- do_check_eq(res_headers.headers["x-another-header"], "hello world");
- let content = await res_headers.get();
- do_check_eq(content, JSON.stringify({"x-another-header": "hello world",
- "x-what-is-weave": "more awesomer"}));
-});
-
-add_task(async function test_headers_object() {
- _("Setting headers object");
- let res_headers = new AsyncResource(server.baseURI + "/headers");
- res_headers.headers = {};
- let content = await res_headers.get();
- do_check_eq(content, "{}");
-});
-
-add_task(async function test_put_override_content_type() {
- _("PUT: override default Content-Type");
- let res_headers = new AsyncResource(server.baseURI + "/headers");
- res_headers.setHeader("Content-Type", "application/foobar");
- do_check_eq(res_headers.headers["content-type"], "application/foobar");
- let content = await res_headers.put("data");
- do_check_eq(content, JSON.stringify({"content-type": "application/foobar"}));
-});
-
-add_task(async function test_post_override_content_type() {
- _("POST: override default Content-Type");
- let res_headers = new AsyncResource(server.baseURI + "/headers");
- res_headers.setHeader("Content-Type", "application/foobar");
- let content = await res_headers.post("data");
- do_check_eq(content, JSON.stringify({"content-type": "application/foobar"}));
-});
-
-add_task(async function test_weave_backoff() {
- _("X-Weave-Backoff header notifies observer");
- let backoffInterval;
- function onBackoff(subject, data) {
- backoffInterval = subject;
- }
- Observers.add("weave:service:backoff:interval", onBackoff);
-
- let res10 = new AsyncResource(server.baseURI + "/backoff");
- await res10.get();
- do_check_eq(backoffInterval, 600);
-});
-
-add_task(async function test_quota_error() {
- _("X-Weave-Quota-Remaining header notifies observer on successful requests.");
- let res10 = new AsyncResource(server.baseURI + "/quota-error");
- let content = await res10.get();
- do_check_eq(content.status, 400);
- do_check_eq(quotaValue, undefined); // HTTP 400, so no observer notification.
-});
-
-add_task(async function test_quota_notice() {
- let res10 = new AsyncResource(server.baseURI + "/quota-notice");
- let content = await res10.get();
- do_check_eq(content.status, 200);
- do_check_eq(quotaValue, 1048576);
-});
-
-add_task(async function test_preserve_exceptions() {
- _("Error handling in ChannelListener etc. preserves exception information");
- let res11 = new AsyncResource("http://localhost:12345/does/not/exist");
- await Assert.rejects(res11.get(), error => {
- do_check_neq(error, null);
- do_check_eq(error.result, Cr.NS_ERROR_CONNECTION_REFUSED);
- do_check_eq(error.message, "NS_ERROR_CONNECTION_REFUSED");
- return true;
- });
-});
-
-add_task(async function test_xpc_exception_handling() {
- _("Exception handling inside fetches.");
- let res14 = new AsyncResource(server.baseURI + "/json");
- res14._onProgress = function(rec) {
- // Provoke an XPC exception without a Javascript wrapper.
- Services.io.newURI("::::::::");
- };
- let warnings = [];
- res14._log.warn = function(msg) { warnings.push(msg); };
-
- await Assert.rejects(res14.get(), error => {
- do_check_eq(error.result, Cr.NS_ERROR_MALFORMED_URI);
- do_check_eq(error.message, "NS_ERROR_MALFORMED_URI");
- return true;
- });
- do_check_eq(warnings.pop(),
- "${action} request to ${url} failed: ${ex}");
- do_check_eq(warnings.pop(),
- "Got exception calling onProgress handler during fetch of " +
- server.baseURI + "/json");
-});
-
-add_task(async function test_js_exception_handling() {
- _("JS exception handling inside fetches.");
- let res15 = new AsyncResource(server.baseURI + "/json");
- res15._onProgress = function(rec) {
- throw new Error("BOO!");
- };
- let warnings = [];
- res15._log.warn = function(msg) { warnings.push(msg); };
-
- await Assert.rejects(res15.get(), error => {
- do_check_eq(error.result, Cr.NS_ERROR_XPC_JAVASCRIPT_ERROR_WITH_DETAILS);
- do_check_eq(error.message, "NS_ERROR_XPC_JAVASCRIPT_ERROR_WITH_DETAILS");
- return true;
- });
- do_check_eq(warnings.pop(),
- "${action} request to ${url} failed: ${ex}");
- do_check_eq(warnings.pop(),
- "Got exception calling onProgress handler during fetch of " +
- server.baseURI + "/json");
-});
-
-add_task(async function test_timeout() {
- _("Ensure channel timeouts are thrown appropriately.");
- let res19 = new AsyncResource(server.baseURI + "/json");
- res19.ABORT_TIMEOUT = 0;
- await Assert.rejects(res19.get(), error => {
- do_check_eq(error.result, Cr.NS_ERROR_NET_TIMEOUT);
- return true;
- });
-});
-
-add_test(function test_uri_construction() {
- _("Testing URI construction.");
- let args = [];
- args.push("newer=" + 1234);
- args.push("limit=" + 1234);
- args.push("sort=" + 1234);
-
- let query = "?" + args.join("&");
-
- let uri1 = CommonUtils.makeURI("http://foo/" + query)
- .QueryInterface(Ci.nsIURL);
- let uri2 = CommonUtils.makeURI("http://foo/")
- .QueryInterface(Ci.nsIURL);
- uri2.query = query;
- do_check_eq(uri1.query, uri2.query);
-
- run_next_test();
-});
-
-/**
- * End of tests that rely on a single HTTP server.
- * All tests after this point must begin and end their own.
- */
-add_test(function eliminate_server() {
- server.stop(run_next_test);
-});
--- a/services/sync/tests/unit/test_resource_ua.js
+++ b/services/sync/tests/unit/test_resource_ua.js
@@ -53,37 +53,37 @@ add_task(async function test_fetchInfo()
await Service._fetchInfo();
_("User-Agent: " + ua);
do_check_eq(ua, expectedUA + ".desktop");
ua = "";
});
add_task(async function test_desktop_post() {
_("Testing direct Resource POST.");
- let r = new AsyncResource(server.baseURI + "/1.1/johndoe/storage/meta/global");
+ let r = new Resource(server.baseURI + "/1.1/johndoe/storage/meta/global");
await r.post("foo=bar");
_("User-Agent: " + ua);
do_check_eq(ua, expectedUA + ".desktop");
ua = "";
});
add_task(async function test_desktop_get() {
_("Testing async.");
Svc.Prefs.set("client.type", "desktop");
- let r = new AsyncResource(server.baseURI + "/1.1/johndoe/storage/meta/global");
+ let r = new Resource(server.baseURI + "/1.1/johndoe/storage/meta/global");
await r.get();
_("User-Agent: " + ua);
do_check_eq(ua, expectedUA + ".desktop");
ua = "";
});
add_task(async function test_mobile_get() {
_("Testing mobile.");
Svc.Prefs.set("client.type", "mobile");
- let r = new AsyncResource(server.baseURI + "/1.1/johndoe/storage/meta/global");
+ let r = new Resource(server.baseURI + "/1.1/johndoe/storage/meta/global");
await r.get();
_("User-Agent: " + ua);
do_check_eq(ua, expectedUA + ".mobile");
ua = "";
});
add_test(function tear_down() {
server.stop(run_next_test);
--- a/services/sync/tests/unit/test_telemetry.js
+++ b/services/sync/tests/unit/test_telemetry.js
@@ -636,17 +636,17 @@ add_task(async function test_events() {
await Service.engineManager.register(BogusEngine);
let engine = Service.engineManager.get("bogus");
engine.enabled = true;
let server = await serverForFoo(engine);
await SyncTestingInfrastructure(server);
try {
- let serverTime = AsyncResource.serverTime;
+ let serverTime = Resource.serverTime;
Service.recordTelemetryEvent("object", "method", "value", { foo: "bar" });
let ping = await wait_for_ping(() => Service.sync(), true, true);
equal(ping.events.length, 1);
let [timestamp, category, method, object, value, extra] = ping.events[0];
ok((typeof timestamp == "number") && timestamp > 0); // timestamp.
equal(category, "sync");
equal(method, "method");
equal(object, "object");
--- a/services/sync/tests/unit/test_warn_on_truncated_response.js
+++ b/services/sync/tests/unit/test_warn_on_truncated_response.js
@@ -51,17 +51,17 @@ add_task(async function test_resource_lo
equal(result, BODY);
await promiseStopServer(httpServer);
});
add_task(async function test_async_resource_logs_content_length_mismatch() {
_("Issuing request.");
let httpServer = httpd_setup({"/content": contentHandler});
- let asyncResource = new AsyncResource(httpServer.baseURI + "/content");
+ let asyncResource = new Resource(httpServer.baseURI + "/content");
let warnMessages = getWarningMessages(asyncResource._log);
let content = await asyncResource.get();
equal(content, BODY);
notEqual(warnMessages.length, 0, "test that warning was logged");
notEqual(content.length, contentLength);
await promiseStopServer(httpServer);
--- a/services/sync/tests/unit/xpcshell.ini
+++ b/services/sync/tests/unit/xpcshell.ini
@@ -37,17 +37,16 @@ support-files =
# We have a number of other libraries that are pretty much standalone.
[test_addon_utils.js]
run-sequentially = Restarts server, can't change pref.
tags = addons
[test_httpd_sync_server.js]
# HTTP layers.
[test_resource.js]
-[test_resource_async.js]
[test_resource_header.js]
[test_resource_ua.js]
[test_syncstoragerequest.js]
# Generic Sync types.
[test_browserid_identity.js]
[test_browserid_identity_telemetry.js]
[test_collection_getBatched.js]