blob: 1f0deba278ee7ca21d48a8c378e3fedb16184ce0 [file] [log] [blame]
'use strict';
// These tests rely on the User Agent providing an implementation of
// platform sensor backends.
//
// In Chromium-based browsers this implementation is provided by a polyfill
// in order to reduce the amount of test-only code shipped to users. To enable
// these tests the browser must be run with these options:
//
// --enable-blink-features=MojoJS,MojoJSTest
async function loadChromiumResources() {
await import('/resources/chromium/generic_sensor_mocks.js');
}
async function initialize_generic_sensor_tests() {
if (typeof GenericSensorTest === 'undefined') {
const script = document.createElement('script');
script.src = '/resources/test-only-api.js';
script.async = false;
const p = new Promise((resolve, reject) => {
script.onload = () => { resolve(); };
script.onerror = e => { reject(e); };
})
document.head.appendChild(script);
await p;
if (isChromiumBased) {
await loadChromiumResources();
}
}
assert_implements(GenericSensorTest, 'GenericSensorTest is unavailable.');
let sensorTest = new GenericSensorTest();
await sensorTest.initialize();
return sensorTest;
}
function sensor_test(func, name, properties) {
promise_test(async (t) => {
t.add_cleanup(() => {
if (sensorTest)
return sensorTest.reset();
});
let sensorTest = await initialize_generic_sensor_tests();
return func(t, sensorTest.getSensorProvider());
}, name, properties);
}
const MOTION_ROTATION_EPSILON = 1e-8;
function generateMotionData(accelerationX, accelerationY, accelerationZ,
accelerationIncludingGravityX,
accelerationIncludingGravityY,
accelerationIncludingGravityZ,
rotationRateAlpha, rotationRateBeta, rotationRateGamma,
interval = 16) {
const motionData = {accelerationX: accelerationX,
accelerationY: accelerationY,
accelerationZ: accelerationZ,
accelerationIncludingGravityX: accelerationIncludingGravityX,
accelerationIncludingGravityY: accelerationIncludingGravityY,
accelerationIncludingGravityZ: accelerationIncludingGravityZ,
rotationRateAlpha: rotationRateAlpha,
rotationRateBeta: rotationRateBeta,
rotationRateGamma: rotationRateGamma,
interval: interval};
return motionData;
}
function generateOrientationData(alpha, beta, gamma, absolute) {
const orientationData = {alpha: alpha,
beta: beta,
gamma: gamma,
absolute: absolute};
return orientationData;
}
async function setMockSensorDataForType(sensorProvider, sensorType, mockDataArray) {
const createdSensor = await sensorProvider.getCreatedSensor(sensorType);
// We call setSensorReadingAndUpdateSharedBuffer() rather than
// setSensorReading() to accommodate Blink's Device Orientation
// implementation, which uses its own timer to read the sensor's shared
// memory buffer rather than relying on SensorReadingChanged(). This timer
// may fire out of sync with the JS timer in MockSensor.startReading(), so
// the former might read the shared memory buffer before the latter has
// updated |this.buffer_|. We thus immediately update the buffer here
// (without consuming data from the ring buffer).
return createdSensor.setSensorReadingImmediately([mockDataArray]);
}
// Device[Orientation|Motion]EventPump treat NaN as a missing value.
let nullToNan = x => (x === null ? NaN : x);
function setMockMotionData(sensorProvider, motionData) {
const degToRad = Math.PI / 180;
return Promise.all([
setMockSensorDataForType(sensorProvider, "Accelerometer", [
nullToNan(motionData.accelerationIncludingGravityX),
nullToNan(motionData.accelerationIncludingGravityY),
nullToNan(motionData.accelerationIncludingGravityZ),
]),
setMockSensorDataForType(sensorProvider, "LinearAccelerationSensor", [
nullToNan(motionData.accelerationX),
nullToNan(motionData.accelerationY),
nullToNan(motionData.accelerationZ),
]),
setMockSensorDataForType(sensorProvider, "Gyroscope", [
nullToNan(motionData.rotationRateAlpha) * degToRad,
nullToNan(motionData.rotationRateBeta) * degToRad,
nullToNan(motionData.rotationRateGamma) * degToRad,
]),
]);
}
function setMockOrientationData(sensorProvider, orientationData) {
let sensorType = orientationData.absolute
? "AbsoluteOrientationEulerAngles" : "RelativeOrientationEulerAngles";
return setMockSensorDataForType(sensorProvider, sensorType, [
nullToNan(orientationData.beta),
nullToNan(orientationData.gamma),
nullToNan(orientationData.alpha),
]);
}
function assertEventEquals(actualEvent, expectedEvent) {
for (let key1 of Object.keys(Object.getPrototypeOf(expectedEvent))) {
if (typeof expectedEvent[key1] === "object" && expectedEvent[key1] !== null) {
for (let key2 of Object.keys(expectedEvent[key1])) {
assert_equals(actualEvent[key1][key2], expectedEvent[key1][key2],
`$[key1].$[key2]`);
}
} else {
assert_equals(actualEvent[key1], expectedEvent[key1], key1);
}
}
}
function getExpectedOrientationEvent(expectedOrientationData) {
return new DeviceOrientationEvent('deviceorientation', {
alpha: expectedOrientationData.alpha,
beta: expectedOrientationData.beta,
gamma: expectedOrientationData.gamma,
absolute: expectedOrientationData.absolute,
});
}
function getExpectedAbsoluteOrientationEvent(expectedOrientationData) {
return new DeviceOrientationEvent('deviceorientationabsolute', {
alpha: expectedOrientationData.alpha,
beta: expectedOrientationData.beta,
gamma: expectedOrientationData.gamma,
absolute: expectedOrientationData.absolute,
});
}
function getExpectedMotionEvent(expectedMotionData) {
return new DeviceMotionEvent('devicemotion', {
acceleration: {
x: expectedMotionData.accelerationX,
y: expectedMotionData.accelerationY,
z: expectedMotionData.accelerationZ,
},
accelerationIncludingGravity: {
x: expectedMotionData.accelerationIncludingGravityX,
y: expectedMotionData.accelerationIncludingGravityY,
z: expectedMotionData.accelerationIncludingGravityZ,
},
rotationRate: {
alpha: expectedMotionData.rotationRateAlpha,
beta: expectedMotionData.rotationRateBeta,
gamma: expectedMotionData.rotationRateGamma,
},
interval: expectedMotionData.interval,
});
}
function waitForEvent(expected_event) {
return new Promise((resolve, reject) => {
window.addEventListener(expected_event.type, (event) => {
try {
assertEventEquals(event, expected_event);
resolve();
} catch (e) {
reject(e);
}
}, { once: true });
});
}