diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:22:09 +0000 |
commit | 43a97878ce14b72f0981164f87f2e35e14151312 (patch) | |
tree | 620249daf56c0258faa40cbdcf9cfba06de2a846 /testing/web-platform/tests/bluetooth/server | |
parent | Initial commit. (diff) | |
download | firefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip |
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/bluetooth/server')
63 files changed, 1807 insertions, 0 deletions
diff --git a/testing/web-platform/tests/bluetooth/server/connect/connection-succeeds.https.window.js b/testing/web-platform/tests/bluetooth/server/connect/connection-succeeds.https.window.js new file mode 100644 index 0000000000..90b62b9265 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/connect/connection-succeeds.https.window.js @@ -0,0 +1,13 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +'use strict'; +const test_desc = 'Device will connect'; + +bluetooth_test(async () => { + let {device, fake_peripheral} = await getDiscoveredHealthThermometerDevice(); + await fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS}); + let gatt = await device.gatt.connect(); + assert_true(gatt.connected); +}, test_desc); diff --git a/testing/web-platform/tests/bluetooth/server/connect/detachedIframe.https.window.js b/testing/web-platform/tests/bluetooth/server/connect/detachedIframe.https.window.js new file mode 100644 index 0000000000..2332cef707 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/connect/detachedIframe.https.window.js @@ -0,0 +1,27 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js + +bluetooth_test(async () => { + let iframe = document.createElement('iframe'); + let error; + + const {device} = await getHealthThermometerDeviceFromIframe(iframe); + + iframe.remove(); + // Set iframe to null to ensure that the GC cleans up as much as possible. + iframe = null; + await garbageCollect(); + + try { + await device.gatt.connect(); + } catch (e) { + // Cannot use promise_rejects_dom() because |e| is thrown from a different + // global. + error = e; + } + assert_not_equals(error, undefined); + assert_equals(error.name, 'NetworkError'); +}, 'connect() rejects in a detached context'); diff --git a/testing/web-platform/tests/bluetooth/server/connect/garbage-collection-ran-during-success.https.window.js b/testing/web-platform/tests/bluetooth/server/connect/garbage-collection-ran-during-success.https.window.js new file mode 100644 index 0000000000..2d2211dec3 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/connect/garbage-collection-ran-during-success.https.window.js @@ -0,0 +1,19 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +'use strict'; +const test_desc = 'Garbage Collection ran during a connect call that ' + + 'succeeds. Should not crash.'; + +bluetooth_test(async () => { + let connectPromise; + { + let {device, fake_peripheral} = + await getDiscoveredHealthThermometerDevice(); + await fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS}); + connectPromise = device.gatt.connect(); + } + await Promise.all([connectPromise, garbageCollect()]); +}, test_desc); diff --git a/testing/web-platform/tests/bluetooth/server/connect/get-same-gatt-server.https.window.js b/testing/web-platform/tests/bluetooth/server/connect/get-same-gatt-server.https.window.js new file mode 100644 index 0000000000..59d7243a65 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/connect/get-same-gatt-server.https.window.js @@ -0,0 +1,19 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +'use strict'; +const test_desc = 'Multiple connects should return the same gatt object.'; + +bluetooth_test(async () => { + let {device, fake_peripheral} = await getDiscoveredHealthThermometerDevice(); + await fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS}); + // 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. + let gatt1 = await device.gatt.connect(); + let gatt2 = await device.gatt.connect(); + assert_equals(gatt1, gatt2); +}, test_desc); diff --git a/testing/web-platform/tests/bluetooth/server/device-same-object.https.window.js b/testing/web-platform/tests/bluetooth/server/device-same-object.https.window.js new file mode 100644 index 0000000000..f9a66d9b69 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/device-same-object.https.window.js @@ -0,0 +1,13 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +'use strict'; +const test_desc = '[SameObject] test for BluetoothRemoteGATTServer\'s device.'; + +bluetooth_test(async () => { + let {device, fake_peripheral} = await getDiscoveredHealthThermometerDevice(); + await fake_peripheral.setNextGATTConnectionResponse({code: HCI_SUCCESS}); + let gatt = await device.gatt.connect(); + assert_equals(gatt.device, device); +}, test_desc); diff --git a/testing/web-platform/tests/bluetooth/server/disconnect/connect-disconnect-twice.https.window.js b/testing/web-platform/tests/bluetooth/server/disconnect/connect-disconnect-twice.https.window.js new file mode 100644 index 0000000000..5d9908df4c --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/disconnect/connect-disconnect-twice.https.window.js @@ -0,0 +1,23 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +'use strict'; +const test_desc = 'Connect + Disconnect twice still results in ' + + '\'connected\' being false.'; +let device, fake_peripheral; + +// TODO(569716): Test that the disconnect signal was sent to the device. +bluetooth_test(async () => { + let {device, fake_peripheral} = await getDiscoveredHealthThermometerDevice(); + await fake_peripheral.setNextGATTConnectionResponse({ + code: HCI_SUCCESS, + }); + let gattServer = await device.gatt.connect(); + await gattServer.disconnect(); + assert_false(gattServer.connected); + + gattServer = await device.gatt.connect(); + await gattServer.disconnect(); + assert_false(gattServer.connected); +}, test_desc); diff --git a/testing/web-platform/tests/bluetooth/server/disconnect/detach-gc.https.window.js b/testing/web-platform/tests/bluetooth/server/disconnect/detach-gc.https.window.js new file mode 100644 index 0000000000..b934b37973 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/disconnect/detach-gc.https.window.js @@ -0,0 +1,34 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +'use strict'; +const test_desc = 'Detach frame then garbage collect. We shouldn\'t crash.'; +let iframe = document.createElement('iframe'); + +bluetooth_test(async () => { + await setUpConnectableHealthThermometerDevice(); + // 1. Load the iframe. + await 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. + await new Promise(resolve => { + callWithTrustedClick(() => { + iframe.contentWindow.postMessage( + { + type: 'RequestAndConnect', + options: {filters: [{services: ['health_thermometer']}]} + }, + '*'); + }); + window.onmessage = messageEvent => { + assert_equals(messageEvent.data, 'Connected'); + iframe.remove(); + garbageCollect().then(resolve); + } + }) +}, test_desc) diff --git a/testing/web-platform/tests/bluetooth/server/disconnect/detachedIframe.https.window.js b/testing/web-platform/tests/bluetooth/server/disconnect/detachedIframe.https.window.js new file mode 100644 index 0000000000..04e0ca0117 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/disconnect/detachedIframe.https.window.js @@ -0,0 +1,28 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js + +bluetooth_test(async () => { + let iframe = document.createElement('iframe'); + let error; + + const {device} = await getHealthThermometerDeviceFromIframe(iframe); + await device.gatt.connect(); + + iframe.remove(); + // Set iframe to null to ensure that the GC cleans up as much as possible. + iframe = null; + await garbageCollect(); + + try { + await device.gatt.disconnect(); + } catch (e) { + // Cannot use promise_rejects_dom() because |e| is thrown from a different + // global. + error = e; + } + assert_not_equals(error, undefined); + assert_equals(error.name, 'NetworkError'); +}, 'disconnect() rejects in a detached context'); diff --git a/testing/web-platform/tests/bluetooth/server/disconnect/disconnect-twice-in-a-row.https.window.js b/testing/web-platform/tests/bluetooth/server/disconnect/disconnect-twice-in-a-row.https.window.js new file mode 100644 index 0000000000..acca9796d5 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/disconnect/disconnect-twice-in-a-row.https.window.js @@ -0,0 +1,20 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +'use strict'; +const test_desc = 'Calling disconnect twice in a row still results in ' + + '\'connected\' being false.'; + +// TODO(569716): Test that the disconnect signal was sent to the device. +bluetooth_test(async () => { + let {device, fake_peripheral} = await getDiscoveredHealthThermometerDevice(); + await fake_peripheral.setNextGATTConnectionResponse({ + code: HCI_SUCCESS, + }); + let gattServer = await device.gatt.connect(); + await gattServer.disconnect(); + assert_false(gattServer.connected); + await gattServer.disconnect(); + assert_false(gattServer.connected); +}, test_desc); diff --git a/testing/web-platform/tests/bluetooth/server/disconnect/gc-detach.https.window.js b/testing/web-platform/tests/bluetooth/server/disconnect/gc-detach.https.window.js new file mode 100644 index 0000000000..1c062a7759 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/disconnect/gc-detach.https.window.js @@ -0,0 +1,36 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +'use strict'; +const test_desc = 'Garbage collect then detach frame. We shouldn\'t crash.'; +let iframe = document.createElement('iframe'); + +bluetooth_test(async () => { + await setUpConnectableHealthThermometerDevice(); + // 1. Load the iframe. + await 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. + await new Promise(resolve => { + callWithTrustedClick(() => { + iframe.contentWindow.postMessage( + { + type: 'RequestAndConnect', + options: {filters: [{services: ['health_thermometer']}]} + }, + '*'); + }); + window.onmessage = messageEvent => { + assert_equals(messageEvent.data, 'Connected'); + garbageCollect().then(() => { + iframe.remove(); + resolve(); + }); + } + }) +}, test_desc) diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnect-called-before.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnect-called-before.https.window.js new file mode 100644 index 0000000000..631545a385 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnect-called-before.https.window.js @@ -0,0 +1,26 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'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(() => getConnectedHealthThermometerDevice({ + 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); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-error.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-error.https.window.js new file mode 100644 index 0000000000..bcf19665d5 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-error.https.window.js @@ -0,0 +1,25 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'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); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-success.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-success.https.window.js new file mode 100644 index 0000000000..0d2fc1044a --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnect-called-during-success.https.window.js @@ -0,0 +1,26 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'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); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnect-discovery-timeout.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnect-discovery-timeout.https.window.js new file mode 100644 index 0000000000..03b0c9d0f3 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnect-discovery-timeout.https.window.js @@ -0,0 +1,46 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = + 'Calls to getPrimaryService when device disconnects and discovery' + + ' times out should reject promise rather than get stuck.'; +let device; + +bluetooth_test( + async (t) => { + let {device, fake_peripheral} = + await getConnectedHealthThermometerDevice({ + filters: [{services: ['health_thermometer']}], + optionalServices: ['generic_access'] + }); + + await fake_peripheral.setNextGATTDiscoveryResponse({ + code: HCI_CONNECTION_TIMEOUT, + }); + await Promise.all([ + fake_peripheral.simulateGATTDisconnection({ + code: HCI_SUCCESS, + }), + // Using promise_rejects_dom here rather than + // assert_promise_rejects_with_message as the race between + // simulateGATTDisconnection and getPrimaryServices might end up giving + // slightly different exception message (i.e has "Failed to execute ... + // on + // ... " prefix when disconnected state is reflected on the renderer + // side). The point of the test is no matter how race between them, the + // promise will be rejected as opposed to get stuck. + promise_rejects_dom(t, 'NetworkError', device.gatt.getPrimaryService('health_thermometer')), + ]); + }, + test_desc, '', + // As specified above there is a race condition between + // simulateGATTDisconnection and getPrimaryServices, the artificial + // GATTDiscoveryResponse might not be consumed in case + // simulateGATTDisconnection happens first. As a result explicitly skip + // all response consumed validation at the end of the test. + /*validate_response_consumed=*/ false); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnect-invalidates-objects.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnect-invalidates-objects.https.window.js new file mode 100644 index 0000000000..56468b24ea --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnect-invalidates-objects.https.window.js @@ -0,0 +1,43 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'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); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnected-device.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnected-device.https.window.js new file mode 100644 index 0000000000..741b2db5ee --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-disconnected-device.https.window.js @@ -0,0 +1,23 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'getPrimaryService 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.getPrimaryService('health_thermometer'), + expected)), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-discovery-complete-no-permission-absent-service.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-discovery-complete-no-permission-absent-service.https.window.js new file mode 100644 index 0000000000..e2f5c87630 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-discovery-complete-no-permission-absent-service.https.window.js @@ -0,0 +1,29 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'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.getPrimaryService(glucose.alias), expected), + assert_promise_rejects_with_message( + device.gatt.getPrimaryService(glucose.name), expected), + assert_promise_rejects_with_message( + device.gatt.getPrimaryService(glucose.uuid), expected)])), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-discovery-complete-service-not-found.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-discovery-complete-service-not-found.https.window.js new file mode 100644 index 0000000000..8e9166b41a --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-discovery-complete-service-not-found.https.window.js @@ -0,0 +1,20 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'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.getPrimaryService('glucose'), + new DOMException( + `No Services matching UUID ${glucose.uuid} found in Device.`, + 'NotFoundError'))), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.https.window.js new file mode 100644 index 0000000000..df182fe8ff --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-error.https.window.js @@ -0,0 +1,28 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'Garbage Collection ran during a getPrimaryService ' + + '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.getPrimaryService('health_thermometer'), + expected); + // Disconnect called to clear attributeInstanceMap and allow the + // object to get garbage collected. + device.gatt.disconnect(); + return garbageCollect(); + }) + .then(() => promise), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.https.window.js new file mode 100644 index 0000000000..8e278af224 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-garbage-collection-ran-during-success.https.window.js @@ -0,0 +1,28 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'Garbage Collection ran during a getPrimaryService 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.getPrimaryService('health_thermometer'), + expected); + device.gatt.disconnect(); + return garbageCollect(); + }) + .then(() => promise), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-get-different-service-after-reconnection.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-get-different-service-after-reconnection.https.window.js new file mode 100644 index 0000000000..d4557f6753 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-get-different-service-after-reconnection.https.window.js @@ -0,0 +1,39 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'Calls to getPrimaryService 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.getPrimaryService('health_thermometer')) + .then(services => services_first_connection = services) + .then(() => device.gatt.disconnect()) + .then(() => device.gatt.connect()) + .then(() => device.gatt.getPrimaryService('health_thermometer')) + .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); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-get-same-object.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-get-same-object.https.window.js new file mode 100644 index 0000000000..b43cefb567 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-get-same-object.https.window.js @@ -0,0 +1,37 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'Calls to getPrimaryService should return the same object.'; +let device; + +bluetooth_test(() => getHealthThermometerDevice({ + filters: [{services: ['health_thermometer']}], + optionalServices: ['generic_access']}) + .then(({device}) => Promise.all([ + device.gatt.getPrimaryService('health_thermometer'), + device.gatt.getPrimaryService('health_thermometer')])) + .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); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-invalid-service-name.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-invalid-service-name.https.window.js new file mode 100644 index 0000000000..cf4ab6c665 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-invalid-service-name.https.window.js @@ -0,0 +1,26 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'Wrong Service name. Reject with TypeError.'; +const expected = new DOMException( + "Failed to execute 'getPrimaryService' 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(() => getConnectedHealthThermometerDevice() + .then(({device}) => assert_promise_rejects_with_message( + device.gatt.getPrimaryService('wrong_name'), + expected, + 'Wrong Service name passed.')), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-no-permission-absent-service.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-no-permission-absent-service.https.window.js new file mode 100644 index 0000000000..3466ded4f9 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-no-permission-absent-service.https.window.js @@ -0,0 +1,27 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'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(() => getConnectedHealthThermometerDevice({ + filters: [{services: ['health_thermometer']}] + }) + .then(({device}) => Promise.all([ + assert_promise_rejects_with_message( + device.gatt.getPrimaryService(glucose.alias), expected), + assert_promise_rejects_with_message( + device.gatt.getPrimaryService(glucose.name), expected), + assert_promise_rejects_with_message( + device.gatt.getPrimaryService(glucose.uuid), expected)])), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.https.window.js new file mode 100644 index 0000000000..6576ef20a3 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-no-permission-for-any-service.https.window.js @@ -0,0 +1,21 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'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(() => getConnectedHealthThermometerDevice({acceptAllDevices: true}) + .then(({device}) => assert_promise_rejects_with_message( + device.gatt.getPrimaryService('heart_rate'), + expected)), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-no-permission-present-service.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-no-permission-present-service.https.window.js new file mode 100644 index 0000000000..3d0b460bc3 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-no-permission-present-service.https.window.js @@ -0,0 +1,26 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'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(() => getConnectedHealthThermometerDevice({ + filters: [{services: ['health_thermometer']}] + }) + .then(({device}) => Promise.all([ + assert_promise_rejects_with_message( + device.gatt.getPrimaryService(generic_access.alias), expected), + assert_promise_rejects_with_message( + device.gatt.getPrimaryService(generic_access.name), expected), + assert_promise_rejects_with_message( + device.gatt.getPrimaryService(generic_access.uuid), expected)])), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-service-not-found.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-service-not-found.https.window.js new file mode 100644 index 0000000000..6e0d2c446b --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryService/gen-service-not-found.https.window.js @@ -0,0 +1,20 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'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.getPrimaryService('glucose'), + new DOMException( + `No Services matching UUID ${glucose.uuid} found in Device.`, + 'NotFoundError'))), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryService/service-found.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryService/service-found.https.window.js new file mode 100644 index 0000000000..b8a930d10c --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryService/service-found.https.window.js @@ -0,0 +1,28 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +'use strict'; +const test_desc = 'Request for service. Should return right service'; + +bluetooth_test(async () => { + let {device} = await getHealthThermometerDevice({ + filters: [{services: ['health_thermometer']}], + optionalServices: ['generic_access'] + }); + let services = await Promise.all([ + device.gatt.getPrimaryService(generic_access.alias), + device.gatt.getPrimaryService(generic_access.name), + device.gatt.getPrimaryService(generic_access.uuid) + ]); + services.forEach(service => { + assert_equals( + service.uuid, generic_access.uuid, + 'Service UUID should be the same as requested UUID.'); + assert_true( + service.isPrimary, + 'getPrimaryService should return a primary service.'); + assert_equals( + service.device, device, 'Service device should be the same as device.'); + }) +}, test_desc); diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryService/two-iframes-from-same-origin.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryService/two-iframes-from-same-origin.https.window.js new file mode 100644 index 0000000000..b7f23a1491 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryService/two-iframes-from-same-origin.https.window.js @@ -0,0 +1,88 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +'use strict'; +const test_desc = 'Two iframes in the same origin should be able to access ' + + 'each other\'s services'; + +const iframe1 = document.createElement('iframe'); +const iframe2 = document.createElement('iframe'); + +function add_iframe(iframe) { + let promise = + new Promise(resolve => iframe.addEventListener('load', resolve)); + iframe.src = '/bluetooth/resources/health-thermometer-iframe.html'; + document.body.appendChild(iframe); + return promise; +} + +function send_message(iframe, command, arg, assert_func) { + let promise = new Promise((resolve, reject) => { + window.addEventListener('message', (messageEvent) => { + try { + assert_func(messageEvent.data); + } catch (e) { + reject(e); + } + resolve(); + }, {once: true}); + }); + if (command === 'RequestAndConnect') { + arg = {filters: [{services: [arg]}]}; + } + callWithTrustedClick( + () => iframe.contentWindow.postMessage( + { + type: command, + options: arg, + }, + '*')); + return promise; +} + +bluetooth_test(async () => { + await getHealthThermometerDevice(); + // 1. Add the first iframe. + await add_iframe(iframe1); + // 2. Connect with the first iframe, requesting the health + // thermometer service. + await send_message( + iframe1, 'RequestAndConnect', 'health_thermometer', + msg => assert_equals(msg, 'Connected')); + // 3. Access the health thermometer service with the first iframe + // (successfully). + await send_message( + iframe1, 'GetService', 'health_thermometer', + msg => assert_equals(msg, 'ServiceReceived')); + // 4. Access the generic access service with the first iframe + // (unsuccessfully). + await send_message(iframe1, 'GetService', 'generic_access', msg => { + let split_msg = msg.split(': '); + assert_equals(split_msg[0], 'FAIL'); + assert_equals(split_msg[1], 'SecurityError'); + }); + // 5. Add the second iframe. + await add_iframe(iframe2); + // 6. Connect with the second iframe, requesting the generic + // access service. + await send_message( + iframe2, 'RequestAndConnect', 'generic_access', + msg => assert_equals(msg, 'Connected')); + // 7. Access the health thermometer service with the second iframe + // (successfully). Both iframes should have access to both + // services at this point since they have the same origin. + await send_message( + iframe2, 'GetService', 'health_thermometer', + msg => assert_equals(msg, 'ServiceReceived')); + // 8. Access the generic access service with the second iframe + // (unsuccessfully). + await send_message( + iframe2, 'GetService', 'generic_access', + msg => assert_equals(msg, 'ServiceReceived')); + // 9. Access the generic access service with the first iframe + // (successfully). + await send_message( + iframe1, 'GetService', 'generic_access', + msg => assert_equals(msg, 'ServiceReceived')); +}, test_desc); diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/blocklisted-services-with-uuid.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/blocklisted-services-with-uuid.https.window.js new file mode 100644 index 0000000000..ccc913e5bf --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/blocklisted-services-with-uuid.https.window.js @@ -0,0 +1,20 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +'use strict'; +const test_desc = 'Request for services. Does not return blocklisted service.'; +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(async () => { + let {device} = await getConnectedHIDDevice({ + filters: [{services: ['device_information']}], + optionalServices: ['human_interface_device'] + }); + assert_promise_rejects_with_message( + device.gatt.getPrimaryServices('human_interface_device'), expected) +}, test_desc); diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/blocklisted-services.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/blocklisted-services.https.window.js new file mode 100644 index 0000000000..ae6be90994 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/blocklisted-services.https.window.js @@ -0,0 +1,22 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +'use strict'; +const test_desc = 'Request for services. Does not return blocklisted service.'; + +bluetooth_test(async () => { + let {device} = await getHIDDevice({ + filters: [{services: ['device_information']}], + optionalServices: ['generic_access', 'human_interface_device'] + }) + let services = await device.gatt.getPrimaryServices(); + assert_equals(services.length, 2); + let uuid_set = new Set(services.map(s => s.uuid)); + + assert_equals(uuid_set.size, 2); + assert_true(uuid_set.has(BluetoothUUID.getService('generic_access'))); + assert_true(uuid_set.has(BluetoothUUID.getService('device_information'))); + assert_false( + uuid_set.has(BluetoothUUID.getService('human_interface_device'))); +}, test_desc); diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/correct-services.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/correct-services.https.window.js new file mode 100644 index 0000000000..f3d883dd2e --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/correct-services.https.window.js @@ -0,0 +1,30 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +'use strict'; +const test_desc = 'Find correct services with UUID.'; +let device, fake_peripheral; + +bluetooth_test(async () => { + let {device, fake_peripheral} = await getConnectedHealthThermometerDevice( + {filters: [{services: ['health_thermometer']}]}); + let fake_service = + await fake_peripheral.addFakeService({uuid: 'health_thermometer'}); + await Promise.all([ + fake_service.addFakeCharacteristic( + {uuid: 'temperature_measurement', properties: ['indicate']}), + fake_service.addFakeCharacteristic( + {uuid: 'temperature_measurement', properties: ['indicate']}) + ]); + await fake_peripheral.setNextGATTDiscoveryResponse({code: HCI_SUCCESS}); + let services = await device.gatt.getPrimaryServices('health_thermometer'); + let [characteristics1, characteristics2] = await Promise.all( + [services[0].getCharacteristics(), services[1].getCharacteristics()]); + if (characteristics1.length === 2) + assert_equals(characteristics2.length, 3); + else if (characteristics2.length === 2) + assert_equals(characteristics1.length, 3); + else + assert_unreached('Invalid lengths.'); +}, test_desc); diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before-with-uuid.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before-with-uuid.https.window.js new file mode 100644 index 0000000000..21b561375d --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before-with-uuid.https.window.js @@ -0,0 +1,26 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'disconnect() called before getPrimaryServices. ' + + '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(() => getConnectedHealthThermometerDevice({ + filters: [{services: ['health_thermometer']}], + optionalServices: ['generic_access'] + }) + .then(_ => ({device} = _)) + .then(() => device.gatt.disconnect()) + .then(() => assert_promise_rejects_with_message( + device.gatt.getPrimaryServices('health_thermometer'), + expected)), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before.https.window.js new file mode 100644 index 0000000000..8e5fea83ab --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-before.https.window.js @@ -0,0 +1,26 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'disconnect() called before getPrimaryServices. ' + + '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(() => getConnectedHealthThermometerDevice({ + filters: [{services: ['health_thermometer']}], + optionalServices: ['generic_access'] + }) + .then(_ => ({device} = _)) + .then(() => device.gatt.disconnect()) + .then(() => assert_promise_rejects_with_message( + device.gatt.getPrimaryServices(), + expected)), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error-with-uuid.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error-with-uuid.https.window.js new file mode 100644 index 0000000000..5c28716b90 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error-with-uuid.https.window.js @@ -0,0 +1,25 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'disconnect() called during a getPrimaryServices ' + + '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.getPrimaryServices('health_thermometer'), + expected) + device.gatt.disconnect(); + return promise; + }), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error.https.window.js new file mode 100644 index 0000000000..ddc3124791 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-error.https.window.js @@ -0,0 +1,25 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'disconnect() called during a getPrimaryServices ' + + '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.getPrimaryServices(), + expected) + device.gatt.disconnect(); + return promise; + }), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success-with-uuid.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success-with-uuid.https.window.js new file mode 100644 index 0000000000..13e3806d31 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success-with-uuid.https.window.js @@ -0,0 +1,26 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'disconnect() called during a getPrimaryServices 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.getPrimaryServices('health_thermometer'), + expected); + device.gatt.disconnect(); + return promise; + }), test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success.https.window.js new file mode 100644 index 0000000000..d6b31936c6 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-called-during-success.https.window.js @@ -0,0 +1,26 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'disconnect() called during a getPrimaryServices 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.getPrimaryServices(), + expected); + device.gatt.disconnect(); + return promise; + }), test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-discovery-timeout-with-uuid.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-discovery-timeout-with-uuid.https.window.js new file mode 100644 index 0000000000..77f7bc81d9 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-discovery-timeout-with-uuid.https.window.js @@ -0,0 +1,46 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = + 'Calls to getPrimaryServices when device disconnects and discovery' + + ' times out should reject promise rather than get stuck.'; +let device; + +bluetooth_test( + async (t) => { + let {device, fake_peripheral} = + await getConnectedHealthThermometerDevice({ + filters: [{services: ['health_thermometer']}], + optionalServices: ['generic_access'] + }); + + await fake_peripheral.setNextGATTDiscoveryResponse({ + code: HCI_CONNECTION_TIMEOUT, + }); + await Promise.all([ + fake_peripheral.simulateGATTDisconnection({ + code: HCI_SUCCESS, + }), + // Using promise_rejects_dom here rather than + // assert_promise_rejects_with_message as the race between + // simulateGATTDisconnection and getPrimaryServices might end up giving + // slightly different exception message (i.e has "Failed to execute ... + // on + // ... " prefix when disconnected state is reflected on the renderer + // side). The point of the test is no matter how race between them, the + // promise will be rejected as opposed to get stuck. + promise_rejects_dom(t, 'NetworkError', device.gatt.getPrimaryServices('health_thermometer')), + ]); + }, + test_desc, '', + // As specified above there is a race condition between + // simulateGATTDisconnection and getPrimaryServices, the artificial + // GATTDiscoveryResponse might not be consumed in case + // simulateGATTDisconnection happens first. As a result explicitly skip + // all response consumed validation at the end of the test. + /*validate_response_consumed=*/ false); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-discovery-timeout.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-discovery-timeout.https.window.js new file mode 100644 index 0000000000..ea55b7b495 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-discovery-timeout.https.window.js @@ -0,0 +1,46 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = + 'Calls to getPrimaryServices when device disconnects and discovery' + + ' times out should reject promise rather than get stuck.'; +let device; + +bluetooth_test( + async (t) => { + let {device, fake_peripheral} = + await getConnectedHealthThermometerDevice({ + filters: [{services: ['health_thermometer']}], + optionalServices: ['generic_access'] + }); + + await fake_peripheral.setNextGATTDiscoveryResponse({ + code: HCI_CONNECTION_TIMEOUT, + }); + await Promise.all([ + fake_peripheral.simulateGATTDisconnection({ + code: HCI_SUCCESS, + }), + // Using promise_rejects_dom here rather than + // assert_promise_rejects_with_message as the race between + // simulateGATTDisconnection and getPrimaryServices might end up giving + // slightly different exception message (i.e has "Failed to execute ... + // on + // ... " prefix when disconnected state is reflected on the renderer + // side). The point of the test is no matter how race between them, the + // promise will be rejected as opposed to get stuck. + promise_rejects_dom(t, 'NetworkError', device.gatt.getPrimaryServices()), + ]); + }, + test_desc, '', + // As specified above there is a race condition between + // simulateGATTDisconnection and getPrimaryServices, the artificial + // GATTDiscoveryResponse might not be consumed in case + // simulateGATTDisconnection happens first. As a result explicitly skip + // all response consumed validation at the end of the test. + /*validate_response_consumed=*/ false); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects-with-uuid.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects-with-uuid.https.window.js new file mode 100644 index 0000000000..8cdb83e3ad --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects-with-uuid.https.window.js @@ -0,0 +1,43 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'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.getPrimaryServices('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); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects.https.window.js new file mode 100644 index 0000000000..9fd536f051 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnect-invalidates-objects.https.window.js @@ -0,0 +1,43 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'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.getPrimaryServices()) + // 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); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnected-device-with-uuid.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnected-device-with-uuid.https.window.js new file mode 100644 index 0000000000..e0393d5e69 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnected-device-with-uuid.https.window.js @@ -0,0 +1,23 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'getPrimaryServices 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.getPrimaryServices('health_thermometer'), + expected)), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnected-device.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnected-device.https.window.js new file mode 100644 index 0000000000..87d74c6ab1 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-disconnected-device.https.window.js @@ -0,0 +1,23 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'getPrimaryServices 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.getPrimaryServices(), + expected)), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-discovery-complete-no-permission-absent-service-with-uuid.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-discovery-complete-no-permission-absent-service-with-uuid.https.window.js new file mode 100644 index 0000000000..6e179dc5d9 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-discovery-complete-no-permission-absent-service-with-uuid.https.window.js @@ -0,0 +1,29 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'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.getPrimaryServices(glucose.alias), expected), + assert_promise_rejects_with_message( + device.gatt.getPrimaryServices(glucose.name), expected), + assert_promise_rejects_with_message( + device.gatt.getPrimaryServices(glucose.uuid), expected)])), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-discovery-complete-service-not-found-with-uuid.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-discovery-complete-service-not-found-with-uuid.https.window.js new file mode 100644 index 0000000000..66cfb491c0 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-discovery-complete-service-not-found-with-uuid.https.window.js @@ -0,0 +1,20 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'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.getPrimaryServices('glucose'), + new DOMException( + `No Services matching UUID ${glucose.uuid} found in Device.`, + 'NotFoundError'))), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.https.window.js new file mode 100644 index 0000000000..a235cf5d18 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error-with-uuid.https.window.js @@ -0,0 +1,28 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'Garbage Collection ran during a getPrimaryServices ' + + '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.getPrimaryServices('health_thermometer'), + expected); + // Disconnect called to clear attributeInstanceMap and allow the + // object to get garbage collected. + device.gatt.disconnect(); + return garbageCollect(); + }) + .then(() => promise), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.https.window.js new file mode 100644 index 0000000000..f174d4aef9 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-error.https.window.js @@ -0,0 +1,28 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'Garbage Collection ran during a getPrimaryServices ' + + '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.getPrimaryServices(), + expected); + // Disconnect called to clear attributeInstanceMap and allow the + // object to get garbage collected. + device.gatt.disconnect(); + return garbageCollect(); + }) + .then(() => promise), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.https.window.js new file mode 100644 index 0000000000..cf5dfb246f --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success-with-uuid.https.window.js @@ -0,0 +1,28 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'Garbage Collection ran during a getPrimaryServices 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.getPrimaryServices('health_thermometer'), + expected); + device.gatt.disconnect(); + return garbageCollect(); + }) + .then(() => promise), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.https.window.js new file mode 100644 index 0000000000..f1c080a946 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-garbage-collection-ran-during-success.https.window.js @@ -0,0 +1,28 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'Garbage Collection ran during a getPrimaryServices 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.getPrimaryServices(), + expected); + device.gatt.disconnect(); + return garbageCollect(); + }) + .then(() => promise), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection-with-uuid.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection-with-uuid.https.window.js new file mode 100644 index 0000000000..2e40d580f3 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection-with-uuid.https.window.js @@ -0,0 +1,39 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'Calls to getPrimaryServices 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.getPrimaryServices('health_thermometer')) + .then(services => services_first_connection = services) + .then(() => device.gatt.disconnect()) + .then(() => device.gatt.connect()) + .then(() => device.gatt.getPrimaryServices('health_thermometer')) + .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); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection.https.window.js new file mode 100644 index 0000000000..ee1fc971bf --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-get-different-service-after-reconnection.https.window.js @@ -0,0 +1,39 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'Calls to getPrimaryServices 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.getPrimaryServices()) + .then(services => services_first_connection = services) + .then(() => device.gatt.disconnect()) + .then(() => device.gatt.connect()) + .then(() => device.gatt.getPrimaryServices()) + .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); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-get-same-object-with-uuid.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-get-same-object-with-uuid.https.window.js new file mode 100644 index 0000000000..b589056a23 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-get-same-object-with-uuid.https.window.js @@ -0,0 +1,37 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'Calls to getPrimaryServices should return the same object.'; +let device; + +bluetooth_test(() => getHealthThermometerDevice({ + filters: [{services: ['health_thermometer']}], + optionalServices: ['generic_access']}) + .then(({device}) => Promise.all([ + device.gatt.getPrimaryServices('health_thermometer'), + device.gatt.getPrimaryServices('health_thermometer')])) + .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); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-get-same-object.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-get-same-object.https.window.js new file mode 100644 index 0000000000..63739add91 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-get-same-object.https.window.js @@ -0,0 +1,37 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'Calls to getPrimaryServices should return the same object.'; +let device; + +bluetooth_test(() => getHealthThermometerDevice({ + filters: [{services: ['health_thermometer']}], + optionalServices: ['generic_access']}) + .then(({device}) => Promise.all([ + device.gatt.getPrimaryServices(), + device.gatt.getPrimaryServices()])) + .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); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-invalid-service-name.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-invalid-service-name.https.window.js new file mode 100644 index 0000000000..a9b1262e6a --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-invalid-service-name.https.window.js @@ -0,0 +1,26 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'use strict'; +const test_desc = 'Wrong Service name. Reject with TypeError.'; +const expected = new DOMException( + "Failed to execute 'getPrimaryServices' 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(() => getConnectedHealthThermometerDevice() + .then(({device}) => assert_promise_rejects_with_message( + device.gatt.getPrimaryServices('wrong_name'), + expected, + 'Wrong Service name passed.')), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-no-permission-absent-service-with-uuid.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-no-permission-absent-service-with-uuid.https.window.js new file mode 100644 index 0000000000..27ad9f008e --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-no-permission-absent-service-with-uuid.https.window.js @@ -0,0 +1,27 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'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(() => getConnectedHealthThermometerDevice({ + filters: [{services: ['health_thermometer']}] + }) + .then(({device}) => Promise.all([ + assert_promise_rejects_with_message( + device.gatt.getPrimaryServices(glucose.alias), expected), + assert_promise_rejects_with_message( + device.gatt.getPrimaryServices(glucose.name), expected), + assert_promise_rejects_with_message( + device.gatt.getPrimaryServices(glucose.uuid), expected)])), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.https.window.js new file mode 100644 index 0000000000..d5f06c23da --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service-with-uuid.https.window.js @@ -0,0 +1,21 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'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(() => getConnectedHealthThermometerDevice({acceptAllDevices: true}) + .then(({device}) => assert_promise_rejects_with_message( + device.gatt.getPrimaryServices('heart_rate'), + expected)), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.https.window.js new file mode 100644 index 0000000000..8aa730d2ed --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-no-permission-for-any-service.https.window.js @@ -0,0 +1,21 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'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(() => getConnectedHealthThermometerDevice({acceptAllDevices: true}) + .then(({device}) => assert_promise_rejects_with_message( + device.gatt.getPrimaryServices(), + expected)), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-no-permission-present-service-with-uuid.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-no-permission-present-service-with-uuid.https.window.js new file mode 100644 index 0000000000..a2047a0e8f --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-no-permission-present-service-with-uuid.https.window.js @@ -0,0 +1,26 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'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(() => getConnectedHealthThermometerDevice({ + filters: [{services: ['health_thermometer']}] + }) + .then(({device}) => Promise.all([ + assert_promise_rejects_with_message( + device.gatt.getPrimaryServices(generic_access.alias), expected), + assert_promise_rejects_with_message( + device.gatt.getPrimaryServices(generic_access.name), expected), + assert_promise_rejects_with_message( + device.gatt.getPrimaryServices(generic_access.uuid), expected)])), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-service-not-found-with-uuid.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-service-not-found-with-uuid.https.window.js new file mode 100644 index 0000000000..a2db1edc4b --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/gen-service-not-found-with-uuid.https.window.js @@ -0,0 +1,20 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/common/gc.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +// Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py +'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.getPrimaryServices('glucose'), + new DOMException( + `No Services matching UUID ${glucose.uuid} found in Device.`, + 'NotFoundError'))), + test_desc); + diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/services-found-with-uuid.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/services-found-with-uuid.https.window.js new file mode 100644 index 0000000000..972e6a75ca --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/services-found-with-uuid.https.window.js @@ -0,0 +1,25 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +'use strict'; +const test_desc = 'Request for services. Should return right number of ' + + 'services.'; + +bluetooth_test(async () => { + let {device} = await getTwoHealthThermometerServicesDevice( + {filters: [{services: ['health_thermometer']}]}); + let services_arrays = await Promise.all([ + device.gatt.getPrimaryServices(health_thermometer.alias), + device.gatt.getPrimaryServices(health_thermometer.name), + device.gatt.getPrimaryServices(health_thermometer.uuid) + ]); + services_arrays.forEach(services => { + assert_equals(services.length, 2); + services.forEach(service => { + assert_equals( + service.uuid, BluetoothUUID.getService('health_thermometer')); + assert_true(service.isPrimary); + }); + }) +}, test_desc); diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/services-found.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/services-found.https.window.js new file mode 100644 index 0000000000..46861175c6 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/services-found.https.window.js @@ -0,0 +1,25 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +'use strict'; +const test_desc = 'Find all services in a device.'; + +bluetooth_test(async () => { + let {device} = await getTwoHealthThermometerServicesDevice({ + filters: [{services: ['health_thermometer']}], + optionalServices: ['generic_access'] + }); + let services = await device.gatt.getPrimaryServices(); + // Expect three service instances. + assert_equals(services.length, 3); + services.forEach(s => assert_true(s.isPrimary)); + + let uuid_set = new Set(services.map(s => s.uuid)); + // Two of the expected services are 'health_thermometer', so + // only 2 unique UUIDs. + assert_equals(uuid_set.size, 2); + + assert_true(uuid_set.has(BluetoothUUID.getService('generic_access'))); + assert_true(uuid_set.has(BluetoothUUID.getService('health_thermometer'))); +}, test_desc); diff --git a/testing/web-platform/tests/bluetooth/server/getPrimaryServices/services-not-found.https.window.js b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/services-not-found.https.window.js new file mode 100644 index 0000000000..6350328241 --- /dev/null +++ b/testing/web-platform/tests/bluetooth/server/getPrimaryServices/services-not-found.https.window.js @@ -0,0 +1,15 @@ +// META: script=/resources/testdriver.js +// META: script=/resources/testdriver-vendor.js +// META: script=/bluetooth/resources/bluetooth-test.js +// META: script=/bluetooth/resources/bluetooth-fake-devices.js +'use strict'; +const test_desc = 'Request for services in a device with no services. Reject ' + + 'with NotFoundError.'; +const expected = + new DOMException('No Services found in device.', 'NotFoundError'); + +bluetooth_test(async () => { + let {device} = await getEmptyHealthThermometerDevice(); + return assert_promise_rejects_with_message( + device.gatt.getPrimaryServices(), expected); +}, test_desc); |