blob: 6eb0f8d66e8c09e3524722177911fe55abb161f9 [file] [log] [blame]
'use strict';
function sensor_mocks(mojo) {
return define('Generic Sensor API mocks', [
'mojo/public/js/core',
'mojo/public/js/bindings',
'mojo/public/js/connection',
'device/generic_sensor/public/interfaces/sensor_provider.mojom',
'device/generic_sensor/public/interfaces/sensor.mojom',
], (core, bindings, connection, sensor_provider, sensor) => {
// Helper function that returns resolved promise with result.
function sensorResponse(success) {
return Promise.resolve({success});
}
// Class that mocks Sensor interface defined in sensor.mojom
class MockSensor {
constructor(stub, handle, offset, size, reportingMode) {
this.client_ = null;
this.stub_ = stub;
this.start_should_fail_ = false;
this.reporting_mode_ = reportingMode;
this.sensor_reading_timer_id_ = null;
this.update_reading_function_ = null;
this.suspend_called_ = null;
this.resume_called_ = null;
this.add_configuration_called_ = null;
this.remove_configuration_called_ = null;
this.active_sensor_configurations_ = [];
let rv = core.mapBuffer(handle, offset, size,
core.MAP_BUFFER_FLAG_NONE);
assert_equals(rv.result, core.RESULT_OK, "Failed to map shared buffer");
this.buffer_array_ = rv.buffer;
this.buffer_ = new Float64Array(this.buffer_array_);
bindings.StubBindings(this.stub_).delegate = this;
bindings.StubBindings(this.stub_).connectionErrorHandler = () => {
reset();
};
}
// Returns default configuration.
getDefaultConfiguration() {
return Promise.resolve({frequency: 5});
}
// Adds configuration for the sensor and starts reporting fake data
// through update_reading_function_ callback.
addConfiguration(configuration) {
assert_not_equals(configuration, null, "Invalid sensor configuration.");
if (this.add_configuration_called_ != null) {
this.add_configuration_called_(this);
}
if (!this.start_should_fail_ && this.update_reading_function_ != null) {
let timeout = (1 / configuration.frequency) * 1000;
this.sensor_reading_timer_id_ = window.setTimeout(() => {
this.update_reading_function_(this.buffer_);
if (this.reporting_mode_ === sensor.ReportingMode.ON_CHANGE) {
this.client_.sensorReadingChanged();
}
}, timeout);
this.active_sensor_configurations_.push(configuration);
}
return sensorResponse(!this.start_should_fail_);
}
// Removes sensor configuration from the list of active configurations and
// stops notification about sensor reading changes if
// active_sensor_configurations_ is empty.
removeConfiguration(configuration) {
if (this.remove_configuration_called_ != null) {
this.remove_configuration_called_(this);
}
let index = this.active_sensor_configurations_.indexOf(configuration);
if (index !== -1) {
this.active_sensor_configurations_.splice(index, 1);
} else {
return sensorResponse(false);
}
if (this.sensor_reading_timer_id_ != null
&& this.active_sensor_configurations_.length === 0) {
window.clearTimeout(this.sensor_reading_timer_id_);
this.sensor_reading_timer_id_ = null;
}
return sensorResponse(true);
}
// Suspends sensor.
suspend() {
if (this.suspend_called_ != null) {
this.suspend_called_(this);
}
}
// Resumes sensor.
resume() {
if (this.resume_called_ != null) {
this.resume_called_(this);
}
}
// Mock functions
// Resets mock Sensor state.
reset() {
if (this.sensor_reading_timer_id_) {
window.clearTimeout(this.sensor_reading_timer_id_);
}
this.start_should_fail_ = false;
this.sensor_reading_timer_id_ = null;
this.active_sensor_configurations_ = [];
this.suspend_called_ = null;
this.resume_called_ = null;
this.add_configuration_called_ = null;
this.remove_configuration_called_ = null;
for (let i = 0; i < this.buffer_.length; ++i) {
this.buffer_[i] = 0;
}
}
// Sets callback that is used to deliver sensor reading updates.
setUpdateSensorReadingFunction(update_reading_function) {
this.update_reading_function_ = update_reading_function;
return Promise.resolve(this);
}
// Sets flag that forces sensor to fail when addConfiguration is invoked.
setStartShouldFail(should_fail) {
this.start_should_fail_ = should_fail;
}
// Returns resolved promise if suspend() was called, rejected otherwise.
suspendCalled() {
return new Promise((resolve, reject) => {
this.suspend_called_ = resolve;
});
}
// Returns resolved promise if resume() was called, rejected otherwise.
resumeCalled() {
return new Promise((resolve, reject) => {
this.resume_called_ = resolve;
});
}
// Resolves promise when addConfiguration() is called.
addConfigurationCalled() {
return new Promise((resolve, reject) => {
this.add_configuration_called_ = resolve;
});
}
// Resolves promise when removeConfiguration() is called.
removeConfigurationCalled() {
return new Promise((resolve, reject) => {
this.remove_configuration_called_ = resolve;
});
}
}
// Helper function that returns resolved promise for getSensor() function.
function getSensorResponse(init_params, client_request) {
return Promise.resolve({init_params, client_request});
}
// Class that mocks SensorProvider interface defined in
// sensor_provider.mojom
class MockSensorProvider {
constructor() {
this.reading_size_in_bytes_ =
sensor_provider.SensorInitParams.kReadBufferSize;
this.shared_buffer_size_in_bytes_ = this.reading_size_in_bytes_ *
sensor.SensorType.LAST;
let rv =
core.createSharedBuffer(
this.shared_buffer_size_in_bytes_,
core.CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE);
assert_equals(rv.result, core.RESULT_OK, "Failed to create buffer");
this.shared_buffer_handle_ = rv.handle;
this.active_sensor_ = null;
this.get_sensor_should_fail_ = false;
this.resolve_func_ = null;
this.is_continuous_ = false;
}
// Returns initialized Sensor proxy to the client.
getSensor(type, stub) {
if (this.get_sensor_should_fail_) {
return getSensorResponse(null, null);
}
let offset =
(sensor.SensorType.LAST - type) * this.reading_size_in_bytes_;
let reporting_mode = sensor.ReportingMode.ON_CHANGE;
if (this.is_continuous_) {
reporting_mode = sensor.ReportingMode.CONTINUOUS;
}
if (this.active_sensor_ == null) {
let mockSensor = new MockSensor(stub, this.shared_buffer_handle_,
offset, this.reading_size_in_bytes_, reporting_mode);
this.active_sensor_ = mockSensor;
}
let rv =
core.duplicateBufferHandle(
this.shared_buffer_handle_,
core.DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE);
assert_equals(rv.result, core.RESULT_OK);
let default_config = {frequency: 5};
let init_params =
new sensor_provider.SensorInitParams(
{ memory: rv.handle,
buffer_offset: offset,
mode: reporting_mode,
default_configuration: default_config });
if (this.resolve_func_ !== null) {
this.resolve_func_(this.active_sensor_);
}
var client_handle = connection.bindProxy(proxy => {
this.active_sensor_.client_ = proxy;
}, sensor.SensorClient);
return getSensorResponse(init_params, client_handle);
}
// Binds object to mojo message pipe
bindToPipe(pipe) {
this.stub_ = connection.bindHandleToStub(
pipe, sensor_provider.SensorProvider);
bindings.StubBindings(this.stub_).delegate = this;
}
// Mock functions
// Resets state of mock SensorProvider between test runs.
reset() {
if (this.active_sensor_ != null) {
this.active_sensor_.reset();
}
this.get_sensor_should_fail_ = false;
this.resolve_func_ = null;
}
// Sets flag that forces mock SensorProvider to fail when getSensor() is
// invoked.
setGetSensorShouldFail(should_fail) {
this.get_sensor_should_fail_ = should_fail;
}
// Returns mock sensor that was created in getSensor to the layout test.
getCreatedSensor() {
if (this.active_sensor_ != null) {
return Promise.resolve(this.active_sensor_);
}
return new Promise((resolve, reject) => {
this.resolve_func_ = resolve;
});
}
// Forces sensor to use |reporting_mode| as an update mode.
setContinuousReportingMode(reporting_mode) {
this.is_continuous_ = reporting_mode;
}
}
let mockSensorProvider = new MockSensorProvider;
mojo.frameInterfaces.addInterfaceOverrideForTesting(
sensor_provider.SensorProvider.name,
pipe => {
mockSensorProvider.bindToPipe(pipe);
});
return Promise.resolve({
mockSensorProvider: mockSensorProvider,
});
});
}
function sensor_test(func, name, properties) {
mojo_test(mojo => sensor_mocks(mojo).then(sensor => {
let result = Promise.resolve(func(sensor));
let cleanUp = () => { sensor.mockSensorProvider.reset(); };
return result.then(cleanUp, cleanUp);
}), name, properties);
}