summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/generic-sensor/resources/generic-sensor-helpers.js
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/generic-sensor/resources/generic-sensor-helpers.js')
-rw-r--r--testing/web-platform/tests/generic-sensor/resources/generic-sensor-helpers.js179
1 files changed, 179 insertions, 0 deletions
diff --git a/testing/web-platform/tests/generic-sensor/resources/generic-sensor-helpers.js b/testing/web-platform/tests/generic-sensor/resources/generic-sensor-helpers.js
new file mode 100644
index 0000000000..146f4292ad
--- /dev/null
+++ b/testing/web-platform/tests/generic-sensor/resources/generic-sensor-helpers.js
@@ -0,0 +1,179 @@
+'use strict';
+
+// If two doubles differ by less than this amount, we can consider them
+// to be effectively equal.
+const kEpsilon = 1e-8;
+
+class RingBuffer {
+ constructor(data) {
+ if (!Array.isArray(data)) {
+ throw new TypeError('`data` must be an array.');
+ }
+
+ this.bufferPosition_ = 0;
+ this.data_ = Array.from(data);
+ }
+
+ get data() {
+ return Array.from(this.data_);
+ }
+
+ next() {
+ const value = this.data_[this.bufferPosition_];
+ this.bufferPosition_ = (this.bufferPosition_ + 1) % this.data_.length;
+ return {done: false, value: value};
+ }
+
+ value() {
+ return this.data_[this.bufferPosition_];
+ }
+
+ [Symbol.iterator]() {
+ return this;
+ }
+
+ reset() {
+ this.bufferPosition_ = 0;
+ }
+};
+
+// Calls test_driver.update_virtual_sensor() until it results in a "reading"
+// event. It waits |timeoutInMs| before considering that an event has not been
+// delivered.
+async function update_virtual_sensor_until_reading(
+ t, readings, readingPromise, testDriverName, timeoutInMs) {
+ while (true) {
+ await test_driver.update_virtual_sensor(
+ testDriverName, readings.next().value);
+ const value = await Promise.race([
+ new Promise(
+ resolve => {t.step_timeout(() => resolve('TIMEOUT'), timeoutInMs)}),
+ readingPromise,
+ ]);
+ if (value !== 'TIMEOUT') {
+ break;
+ }
+ }
+}
+
+// This could be turned into a t.step_wait() call once
+// https://github.com/web-platform-tests/wpt/pull/34289 is merged.
+async function wait_for_virtual_sensor_state(testDriverName, predicate) {
+ const result =
+ await test_driver.get_virtual_sensor_information(testDriverName);
+ if (!predicate(result)) {
+ await wait_for_virtual_sensor_state(testDriverName, predicate);
+ }
+}
+
+function validate_sensor_data(sensorData) {
+ if (!('sensorName' in sensorData)) {
+ throw new TypeError('sensorData.sensorName is missing');
+ }
+ if (!('permissionName' in sensorData)) {
+ throw new TypeError('sensorData.permissionName is missing');
+ }
+ if (!('testDriverName' in sensorData)) {
+ throw new TypeError('sensorData.testDriverName is missing');
+ }
+ if (sensorData.featurePolicyNames !== undefined &&
+ !Array.isArray(sensorData.featurePolicyNames)) {
+ throw new TypeError('sensorData.featurePolicyNames must be an array');
+ }
+}
+
+function validate_reading_data(readingData) {
+ if (!Array.isArray(readingData.readings)) {
+ throw new TypeError('readingData.readings must be an array.');
+ }
+ if (!Array.isArray(readingData.expectedReadings)) {
+ throw new TypeError('readingData.expectedReadings must be an array.');
+ }
+ if (readingData.readings.length < readingData.expectedReadings.length) {
+ throw new TypeError(
+ 'readingData.readings\' length must be bigger than ' +
+ 'or equal to readingData.expectedReadings\' length.');
+ }
+ if (readingData.expectedRemappedReadings &&
+ !Array.isArray(readingData.expectedRemappedReadings)) {
+ throw new TypeError(
+ 'readingData.expectedRemappedReadings must be an ' +
+ 'array.');
+ }
+ if (readingData.expectedRemappedReadings &&
+ readingData.expectedReadings.length !=
+ readingData.expectedRemappedReadings.length) {
+ throw new TypeError(
+ 'readingData.expectedReadings and ' +
+ 'readingData.expectedRemappedReadings must have the same ' +
+ 'length.');
+ }
+}
+
+function get_sensor_reading_properties(sensor) {
+ const className = sensor[Symbol.toStringTag];
+ if ([
+ 'Accelerometer', 'GravitySensor', 'Gyroscope',
+ 'LinearAccelerationSensor', 'Magnetometer', 'ProximitySensor'
+ ].includes(className)) {
+ return ['x', 'y', 'z'];
+ } else if (className == 'AmbientLightSensor') {
+ return ['illuminance'];
+ } else if ([
+ 'AbsoluteOrientationSensor', 'RelativeOrientationSensor'
+ ].includes(className)) {
+ return ['quaternion'];
+ } else {
+ throw new TypeError(`Unexpected sensor '${className}'`);
+ }
+}
+
+// Checks that `sensor` and `expectedSensorLike` have the same properties
+// (except for timestamp) and they have the same values.
+//
+// Options allows configuring some aspects of the comparison:
+// - ignoreTimestamps (boolean): If true, `sensor` and `expectedSensorLike`'s
+// "timestamp" attribute will not be compared. If `expectedSensorLike` does
+// not have a "timestamp" attribute, the values will not be compared either.
+// This is particularly useful when comparing sensor objects from different
+// origins (and consequently different time origins).
+function assert_sensor_reading_equals(
+ sensor, expectedSensorLike, options = {}) {
+ for (const prop of get_sensor_reading_properties(sensor)) {
+ assert_true(
+ prop in expectedSensorLike,
+ `expectedSensorLike must have a property called '${prop}'`);
+ if (Array.isArray(sensor[prop]))
+ assert_array_approx_equals(
+ sensor[prop], expectedSensorLike[prop], kEpsilon);
+ else
+ assert_approx_equals(sensor[prop], expectedSensorLike[prop], kEpsilon);
+ }
+ assert_not_equals(sensor.timestamp, null);
+
+ if ('timestamp' in expectedSensorLike && !options.ignoreTimestamps) {
+ assert_equals(
+ sensor.timestamp, expectedSensorLike.timestamp,
+ 'Sensor timestamps must be equal');
+ }
+}
+
+function assert_sensor_reading_is_null(sensor) {
+ for (const prop of get_sensor_reading_properties(sensor)) {
+ assert_equals(sensor[prop], null);
+ }
+ assert_equals(sensor.timestamp, null);
+}
+
+function serialize_sensor_data(sensor) {
+ const sensorData = {};
+ for (const property of get_sensor_reading_properties(sensor)) {
+ sensorData[property] = sensor[property];
+ }
+ sensorData['timestamp'] = sensor.timestamp;
+
+ // Note that this is not serialized by postMessage().
+ sensorData[Symbol.toStringTag] = sensor[Symbol.toStringTag];
+
+ return sensorData;
+}