mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
Auto merge of #19801 - servo:wptup, r=jdm
Update web-platform-tests <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/19801) <!-- Reviewable:end -->
This commit is contained in:
commit
b62b51ab4b
832 changed files with 16026 additions and 2649 deletions
|
@ -87,7 +87,7 @@ matrix:
|
|||
apt:
|
||||
packages:
|
||||
- libnss3-tools
|
||||
env: JOB=wpt_integration TOXENV=py27 SCRIPT=tools/ci/ci_wpt.sh
|
||||
env: JOB=wpt_integration TOXENV=py27,py27-flake8 SCRIPT=tools/ci/ci_wpt.sh
|
||||
exclude:
|
||||
- env: # exclude empty env from the top-level above
|
||||
allow_failures:
|
||||
|
|
|
@ -38,7 +38,8 @@ function makeVideo() {
|
|||
video.oncanplaythrough = function() {
|
||||
resolve(video);
|
||||
};
|
||||
video.src = "/images/pattern.ogv";
|
||||
video.onerror = reject;
|
||||
video.src = getVideoURI("/images/pattern");
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/common/canvas-tests.js"></script>
|
||||
<script src="/common/media.js"></script>
|
||||
<script src="common.js"></script>
|
||||
<link rel="stylesheet" href="/common/canvas-tests.css">
|
||||
<body>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<!doctype html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/common/media.js"></script>
|
||||
<script src="common.js"></script>
|
||||
<script>
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ test_first_argument(["bits", new Blob(["bits"]), new Blob(), new Uint8Array([0x5
|
|||
test_first_argument([12], 2, "Number in fileBits");
|
||||
test_first_argument([[1,2,3]], 5, "Array in fileBits");
|
||||
test_first_argument([{}], 15, "Object in fileBits"); // "[object Object]"
|
||||
test_first_argument([document], 21, "HTMLDocument in fileBits"); // "[object HTMLDocument]"
|
||||
test_first_argument([document.body], 24, "HTMLBodyElement in fileBits"); // "[object HTMLBodyElement]"
|
||||
test_first_argument([to_string_obj], 8, "Object with toString in fileBits");
|
||||
test_first_argument({[Symbol.iterator]() {
|
||||
let i = 0;
|
||||
|
@ -88,7 +88,7 @@ test_second_argument("dummy/foo", "dummy:foo", "Using special character in fileN
|
|||
test_second_argument(null, "null", "Using null fileName");
|
||||
test_second_argument(1, "1", "Using number fileName");
|
||||
test_second_argument('', '', "Using empty string fileName");
|
||||
test_second_argument(document, '[object HTMLDocument]', "Using object fileName");
|
||||
test_second_argument(document.body, '[object HTMLBodyElement]', "Using object fileName");
|
||||
|
||||
// testing the third argument
|
||||
[
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
<script>
|
||||
|
||||
const iframe_scripts = [
|
||||
'/resources/testharness.js',
|
||||
'resources/fetch-tests.js',
|
||||
'url-format.any.js',
|
||||
'url-with-xhr.any.js',
|
||||
|
@ -18,6 +17,8 @@ const iframe_scripts = [
|
|||
];
|
||||
|
||||
let html = '<!doctype html>\n<meta charset="utf-8">\n<body>\n';
|
||||
html = html + '<script src="/resources/testharness.js"></' + 'script>\n';
|
||||
html = html + '<script>setup({"explicit_timeout": true});</' + 'script>\n';
|
||||
for (const script of iframe_scripts)
|
||||
html = html + '<script src="' + script + '"></' + 'script>\n';
|
||||
|
||||
|
@ -27,4 +28,4 @@ frame.setAttribute('style', 'display:none;');
|
|||
|
||||
fetch_tests_from_window(frame.contentWindow);
|
||||
|
||||
</script>
|
||||
</script>
|
||||
|
|
|
@ -2,7 +2,7 @@ const blob = new Blob(['test']);
|
|||
const file = new File(['test'], 'name');
|
||||
|
||||
test(() => {
|
||||
const url_count = 10000;
|
||||
const url_count = 5000;
|
||||
let list = [];
|
||||
|
||||
for (let i = 0; i < url_count; ++i)
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<title>IDL check of WebCrypto</title>
|
||||
<link rel="help" href="https://w3c.github.io/webcrypto/Overview.html#crypto-interface">
|
||||
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=/resources/WebIDLParser.js></script>
|
||||
<script src=/resources/idlharness.js></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1 class="instructions">Description</h1>
|
||||
|
||||
<p class="instructions">This test verifies that the implementations of the WebCrypto API match with its WebIDL definition.</p>
|
||||
|
||||
<div id='log'></div>
|
||||
|
||||
<script>
|
||||
var file_input;
|
||||
setup(function() {
|
||||
var idl_array = new IdlArray();
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
request.open("GET", "WebCryptoAPI.idl");
|
||||
request.send();
|
||||
request.onload = function() {
|
||||
var idls = request.responseText;
|
||||
|
||||
idl_array.add_idls(idls);
|
||||
|
||||
idl_array.add_objects({"Crypto":["crypto"], "SubtleCrypto":["crypto.subtle"]});
|
||||
|
||||
idl_array.test();
|
||||
done();
|
||||
};
|
||||
}, {explicit_done: true});
|
||||
</script>
|
|
@ -24,7 +24,7 @@ setup(function() {
|
|||
var idl_array = new IdlArray();
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
request.open("GET", "WebCryptoAPI.idl");
|
||||
request.open("GET", "../interfaces/WebCryptoAPI.idl");
|
||||
request.send();
|
||||
request.onload = function() {
|
||||
var idls = request.responseText;
|
||||
|
|
|
@ -2,7 +2,7 @@ importScripts("/resources/testharness.js");
|
|||
importScripts("/resources/WebIDLParser.js", "/resources/idlharness.js");
|
||||
|
||||
var request = new XMLHttpRequest();
|
||||
request.open("GET", "WebCryptoAPI.idl");
|
||||
request.open("GET", "../interfaces/WebCryptoAPI.idl");
|
||||
request.send();
|
||||
request.onload = function() {
|
||||
var idl_array = new IdlArray();
|
|
@ -1,5 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<body>
|
||||
<title>Accelerometer Feature Policy Test: Disabled</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/feature-policy/resources/featurepolicy.js"></script>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<body>
|
||||
<title>Accelerometer Feature Policy Test: Enabled by attribute redirect on load</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/feature-policy/resources/featurepolicy.js"></script>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<body>
|
||||
<title>Accelerometer Feature Policy Test: Enabled by attribute</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/feature-policy/resources/featurepolicy.js"></script>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<body>
|
||||
<title>Accelerometer Feature Policy Test: Enabled</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/feature-policy/resources/featurepolicy.js"></script>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<body>
|
||||
<title>Accelerometer Feature Policy Test: Enabled on self origin</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/feature-policy/resources/featurepolicy.js"></script>
|
||||
|
|
|
@ -11,5 +11,6 @@
|
|||
|
||||
runGenericSensorTests(Accelerometer);
|
||||
runGenericSensorTests(GravitySensor);
|
||||
runGenericSensorTests(LinearAccelerationSensor);
|
||||
|
||||
</script>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/generic-sensor/generic-sensor-tests.js"></script>
|
||||
<div id="log"></div>
|
||||
<h2>Precondition</h2>
|
||||
<h2>Note:</h2>
|
||||
<ol>
|
||||
<li>
|
||||
Run test in an insecure context, e.g. http://example.com/.
|
||||
|
@ -17,5 +17,6 @@
|
|||
|
||||
runGenericSensorInsecureContext("Accelerometer");
|
||||
runGenericSensorInsecureContext("GravitySensor");
|
||||
runGenericSensorInsecureContext("LinearAccelerationSensor");
|
||||
|
||||
</script>
|
||||
|
|
|
@ -17,5 +17,6 @@
|
|||
|
||||
runGenericSensorOnerror(Accelerometer);
|
||||
runGenericSensorOnerror(GravitySensor);
|
||||
runGenericSensorOnerror(LinearAccelerationSensor);
|
||||
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<body>
|
||||
<title>AmbientLightSensor Feature Policy Test: Enabled by attribute redirect on load</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/feature-policy/resources/featurepolicy.js"></script>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<body>
|
||||
<title>AmbientLightSensor Feature Policy Test: Enabled by attribute</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/feature-policy/resources/featurepolicy.js"></script>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<body>
|
||||
<title>AmbientLightSensor Feature Policy Test: Enabled</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/feature-policy/resources/featurepolicy.js"></script>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<body>
|
||||
<title>AmbientLightSensor Feature Policy Test: Enabled on self origin</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/feature-policy/resources/featurepolicy.js"></script>
|
||||
|
|
|
@ -39,6 +39,10 @@ var emptyFormDataTest = { id: "EmptyFormData", data: CreateEmptyFormDataPayload(
|
|||
var smallFormDataTest = { id: "SmallFormData", data: CreateFormDataFromPayload(smallPayload) };
|
||||
var mediumFormDataTest = { id: "MediumFormData", data: CreateFormDataFromPayload(mediumPayload) };
|
||||
var largeFormDataTest = { id: "LargeFormData", data: CreateFormDataFromPayload(largePayload) };
|
||||
var smallSafeContentTypeEncodedTest = { id: "SmallSafeContentTypeEncoded", data: new Blob([smallPayload], { type: 'application/x-www-form-urlencoded' }) };
|
||||
var smallSafeContentTypeFormTest = { id: "SmallSafeContentTypeForm", data: new FormData() };
|
||||
var smallSafeContentTypeTextTest = { id: "SmallSafeContentTypeText", data: new Blob([smallPayload], { type: 'text/plain' }) };
|
||||
var smallCORSContentTypeTextTest = { id: "SmallCORSContentTypeText", data: new Blob([smallPayload], { type: 'text/html' }) };
|
||||
// We don't test maxFormData because the extra multipart separators make it difficult to
|
||||
// calculate a maxPayload.
|
||||
|
||||
|
@ -57,7 +61,9 @@ var allTests = [].concat(stringTests, stringMaxTest, blobTests, blobMaxTest, buf
|
|||
// This special cross section of test cases is meant to provide a slimmer but reasonably-
|
||||
// representative set of tests for parameterization across variables (e.g. redirect codes,
|
||||
// cors modes, etc.)
|
||||
var sampleTests = [noDataTest, nullDataTest, undefinedDataTest, smallStringTest, smallBlobTest, smallBufferSourceTest, smallFormDataTest];
|
||||
var sampleTests = [noDataTest, nullDataTest, undefinedDataTest, smallStringTest, smallBlobTest, smallBufferSourceTest, smallFormDataTest, smallSafeContentTypeEncodedTest, smallSafeContentTypeFormTest, smallSafeContentTypeTextTest];
|
||||
|
||||
var preflightTests = [smallCORSContentTypeTextTest];
|
||||
|
||||
// Build a test lookup table, which is useful when instructing a web worker or an iframe
|
||||
// to run a test, so that we don't have to marshal the entire test case across a process boundary.
|
||||
|
|
|
@ -38,4 +38,30 @@
|
|||
runTests(sampleTests);
|
||||
});
|
||||
|
||||
// Now test a cross-origin request that doesn't use a safelisted Content-Type and ensure
|
||||
// we are applying the proper restrictions. Since a non-safelisted Content-Type request
|
||||
// header is used there should be a preflight/options request and we should only succeed
|
||||
// send the payload if the proper CORS headers are used.
|
||||
{
|
||||
// Implement the self.buildId extension to identify the parameterized
|
||||
// test in the report.
|
||||
self.buildId = function (baseId) {
|
||||
return `${baseId}-PREFLIGHT-ALLOW`;
|
||||
};
|
||||
|
||||
// Implement the self.buildBaseUrl and self.buildTargetUrl extensions
|
||||
// to change the target URL to use a cross-origin domain name.
|
||||
self.buildBaseUrl = function (baseUrl) {
|
||||
return "http://{{domains[www]}}:{{ports[http][0]}}";
|
||||
};
|
||||
|
||||
// Implement the self.buildTargetUrl extension to append a directive
|
||||
// to the handler, that it should return CORS headers for the preflight we expect.
|
||||
self.buildTargetUrl = function (targetUrl) {
|
||||
return `${targetUrl}&origin=http://{{host}}:{{ports[http][0]}}&credentials=true&preflightExpected=true`;
|
||||
}
|
||||
|
||||
runTests(preflightTests);
|
||||
}
|
||||
|
||||
done();
|
|
@ -60,40 +60,52 @@ def main(request, response):
|
|||
# with the unique session id, in order to retrieve a range of results
|
||||
# later knowing the index range.
|
||||
test_idx = request.GET.first("tidx")
|
||||
|
||||
test_data_key = build_stash_key(session_id, test_idx)
|
||||
test_data = { "id": test_id, "error": None }
|
||||
|
||||
payload = ""
|
||||
if "Content-Type" in request.headers and \
|
||||
"form-data" in request.headers["Content-Type"]:
|
||||
if "payload" in request.POST:
|
||||
# The payload was sent as a FormData.
|
||||
payload = request.POST.first("payload")
|
||||
# Only store the actual POST requests, not any preflight/OPTIONS requests we may get.
|
||||
if request.method == "POST":
|
||||
test_data_key = build_stash_key(session_id, test_idx)
|
||||
|
||||
payload = ""
|
||||
if "Content-Type" in request.headers and \
|
||||
"form-data" in request.headers["Content-Type"]:
|
||||
if "payload" in request.POST:
|
||||
# The payload was sent as a FormData.
|
||||
payload = request.POST.first("payload")
|
||||
else:
|
||||
# A FormData was sent with an empty payload.
|
||||
pass
|
||||
else:
|
||||
# A FormData was sent with an empty payload.
|
||||
pass
|
||||
else:
|
||||
# The payload was sent as either a string, Blob, or BufferSource.
|
||||
payload = request.body
|
||||
# The payload was sent as either a string, Blob, or BufferSource.
|
||||
payload = request.body
|
||||
|
||||
payload_parts = filter(None, payload.split(":"))
|
||||
if len(payload_parts) > 0:
|
||||
payload_size = int(payload_parts[0])
|
||||
payload_parts = filter(None, payload.split(":"))
|
||||
if len(payload_parts) > 0:
|
||||
payload_size = int(payload_parts[0])
|
||||
|
||||
# Confirm the payload size sent matches with the number of characters sent.
|
||||
if payload_size != len(payload_parts[1]):
|
||||
test_data["error"] = "expected %d characters but got %d" % (payload_size, len(payload_parts[1]))
|
||||
# Confirm the payload size sent matches with the number of characters sent.
|
||||
if payload_size != len(payload_parts[1]):
|
||||
test_data["error"] = "expected %d characters but got %d" % (payload_size, len(payload_parts[1]))
|
||||
else:
|
||||
# Confirm the payload contains the correct characters.
|
||||
for i in range(0, payload_size):
|
||||
if payload_parts[1][i] != "*":
|
||||
test_data["error"] = "expected '*' at index %d but got '%s''" % (i, payload_parts[1][i])
|
||||
break
|
||||
|
||||
# Store the result in the stash so that it can be retrieved
|
||||
# later with a 'stat' command.
|
||||
request.server.stash.put(test_data_key, test_data)
|
||||
elif request.method == "OPTIONS":
|
||||
# If we expect a preflight, then add the cors headers we expect, otherwise log an error as we shouldn't
|
||||
# send a preflight for all requests.
|
||||
if "preflightExpected" in request.GET:
|
||||
response.headers.set("Access-Control-Allow-Headers", "content-type")
|
||||
response.headers.set("Access-Control-Allow-Methods", "POST")
|
||||
else:
|
||||
# Confirm the payload contains the correct characters.
|
||||
for i in range(0, payload_size):
|
||||
if payload_parts[1][i] != "*":
|
||||
test_data["error"] = "expected '*' at index %d but got '%s''" % (i, payload_parts[1][i])
|
||||
break
|
||||
|
||||
# Store the result in the stash so that it can be retrieved
|
||||
# later with a 'stat' command.
|
||||
request.server.stash.put(test_data_key, test_data)
|
||||
test_data_key = build_stash_key(session_id, test_idx)
|
||||
test_data["error"] = "Preflight not expected."
|
||||
request.server.stash.put(test_data_key, test_data)
|
||||
elif command == "stat":
|
||||
test_idx_min = int(request.GET.first("tidx_min"))
|
||||
test_idx_max = int(request.GET.first("tidx_max"))
|
||||
|
|
|
@ -10,3 +10,39 @@ The Chromium implementation is provided by
|
|||
`../resources/chromium/web-bluetooth-test.js`.
|
||||
|
||||
[Web Bluetooth Testing API]: https://docs.google.com/document/d/1Nhv_oVDCodd1pEH_jj9k8gF4rPGb_84VYaZ9IG8M_WY/
|
||||
|
||||
# Generated gen-* files from generator.py
|
||||
|
||||
`generator.py` builds `gen-*.html` tests using templates in
|
||||
`script-tests/*/*.js`.
|
||||
|
||||
The subdirectory structure in `bluetooth/script-test/*` is recreated into
|
||||
`bluetooth/*`. The generator expands each CALL function from templates
|
||||
into new leaf directories and files.
|
||||
|
||||
Example:
|
||||
|
||||
`script-tests/server/get-same-object.js` contains:
|
||||
|
||||
```
|
||||
gattServer.CALLS([
|
||||
getPrimaryService('heart_rate')|
|
||||
getPrimaryServices()|
|
||||
getPrimaryServices('heart_rate')[UUID]]),
|
||||
```
|
||||
|
||||
Generating:
|
||||
|
||||
```
|
||||
server/getPrimaryService/gen-get-same-object.html
|
||||
server/getPrimaryServices/gen-get-same-object.html
|
||||
server/getPrimaryServices/gen-get-same-object-with-uuid.html
|
||||
```
|
||||
|
||||
Usage:
|
||||
|
||||
```
|
||||
$ python generate.py
|
||||
```
|
||||
|
||||
More details documented in `generate.py`.
|
|
@ -0,0 +1,26 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'HeartRate device properties';
|
||||
|
||||
bluetooth_test(() => getHealthThermometerService()
|
||||
.then(({service}) => Promise.all([
|
||||
service.getCharacteristic('temperature_measurement'),
|
||||
service.getCharacteristic('measurement_interval')]))
|
||||
.then(([temperature_measurement, measurement_interval]) => {
|
||||
let tm_expected_properties =
|
||||
new TestCharacteristicProperties(['indicate']);
|
||||
assert_properties_equal(temperature_measurement.properties,
|
||||
tm_expected_properties);
|
||||
|
||||
let mi_expected_properties =
|
||||
new TestCharacteristicProperties(['read', 'write', 'indicate']);
|
||||
assert_properties_equal(measurement_interval.properties,
|
||||
mi_expected_properties);
|
||||
}), test_desc);
|
||||
</script>
|
|
@ -0,0 +1,25 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Characteristic gets removed. Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Characteristic no longer exists.',
|
||||
'InvalidStateError');
|
||||
let fake_peripheral, characteristic, fake_characteristic;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({fake_peripheral, characteristic, fake_characteristic} = _))
|
||||
.then(() => characteristic.getDescriptor(user_description.name))
|
||||
.then(() => null, (e) => assert_unreached('Caught error unexpectedly.', e))
|
||||
.then(() => fake_characteristic.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
characteristic.getDescriptor(user_description.name), expected)),
|
||||
test_desc);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,39 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Calls to getDescriptor should return the same object.';
|
||||
let characteristic;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({characteristic} = _))
|
||||
.then(() => Promise.all([
|
||||
characteristic.getDescriptor(user_description.alias),
|
||||
characteristic.getDescriptor(user_description.name),
|
||||
characteristic.getDescriptor(user_description.uuid)
|
||||
]))
|
||||
.then(descriptors_arrays => {
|
||||
assert_true(descriptors_arrays.length > 0)
|
||||
|
||||
// Convert to arrays if necessary.
|
||||
for (let i = 0; i < descriptors_arrays.length; i++) {
|
||||
descriptors_arrays[i] = [].concat(descriptors_arrays[i]);
|
||||
}
|
||||
|
||||
for (let i = 1; i < descriptors_arrays.length; i++) {
|
||||
assert_equals(descriptors_arrays[0].length,
|
||||
descriptors_arrays[i].length);
|
||||
}
|
||||
|
||||
let base_set = new Set(descriptors_arrays[0]);
|
||||
for (let descriptors of descriptors_arrays) {
|
||||
descriptors.forEach(descriptor => assert_true(base_set.has(descriptor)));
|
||||
}
|
||||
}), test_desc);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,25 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Characteristic gets removed. Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Characteristic no longer exists.',
|
||||
'InvalidStateError');
|
||||
let fake_peripheral, characteristic, fake_characteristic;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({fake_peripheral, characteristic, fake_characteristic} = _))
|
||||
.then(() => characteristic.getDescriptor(user_description.name))
|
||||
.then(() => null, (e) => assert_unreached('Caught error unexpectedly.', e))
|
||||
.then(() => fake_characteristic.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
characteristic.getDescriptors(user_description.name), expected)),
|
||||
test_desc);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,25 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Characteristic gets removed. Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Characteristic no longer exists.',
|
||||
'InvalidStateError');
|
||||
let fake_peripheral, characteristic, fake_characteristic;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({fake_peripheral, characteristic, fake_characteristic} = _))
|
||||
.then(() => characteristic.getDescriptor(user_description.name))
|
||||
.then(() => null, (e) => assert_unreached('Caught error unexpectedly.', e))
|
||||
.then(() => fake_characteristic.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
characteristic.getDescriptors(), expected)),
|
||||
test_desc);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,39 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Calls to getDescriptors should return the same object.';
|
||||
let characteristic;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({characteristic} = _))
|
||||
.then(() => Promise.all([
|
||||
characteristic.getDescriptors(user_description.alias),
|
||||
characteristic.getDescriptors(user_description.name),
|
||||
characteristic.getDescriptors(user_description.uuid)
|
||||
]))
|
||||
.then(descriptors_arrays => {
|
||||
assert_true(descriptors_arrays.length > 0)
|
||||
|
||||
// Convert to arrays if necessary.
|
||||
for (let i = 0; i < descriptors_arrays.length; i++) {
|
||||
descriptors_arrays[i] = [].concat(descriptors_arrays[i]);
|
||||
}
|
||||
|
||||
for (let i = 1; i < descriptors_arrays.length; i++) {
|
||||
assert_equals(descriptors_arrays[0].length,
|
||||
descriptors_arrays[i].length);
|
||||
}
|
||||
|
||||
let base_set = new Set(descriptors_arrays[0]);
|
||||
for (let descriptors of descriptors_arrays) {
|
||||
descriptors.forEach(descriptor => assert_true(base_set.has(descriptor)));
|
||||
}
|
||||
}), test_desc);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Characteristic is removed. Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Characteristic no longer exists.',
|
||||
'InvalidStateError');
|
||||
let characteristic, fake_characteristic;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({characteristic, fake_characteristic} = _))
|
||||
.then(() => fake_characteristic.remove())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
characteristic.startNotifications(),
|
||||
expected,
|
||||
'Characteristic got removed.')),
|
||||
test_desc);
|
||||
</script>
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Add multiple event listeners then readValue().';
|
||||
let characteristic, fake_characteristic;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({characteristic, fake_characteristic} = _))
|
||||
.then(() => fake_characteristic.setNextReadResponse(GATT_SUCCESS, [0,1,2]))
|
||||
.then(() => assert_promise_resolves_after_event(
|
||||
characteristic,
|
||||
'readValue',
|
||||
'characteristicvaluechanged',
|
||||
3 /* attach 3 listeners */))
|
||||
.then(results => {
|
||||
let read_value = new Uint8Array(results[0].buffer);
|
||||
let event_values = results.slice(1).map(v => new Uint8Array(v.buffer));
|
||||
for (let event_value of event_values) {
|
||||
assert_equals(event_value.buffer, read_value.buffer);
|
||||
assert_array_equals(event_value, read_value);
|
||||
}
|
||||
}), test_desc);
|
||||
</script>
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Characteristic gets removed. Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Characteristic no longer exists.',
|
||||
'InvalidStateError');
|
||||
let characteristic, fake_characteristic;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({characteristic, fake_characteristic} = _))
|
||||
.then(() => fake_characteristic.remove())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
characteristic.readValue(),
|
||||
expected,
|
||||
'Characteristic got removed.')),
|
||||
test_desc);
|
||||
</script>
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Reading a characteristic should fire an event.';
|
||||
let characteristic, fake_characteristic;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({characteristic, fake_characteristic} = _))
|
||||
.then(() => fake_characteristic.setNextReadResponse(
|
||||
GATT_SUCCESS, [0, 1, 2]))
|
||||
.then(() => assert_promise_resolves_after_event(
|
||||
characteristic,
|
||||
'readValue',
|
||||
'characteristicvaluechanged'))
|
||||
.then(results => new Promise(resolve => {
|
||||
let read_value = new Uint8Array(results[0].buffer);
|
||||
let event_value = new Uint8Array(results[1].buffer);
|
||||
assert_equals(event_value.buffer, read_value.buffer);
|
||||
assert_array_equals(event_value, read_value);
|
||||
resolve();
|
||||
})), test_desc);
|
||||
</script>
|
|
@ -0,0 +1,25 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Characteristic gets removed. Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Characteristic no longer exists.',
|
||||
'InvalidStateError');
|
||||
let fake_peripheral, characteristic, fake_characteristic;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({fake_peripheral, characteristic, fake_characteristic} = _))
|
||||
.then(() => characteristic.getDescriptor(user_description.name))
|
||||
.then(() => null, (e) => assert_unreached('Caught error unexpectedly.', e))
|
||||
.then(() => fake_characteristic.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
characteristic.readValue(), expected)),
|
||||
test_desc);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'A read request succeeds and returns the characteristic\'s ' +
|
||||
'value.';
|
||||
const EXPECTED_VALUE = [0, 1, 2];
|
||||
|
||||
let characteristic, fake_characteristic;
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({characteristic, fake_characteristic} = _))
|
||||
.then(() => fake_characteristic.setNextReadResponse(
|
||||
GATT_SUCCESS,
|
||||
EXPECTED_VALUE))
|
||||
.then(() => characteristic.readValue())
|
||||
.then(value => assert_array_equals(
|
||||
new Uint8Array(value.buffer),
|
||||
EXPECTED_VALUE)),
|
||||
test_desc);
|
||||
</script>
|
|
@ -0,0 +1,23 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Succesful read should update characteristic.value';
|
||||
const EXPECTED_VALUE = [0, 1, 2];
|
||||
let characteristic, fake_characteristic;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({characteristic, fake_characteristic} = _))
|
||||
.then(() => assert_equals(characteristic.value, null))
|
||||
.then(() => fake_characteristic.setNextReadResponse(
|
||||
GATT_SUCCESS, EXPECTED_VALUE))
|
||||
.then(() => characteristic.readValue())
|
||||
.then(() => assert_array_equals(
|
||||
new Uint8Array(characteristic.value.buffer),
|
||||
EXPECTED_VALUE)),
|
||||
test_desc);
|
||||
</script>
|
|
@ -0,0 +1,25 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Characteristic gets removed. Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Characteristic no longer exists.',
|
||||
'InvalidStateError');
|
||||
let fake_peripheral, characteristic, fake_characteristic;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({fake_peripheral, characteristic, fake_characteristic} = _))
|
||||
.then(() => characteristic.getDescriptor(user_description.name))
|
||||
.then(() => null, (e) => assert_unreached('Caught error unexpectedly.', e))
|
||||
.then(() => fake_characteristic.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
characteristic.startNotifications(), expected)),
|
||||
test_desc);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Characteristic gets removed. Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Characteristic no longer exists.',
|
||||
'InvalidStateError');
|
||||
let characteristic, fake_characteristic;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({characteristic, fake_characteristic} = _))
|
||||
.then(() => fake_characteristic.remove())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
characteristic.writeValue(new ArrayBuffer(1 /* length */)),
|
||||
expected,
|
||||
'Characteristic got removed.')),
|
||||
test_desc);
|
||||
</script>
|
|
@ -0,0 +1,25 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Characteristic gets removed. Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Characteristic no longer exists.',
|
||||
'InvalidStateError');
|
||||
let fake_peripheral, characteristic, fake_characteristic;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({fake_peripheral, characteristic, fake_characteristic} = _))
|
||||
.then(() => characteristic.getDescriptor(user_description.name))
|
||||
.then(() => null, (e) => assert_unreached('Caught error unexpectedly.', e))
|
||||
.then(() => fake_characteristic.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
characteristic.writeValue(new Uint8Array(1)), expected)),
|
||||
test_desc);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,41 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'A regular write request to a writable characteristic ' +
|
||||
'should succeed.';
|
||||
let typed_array = Uint8Array.of(1, 2);
|
||||
let array_buffer = Uint8Array.of(3, 4).buffer;
|
||||
let data_view = new DataView(new ArrayBuffer(2));
|
||||
let characteristic, fake_characteristic;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({characteristic, fake_characteristic} = _))
|
||||
.then(() => new Promise(resolve => {
|
||||
data_view.setUint8(0, 5);
|
||||
data_view.setUint8(1, 6);
|
||||
resolve();
|
||||
}))
|
||||
.then(() => fake_characteristic.getLastWrittenValue())
|
||||
.then(last_value => assert_true(last_value === null))
|
||||
|
||||
.then(() => fake_characteristic.setNextWriteResponse(GATT_SUCCESS))
|
||||
.then(() => characteristic.writeValue(typed_array))
|
||||
.then(() => fake_characteristic.getLastWrittenValue())
|
||||
.then(last_value => assert_array_equals(last_value, [1, 2]))
|
||||
|
||||
.then(() => fake_characteristic.setNextWriteResponse(GATT_SUCCESS))
|
||||
.then(() => characteristic.writeValue(array_buffer))
|
||||
.then(() => fake_characteristic.getLastWrittenValue())
|
||||
.then(last_value => assert_array_equals(last_value, [3, 4]))
|
||||
|
||||
.then(() => fake_characteristic.setNextWriteResponse(GATT_SUCCESS))
|
||||
.then(() => characteristic.writeValue(data_view))
|
||||
.then(() => fake_characteristic.getLastWrittenValue())
|
||||
.then(last_value => assert_array_equals(last_value, [5, 6])),
|
||||
test_desc);
|
||||
</script>
|
189
tests/wpt/web-platform-tests/bluetooth/generate.py
Normal file
189
tests/wpt/web-platform-tests/bluetooth/generate.py
Normal file
|
@ -0,0 +1,189 @@
|
|||
# Copyright 2016 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
#
|
||||
# TODO(509038): Delete the file in LayoutTests/bluetooth after all the script
|
||||
# tests have been migrated to this directory.
|
||||
"""Generator script for Web Bluetooth LayoutTests.
|
||||
|
||||
For each script-tests/X.js creates the following test files depending on the
|
||||
contents of X.js
|
||||
- getPrimaryService/X.html
|
||||
- getPrimaryServices/X.html
|
||||
- getPrimaryServices/X-with-uuid.html
|
||||
|
||||
script-tests/X.js files should contain "CALLS([variation1 | variation2 | ...])"
|
||||
tokens that indicate what files to generate. Each variation in CALLS([...])
|
||||
should corresponds to a js function call and its arguments. Additionally a
|
||||
variation can end in [UUID] to indicate that the generated file's name should
|
||||
have the -with-uuid suffix.
|
||||
|
||||
The PREVIOUS_CALL token will be replaced with the function that replaced CALLS.
|
||||
|
||||
The FUNCTION_NAME token will be replaced with the name of the function that
|
||||
replaced CALLS.
|
||||
|
||||
For example, for the following template file:
|
||||
|
||||
// script-tests/example.js
|
||||
promise_test(() => {
|
||||
return navigator.bluetooth.requestDevice(...)
|
||||
.then(device => device.gatt.CALLS([
|
||||
getPrimaryService('heart_rate')|
|
||||
getPrimaryServices('heart_rate')[UUID]]))
|
||||
.then(device => device.gatt.PREVIOUS_CALL);
|
||||
}, 'example test for FUNCTION_NAME');
|
||||
|
||||
this script will generate:
|
||||
|
||||
// getPrimaryService/example.html
|
||||
promise_test(() => {
|
||||
return navigator.bluetooth.requestDevice(...)
|
||||
.then(device => device.gatt.getPrimaryService('heart_rate'))
|
||||
.then(device => device.gatt.getPrimaryService('heart_rate'));
|
||||
}, 'example test for getPrimaryService');
|
||||
|
||||
// getPrimaryServices/example-with-uuid.html
|
||||
promise_test(() => {
|
||||
return navigator.bluetooth.requestDevice(...)
|
||||
.then(device => device.gatt.getPrimaryServices('heart_rate'))
|
||||
.then(device => device.gatt.getPrimaryServices('heart_rate'));
|
||||
}, 'example test for getPrimaryServices');
|
||||
|
||||
Run
|
||||
$ python //third_party/WebKit/LayoutTests/bluetooth/generate.py
|
||||
and commit the generated files.
|
||||
"""
|
||||
|
||||
import fnmatch
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import logging
|
||||
|
||||
TEMPLATES_DIR = 'script-tests'
|
||||
|
||||
|
||||
class GeneratedTest:
|
||||
|
||||
def __init__(self, data, path, template):
|
||||
self.data = data
|
||||
self.path = path
|
||||
self.template = template
|
||||
|
||||
|
||||
def GetGeneratedTests():
|
||||
"""Yields a GeneratedTest for each call in templates in script-tests."""
|
||||
bluetooth_tests_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
# Read Base Test Template.
|
||||
base_template_file_handle = open(
|
||||
os.path.join(
|
||||
bluetooth_tests_dir,
|
||||
TEMPLATES_DIR,
|
||||
'base_test_html.template'
|
||||
), 'r')
|
||||
base_template_file_data = base_template_file_handle.read().decode('utf-8')
|
||||
base_template_file_handle.close()
|
||||
|
||||
# Get Templates.
|
||||
|
||||
template_path = os.path.join(bluetooth_tests_dir, TEMPLATES_DIR)
|
||||
|
||||
available_templates = []
|
||||
for root, _, files in os.walk(template_path):
|
||||
for template in files:
|
||||
if template.endswith('.js'):
|
||||
available_templates.append(os.path.join(root, template))
|
||||
|
||||
# Generate Test Files
|
||||
for template in available_templates:
|
||||
# Read template
|
||||
template_file_handle = open(template, 'r')
|
||||
template_file_data = template_file_handle.read().decode('utf-8')
|
||||
template_file_handle.close()
|
||||
|
||||
template_name = os.path.splitext(os.path.basename(template))[0]
|
||||
|
||||
# Find function names in multiline pattern: CALLS( [ function_name,function_name2[UUID] ])
|
||||
result = re.search(
|
||||
r'CALLS\(' + # CALLS(
|
||||
r'[^\[]*' + # Any characters not [, allowing for new lines.
|
||||
r'\[' + # [
|
||||
r'(.*?)' + # group matching: function_name(), function_name2[UUID]
|
||||
r'\]\)', # adjacent closing characters: ])
|
||||
template_file_data, re.MULTILINE | re.DOTALL)
|
||||
|
||||
if result is None:
|
||||
raise Exception('Template must contain \'CALLS\' tokens')
|
||||
|
||||
new_test_file_data = base_template_file_data.replace('TEST',
|
||||
template_file_data)
|
||||
# Replace CALLS([...]) with CALLS so that we don't have to replace the
|
||||
# CALLS([...]) for every new test file.
|
||||
new_test_file_data = new_test_file_data.replace(result.group(), 'CALLS')
|
||||
|
||||
# Replace 'PREVIOUS_CALL' with 'CALLS' so that we can replace it while
|
||||
# replacing CALLS.
|
||||
new_test_file_data = new_test_file_data.replace('PREVIOUS_CALL', 'CALLS')
|
||||
|
||||
for call in result.group(1).split('|'):
|
||||
# Parse call
|
||||
call = call.strip()
|
||||
function_name, args, uuid_suffix = re.search(r'(.*?)\((.*)\)(\[UUID\])?', call).groups()
|
||||
|
||||
# Replace template tokens
|
||||
call_test_file_data = new_test_file_data
|
||||
call_test_file_data = call_test_file_data.replace('CALLS', '{}({})'.format(function_name, args))
|
||||
call_test_file_data = call_test_file_data.replace('FUNCTION_NAME', function_name)
|
||||
|
||||
# Get test file name
|
||||
group_dir = os.path.basename(os.path.abspath(os.path.join(template, os.pardir)))
|
||||
|
||||
call_test_file_name = 'gen-{}{}.https.html'.format(template_name, '-with-uuid' if uuid_suffix else '')
|
||||
call_test_file_path = os.path.join(bluetooth_tests_dir, group_dir, function_name, call_test_file_name)
|
||||
|
||||
yield GeneratedTest(call_test_file_data, call_test_file_path, template)
|
||||
|
||||
def main():
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
previous_generated_files = set()
|
||||
current_path = os.path.dirname(os.path.realpath(__file__))
|
||||
for root, _, filenames in os.walk(current_path):
|
||||
for filename in fnmatch.filter(filenames, 'gen-*.https.html'):
|
||||
previous_generated_files.add(os.path.join(root, filename))
|
||||
|
||||
generated_files = set()
|
||||
for generated_test in GetGeneratedTests():
|
||||
prev_len = len(generated_files)
|
||||
generated_files.add(generated_test.path)
|
||||
if prev_len == len(generated_files):
|
||||
logging.info('Generated the same test twice for template:\n%s',
|
||||
generated_test.template)
|
||||
|
||||
# Create or open test file
|
||||
directory = os.path.dirname(generated_test.path)
|
||||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
test_file_handle = open(generated_test.path, 'wb')
|
||||
|
||||
# Write contents
|
||||
test_file_handle.write(generated_test.data.encode('utf-8'))
|
||||
test_file_handle.close()
|
||||
|
||||
new_generated_files = generated_files - previous_generated_files
|
||||
if len(new_generated_files) != 0:
|
||||
logging.info('Newly generated tests:')
|
||||
for generated_file in new_generated_files:
|
||||
logging.info(generated_file)
|
||||
|
||||
obsolete_files = previous_generated_files - generated_files
|
||||
if len(obsolete_files) != 0:
|
||||
logging.warning('The following files might be obsolete:')
|
||||
for generated_file in obsolete_files:
|
||||
logging.warning(generated_file)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
56
tests/wpt/web-platform-tests/bluetooth/generate_test.py
Executable file
56
tests/wpt/web-platform-tests/bluetooth/generate_test.py
Executable file
|
@ -0,0 +1,56 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
# Copyright 2016 The Chromium Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
#
|
||||
# TODO(50903): Delete the file in LayoutTests/bluetooth after all the tests have
|
||||
# been migrated to this directory.
|
||||
"""Test that the set of gen-* files is the same as the generated files."""
|
||||
|
||||
import fnmatch
|
||||
import os
|
||||
import sys
|
||||
import generate
|
||||
import logging
|
||||
|
||||
UPDATE_TIP = 'To update the generated tests, run:\n' \
|
||||
'$ python third_party/WebKit/LayoutTests/bluetooth/generate.py'
|
||||
|
||||
|
||||
def main():
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logging.info(UPDATE_TIP)
|
||||
generated_files = set()
|
||||
# Tests data in gen-* files is the same as the data generated.
|
||||
for generated_test in generate.GetGeneratedTests():
|
||||
generated_files.add(generated_test.path)
|
||||
try:
|
||||
with open(generated_test.path, 'r') as f:
|
||||
data = f.read().decode('utf-8')
|
||||
if data != generated_test.data:
|
||||
logging.error('%s does not match template', generated_test.path)
|
||||
return -1
|
||||
except IOError, e:
|
||||
if e.errno == 2:
|
||||
logging.error('Missing generated test:\n%s\nFor template:\n%s',
|
||||
generated_test.path,
|
||||
generated_test.template)
|
||||
return -1
|
||||
|
||||
# Tests that there are no obsolete generated files.
|
||||
previous_generated_files = set()
|
||||
current_path = os.path.dirname(os.path.realpath(__file__))
|
||||
for root, _, filenames in os.walk(current_path):
|
||||
for filename in fnmatch.filter(filenames, 'gen-*.https.html'):
|
||||
previous_generated_files.add(os.path.join(root, filename))
|
||||
|
||||
if previous_generated_files != generated_files:
|
||||
logging.error('There are extra generated tests. Please remove them.')
|
||||
for test_path in previous_generated_files - generated_files:
|
||||
logging.error('%s', test_path)
|
||||
return -1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
|
@ -4,6 +4,7 @@
|
|||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Bluetooth IDL test';
|
||||
|
||||
test(() => {
|
||||
assert_throws(new TypeError(), () => new Bluetooth(),
|
||||
|
@ -14,6 +15,5 @@ test(() => {
|
|||
// Bluetooth implements BluetoothDiscovery;
|
||||
assert_true('requestDevice' in navigator.bluetooth);
|
||||
assert_equals(navigator.bluetooth.requestDevice.length, 0);
|
||||
}, 'Bluetooth IDL test');
|
||||
|
||||
}, test_desc);
|
||||
</script>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = '[SameObject] test for navigator.bluetooth';
|
||||
|
||||
test(() => {
|
||||
assert_true('bluetooth' in navigator,
|
||||
|
@ -11,5 +12,5 @@ test(() => {
|
|||
|
||||
test(() => {
|
||||
assert_equals(navigator.bluetooth, navigator.bluetooth);
|
||||
}, '[SameObject] test for navigator.bluetooth');
|
||||
}, test_desc);
|
||||
</script>
|
||||
|
|
|
@ -6,12 +6,11 @@
|
|||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
bluetooth_test(() => {
|
||||
return setUpPreconnectedDevice({name: ''})
|
||||
const test_desc = 'Device with empty name and no UUIDs nearby. Should be ' +
|
||||
'found if acceptAllDevices is true.';
|
||||
|
||||
bluetooth_test(() => setUpPreconnectedDevice({name: ''})
|
||||
.then(() => requestDeviceWithTrustedClick({acceptAllDevices: true}))
|
||||
.then(device => {
|
||||
assert_equals(device.name, '');
|
||||
});
|
||||
}, 'Device with empty name and no UUIDs nearby. Should be found if ' +
|
||||
'acceptAllDevices is true.');
|
||||
.then(device => assert_equals(device.name, '')),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -5,13 +5,12 @@
|
|||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
bluetooth_test(() => {
|
||||
let device_name = 'LE Device';
|
||||
return setUpPreconnectedDevice({name: device_name})
|
||||
const test_desc = 'A device with name and no UUIDs nearby. Should be found if ' +
|
||||
'acceptAllDevices is true.';
|
||||
const name = 'LE Device';
|
||||
|
||||
bluetooth_test(() => setUpPreconnectedDevice({name: name})
|
||||
.then(() => requestDeviceWithTrustedClick({acceptAllDevices: true}))
|
||||
.then(device => {
|
||||
assert_equals(device.name, device_name);
|
||||
});
|
||||
}, 'A device with name and no UUIDs nearby. Should be found if ' +
|
||||
'acceptAllDevices is true.');
|
||||
.then(device => assert_equals(device.name, name)),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -6,15 +6,17 @@
|
|||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
bluetooth_test(() => {
|
||||
return getHealthThermometerDevice({acceptAllDevices: true})
|
||||
const test_desc = 'requestDevice called with acceptAllDevices: true and ' +
|
||||
'with no optionalServices. Should not get access to any services.';
|
||||
const expected = new DOMException(
|
||||
'Origin is not allowed to access any service. ' +
|
||||
'Tip: Add the service UUID to \'optionalServices\' in ' +
|
||||
'requestDevice() options. https://goo.gl/HxfxSQ',
|
||||
'SecurityError');
|
||||
|
||||
bluetooth_test(() => getHealthThermometerDevice({acceptAllDevices: true})
|
||||
.then(({device}) => assert_promise_rejects_with_message(
|
||||
device.gatt.getPrimaryServices(),
|
||||
new DOMException(
|
||||
'Origin is not allowed to access any service. ' +
|
||||
'Tip: Add the service UUID to \'optionalServices\' in ' +
|
||||
'requestDevice() options. https://goo.gl/HxfxSQ',
|
||||
'SecurityError')));
|
||||
}, 'requestDevice called with acceptAllDevices: true and with no ' +
|
||||
'optionalServices. Should not get access to any services.');
|
||||
expected)),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -9,19 +9,18 @@
|
|||
const test_desc = 'requestDevice called with acceptAllDevices: true and with ' +
|
||||
'optionalServices. Should get access to services.';
|
||||
|
||||
bluetooth_test(() =>
|
||||
getTwoHealthThermometerServicesDevice()
|
||||
.then(() => requestDeviceWithTrustedClick({
|
||||
acceptAllDevices: true,
|
||||
optionalServices: ['health_thermometer']
|
||||
}))
|
||||
.then(device => device.gatt.connect())
|
||||
.then(gattServer => gattServer.getPrimaryServices())
|
||||
.then(services => {
|
||||
assert_equals(services.length, 2);
|
||||
services.forEach(service => {
|
||||
assert_equals(service.uuid,
|
||||
BluetoothUUID.getService('health_thermometer'));
|
||||
});
|
||||
}), test_desc);
|
||||
bluetooth_test(() => getTwoHealthThermometerServicesDevice()
|
||||
.then(() => requestDeviceWithTrustedClick({
|
||||
acceptAllDevices: true,
|
||||
optionalServices: ['health_thermometer']
|
||||
}))
|
||||
.then(device => device.gatt.connect())
|
||||
.then(gattServer => gattServer.getPrimaryServices())
|
||||
.then(services => {
|
||||
assert_equals(services.length, 2);
|
||||
services.forEach(service => {
|
||||
assert_equals(service.uuid,
|
||||
BluetoothUUID.getService('health_thermometer'));
|
||||
});
|
||||
}), test_desc);
|
||||
</script>
|
||||
|
|
|
@ -4,27 +4,27 @@ let device;
|
|||
|
||||
function requestDeviceWithOptionsAndConnect(options) {
|
||||
return navigator.bluetooth.requestDevice(options)
|
||||
.then(device => device.gatt.connect());
|
||||
.then(device => device.gatt.connect());
|
||||
}
|
||||
|
||||
window.onmessage = messageEvent => {
|
||||
switch (messageEvent.data.type) {
|
||||
case 'RequestAndConnect':
|
||||
requestDeviceWithOptionsAndConnect(messageEvent.data.options)
|
||||
.then(gatt => {
|
||||
device = gatt.device;
|
||||
parent.postMessage('Connected', '*');
|
||||
}).catch(err => {
|
||||
parent.postMessage(`FAIL: ${err}`, '*');
|
||||
});
|
||||
.then(gatt => {
|
||||
device = gatt.device;
|
||||
parent.postMessage('Connected', '*');
|
||||
}).catch(err => {
|
||||
parent.postMessage(`FAIL: ${err}`, '*');
|
||||
});
|
||||
break;
|
||||
case 'DiscoverServices':
|
||||
requestDeviceWithOptionsAndConnect(messageEvent.data.options)
|
||||
.then(gatt => gatt.getPrimaryServices())
|
||||
.then(() => parent.postMessage('DiscoveryComplete', '*'))
|
||||
.catch(err => {
|
||||
parent.postMessage(`FAIL: ${err}`, '*');
|
||||
});
|
||||
.then(gatt => gatt.getPrimaryServices())
|
||||
.then(() => parent.postMessage('DiscoveryComplete', '*'))
|
||||
.catch(err => {
|
||||
parent.postMessage(`FAIL: ${err}`, '*');
|
||||
});
|
||||
break;
|
||||
default:
|
||||
parent.postMessage(`FAIL: Bad message type: ${messageEvent.data.type}`,
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
TEST
|
||||
</script>
|
|
@ -0,0 +1,22 @@
|
|||
'use strict';
|
||||
const test_desc = 'Characteristic gets removed. Reject with InvalidStateError.';
|
||||
const expected = new DOMException('GATT Characteristic no longer exists.',
|
||||
'InvalidStateError');
|
||||
let fake_peripheral, characteristic, fake_characteristic;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({fake_peripheral, characteristic, fake_characteristic} = _))
|
||||
.then(() => characteristic.getDescriptor(user_description.name))
|
||||
.then(() => null, (e) => assert_unreached('Caught error unexpectedly.', e))
|
||||
.then(() => fake_characteristic.remove())
|
||||
.then(() => fake_peripheral.simulateGATTServicesChanged())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
characteristic.CALLS([
|
||||
getDescriptor(user_description.name)|
|
||||
getDescriptors(user_description.name)[UUID]|
|
||||
getDescriptors()|
|
||||
readValue()|
|
||||
writeValue(new Uint8Array(1))|
|
||||
startNotifications()
|
||||
]), expected)),
|
||||
test_desc);
|
|
@ -0,0 +1,32 @@
|
|||
'use strict';
|
||||
const test_desc = 'Calls to FUNCTION_NAME should return the same object.';
|
||||
let characteristic;
|
||||
|
||||
bluetooth_test(() => getMeasurementIntervalCharacteristic()
|
||||
.then(_ => ({characteristic} = _))
|
||||
.then(() => Promise.all([
|
||||
characteristic.CALLS([
|
||||
getDescriptor(user_description.alias)|
|
||||
getDescriptors(user_description.alias)
|
||||
]),
|
||||
characteristic.FUNCTION_NAME(user_description.name),
|
||||
characteristic.FUNCTION_NAME(user_description.uuid)
|
||||
]))
|
||||
.then(descriptors_arrays => {
|
||||
assert_true(descriptors_arrays.length > 0)
|
||||
|
||||
// Convert to arrays if necessary.
|
||||
for (let i = 0; i < descriptors_arrays.length; i++) {
|
||||
descriptors_arrays[i] = [].concat(descriptors_arrays[i]);
|
||||
}
|
||||
|
||||
for (let i = 1; i < descriptors_arrays.length; i++) {
|
||||
assert_equals(descriptors_arrays[0].length,
|
||||
descriptors_arrays[i].length);
|
||||
}
|
||||
|
||||
let base_set = new Set(descriptors_arrays[0]);
|
||||
for (let descriptors of descriptors_arrays) {
|
||||
descriptors.forEach(descriptor => assert_true(base_set.has(descriptor)));
|
||||
}
|
||||
}), test_desc);
|
|
@ -0,0 +1,22 @@
|
|||
'use strict';
|
||||
const test_desc = 'disconnect() called before FUNCTION_NAME. ' +
|
||||
'Reject with NetworkError.';
|
||||
const expected = new DOMException(
|
||||
'GATT Server is disconnected. Cannot retrieve services. (Re)connect ' +
|
||||
'first with `device.gatt.connect`.',
|
||||
'NetworkError');
|
||||
let device;
|
||||
|
||||
bluetooth_test(() => getHealthThermometerDevice({
|
||||
filters: [{services: ['health_thermometer']}],
|
||||
optionalServices: ['generic_access']
|
||||
})
|
||||
.then(_ => ({device} = _))
|
||||
.then(() => device.gatt.disconnect())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
device.gatt.CALLS([
|
||||
getPrimaryService('health_thermometer')|
|
||||
getPrimaryServices()|
|
||||
getPrimaryServices('health_thermometer')[UUID]]),
|
||||
expected)),
|
||||
test_desc);
|
|
@ -0,0 +1,22 @@
|
|||
'use strict';
|
||||
const test_desc = 'disconnect() called during a FUNCTION_NAME ' +
|
||||
'call that fails. Reject with NetworkError.';
|
||||
const expected = new DOMException(
|
||||
'GATT Server is disconnected. Cannot retrieve services. (Re)connect ' +
|
||||
'first with `device.gatt.connect`.', 'NetworkError');
|
||||
let device;
|
||||
|
||||
bluetooth_test(() => getEmptyHealthThermometerDevice()
|
||||
.then(_ => ({device} = _))
|
||||
.then(() => {
|
||||
let promise = assert_promise_rejects_with_message(
|
||||
device.gatt.CALLS([
|
||||
getPrimaryService('health_thermometer')|
|
||||
getPrimaryServices()|
|
||||
getPrimaryServices('health_thermometer')[UUID]
|
||||
]),
|
||||
expected)
|
||||
device.gatt.disconnect();
|
||||
return promise;
|
||||
}),
|
||||
test_desc);
|
|
@ -0,0 +1,23 @@
|
|||
'use strict';
|
||||
const test_desc = 'disconnect() called during a FUNCTION_NAME call that ' +
|
||||
'succeeds. Reject with NetworkError.';
|
||||
const expected = new DOMException(
|
||||
'GATT Server is disconnected. Cannot retrieve services. (Re)connect ' +
|
||||
'first with `device.gatt.connect`.',
|
||||
'NetworkError');
|
||||
|
||||
bluetooth_test(() => getHealthThermometerDevice({
|
||||
filters: [{services: ['health_thermometer']}],
|
||||
optionalServices: ['generic_access']
|
||||
})
|
||||
.then(({device}) => {
|
||||
let promise = assert_promise_rejects_with_message(
|
||||
device.gatt.CALLS([
|
||||
getPrimaryService('health_thermometer')|
|
||||
getPrimaryServices()|
|
||||
getPrimaryServices('health_thermometer')[UUID]
|
||||
]),
|
||||
expected);
|
||||
device.gatt.disconnect();
|
||||
return promise;
|
||||
}), test_desc);
|
|
@ -0,0 +1,39 @@
|
|||
'use strict';
|
||||
const test_desc = 'Calls on services after we disconnect and connect again. '+
|
||||
'Should reject with InvalidStateError.';
|
||||
let device, services;
|
||||
|
||||
bluetooth_test(() => getHealthThermometerDevice({
|
||||
filters: [{services: ['health_thermometer']}]
|
||||
})
|
||||
.then(_ => ({device} = _))
|
||||
.then(() => device.gatt.CALLS([
|
||||
getPrimaryService('health_thermometer')|
|
||||
getPrimaryServices()|
|
||||
getPrimaryServices('health_thermometer')[UUID]]))
|
||||
// Convert to array if necessary.
|
||||
.then(s => services = [].concat(s))
|
||||
.then(() => device.gatt.disconnect())
|
||||
.then(() => device.gatt.connect())
|
||||
.then(() => {
|
||||
let promises = Promise.resolve();
|
||||
for (let service of services) {
|
||||
let error = new DOMException(
|
||||
`Service with UUID ${service.uuid} is no longer valid. Remember ` +
|
||||
`to retrieve the service again after reconnecting.`,
|
||||
'InvalidStateError');
|
||||
promises = promises.then(() =>
|
||||
assert_promise_rejects_with_message(
|
||||
service.getCharacteristic('measurement_interval'),
|
||||
error));
|
||||
promises = promises.then(() =>
|
||||
assert_promise_rejects_with_message(
|
||||
service.getCharacteristics(),
|
||||
error));
|
||||
promises = promises.then(() =>
|
||||
assert_promise_rejects_with_message(
|
||||
service.getCharacteristics('measurement_interval'),
|
||||
error));
|
||||
}
|
||||
return promises;
|
||||
}), test_desc);
|
|
@ -0,0 +1,20 @@
|
|||
'use strict';
|
||||
const test_desc = 'FUNCTION_NAME called before connecting. Reject with ' +
|
||||
'NetworkError.';
|
||||
const expected = new DOMException(
|
||||
'GATT Server is disconnected. Cannot retrieve services. (Re)connect ' +
|
||||
'first with `device.gatt.connect`.',
|
||||
'NetworkError');
|
||||
|
||||
bluetooth_test(() => getDiscoveredHealthThermometerDevice({
|
||||
filters: [{services: ['health_thermometer']}],
|
||||
optionalServices: ['generic_access']
|
||||
})
|
||||
.then(({device}) => assert_promise_rejects_with_message(
|
||||
device.gatt.CALLS([
|
||||
getPrimaryService('health_thermometer')|
|
||||
getPrimaryServices()|
|
||||
getPrimaryServices('health_thermometer')[UUID]
|
||||
]),
|
||||
expected)),
|
||||
test_desc);
|
|
@ -0,0 +1,25 @@
|
|||
'use strict';
|
||||
const test_desc = 'Request for absent service without permission. Should ' +
|
||||
'Reject with SecurityError even if services have been discovered already.';
|
||||
const expected = new DOMException(
|
||||
'Origin is not allowed to access the service. Tip: Add the service ' +
|
||||
'UUID to \'optionalServices\' in requestDevice() options. ' +
|
||||
'https://goo.gl/HxfxSQ',
|
||||
'SecurityError');
|
||||
let device;
|
||||
|
||||
bluetooth_test(() => getHealthThermometerDeviceWithServicesDiscovered({
|
||||
filters: [{services: ['health_thermometer']}]
|
||||
})
|
||||
.then(_ => ({device} = _))
|
||||
.then(() => Promise.all([
|
||||
assert_promise_rejects_with_message(
|
||||
device.gatt.CALLS([
|
||||
getPrimaryService(glucose.alias)|
|
||||
getPrimaryServices(glucose.alias)[UUID]
|
||||
]), expected),
|
||||
assert_promise_rejects_with_message(
|
||||
device.gatt.FUNCTION_NAME(glucose.name), expected),
|
||||
assert_promise_rejects_with_message(
|
||||
device.gatt.FUNCTION_NAME(glucose.uuid), expected)])),
|
||||
test_desc);
|
|
@ -0,0 +1,16 @@
|
|||
'use strict';
|
||||
const test_desc = 'Request for absent service. Must reject with ' +
|
||||
'NotFoundError even when the services have previously been discovered.';
|
||||
|
||||
bluetooth_test(() => getHealthThermometerDeviceWithServicesDiscovered({
|
||||
filters: [{services: ['health_thermometer']}],
|
||||
optionalServices: ['glucose']})
|
||||
.then(({device}) => assert_promise_rejects_with_message(
|
||||
device.gatt.CALLS([
|
||||
getPrimaryService('glucose')|
|
||||
getPrimaryServices('glucose')[UUID]
|
||||
]),
|
||||
new DOMException(
|
||||
`No Services matching UUID ${glucose.uuid} found in Device.`,
|
||||
'NotFoundError'))),
|
||||
test_desc);
|
|
@ -0,0 +1,25 @@
|
|||
'use strict';
|
||||
const test_desc = 'Garbage Collection ran during a FUNCTION_NAME ' +
|
||||
'call that failed. Should not crash.'
|
||||
const expected = new DOMException(
|
||||
'GATT Server is disconnected. Cannot retrieve services. (Re)connect first ' +
|
||||
'with `device.gatt.connect`.',
|
||||
'NetworkError');
|
||||
let promise;
|
||||
|
||||
bluetooth_test(() => getEmptyHealthThermometerDevice()
|
||||
.then(({device}) => {
|
||||
promise = assert_promise_rejects_with_message(
|
||||
device.gatt.CALLS([
|
||||
getPrimaryService('health_thermometer')|
|
||||
getPrimaryServices()|
|
||||
getPrimaryServices('health_thermometer')[UUID]
|
||||
]),
|
||||
expected);
|
||||
// Disconnect called to clear attributeInstanceMap and allow the
|
||||
// object to get garbage collected.
|
||||
device.gatt.disconnect();
|
||||
return runGarbageCollection();
|
||||
})
|
||||
.then(() => promise),
|
||||
test_desc);
|
|
@ -0,0 +1,24 @@
|
|||
'use strict';
|
||||
const test_desc = 'Garbage Collection ran during a FUNCTION_NAME call that ' +
|
||||
'succeeds. Should not crash.';
|
||||
const expected = new DOMException(
|
||||
'GATT Server is disconnected. Cannot retrieve services. ' +
|
||||
'(Re)connect first with `device.gatt.connect`.',
|
||||
'NetworkError');
|
||||
let promise;
|
||||
|
||||
bluetooth_test(() => getHealthThermometerDevice({
|
||||
filters: [{services: ['health_thermometer']}]
|
||||
})
|
||||
.then(({device}) => {
|
||||
promise = assert_promise_rejects_with_message(
|
||||
device.gatt.CALLS([
|
||||
getPrimaryService('health_thermometer') |
|
||||
getPrimaryServices() |
|
||||
getPrimaryServices('health_thermometer')[UUID]]),
|
||||
expected);
|
||||
device.gatt.disconnect();
|
||||
return runGarbageCollection();
|
||||
})
|
||||
.then(() => promise),
|
||||
test_desc);
|
|
@ -0,0 +1,35 @@
|
|||
'use strict';
|
||||
const test_desc = 'Calls to FUNCTION_NAME after a disconnection should return ' +
|
||||
'a different object.';
|
||||
let device, services_first_connection, services_second_connection;
|
||||
|
||||
bluetooth_test(() => getHealthThermometerDevice({
|
||||
filters: [{services: ['health_thermometer']}],
|
||||
optionalServices: ['generic_access']
|
||||
})
|
||||
.then(_ => ({device} = _))
|
||||
.then(() => device.gatt.CALLS([
|
||||
getPrimaryService('health_thermometer')|
|
||||
getPrimaryServices()|
|
||||
getPrimaryServices('health_thermometer')[UUID]]))
|
||||
.then(services => services_first_connection = services)
|
||||
.then(() => device.gatt.disconnect())
|
||||
.then(() => device.gatt.connect())
|
||||
.then(() => device.gatt.PREVIOUS_CALL)
|
||||
.then(services => services_second_connection = services)
|
||||
.then(() => {
|
||||
// Convert to arrays if necessary.
|
||||
services_first_connection = [].concat(services_first_connection);
|
||||
services_second_connection = [].concat(services_second_connection);
|
||||
|
||||
assert_equals(services_first_connection.length,
|
||||
services_second_connection.length);
|
||||
|
||||
let first_connection_set = new Set(services_first_connection);
|
||||
let second_connection_set = new Set(services_second_connection);
|
||||
|
||||
// The two sets should be disjoint.
|
||||
let common_services = services_first_connection.filter(
|
||||
val => second_connection_set.has(val));
|
||||
assert_equals(common_services.length, 0);
|
||||
}), test_desc);
|
|
@ -0,0 +1,33 @@
|
|||
'use strict';
|
||||
const test_desc = 'Calls to FUNCTION_NAME should return the same object.';
|
||||
let device;
|
||||
|
||||
bluetooth_test(() => getHealthThermometerDevice({
|
||||
filters: [{services: ['health_thermometer']}],
|
||||
optionalServices: ['generic_access']})
|
||||
.then(({device}) => Promise.all([
|
||||
device.gatt.CALLS([
|
||||
getPrimaryService('health_thermometer')|
|
||||
getPrimaryServices()|
|
||||
getPrimaryServices('health_thermometer')[UUID]]),
|
||||
device.gatt.PREVIOUS_CALL]))
|
||||
.then(([services_first_call, services_second_call]) => {
|
||||
// Convert to arrays if necessary.
|
||||
services_first_call = [].concat(services_first_call);
|
||||
services_second_call = [].concat(services_second_call);
|
||||
|
||||
assert_equals(services_first_call.length, services_second_call.length);
|
||||
|
||||
let first_call_set = new Set(services_first_call);
|
||||
assert_equals(services_first_call.length, first_call_set.size);
|
||||
let second_call_set = new Set(services_second_call);
|
||||
assert_equals(services_second_call.length, second_call_set.size);
|
||||
|
||||
services_first_call.forEach(service => {
|
||||
assert_true(second_call_set.has(service))
|
||||
});
|
||||
|
||||
services_second_call.forEach(service => {
|
||||
assert_true(first_call_set.has(service));
|
||||
});
|
||||
}), test_desc);
|
|
@ -0,0 +1,22 @@
|
|||
'use strict';
|
||||
const test_desc = 'Wrong Service name. Reject with TypeError.';
|
||||
const expected = new DOMException(
|
||||
"Failed to execute 'FUNCTION_NAME' on " +
|
||||
"'BluetoothRemoteGATTServer': Invalid Service name: " +
|
||||
"'wrong_name'. It must be a valid UUID alias (e.g. 0x1234), " +
|
||||
"UUID (lowercase hex characters e.g. " +
|
||||
"'00001234-0000-1000-8000-00805f9b34fb'), " +
|
||||
"or recognized standard name from " +
|
||||
"https://www.bluetooth.com/specifications/gatt/services" +
|
||||
" e.g. 'alert_notification'.",
|
||||
'TypeError');
|
||||
|
||||
bluetooth_test(() => getHealthThermometerDevice()
|
||||
.then(({device}) => assert_promise_rejects_with_message(
|
||||
device.gatt.CALLS([
|
||||
getPrimaryService('wrong_name')|
|
||||
getPrimaryServices('wrong_name')
|
||||
]),
|
||||
expected,
|
||||
'Wrong Service name passed.')),
|
||||
test_desc);
|
|
@ -0,0 +1,23 @@
|
|||
'use strict';
|
||||
const test_desc = 'Request for absent service without permission. ' +
|
||||
'Reject with SecurityError.';
|
||||
const expected = new DOMException(
|
||||
'Origin is not allowed to access the service. Tip: Add the service UUID ' +
|
||||
'to \'optionalServices\' in requestDevice() options. ' +
|
||||
'https://goo.gl/HxfxSQ',
|
||||
'SecurityError');
|
||||
|
||||
bluetooth_test(() => getHealthThermometerDevice({
|
||||
filters: [{services: ['health_thermometer']}]
|
||||
})
|
||||
.then(({device}) => Promise.all([
|
||||
assert_promise_rejects_with_message(
|
||||
device.gatt.CALLS([
|
||||
getPrimaryService(glucose.alias)|
|
||||
getPrimaryServices(glucose.alias)[UUID]
|
||||
]), expected),
|
||||
assert_promise_rejects_with_message(
|
||||
device.gatt.FUNCTION_NAME(glucose.name), expected),
|
||||
assert_promise_rejects_with_message(
|
||||
device.gatt.FUNCTION_NAME(glucose.uuid), expected)])),
|
||||
test_desc);
|
|
@ -0,0 +1,17 @@
|
|||
'use strict';
|
||||
const test_desc = 'Request for present service without permission to access ' +
|
||||
'any service. Reject with SecurityError.';
|
||||
const expected = new DOMException(
|
||||
'Origin is not allowed to access any service. Tip: Add the service ' +
|
||||
'UUID to \'optionalServices\' in requestDevice() options. ' +
|
||||
'https://goo.gl/HxfxSQ',
|
||||
'SecurityError');
|
||||
|
||||
bluetooth_test(() => getHealthThermometerDevice({acceptAllDevices: true})
|
||||
.then(({device}) => assert_promise_rejects_with_message(
|
||||
device.gatt.CALLS([
|
||||
getPrimaryService('heart_rate')|
|
||||
getPrimaryServices()|
|
||||
getPrimaryServices('heart_rate')[UUID]]),
|
||||
expected)),
|
||||
test_desc);
|
|
@ -0,0 +1,22 @@
|
|||
'use strict';
|
||||
const test_desc = 'Request for present service without permission. ' +
|
||||
'Reject with SecurityError.';
|
||||
const expected = new DOMException(
|
||||
'Origin is not allowed to access the service. Tip: Add the service UUID ' +
|
||||
'to \'optionalServices\' in requestDevice() options. https://goo.gl/HxfxSQ',
|
||||
'SecurityError');
|
||||
|
||||
bluetooth_test(() => getHealthThermometerDevice({
|
||||
filters: [{services: ['health_thermometer']}]
|
||||
})
|
||||
.then(({device}) => Promise.all([
|
||||
assert_promise_rejects_with_message(
|
||||
device.gatt.CALLS([
|
||||
getPrimaryService(generic_access.alias)|
|
||||
getPrimaryServices(generic_access.alias)[UUID]
|
||||
]), expected),
|
||||
assert_promise_rejects_with_message(
|
||||
device.gatt.FUNCTION_NAME(generic_access.name), expected),
|
||||
assert_promise_rejects_with_message(
|
||||
device.gatt.FUNCTION_NAME(generic_access.uuid), expected)])),
|
||||
test_desc);
|
|
@ -0,0 +1,16 @@
|
|||
'use strict';
|
||||
const test_desc = 'Request for absent service. Reject with NotFoundError.';
|
||||
|
||||
bluetooth_test(() => getHealthThermometerDevice({
|
||||
filters: [{services: ['health_thermometer']}],
|
||||
optionalServices: ['glucose']
|
||||
})
|
||||
.then(({device}) => assert_promise_rejects_with_message(
|
||||
device.gatt.CALLS([
|
||||
getPrimaryService('glucose')|
|
||||
getPrimaryServices('glucose')[UUID]
|
||||
]),
|
||||
new DOMException(
|
||||
`No Services matching UUID ${glucose.uuid} found in Device.`,
|
||||
'NotFoundError'))),
|
||||
test_desc);
|
|
@ -6,12 +6,14 @@
|
|||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
bluetooth_test(() => {
|
||||
return getDiscoveredHealthThermometerDevice()
|
||||
.then(({device, fake_peripheral}) => {
|
||||
return fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS})
|
||||
.then(() => device.gatt.connect())
|
||||
.then(gatt => assert_true(gatt.connected));
|
||||
});
|
||||
}, 'Device will connect');
|
||||
const test_desc = 'Device will connect';
|
||||
let device, fake_peripheral;
|
||||
|
||||
bluetooth_test(() => getDiscoveredHealthThermometerDevice()
|
||||
.then(_ => ({device, fake_peripheral} = _))
|
||||
.then(() =>
|
||||
fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS}))
|
||||
.then(() => device.gatt.connect())
|
||||
.then(gatt => assert_true(gatt.connected)),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -6,17 +6,17 @@
|
|||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
bluetooth_test(() => {
|
||||
return getDiscoveredHealthThermometerDevice()
|
||||
.then(({device, fake_peripheral}) => {
|
||||
return fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS})
|
||||
.then(() => {
|
||||
// Don't return the promise and let |device| go out of scope
|
||||
// so that it gets garbage collected.
|
||||
device.gatt.connect();
|
||||
});
|
||||
})
|
||||
.then(runGarbageCollection)
|
||||
}, 'Garbage Collection ran during a connect call that succeeds. ' +
|
||||
'Should not crash.');
|
||||
const test_desc = 'Garbage Collection ran during a connect call that ' +
|
||||
'succeeds. Should not crash.';
|
||||
let device, fake_peripheral;
|
||||
|
||||
bluetooth_test(() => getDiscoveredHealthThermometerDevice()
|
||||
.then(_ => ({device, fake_peripheral} = _))
|
||||
.then(() =>
|
||||
fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS}))
|
||||
// Don't return the promise and let |device| go out of scope
|
||||
// so that it gets garbage collected.
|
||||
.then(() => device.gatt.connect())
|
||||
.then(runGarbageCollection),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -6,20 +6,20 @@
|
|||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
bluetooth_test(() => {
|
||||
return getDiscoveredHealthThermometerDevice()
|
||||
.then(({device, fake_peripheral}) => {
|
||||
return fake_peripheral
|
||||
.setNextGATTConnectionResponse({code: HCI_SUCCESS})
|
||||
.then(() => device.gatt.connect())
|
||||
.then(gatt1 => {
|
||||
// No second response is necessary because an ATT Bearer
|
||||
// already exists from the first connection.
|
||||
// See https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect
|
||||
// step 5.1.
|
||||
return device.gatt.connect().then(gatt2 => [gatt1, gatt2]);
|
||||
});
|
||||
})
|
||||
.then(([gatt1, gatt2]) => assert_equals(gatt1, gatt2));
|
||||
}, 'Multiple connects should return the same gatt object.');
|
||||
const test_desc = 'Multiple connects should return the same gatt object.';
|
||||
let device, fake_peripheral;
|
||||
|
||||
bluetooth_test(() => getDiscoveredHealthThermometerDevice()
|
||||
.then(_ => ({device, fake_peripheral} = _))
|
||||
.then(() =>
|
||||
fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS}))
|
||||
.then(() => device.gatt.connect())
|
||||
// No second response is necessary because an ATT Bearer
|
||||
// already exists from the first connection.
|
||||
// See https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect
|
||||
// step 5.1.
|
||||
.then(gatt1 => device.gatt.connect()
|
||||
.then(gatt2 => [gatt1, gatt2]))
|
||||
.then(([gatt1, gatt2]) => assert_equals(gatt1, gatt2)),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
bluetooth_test(() => {
|
||||
return getDiscoveredHealthThermometerDevice()
|
||||
.then(({device, fake_peripheral}) => {
|
||||
return fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS})
|
||||
.then(() => device.gatt.connect());
|
||||
})
|
||||
.then(gatt => {
|
||||
assert_equals(gatt.device, gatt.device);
|
||||
});
|
||||
}, "[SameObject] test for BluetoothRemoteGATTServer's device.");
|
||||
const test_desc = '[SameObject] test for BluetoothRemoteGATTServer\'s device.';
|
||||
let device, fake_peripheral;
|
||||
|
||||
bluetooth_test(() => getDiscoveredHealthThermometerDevice()
|
||||
.then(_ => ({device, fake_peripheral} = _))
|
||||
.then(() =>
|
||||
fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS}))
|
||||
.then(() => device.gatt.connect())
|
||||
.then(gatt => assert_equals(gatt.device, gatt.device)),
|
||||
test_desc);
|
||||
</script>
|
||||
|
|
|
@ -12,18 +12,18 @@ let device, fake_peripheral;
|
|||
|
||||
// TODO(569716): Test that the disconnect signal was sent to the device.
|
||||
bluetooth_test(() => getDiscoveredHealthThermometerDevice()
|
||||
.then(_ => ({device, fake_peripheral} = _))
|
||||
.then(() => fake_peripheral.setNextGATTConnectionResponse({
|
||||
code: HCI_SUCCESS,
|
||||
}))
|
||||
.then(() => device.gatt.connect()
|
||||
.then(gattServer => {
|
||||
gattServer.disconnect();
|
||||
assert_false(gattServer.connected);
|
||||
})
|
||||
.then(() => device.gatt.connect())
|
||||
.then(gattServer => {
|
||||
gattServer.disconnect();
|
||||
assert_false(gattServer.connected);
|
||||
})), test_desc);
|
||||
.then(_ => ({device, fake_peripheral} = _))
|
||||
.then(() => fake_peripheral.setNextGATTConnectionResponse({
|
||||
code: HCI_SUCCESS,
|
||||
}))
|
||||
.then(() => device.gatt.connect()
|
||||
.then(gattServer => {
|
||||
gattServer.disconnect();
|
||||
assert_false(gattServer.connected);
|
||||
})
|
||||
.then(() => device.gatt.connect())
|
||||
.then(gattServer => {
|
||||
gattServer.disconnect();
|
||||
assert_false(gattServer.connected);
|
||||
})), test_desc);
|
||||
</script>
|
||||
|
|
|
@ -11,26 +11,26 @@ const test_desc = 'Detach frame then garbage collect. We shouldn\'t crash.';
|
|||
let iframe = document.createElement('iframe');
|
||||
|
||||
bluetooth_test(() => setUpConnectableHealthThermometerDevice()
|
||||
// 1. Load the iframe.
|
||||
.then(() => new Promise(resolve => {
|
||||
iframe.src = '/bluetooth/resources/health-thermometer-iframe.html';
|
||||
document.body.appendChild(iframe);
|
||||
iframe.addEventListener('load', resolve);
|
||||
}))
|
||||
// 2. Connect device, detach the iframe, and run garbage collection.
|
||||
.then(() => new Promise(resolve => {
|
||||
callWithTrustedClick(() => {
|
||||
iframe.contentWindow.postMessage({
|
||||
type: 'RequestAndConnect',
|
||||
options: {filters: [{services: ['health_thermometer']}]}
|
||||
}, '*');
|
||||
});
|
||||
// 1. Load the iframe.
|
||||
.then(() => new Promise(resolve => {
|
||||
iframe.src = '/bluetooth/resources/health-thermometer-iframe.html';
|
||||
document.body.appendChild(iframe);
|
||||
iframe.addEventListener('load', resolve);
|
||||
}))
|
||||
// 2. Connect device, detach the iframe, and run garbage collection.
|
||||
.then(() => new Promise(resolve => {
|
||||
callWithTrustedClick(() => {
|
||||
iframe.contentWindow.postMessage({
|
||||
type: 'RequestAndConnect',
|
||||
options: {filters: [{services: ['health_thermometer']}]}
|
||||
}, '*');
|
||||
});
|
||||
|
||||
window.onmessage = messageEvent => {
|
||||
assert_equals(messageEvent.data, 'Connected');
|
||||
iframe.remove();
|
||||
runGarbageCollection().then(resolve);
|
||||
}
|
||||
})), test_desc)
|
||||
window.onmessage = messageEvent => {
|
||||
assert_equals(messageEvent.data, 'Connected');
|
||||
iframe.remove();
|
||||
runGarbageCollection().then(resolve);
|
||||
}
|
||||
})), test_desc)
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -12,15 +12,15 @@ let device, fake_peripheral;
|
|||
|
||||
// TODO(569716): Test that the disconnect signal was sent to the device.
|
||||
bluetooth_test(() => getDiscoveredHealthThermometerDevice()
|
||||
.then(_ => ({device, fake_peripheral} = _))
|
||||
.then(() => fake_peripheral.setNextGATTConnectionResponse({
|
||||
code: HCI_SUCCESS,
|
||||
}))
|
||||
.then(() => device.gatt.connect())
|
||||
.then(gattServer => {
|
||||
gattServer.disconnect();
|
||||
assert_false(gattServer.connected);
|
||||
gattServer.disconnect();
|
||||
assert_false(gattServer.connected);
|
||||
}), test_desc);
|
||||
.then(_ => ({device, fake_peripheral} = _))
|
||||
.then(() => fake_peripheral.setNextGATTConnectionResponse({
|
||||
code: HCI_SUCCESS,
|
||||
}))
|
||||
.then(() => device.gatt.connect())
|
||||
.then(gattServer => {
|
||||
gattServer.disconnect();
|
||||
assert_false(gattServer.connected);
|
||||
gattServer.disconnect();
|
||||
assert_false(gattServer.connected);
|
||||
}), test_desc);
|
||||
</script>
|
||||
|
|
|
@ -11,28 +11,28 @@ const test_desc = 'Garbage collect then detach frame. We shouldn\'t crash.';
|
|||
let iframe = document.createElement('iframe');
|
||||
|
||||
bluetooth_test(() => setUpConnectableHealthThermometerDevice()
|
||||
// 1. Load the iframe.
|
||||
.then((f) => new Promise(resolve => {
|
||||
iframe.src = '/bluetooth/resources/health-thermometer-iframe.html';
|
||||
document.body.appendChild(iframe);
|
||||
iframe.addEventListener('load', resolve);
|
||||
}))
|
||||
// 2. Connect device, run garbage collection, and detach iframe.
|
||||
.then(() => new Promise(resolve => {
|
||||
callWithTrustedClick(() => {
|
||||
iframe.contentWindow.postMessage({
|
||||
type: 'RequestAndConnect',
|
||||
options: {filters: [{services: ['health_thermometer']}]}
|
||||
}, '*');
|
||||
});
|
||||
|
||||
window.onmessage = messageEvent => {
|
||||
assert_equals(messageEvent.data, 'Connected');
|
||||
runGarbageCollection().then(() => {
|
||||
iframe.remove();
|
||||
resolve();
|
||||
// 1. Load the iframe.
|
||||
.then((f) => new Promise(resolve => {
|
||||
iframe.src = '/bluetooth/resources/health-thermometer-iframe.html';
|
||||
document.body.appendChild(iframe);
|
||||
iframe.addEventListener('load', resolve);
|
||||
}))
|
||||
// 2. Connect device, run garbage collection, and detach iframe.
|
||||
.then(() => new Promise(resolve => {
|
||||
callWithTrustedClick(() => {
|
||||
iframe.contentWindow.postMessage({
|
||||
type: 'RequestAndConnect',
|
||||
options: {filters: [{services: ['health_thermometer']}]}
|
||||
}, '*');
|
||||
});
|
||||
}
|
||||
})), test_desc)
|
||||
|
||||
window.onmessage = messageEvent => {
|
||||
assert_equals(messageEvent.data, 'Connected');
|
||||
runGarbageCollection().then(() => {
|
||||
iframe.remove();
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
})), test_desc)
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'disconnect() called before getPrimaryService. ' +
|
||||
'Reject with NetworkError.';
|
||||
const expected = new DOMException(
|
||||
'GATT Server is disconnected. Cannot retrieve services. (Re)connect ' +
|
||||
'first with `device.gatt.connect`.',
|
||||
'NetworkError');
|
||||
let device;
|
||||
|
||||
bluetooth_test(() => getHealthThermometerDevice({
|
||||
filters: [{services: ['health_thermometer']}],
|
||||
optionalServices: ['generic_access']
|
||||
})
|
||||
.then(_ => ({device} = _))
|
||||
.then(() => device.gatt.disconnect())
|
||||
.then(() => assert_promise_rejects_with_message(
|
||||
device.gatt.getPrimaryService('health_thermometer'),
|
||||
expected)),
|
||||
test_desc);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,28 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'disconnect() called during a getPrimaryService ' +
|
||||
'call that fails. Reject with NetworkError.';
|
||||
const expected = new DOMException(
|
||||
'GATT Server is disconnected. Cannot retrieve services. (Re)connect ' +
|
||||
'first with `device.gatt.connect`.', 'NetworkError');
|
||||
let device;
|
||||
|
||||
bluetooth_test(() => getEmptyHealthThermometerDevice()
|
||||
.then(_ => ({device} = _))
|
||||
.then(() => {
|
||||
let promise = assert_promise_rejects_with_message(
|
||||
device.gatt.getPrimaryService('health_thermometer'),
|
||||
expected)
|
||||
device.gatt.disconnect();
|
||||
return promise;
|
||||
}),
|
||||
test_desc);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,29 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'disconnect() called during a getPrimaryService call that ' +
|
||||
'succeeds. Reject with NetworkError.';
|
||||
const expected = new DOMException(
|
||||
'GATT Server is disconnected. Cannot retrieve services. (Re)connect ' +
|
||||
'first with `device.gatt.connect`.',
|
||||
'NetworkError');
|
||||
|
||||
bluetooth_test(() => getHealthThermometerDevice({
|
||||
filters: [{services: ['health_thermometer']}],
|
||||
optionalServices: ['generic_access']
|
||||
})
|
||||
.then(({device}) => {
|
||||
let promise = assert_promise_rejects_with_message(
|
||||
device.gatt.getPrimaryService('health_thermometer'),
|
||||
expected);
|
||||
device.gatt.disconnect();
|
||||
return promise;
|
||||
}), test_desc);
|
||||
|
||||
</script>
|
|
@ -0,0 +1,46 @@
|
|||
<!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
|
||||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
<script src="/bluetooth/resources/bluetooth-helpers.js"></script>
|
||||
<script>
|
||||
'use strict';
|
||||
const test_desc = 'Calls on services after we disconnect and connect again. '+
|
||||
'Should reject with InvalidStateError.';
|
||||
let device, services;
|
||||
|
||||
bluetooth_test(() => getHealthThermometerDevice({
|
||||
filters: [{services: ['health_thermometer']}]
|
||||
})
|
||||
.then(_ => ({device} = _))
|
||||
.then(() => device.gatt.getPrimaryService('health_thermometer'))
|
||||
// Convert to array if necessary.
|
||||
.then(s => services = [].concat(s))
|
||||
.then(() => device.gatt.disconnect())
|
||||
.then(() => device.gatt.connect())
|
||||
.then(() => {
|
||||
let promises = Promise.resolve();
|
||||
for (let service of services) {
|
||||
let error = new DOMException(
|
||||
`Service with UUID ${service.uuid} is no longer valid. Remember ` +
|
||||
`to retrieve the service again after reconnecting.`,
|
||||
'InvalidStateError');
|
||||
promises = promises.then(() =>
|
||||
assert_promise_rejects_with_message(
|
||||
service.getCharacteristic('measurement_interval'),
|
||||
error));
|
||||
promises = promises.then(() =>
|
||||
assert_promise_rejects_with_message(
|
||||
service.getCharacteristics(),
|
||||
error));
|
||||
promises = promises.then(() =>
|
||||
assert_promise_rejects_with_message(
|
||||
service.getCharacteristics('measurement_interval'),
|
||||
error));
|
||||
}
|
||||
return promises;
|
||||
}), test_desc);
|
||||
|
||||
</script>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue