diff options
Diffstat (limited to 'dom/reporting/tests')
-rw-r--r-- | dom/reporting/tests/browser.toml | 7 | ||||
-rw-r--r-- | dom/reporting/tests/browser_cleanup.js | 276 | ||||
-rw-r--r-- | dom/reporting/tests/common_deprecated.js | 214 | ||||
-rw-r--r-- | dom/reporting/tests/delivering.sjs | 111 | ||||
-rw-r--r-- | dom/reporting/tests/empty.html | 1 | ||||
-rw-r--r-- | dom/reporting/tests/gtest/TestReportToParser.cpp | 418 | ||||
-rw-r--r-- | dom/reporting/tests/gtest/moz.build | 13 | ||||
-rw-r--r-- | dom/reporting/tests/iframe_delivering.html | 92 | ||||
-rw-r--r-- | dom/reporting/tests/mochitest.toml | 29 | ||||
-rw-r--r-- | dom/reporting/tests/test_delivering.html | 45 | ||||
-rw-r--r-- | dom/reporting/tests/test_deprecated.html | 51 | ||||
-rw-r--r-- | dom/reporting/tests/test_memoryPressure.html | 33 | ||||
-rw-r--r-- | dom/reporting/tests/worker_delivering.js | 5 | ||||
-rw-r--r-- | dom/reporting/tests/worker_deprecated.js | 28 |
14 files changed, 1323 insertions, 0 deletions
diff --git a/dom/reporting/tests/browser.toml b/dom/reporting/tests/browser.toml new file mode 100644 index 0000000000..1f6354edd4 --- /dev/null +++ b/dom/reporting/tests/browser.toml @@ -0,0 +1,7 @@ +[DEFAULT] +support-files = [ + "delivering.sjs", + "empty.html", +] + +["browser_cleanup.js"] diff --git a/dom/reporting/tests/browser_cleanup.js b/dom/reporting/tests/browser_cleanup.js new file mode 100644 index 0000000000..e50b8db1da --- /dev/null +++ b/dom/reporting/tests/browser_cleanup.js @@ -0,0 +1,276 @@ +/* eslint-disable mozilla/no-arbitrary-setTimeout */ + +const TEST_HOST = "example.org"; +const TEST_DOMAIN = "https://" + TEST_HOST; +const TEST_PATH = "/browser/dom/reporting/tests/"; +const TEST_TOP_PAGE = TEST_DOMAIN + TEST_PATH + "empty.html"; +const TEST_SJS = TEST_DOMAIN + TEST_PATH + "delivering.sjs"; + +async function storeReportingHeader(browser, extraParams = "") { + await SpecialPowers.spawn( + browser, + [{ url: TEST_SJS, extraParams }], + async obj => { + await content + .fetch( + obj.url + + "?task=header" + + (obj.extraParams.length ? "&" + obj.extraParams : "") + ) + .then(r => r.text()) + .then(text => { + is(text, "OK", "Report-to header sent"); + }); + } + ); +} + +add_task(async function () { + await SpecialPowers.flushPrefEnv(); + await SpecialPowers.pushPrefEnv({ + set: [ + ["dom.reporting.enabled", true], + ["dom.reporting.header.enabled", true], + ["dom.reporting.testing.enabled", true], + ["dom.reporting.delivering.timeout", 1], + ["dom.reporting.cleanup.timeout", 1], + ["privacy.userContext.enabled", true], + ], + }); +}); + +add_task(async function () { + info("Testing a total cleanup"); + + let tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE); + gBrowser.selectedTab = tab; + + let browser = gBrowser.getBrowserForTab(tab); + await BrowserTestUtils.browserLoaded(browser); + + ok( + !ChromeUtils.hasReportingHeaderForOrigin(TEST_DOMAIN), + "No data before the test" + ); + + await storeReportingHeader(browser); + ok(ChromeUtils.hasReportingHeaderForOrigin(TEST_DOMAIN), "We have data"); + + await new Promise(resolve => { + Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => + resolve() + ); + }); + + ok( + !ChromeUtils.hasReportingHeaderForOrigin(TEST_DOMAIN), + "No data before a full cleanup" + ); + + info("Removing the tab"); + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function () { + info("Testing a total QuotaManager cleanup"); + + let tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE); + gBrowser.selectedTab = tab; + + let browser = gBrowser.getBrowserForTab(tab); + await BrowserTestUtils.browserLoaded(browser); + + ok( + !ChromeUtils.hasReportingHeaderForOrigin(TEST_DOMAIN), + "No data before the test" + ); + + await storeReportingHeader(browser); + ok(ChromeUtils.hasReportingHeaderForOrigin(TEST_DOMAIN), "We have data"); + + await new Promise(resolve => { + Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_REPORTS, value => + resolve() + ); + }); + + ok( + !ChromeUtils.hasReportingHeaderForOrigin(TEST_DOMAIN), + "No data before a reports cleanup" + ); + + info("Removing the tab"); + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function () { + info("Testing a QuotaManager host cleanup"); + + let tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE); + gBrowser.selectedTab = tab; + + let browser = gBrowser.getBrowserForTab(tab); + await BrowserTestUtils.browserLoaded(browser); + + ok( + !ChromeUtils.hasReportingHeaderForOrigin(TEST_DOMAIN), + "No data before the test" + ); + + await storeReportingHeader(browser); + ok(ChromeUtils.hasReportingHeaderForOrigin(TEST_DOMAIN), "We have data"); + + await new Promise(resolve => { + Services.clearData.deleteDataFromHost( + TEST_HOST, + true, + Ci.nsIClearDataService.CLEAR_REPORTS, + value => resolve() + ); + }); + + ok( + !ChromeUtils.hasReportingHeaderForOrigin(TEST_DOMAIN), + "No data before a reports cleanup" + ); + + info("Removing the tab"); + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function () { + info("Testing a 410 endpoint status"); + + let tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE); + gBrowser.selectedTab = tab; + + let browser = gBrowser.getBrowserForTab(tab); + await BrowserTestUtils.browserLoaded(browser); + + ok( + !ChromeUtils.hasReportingHeaderForOrigin(TEST_DOMAIN), + "No data before the test" + ); + + await storeReportingHeader(browser, "410=true"); + ok(ChromeUtils.hasReportingHeaderForOrigin(TEST_DOMAIN), "We have data"); + + await SpecialPowers.spawn(browser, [], async _ => { + let testingInterface = new content.TestingDeprecatedInterface(); + ok(!!testingInterface, "Created a deprecated interface"); + }); + + await new Promise((resolve, reject) => { + let count = 0; + let id = setInterval(_ => { + ++count; + if (count > 10) { + ok(false, "Something went wrong."); + clearInterval(id); + reject(); + } + + if (!ChromeUtils.hasReportingHeaderForOrigin(TEST_DOMAIN)) { + ok(true, "No data after a 410!"); + clearInterval(id); + resolve(); + } + }, 1000); + }); + + info("Removing the tab"); + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function () { + info("Creating a new container"); + + let identity = ContextualIdentityService.create( + "Report-To-Test", + "fingerprint", + "orange" + ); + + info("Creating a new container tab"); + let tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE, { + userContextId: identity.userContextId, + }); + is( + tab.getAttribute("usercontextid"), + "" + identity.userContextId, + "New tab has the right UCI" + ); + gBrowser.selectedTab = tab; + + let browser = gBrowser.getBrowserForTab(tab); + await BrowserTestUtils.browserLoaded(browser); + + ok( + !ChromeUtils.hasReportingHeaderForOrigin(TEST_DOMAIN), + "No data before the test" + ); + + await storeReportingHeader(browser); + ok( + !ChromeUtils.hasReportingHeaderForOrigin(TEST_DOMAIN), + "We don't have data for the origin" + ); + ok( + ChromeUtils.hasReportingHeaderForOrigin( + TEST_DOMAIN + "^userContextId=" + identity.userContextId + ), + "We have data for the origin + userContextId" + ); + + info("Removing the tab"); + BrowserTestUtils.removeTab(tab); + + ContextualIdentityService.remove(identity.userContextId); + + ok( + !ChromeUtils.hasReportingHeaderForOrigin( + TEST_DOMAIN + "^userContextId=" + identity.userContextId + ), + "No more data after a container removal" + ); +}); + +add_task(async function () { + info("TTL cleanup"); + + let tab = BrowserTestUtils.addTab(gBrowser, TEST_TOP_PAGE); + gBrowser.selectedTab = tab; + + let browser = gBrowser.getBrowserForTab(tab); + await BrowserTestUtils.browserLoaded(browser); + + ok( + !ChromeUtils.hasReportingHeaderForOrigin(TEST_DOMAIN), + "No data before the test" + ); + + await storeReportingHeader(browser); + ok( + ChromeUtils.hasReportingHeaderForOrigin(TEST_DOMAIN), + "We have data for the origin" + ); + + // Let's wait a bit. + await new Promise(resolve => { + setTimeout(resolve, 5000); + }); + + ok(!ChromeUtils.hasReportingHeaderForOrigin(TEST_DOMAIN), "No data anymore"); + + info("Removing the tab"); + BrowserTestUtils.removeTab(tab); +}); + +add_task(async function () { + info("Cleaning up."); + await new Promise(resolve => { + Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => + resolve() + ); + }); +}); diff --git a/dom/reporting/tests/common_deprecated.js b/dom/reporting/tests/common_deprecated.js new file mode 100644 index 0000000000..8f8415fcf3 --- /dev/null +++ b/dom/reporting/tests/common_deprecated.js @@ -0,0 +1,214 @@ +let testingInterface; + +// eslint-disable-next-line no-unused-vars +function test_deprecatedInterface() { + info("Testing DeprecatedTestingInterface report"); + return new Promise(resolve => { + let obs = new ReportingObserver((reports, o) => { + is(obs, o, "Same observer!"); + ok(reports.length == 1, "We have 1 report"); + + let report = reports[0]; + is(report.type, "deprecation", "Deprecation report received"); + is(report.url, location.href, "URL is location"); + ok(!!report.body, "The report has a body"); + ok( + report.body instanceof DeprecationReportBody, + "Correct type for the body" + ); + is( + report.body.id, + "DeprecatedTestingInterface", + "report.body.id matches DeprecatedTestingMethod" + ); + ok(!report.body.anticipatedRemoval, "We don't have a anticipatedRemoval"); + ok( + report.body.message.includes("TestingDeprecatedInterface"), + "We have a message" + ); + is( + report.body.sourceFile, + location.href + .split("?")[0] + .replace("test_deprecated.html", "common_deprecated.js") + .replace("worker_deprecated.js", "common_deprecated.js"), + "We have a sourceFile" + ); + is(report.body.lineNumber, 48, "We have a lineNumber"); + is(report.body.columnNumber, 24, "We have a columnNumber"); + + obs.disconnect(); + resolve(); + }); + ok(!!obs, "ReportingObserver is a thing"); + + obs.observe(); + ok(true, "ReportingObserver.observe() is callable"); + + testingInterface = new TestingDeprecatedInterface(); + ok(true, "Created a deprecated interface"); + }); +} + +// eslint-disable-next-line no-unused-vars +function test_deprecatedMethod() { + info("Testing DeprecatedTestingMethod report"); + return new Promise(resolve => { + let obs = new ReportingObserver((reports, o) => { + is(obs, o, "Same observer!"); + ok(reports.length == 1, "We have 1 report"); + + let report = reports[0]; + is(report.type, "deprecation", "Deprecation report received"); + is(report.url, location.href, "URL is location"); + ok(!!report.body, "The report has a body"); + ok( + report.body instanceof DeprecationReportBody, + "Correct type for the body" + ); + is( + report.body.id, + "DeprecatedTestingMethod", + "report.body.id matches DeprecatedTestingMethod" + ); + ok(!report.body.anticipatedRemoval, "We don't have a anticipatedRemoval"); + ok( + report.body.message.includes( + "TestingDeprecatedInterface.deprecatedMethod" + ), + "We have a message" + ); + is( + report.body.sourceFile, + location.href + .split("?")[0] + .replace("test_deprecated.html", "common_deprecated.js") + .replace("worker_deprecated.js", "common_deprecated.js"), + "We have a sourceFile" + ); + is(report.body.lineNumber, 100, "We have a lineNumber"); + is(report.body.columnNumber, 22, "We have a columnNumber"); + + obs.disconnect(); + resolve(); + }); + ok(!!obs, "ReportingObserver is a thing"); + + obs.observe(); + ok(true, "ReportingObserver.observe() is callable"); + + testingInterface.deprecatedMethod(); + ok(true, "Run a deprecated method."); + }); +} + +// eslint-disable-next-line no-unused-vars +function test_deprecatedMethodWithDataURI() { + info("Testing deprecatedMethodWithDataURI report"); + + const uri = `data:text/html,<script> + window.onload = () => { + let obs = new ReportingObserver((reports, o) => { + obs.disconnect(); + let report = reports[0]; + const message = (report.url == "data:...") ? "passed" : "failed"; + window.opener.postMessage(message, "http://mochi.test:8888"); + close(); + }); + + obs.observe(); + let testingInterface = new TestingDeprecatedInterface(); + testingInterface.deprecatedMethod(); + }; + </script>`; + + return new Promise((resolve, reject) => { + window.open(uri); + window.addEventListener("message", e => { + is(e.data, "passed", "The data URI is truncated"); + resolve(); + }); + }); +} + +// eslint-disable-next-line no-unused-vars +function test_deprecatedAttribute() { + info("Testing DeprecatedTestingAttribute report"); + return new Promise(resolve => { + let obs = new ReportingObserver((reports, o) => { + is(obs, o, "Same observer!"); + ok(reports.length == 1, "We have 1 report"); + + let report = reports[0]; + is(report.type, "deprecation", "Deprecation report received"); + is(report.url, location.href, "URL is location"); + ok(!!report.body, "The report has a body"); + ok( + report.body instanceof DeprecationReportBody, + "Correct type for the body" + ); + is( + report.body.id, + "DeprecatedTestingAttribute", + "report.body.id matches DeprecatedTestingAttribute" + ); + ok(!report.body.anticipatedRemoval, "We don't have a anticipatedRemoval"); + ok( + report.body.message.includes( + "TestingDeprecatedInterface.deprecatedAttribute" + ), + "We have a message" + ); + is( + report.body.sourceFile, + location.href + .split("?")[0] + .replace("test_deprecated.html", "common_deprecated.js") + .replace("worker_deprecated.js", "common_deprecated.js"), + "We have a sourceFile" + ); + is(report.body.lineNumber, 181, "We have a lineNumber"); + is(report.body.columnNumber, 8, "We have a columnNumber"); + + obs.disconnect(); + resolve(); + }); + ok(!!obs, "ReportingObserver is a thing"); + + obs.observe(); + ok(true, "ReportingObserver.observe() is callable"); + + ok(testingInterface.deprecatedAttribute, "Attributed called"); + }); +} + +// eslint-disable-next-line no-unused-vars +function test_takeRecords() { + info("Testing ReportingObserver.takeRecords()"); + let p = new Promise(resolve => { + let obs = new ReportingObserver((reports, o) => { + is(obs, o, "Same observer!"); + resolve(obs); + }); + ok(!!obs, "ReportingObserver is a thing"); + + obs.observe(); + ok(true, "ReportingObserver.observe() is callable"); + + testingInterface.deprecatedMethod(); + ok(true, "Run a deprecated method."); + }); + + return p.then(obs => { + let reports = obs.takeRecords(); + is(reports.length, 0, "No reports after an callback"); + + testingInterface.deprecatedAttribute + 1; + + reports = obs.takeRecords(); + ok(reports.length >= 1, "We have at least 1 report"); + + reports = obs.takeRecords(); + is(reports.length, 0, "No more reports"); + }); +} diff --git a/dom/reporting/tests/delivering.sjs b/dom/reporting/tests/delivering.sjs new file mode 100644 index 0000000000..5bc3e17f3e --- /dev/null +++ b/dom/reporting/tests/delivering.sjs @@ -0,0 +1,111 @@ +const CC = Components.Constructor; +const BinaryInputStream = CC( + "@mozilla.org/binaryinputstream;1", + "nsIBinaryInputStream", + "setInputStream" +); + +function handleRequest(aRequest, aResponse) { + var params = new URLSearchParams(aRequest.queryString); + + // Report-to setter + if (aRequest.method == "GET" && params.get("task") == "header") { + let extraParams = []; + + if (params.has("410")) { + extraParams.push("410=true"); + } + + if (params.has("worker")) { + extraParams.push("worker=true"); + } + + let body = { + max_age: 1, + endpoints: [ + { + url: + "https://example.org/tests/dom/reporting/tests/delivering.sjs" + + (extraParams.length ? "?" + extraParams.join("&") : ""), + priority: 1, + weight: 1, + }, + ], + }; + + aResponse.setStatusLine(aRequest.httpVersion, 200, "OK"); + aResponse.setHeader("Report-to", JSON.stringify(body), false); + aResponse.write("OK"); + return; + } + + // Report check + if (aRequest.method == "GET" && params.get("task") == "check") { + aResponse.setStatusLine(aRequest.httpVersion, 200, "OK"); + + let reports = getState("report"); + if (!reports) { + aResponse.write(""); + return; + } + + if (params.has("min")) { + let json = JSON.parse(reports); + if (json.length < params.get("min")) { + aResponse.write(""); + return; + } + } + + aResponse.setStatusLine(aRequest.httpVersion, 200, "OK"); + aResponse.write(getState("report")); + + setState("report", ""); + return; + } + + if (aRequest.method == "POST") { + var body = new BinaryInputStream(aRequest.bodyInputStream); + + var avail; + var bytes = []; + while ((avail = body.available()) > 0) { + Array.prototype.push.apply(bytes, body.readByteArray(avail)); + } + + let reports = getState("report"); + if (!reports) { + reports = []; + } else { + reports = JSON.parse(reports); + } + + const incoming_reports = JSON.parse(String.fromCharCode.apply(null, bytes)); + for (let report of incoming_reports) { + let data = { + contentType: aRequest.getHeader("content-type"), + origin: aRequest.getHeader("origin"), + body: report, + url: + aRequest.scheme + + "://" + + aRequest.host + + aRequest.path + + (aRequest.queryString ? "&" + aRequest.queryString : ""), + }; + reports.push(data); + } + + setState("report", JSON.stringify(reports)); + + if (params.has("410")) { + aResponse.setStatusLine(aRequest.httpVersion, 410, "Gone"); + } else { + aResponse.setStatusLine(aRequest.httpVersion, 200, "OK"); + } + return; + } + + aResponse.setStatusLine(aRequest.httpVersion, 500, "Internal error"); + aResponse.write("Invalid request"); +} diff --git a/dom/reporting/tests/empty.html b/dom/reporting/tests/empty.html new file mode 100644 index 0000000000..cd0875583a --- /dev/null +++ b/dom/reporting/tests/empty.html @@ -0,0 +1 @@ +Hello world! diff --git a/dom/reporting/tests/gtest/TestReportToParser.cpp b/dom/reporting/tests/gtest/TestReportToParser.cpp new file mode 100644 index 0000000000..a3549886a3 --- /dev/null +++ b/dom/reporting/tests/gtest/TestReportToParser.cpp @@ -0,0 +1,418 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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/. */ + +#include "gtest/gtest.h" +#include "mozilla/dom/ReportingHeader.h" +#include "nsNetUtil.h" +#include "nsIURI.h" + +using namespace mozilla; +using namespace mozilla::dom; + +TEST(ReportToParser, Basic) +{ + nsCOMPtr<nsIURI> uri; + + nsresult rv = NS_NewURI(getter_AddRefs(uri), "https://example.com"); + ASSERT_EQ(NS_OK, rv); + + bool urlEqual = false; + + // Empty header. + UniquePtr<ReportingHeader::Client> client = + ReportingHeader::ParseHeader(nullptr, uri, ""_ns); + ASSERT_TRUE(!client); + + // Empty header. + client = ReportingHeader::ParseHeader(nullptr, uri, " "_ns); + ASSERT_TRUE(!client); + + // No minimal attributes + client = ReportingHeader::ParseHeader(nullptr, uri, "{}"_ns); + ASSERT_TRUE(!client); + + // Single client + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString( + "{\"max_age\": 42, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_TRUE(client->mGroups.ElementAt(0).mName.EqualsLiteral("default")); + ASSERT_FALSE(client->mGroups.ElementAt(0).mIncludeSubdomains); + ASSERT_EQ(42, client->mGroups.ElementAt(0).mTTL); + ASSERT_EQ((uint32_t)1, client->mGroups.ElementAt(0).mEndpoints.Length()); + ASSERT_TRUE( + NS_SUCCEEDED( + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mUrl->Equals( + uri, &urlEqual)) && + urlEqual); + ASSERT_EQ((uint32_t)1, + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mPriority); + ASSERT_EQ((uint32_t)2, + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mWeight); + + // 2 clients, same group name. + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString( + "{\"max_age\": 43, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}," + "{\"max_age\": 44, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_TRUE(client->mGroups.ElementAt(0).mName.EqualsLiteral("default")); + ASSERT_EQ(43, client->mGroups.ElementAt(0).mTTL); + + // 2 clients, the first one with an invalid group name. + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString( + "{\"max_age\": 43, \"group\": 123, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}," + "{\"max_age\": 44, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_TRUE(client->mGroups.ElementAt(0).mName.EqualsLiteral("default")); + ASSERT_EQ(44, client->mGroups.ElementAt(0).mTTL); + + // 2 clients, the first one with an invalid group name. + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString( + "{\"max_age\": 43, \"group\": null, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}," + "{\"max_age\": 44, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_TRUE(client->mGroups.ElementAt(0).mName.EqualsLiteral("default")); + ASSERT_EQ(44, client->mGroups.ElementAt(0).mTTL); + + // 2 clients, the first one with an invalid group name. + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString( + "{\"max_age\": 43, \"group\": {}, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}," + "{\"max_age\": 44, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_TRUE(client->mGroups.ElementAt(0).mName.EqualsLiteral("default")); + ASSERT_EQ(44, client->mGroups.ElementAt(0).mTTL); + + // Single client: optional params + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString( + "{\"max_age\": 45, \"group\": \"foobar\", \"include_subdomains\": " + "true, \"endpoints\": [{\"url\": \"https://example.com\", " + "\"priority\": 1, \"weight\": 2}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_TRUE(client->mGroups.ElementAt(0).mName.EqualsLiteral("foobar")); + ASSERT_TRUE(client->mGroups.ElementAt(0).mIncludeSubdomains); + ASSERT_EQ(45, client->mGroups.ElementAt(0).mTTL); + + // 2 clients, the first incomplete: missing max_age. + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString( + "{\"endpoints\": [{\"url\": \"https://example.com\", \"priority\": " + "1, \"weight\": 2}]}," + "{\"max_age\": 46, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_EQ(46, client->mGroups.ElementAt(0).mTTL); + + // 2 clients, the first incomplete: invalid max_age. + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString( + "{\"max_age\": null, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}," + "{\"max_age\": 46, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_EQ(46, client->mGroups.ElementAt(0).mTTL); + + // 2 clients, the first incomplete: invalid max_age. + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString( + "{\"max_age\": \"foobar\", \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}," + "{\"max_age\": 46, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_EQ(46, client->mGroups.ElementAt(0).mTTL); + + // 2 clients, the first incomplete: invalid max_age. + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString( + "{\"max_age\": {}, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}," + "{\"max_age\": 46, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_EQ(46, client->mGroups.ElementAt(0).mTTL); + + // 2 clients, the first incomplete: missing endpoints + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString( + "{\"max_age\": 47}," + "{\"max_age\": 48, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_EQ(48, client->mGroups.ElementAt(0).mTTL); + + // 2 clients, the first incomplete: invalid endpoints + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString( + "{\"max_age\": 47, \"endpoints\": null }," + "{\"max_age\": 48, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_EQ(48, client->mGroups.ElementAt(0).mTTL); + + // 2 clients, the first incomplete: invalid endpoints + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString( + "{\"max_age\": 47, \"endpoints\": \"abc\" }," + "{\"max_age\": 48, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_EQ(48, client->mGroups.ElementAt(0).mTTL); + + // 2 clients, the first incomplete: invalid endpoints + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString( + "{\"max_age\": 47, \"endpoints\": 42 }," + "{\"max_age\": 48, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_EQ(48, client->mGroups.ElementAt(0).mTTL); + + // 2 clients, the first incomplete: invalid endpoints + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString( + "{\"max_age\": 47, \"endpoints\": {} }," + "{\"max_age\": 48, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_EQ(48, client->mGroups.ElementAt(0).mTTL); + + // 2 clients, the first incomplete: empty endpoints + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString( + "{\"max_age\": 49, \"endpoints\": []}," + "{\"max_age\": 50, \"endpoints\": [{\"url\": " + "\"https://example.com\", \"priority\": 1, \"weight\": 2}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_EQ(50, client->mGroups.ElementAt(0).mTTL); + + // 2 endpoints, the first incomplete: missing url + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString("{\"max_age\": 51, \"endpoints\": [" + " {\"priority\": 1, \"weight\": 2}," + " {\"url\": \"https://example.com\", \"priority\": 1, " + "\"weight\": 2}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_EQ((uint32_t)1, client->mGroups.ElementAt(0).mEndpoints.Length()); + ASSERT_TRUE( + NS_SUCCEEDED( + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mUrl->Equals( + uri, &urlEqual)) && + urlEqual); + ASSERT_EQ((uint32_t)1, + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mPriority); + ASSERT_EQ((uint32_t)2, + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mWeight); + + // 2 endpoints, the first incomplete: invalid url + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString("{\"max_age\": 51, \"endpoints\": [" + " {\"url\": 42, \"priority\": 1, \"weight\": 2}," + " {\"url\": \"https://example.com\", \"priority\": 1, " + "\"weight\": 2}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_EQ((uint32_t)1, client->mGroups.ElementAt(0).mEndpoints.Length()); + ASSERT_TRUE( + NS_SUCCEEDED( + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mUrl->Equals( + uri, &urlEqual)) && + urlEqual); + ASSERT_EQ((uint32_t)1, + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mPriority); + ASSERT_EQ((uint32_t)2, + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mWeight); + + // 2 endpoints, the first incomplete: invalid url + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString( + "{\"max_age\": 51, \"endpoints\": [" + " {\"url\": \"something here\", \"priority\": 1, \"weight\": 2}," + " {\"url\": \"https://example.com\", \"priority\": 1, \"weight\": " + "2}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_EQ((uint32_t)1, client->mGroups.ElementAt(0).mEndpoints.Length()); + ASSERT_TRUE( + NS_SUCCEEDED( + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mUrl->Equals( + uri, &urlEqual)) && + urlEqual); + ASSERT_EQ((uint32_t)1, + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mPriority); + ASSERT_EQ((uint32_t)2, + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mWeight); + + // 2 endpoints, the first incomplete: invalid url + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString("{\"max_age\": 51, \"endpoints\": [" + " {\"url\": {}, \"priority\": 1, \"weight\": 2}," + " {\"url\": \"https://example.com\", \"priority\": 1, " + "\"weight\": 2}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_EQ((uint32_t)1, client->mGroups.ElementAt(0).mEndpoints.Length()); + ASSERT_TRUE( + NS_SUCCEEDED( + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mUrl->Equals( + uri, &urlEqual)) && + urlEqual); + ASSERT_EQ((uint32_t)1, + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mPriority); + ASSERT_EQ((uint32_t)2, + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mWeight); + + // 2 endpoints, the first incomplete: missing priority + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString("{\"max_age\": 52, \"endpoints\": [" + " {\"url\": \"https://example.com\", \"weight\": 3}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_EQ((uint32_t)1, client->mGroups.ElementAt(0).mEndpoints.Length()); + ASSERT_TRUE( + NS_SUCCEEDED( + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mUrl->Equals( + uri, &urlEqual)) && + urlEqual); + ASSERT_EQ((uint32_t)1, + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mPriority); + ASSERT_EQ((uint32_t)3, + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mWeight); + + // 2 endpoints, the first incomplete: invalid priority + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString("{\"max_age\": 52, \"endpoints\": [" + " {\"url\": \"https://example.com\", \"priority\": " + "{}, \"weight\": 2}," + " {\"url\": \"https://example.com\", \"priority\": 2, " + "\"weight\": 3}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_EQ((uint32_t)1, client->mGroups.ElementAt(0).mEndpoints.Length()); + ASSERT_TRUE( + NS_SUCCEEDED( + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mUrl->Equals( + uri, &urlEqual)) && + urlEqual); + ASSERT_EQ((uint32_t)2, + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mPriority); + ASSERT_EQ((uint32_t)3, + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mWeight); + + // 2 endpoints, the first incomplete: invalid priority + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString("{\"max_age\": 52, \"endpoints\": [" + " {\"url\": \"https://example.com\", \"priority\": " + "\"ok\", \"weight\": 2}," + " {\"url\": \"https://example.com\", \"priority\": 2, " + "\"weight\": 3}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_EQ((uint32_t)1, client->mGroups.ElementAt(0).mEndpoints.Length()); + ASSERT_TRUE( + NS_SUCCEEDED( + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mUrl->Equals( + uri, &urlEqual)) && + urlEqual); + ASSERT_EQ((uint32_t)2, + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mPriority); + ASSERT_EQ((uint32_t)3, + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mWeight); + + // 2 endpoints, the first incomplete: missing weight + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString( + "{\"max_age\": 52, \"endpoints\": [" + " {\"url\": \"https://example.com\", \"priority\": 5}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_EQ((uint32_t)1, client->mGroups.ElementAt(0).mEndpoints.Length()); + ASSERT_TRUE( + NS_SUCCEEDED( + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mUrl->Equals( + uri, &urlEqual)) && + urlEqual); + ASSERT_EQ((uint32_t)5, + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mPriority); + ASSERT_EQ((uint32_t)1, + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mWeight); + + // 2 endpoints, the first incomplete: invalid weight + client = ReportingHeader::ParseHeader( + nullptr, uri, + nsLiteralCString("{\"max_age\": 52, \"endpoints\": [" + " {\"url\": \"https://example.com\", \"priority\": 4, " + "\"weight\": []}," + " {\"url\": \"https://example.com\", \"priority\": 5, " + "\"weight\": 6}]}")); + ASSERT_TRUE(!!client); + ASSERT_EQ((uint32_t)1, client->mGroups.Length()); + ASSERT_EQ((uint32_t)1, client->mGroups.ElementAt(0).mEndpoints.Length()); + ASSERT_TRUE( + NS_SUCCEEDED( + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mUrl->Equals( + uri, &urlEqual)) && + urlEqual); + ASSERT_EQ((uint32_t)5, + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mPriority); + ASSERT_EQ((uint32_t)6, + client->mGroups.ElementAt(0).mEndpoints.ElementAt(0).mWeight); +} diff --git a/dom/reporting/tests/gtest/moz.build b/dom/reporting/tests/gtest/moz.build new file mode 100644 index 0000000000..860ef48d1e --- /dev/null +++ b/dom/reporting/tests/gtest/moz.build @@ -0,0 +1,13 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +UNIFIED_SOURCES = [ + "TestReportToParser.cpp", +] + +include("/ipc/chromium/chromium-config.mozbuild") + +FINAL_LIBRARY = "xul-gtest" diff --git a/dom/reporting/tests/iframe_delivering.html b/dom/reporting/tests/iframe_delivering.html new file mode 100644 index 0000000000..e8c5e9e3a4 --- /dev/null +++ b/dom/reporting/tests/iframe_delivering.html @@ -0,0 +1,92 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for delivering reports</title> +</head> +<body> + +<script type="application/javascript"> + +function ok(a, msg) { + parent.postMessage({type: "test", check: !!a, msg }, "*"); +} + +function is(a, b, msg) { + ok(a === b, msg); +} + +function finish() { + parent.postMessage({type: "finish" }, "*"); +} + +function checkReport() { + return new Promise(resolve => { + let id = setInterval(_ => { + fetch("delivering.sjs?task=check&min=3") + .then(r => r.text()) + .then(text => { + if (text) { + resolve(JSON.parse(text)); + clearInterval(id); + } + }); + }, 1000); + }); +} + +function runTests(extraParams = "") { + // Call a deprecating operation. + for (let i = 0; i < 100; ++i) { + new TestingDeprecatedInterface(); + } + ok(true, "Created a deprecated interface"); + + // Check if the report has been received. + return checkReport() + .then(reports => { + is(reports.length, 3, "We have 1 report"); + + let report = reports[0]; + is(report.contentType, "application/reports+json", "Correct mime-type"); + is(report.origin, "https://example.org", "Origin correctly set"); + is(report.url, "https://example.org/tests/dom/reporting/tests/delivering.sjs" + extraParams, "URL is correctly set"); + ok(!!report.body, "We have a report.body"); + ok(report.body.age > 0, "Age is correctly set"); + is(report.body.url, window.location.href, "URL is correctly set"); + is(report.body.user_agent, navigator.userAgent, "User-agent matches"); + ok(report.body.type, "deprecation", "Type is fine."); + ok(!!report.body.body, "We have the real report.body"); + is(report.body.body.id, "DeprecatedTestingInterface", "Correct report.body.id"); + is(report.body.body.message, "TestingDeprecatedInterface is a testing-only interface and this is its testing deprecation message.", "We have a report.body.message"); + is(report.body.body.sourceFile, "https://example.org/tests/dom/reporting/tests/iframe_delivering.html", "report.body.sourceFile"); + is(report.body.body.lineNumber, 40, "report.body.lineNumber"); + is(report.body.body.columnNumber, 5, "report.body.columnNumber"); + }); +} + +// Let's register a group + endpoint +fetch("delivering.sjs?task=header") +.then(r => r.text()) +.then(text => { + is(text, "OK", "Report-to header sent"); +}) +.then(_ => { + return runTests(); +}) + +// Let's register a group + endpoint from a worker +.then(_ => { + return new Promise(resolve => { + let w = new Worker("worker_delivering.js"); + w.onmessage = e => resolve(); + }); +}) +.then(_ => { + return runTests("&worker=true"); +}) + +.then(finish); + +</script> +</body> +</html> diff --git a/dom/reporting/tests/mochitest.toml b/dom/reporting/tests/mochitest.toml new file mode 100644 index 0000000000..4faddd217c --- /dev/null +++ b/dom/reporting/tests/mochitest.toml @@ -0,0 +1,29 @@ +[DEFAULT] +prefs = [ + "dom.reporting.enabled=true", + "dom.reporting.header.enabled=true", + "dom.reporting.testing.enabled=true", +] + +["test_delivering.html"] +support-files = [ + "delivering.sjs", + "iframe_delivering.html", + "worker_delivering.js", +] +skip-if = [ + "http3", + "http2", +] + +["test_deprecated.html"] +support-files = [ + "common_deprecated.js", + "worker_deprecated.js", +] +skip-if = [ + "http3", + "http2", +] + +["test_memoryPressure.html"] diff --git a/dom/reporting/tests/test_delivering.html b/dom/reporting/tests/test_delivering.html new file mode 100644 index 0000000000..2c552273e0 --- /dev/null +++ b/dom/reporting/tests/test_delivering.html @@ -0,0 +1,45 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for delivering reports</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> + +<script type="application/javascript"> + +// Setting prefs. +SpecialPowers.pushPrefEnv({ set: [ + ["dom_reporting_delivering_timeout", 1], + ["dom_reporting_delivering_maxFailures", 2], + ["dom.reporting.delivering.maxReports", 3], +]}) + +// Tests run in iframes because the origin must be secure for report-to header. +.then(_ => { + window.addEventListener("message", e => { + if (e.data.type == "finish") { + SimpleTest.finish(); + return; + } + + if (e.data.type == "test") { + ok(e.data.check, e.data.msg); + return; + } + + ok(false, "Invalid message"); + }); + + let ifr = document.createElement("iframe"); + ifr.src = "https://example.org/tests/dom/reporting/tests/iframe_delivering.html"; + + document.body.appendChild(ifr); +}); + +SimpleTest.waitForExplicitFinish(); + +</script> +</body> +</html> diff --git a/dom/reporting/tests/test_deprecated.html b/dom/reporting/tests/test_deprecated.html new file mode 100644 index 0000000000..da55978e9b --- /dev/null +++ b/dom/reporting/tests/test_deprecated.html @@ -0,0 +1,51 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for Deprecated reports</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="common_deprecated.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> + +<script type="application/javascript"> + +test_deprecatedInterface() +.then(() => test_deprecatedMethod()) +.then(() => test_deprecatedMethodWithDataURI()) +.then(() => test_deprecatedAttribute()) +.then(() => test_takeRecords()) +.then(() => { + info("Workers!"); + + return new Promise(resolve => { + const w = new Worker("worker_deprecated.js"); + w.onmessage = e => { + switch (e.data.type) { + case "info": + info(e.data.msg); + break; + + case "check": + ok(e.data.check, e.data.msg); + break; + + case "finish": + resolve(); + break; + + default: + ok(false, "Invalid message"); + break; + } + } + }); +}) + +.then(() => { SimpleTest.finish(); }); + +SimpleTest.waitForExplicitFinish(); + +</script> +</body> +</html> diff --git a/dom/reporting/tests/test_memoryPressure.html b/dom/reporting/tests/test_memoryPressure.html new file mode 100644 index 0000000000..1bb887b05e --- /dev/null +++ b/dom/reporting/tests/test_memoryPressure.html @@ -0,0 +1,33 @@ +<!DOCTYPE HTML> +<html> +<head> + <title>Test for ReportingObserver + memory-pressure</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> + +<script type="application/javascript"> + +info("Testing TakeRecords() without memory-pressure"); +let o = new ReportingObserver(() => {}); +o.observe(); + +new TestingDeprecatedInterface(); +let r = o.takeRecords(); +is(r.length, 1, "We have 1 report"); + +r = o.takeRecords(); +is(r.length, 0, "We have 0 reports after a takeRecords()"); + +info("Testing DeprecatedTestingMethod report"); + +new TestingDeprecatedInterface(); +SpecialPowers.Services.obs.notifyObservers(null, "memory-pressure", "heap-minimize"); + +r = o.takeRecords(); +is(r.length, 0, "We have 0 reports after a memory-pressure"); + +</script> +</body> +</html> diff --git a/dom/reporting/tests/worker_delivering.js b/dom/reporting/tests/worker_delivering.js new file mode 100644 index 0000000000..539bcd231c --- /dev/null +++ b/dom/reporting/tests/worker_delivering.js @@ -0,0 +1,5 @@ +fetch("delivering.sjs?task=header&worker=true") + .then(r => r.text()) + .then(text => { + postMessage("All good!"); + }); diff --git a/dom/reporting/tests/worker_deprecated.js b/dom/reporting/tests/worker_deprecated.js new file mode 100644 index 0000000000..f6b57896f6 --- /dev/null +++ b/dom/reporting/tests/worker_deprecated.js @@ -0,0 +1,28 @@ +/* eslint-disable no-undef */ + +// eslint-disable-next-line no-unused-vars +function ok(a, msg) { + postMessage({ type: "check", check: !!a, msg }); +} + +// eslint-disable-next-line no-unused-vars +function is(a, b, msg) { + ok(a === b, msg); +} + +// eslint-disable-next-line no-unused-vars +function info(msg) { + postMessage({ type: "info", msg }); +} + +function finish() { + postMessage({ type: "finish" }); +} + +importScripts("common_deprecated.js"); + +test_deprecatedInterface() + .then(() => test_deprecatedMethod()) + .then(() => test_deprecatedAttribute()) + .then(() => test_takeRecords()) + .then(() => finish()); |