// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/device/generic_sensor/platform_sensor_reader_winrt.h"
#include <objbase.h>
#include "base/notreached.h"
#include "base/numerics/angle_conversions.h"
#include "base/numerics/math_constants.h"
#include "base/run_loop.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/test/bind.h"
#include "base/test/gmock_callback_support.h"
#include "base/test/task_environment.h"
#include "base/win/core_winrt_util.h"
#include "base/win/scoped_com_initializer.h"
#include "services/device/generic_sensor/generic_sensor_consts.h"
#include "services/device/generic_sensor/platform_sensor_reader_win_base.h"
#include "services/device/public/cpp/generic_sensor/platform_sensor_configuration.h"
#include "services/device/public/cpp/generic_sensor/sensor_reading.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/quaternion.h"
#include "ui/gfx/geometry/vector3d_f.h"
namespace device {
static constexpr unsigned long kExpectedMinimumReportInterval = 213;
static constexpr double kExpectedReportFrequencySet = 25.0;
static constexpr unsigned long kExpectedReportIntervalSet = 40;
// Base mock class for the Windows::Devices::Sensors::I*SensorReadings
template <class ISensorReading>
class FakeSensorReadingWinrt
: public Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<
Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>,
ISensorReading> {
public:
FakeSensorReadingWinrt(ABI::Windows::Foundation::DateTime time_stamp)
: time_stamp_(time_stamp) {}
IFACEMETHODIMP get_Timestamp(
ABI::Windows::Foundation::DateTime* time_stamp) override {
*time_stamp = time_stamp_;
return get_timestamp_return_code_;
}
void SetGetTimestampReturnCode(HRESULT return_code) {
get_timestamp_return_code_ = return_code;
}
protected:
ABI::Windows::Foundation::DateTime time_stamp_;
HRESULT get_timestamp_return_code_ = S_OK;
};
class FakeLightSensorReadingWinrt
: public FakeSensorReadingWinrt<
ABI::Windows::Devices::Sensors::ILightSensorReading> {
public:
FakeLightSensorReadingWinrt(ABI::Windows::Foundation::DateTime time_stamp,
float lux)
: FakeSensorReadingWinrt(time_stamp), lux_(lux) {}
~FakeLightSensorReadingWinrt() override = default;
IFACEMETHODIMP get_IlluminanceInLux(float* lux) override {
*lux = lux_;
return get_illuminance_in_lux_return_code_;
}
void SetGetIlluminanceInLuxReturnCode(HRESULT return_code) {
get_illuminance_in_lux_return_code_ = return_code;
}
private:
float lux_;
HRESULT get_illuminance_in_lux_return_code_ = S_OK;
};
class FakeAccelerometerReadingWinrt
: public FakeSensorReadingWinrt<
ABI::Windows::Devices::Sensors::IAccelerometerReading> {
public:
FakeAccelerometerReadingWinrt(ABI::Windows::Foundation::DateTime time_stamp,
double x,
double y,
double z)
: FakeSensorReadingWinrt(time_stamp), x_(x), y_(y), z_(z) {}
~FakeAccelerometerReadingWinrt() override = default;
IFACEMETHODIMP get_AccelerationX(double* x) override {
*x = x_;
return get_x_return_code_;
}
IFACEMETHODIMP get_AccelerationY(double* y) override {
*y = y_;
return get_y_return_code_;
}
IFACEMETHODIMP get_AccelerationZ(double* z) override {
*z = z_;
return get_z_return_code_;
}
void SetGetXReturnCode(HRESULT return_code) {
get_x_return_code_ = return_code;
}
void SetGetYReturnCode(HRESULT return_code) {
get_y_return_code_ = return_code;
}
void SetGetZReturnCode(HRESULT return_code) {
get_z_return_code_ = return_code;
}
private:
double x_;
double y_;
double z_;
HRESULT get_x_return_code_ = S_OK;
HRESULT get_y_return_code_ = S_OK;
HRESULT get_z_return_code_ = S_OK;
};
class FakeGyrometerReadingWinrt
: public FakeSensorReadingWinrt<
ABI::Windows::Devices::Sensors::IGyrometerReading> {
public:
FakeGyrometerReadingWinrt(ABI::Windows::Foundation::DateTime time_stamp,
double x,
double y,
double z)
: FakeSensorReadingWinrt(time_stamp), x_(x), y_(y), z_(z) {}
~FakeGyrometerReadingWinrt() override = default;
IFACEMETHODIMP get_AngularVelocityX(double* x) override {
*x = x_;
return get_x_return_code_;
}
IFACEMETHODIMP get_AngularVelocityY(double* y) override {
*y = y_;
return get_y_return_code_;
}
IFACEMETHODIMP get_AngularVelocityZ(double* z) override {
*z = z_;
return get_z_return_code_;
}
void SetGetXReturnCode(HRESULT return_code) {
get_x_return_code_ = return_code;
}
void SetGetYReturnCode(HRESULT return_code) {
get_y_return_code_ = return_code;
}
void SetGetZReturnCode(HRESULT return_code) {
get_z_return_code_ = return_code;
}
private:
double x_;
double y_;
double z_;
HRESULT get_x_return_code_ = S_OK;
HRESULT get_y_return_code_ = S_OK;
HRESULT get_z_return_code_ = S_OK;
};
class FakeInclinometerReadingWinrt
: public FakeSensorReadingWinrt<
ABI::Windows::Devices::Sensors::IInclinometerReading> {
public:
FakeInclinometerReadingWinrt(ABI::Windows::Foundation::DateTime time_stamp,
float x,
float y,
float z)
: FakeSensorReadingWinrt(time_stamp), x_(x), y_(y), z_(z) {}
~FakeInclinometerReadingWinrt() override = default;
IFACEMETHODIMP get_PitchDegrees(float* x) override {
*x = x_;
return get_x_return_code_;
}
IFACEMETHODIMP get_RollDegrees(float* y) override {
*y = y_;
return get_y_return_code_;
}
IFACEMETHODIMP get_YawDegrees(float* z) override {
*z = z_;
return get_z_return_code_;
}
void SetGetXReturnCode(HRESULT return_code) {
get_x_return_code_ = return_code;
}
void SetGetYReturnCode(HRESULT return_code) {
get_y_return_code_ = return_code;
}
void SetGetZReturnCode(HRESULT return_code) {
get_z_return_code_ = return_code;
}
private:
float x_;
float y_;
float z_;
HRESULT get_x_return_code_ = S_OK;
HRESULT get_y_return_code_ = S_OK;
HRESULT get_z_return_code_ = S_OK;
};
class FakeMagnetometerReadingWinrt
: public FakeSensorReadingWinrt<
ABI::Windows::Devices::Sensors::IMagnetometerReading> {
public:
FakeMagnetometerReadingWinrt(ABI::Windows::Foundation::DateTime time_stamp,
float x,
float y,
float z)
: FakeSensorReadingWinrt(time_stamp), x_(x), y_(y), z_(z) {}
~FakeMagnetometerReadingWinrt() override = default;
IFACEMETHODIMP get_MagneticFieldX(float* x) override {
*x = x_;
return get_x_return_code_;
}
IFACEMETHODIMP get_MagneticFieldY(float* y) override {
*y = y_;
return get_y_return_code_;
}
IFACEMETHODIMP get_MagneticFieldZ(float* z) override {
*z = z_;
return get_z_return_code_;
}
IFACEMETHODIMP get_DirectionalAccuracy(
ABI::Windows::Devices::Sensors::MagnetometerAccuracy*) override {
return E_NOTIMPL;
}
void SetGetXReturnCode(HRESULT return_code) {
get_x_return_code_ = return_code;
}
void SetGetYReturnCode(HRESULT return_code) {
get_y_return_code_ = return_code;
}
void SetGetZReturnCode(HRESULT return_code) {
get_z_return_code_ = return_code;
}
private:
float x_;
float y_;
float z_;
HRESULT get_x_return_code_ = S_OK;
HRESULT get_y_return_code_ = S_OK;
HRESULT get_z_return_code_ = S_OK;
};
class FakeSensorQuaternion
: public Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<
Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>,
ABI::Windows::Devices::Sensors::ISensorQuaternion> {
public:
FakeSensorQuaternion(float w, float x, float y, float z)
: w_(w), x_(x), y_(y), z_(z) {}
~FakeSensorQuaternion() override = default;
IFACEMETHODIMP get_W(float* w) override {
*w = w_;
return S_OK;
}
IFACEMETHODIMP get_X(float* x) override {
*x = x_;
return S_OK;
}
IFACEMETHODIMP get_Y(float* y) override {
*y = y_;
return S_OK;
}
IFACEMETHODIMP get_Z(float* z) override {
*z = z_;
return S_OK;
}
private:
float w_;
float x_;
float y_;
float z_;
};
class FakeOrientationSensorReadingWinrt
: public FakeSensorReadingWinrt<
ABI::Windows::Devices::Sensors::IOrientationSensorReading> {
public:
FakeOrientationSensorReadingWinrt(
ABI::Windows::Foundation::DateTime time_stamp,
float w,
float x,
float y,
float z)
: FakeSensorReadingWinrt(time_stamp) {
quaternion_ = Microsoft::WRL::Make<FakeSensorQuaternion>(w, x, y, z);
}
~FakeOrientationSensorReadingWinrt() override = default;
IFACEMETHODIMP get_Quaternion(
ABI::Windows::Devices::Sensors::ISensorQuaternion** quaternion) override {
quaternion_.CopyTo(quaternion);
return S_OK;
}
IFACEMETHODIMP get_RotationMatrix(
ABI::Windows::Devices::Sensors::ISensorRotationMatrix** ppMatrix)
override {
return E_NOTIMPL;
}
void SetGetQuaternionReturnCode(HRESULT return_code) {
get_quaternion_return_code_ = return_code;
}
private:
Microsoft::WRL::ComPtr<ABI::Windows::Devices::Sensors::ISensorQuaternion>
quaternion_;
HRESULT get_quaternion_return_code_ = S_OK;
};
// Mock class for Windows::Devices::Sensors::ISensorReadingChangedEventArgs,
// allows reading changed events to return mock sensor readings.
template <class ISensorReading, class ISensorReadingChangedEventArgs>
class FakeSensorReadingChangedEventArgsWinrt
: public Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<
Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>,
ISensorReadingChangedEventArgs> {
public:
FakeSensorReadingChangedEventArgsWinrt(
const Microsoft::WRL::ComPtr<ISensorReading>& reading)
: reading_(reading) {}
~FakeSensorReadingChangedEventArgsWinrt() override = default;
IFACEMETHODIMP get_Reading(ISensorReading** reading) override {
return reading_.CopyTo(reading);
}
private:
Microsoft::WRL::ComPtr<ISensorReading> reading_;
};
// Mock client used to receive sensor data callbacks
class MockClient : public PlatformSensorReaderWinBase::Client {
public:
MOCK_METHOD1(OnReadingUpdated, void(const SensorReading& reading));
MOCK_METHOD0(OnSensorError, void());
protected:
~MockClient() override = default;
};
// Base mock class for Windows.Devices.Sensors.ISensor*, injected into
// PlatformSensorReaderWinrt* to mock out the underlying
// Windows.Devices.Sensors dependency.
template <class ISensor,
class Sensor,
class ISensorReading,
class ISensorReadingChangedEventArgs,
class SensorReadingChangedEventArgs>
class FakeSensorWinrt
: public Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<
Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>,
ISensor> {
public:
~FakeSensorWinrt() override = default;
IFACEMETHODIMP GetCurrentReading(ISensorReading** ppReading) override {
return E_NOTIMPL;
}
IFACEMETHODIMP get_MinimumReportInterval(UINT32* pValue) override {
*pValue = kExpectedMinimumReportInterval;
return get_minimum_report_interval_return_code_;
}
IFACEMETHODIMP get_ReportInterval(UINT32* pValue) override {
return E_NOTIMPL;
}
IFACEMETHODIMP put_ReportInterval(UINT32 value) override {
EXPECT_EQ(value, kExpectedReportIntervalSet);
return put_report_interval_return_code_;
}
IFACEMETHODIMP add_ReadingChanged(
ABI::Windows::Foundation::
ITypedEventHandler<Sensor*, SensorReadingChangedEventArgs*>* pHandler,
EventRegistrationToken* pToken) override {
handler_ = pHandler;
return add_reading_changed_return_code_;
}
IFACEMETHODIMP remove_ReadingChanged(EventRegistrationToken iToken) override {
handler_.Reset();
return remove_reading_changed_return_code_;
}
// Invokes the handler added via add_ReadingChanged() with the reading
// described by |reading|.
//
// The invocation is asynchronous to better simulate real behavior, where
// Windows delivers the reading notifications in a separate MTA thread.
void TriggerFakeSensorReading(
Microsoft::WRL::ComPtr<ISensorReading> reading) {
Microsoft::WRL::ComPtr<ISensorReadingChangedEventArgs> reading_event_args =
Microsoft::WRL::Make<FakeSensorReadingChangedEventArgsWinrt<
ISensorReading, ISensorReadingChangedEventArgs>>(reading);
base::ThreadPool::PostTask(
FROM_HERE, {base::MayBlock()},
base::BindLambdaForTesting(
// Copy |handler_| and |reading_event_args| to ensure they do not
// lose their values when TriggerFakeSensorReading() exits.
[this, handler = handler_, reading_event_args]() {
ASSERT_TRUE(handler);
EXPECT_HRESULT_SUCCEEDED(
handler->Invoke(this, reading_event_args.Get()));
}));
}
// Returns true if any clients are registered for readings via
// add_ReadingChanged(), false otherwise.
bool IsSensorStarted() { return handler_; }
void SetGetMinimumReportIntervalReturnCode(HRESULT return_code) {
get_minimum_report_interval_return_code_ = return_code;
}
void SetPutReportIntervalReturnCode(HRESULT return_code) {
put_report_interval_return_code_ = return_code;
}
void SetAddReadingChangedReturnCode(HRESULT return_code) {
add_reading_changed_return_code_ = return_code;
}
void SetRemoveReadingChangedReturnCode(HRESULT return_code) {
remove_reading_changed_return_code_ = return_code;
}
private:
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::ITypedEventHandler<
Sensor*,
SensorReadingChangedEventArgs*>>
handler_;
HRESULT put_report_interval_return_code_ = S_OK;
HRESULT get_minimum_report_interval_return_code_ = S_OK;
HRESULT add_reading_changed_return_code_ = S_OK;
HRESULT remove_reading_changed_return_code_ = S_OK;
};
class FakeAccelerometerSensorWinrt
: public FakeSensorWinrt<
ABI::Windows::Devices::Sensors::IAccelerometer,
ABI::Windows::Devices::Sensors::Accelerometer,
ABI::Windows::Devices::Sensors::IAccelerometerReading,
ABI::Windows::Devices::Sensors::IAccelerometerReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::
AccelerometerReadingChangedEventArgs> {
public:
FakeAccelerometerSensorWinrt() = default;
~FakeAccelerometerSensorWinrt() override = default;
IFACEMETHODIMP add_Shaken(
ABI::Windows::Foundation::ITypedEventHandler<
ABI::Windows::Devices::Sensors::Accelerometer*,
ABI::Windows::Devices::Sensors::AccelerometerShakenEventArgs*>*,
EventRegistrationToken*) override {
return E_NOTIMPL;
}
IFACEMETHODIMP remove_Shaken(EventRegistrationToken) override {
return E_NOTIMPL;
}
};
template <class ISensorStatics,
class ISensor,
class Sensor,
class ISensorReading,
class ISensorReadingChangedEventArgs,
class SensorReadingChangedEventArgs>
class FakeSensorFactoryWinrt
: public Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags<
Microsoft::WRL::WinRt | Microsoft::WRL::InhibitRoOriginateError>,
ISensorStatics> {
public:
FakeSensorFactoryWinrt() {
fake_sensor_ =
Microsoft::WRL::Make<FakeSensorWinrt<ISensor, Sensor, ISensorReading,
ISensorReadingChangedEventArgs,
SensorReadingChangedEventArgs>>();
}
FakeSensorFactoryWinrt(
Microsoft::WRL::ComPtr<FakeSensorWinrt<ISensor,
Sensor,
ISensorReading,
ISensorReadingChangedEventArgs,
SensorReadingChangedEventArgs>>
fake_sensor)
: fake_sensor_(fake_sensor) {}
~FakeSensorFactoryWinrt() override = default;
IFACEMETHODIMP GetDefault(ISensor** ppResult) override {
if (fake_sensor_ && SUCCEEDED(get_default_return_code_)) {
return fake_sensor_.CopyTo(ppResult);
}
return get_default_return_code_;
}
Microsoft::WRL::ComPtr<FakeSensorWinrt<ISensor,
Sensor,
ISensorReading,
ISensorReadingChangedEventArgs,
SensorReadingChangedEventArgs>>
fake_sensor_;
void SetGetDefaultReturnCode(HRESULT return_code) {
get_default_return_code_ = return_code;
}
private:
HRESULT get_default_return_code_ = S_OK;
};
class PlatformSensorReaderTestWinrt : public testing::Test {
public:
void SetUp() override {
// Ensure each test starts with a fresh task runner.
com_sta_task_runner_ =
base::ThreadPool::CreateCOMSTATaskRunner({base::MayBlock()});
}
// Synchronously creates a new PlatformSensorReaderWinrtBase-derived class on
// |com_sta_task_runner_| and returns it.
//
// This better simulates real behavior, as PlatformSensorProviderWinrt
// creates readers on a COM STA task runner.
template <typename SensorReader,
typename ISensorStatics,
typename... OtherFactoryTypes>
auto CreateAndInitializeSensor(
const Microsoft::WRL::ComPtr<
FakeSensorFactoryWinrt<ISensorStatics, OtherFactoryTypes...>>&
fake_sensor_factory) {
std::unique_ptr<SensorReader, base::OnTaskRunnerDeleter> reader(
nullptr, base::OnTaskRunnerDeleter(com_sta_task_runner_));
base::RunLoop run_loop;
com_sta_task_runner_->PostTaskAndReply(
FROM_HERE, base::BindLambdaForTesting([&]() {
reader.reset(new SensorReader);
reader->InitForTesting(base::BindLambdaForTesting(
[&](ISensorStatics** sensor_factory) -> HRESULT {
return fake_sensor_factory.CopyTo(sensor_factory);
}));
ASSERT_TRUE(reader->Initialize());
}),
run_loop.QuitClosure());
run_loop.Run();
return reader;
}
protected:
scoped_refptr<base::SingleThreadTaskRunner> com_sta_task_runner_;
base::test::TaskEnvironment task_environment_;
base::win::ScopedCOMInitializer scoped_com_initializer_;
};
// Tests that PlatformSensorReaderWinrtBase returns the expected error
// if it could not create the underlying sensor.
TEST_F(PlatformSensorReaderTestWinrt, FailedSensorCreate) {
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::ILightSensorStatics,
ABI::Windows::Devices::Sensors::ILightSensor,
ABI::Windows::Devices::Sensors::LightSensor,
ABI::Windows::Devices::Sensors::ILightSensorReading,
ABI::Windows::Devices::Sensors::ILightSensorReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::LightSensorReadingChangedEventArgs>>();
// Case: sensor was created successfully
auto sensor = std::make_unique<PlatformSensorReaderWinrtLightSensor>();
sensor->InitForTesting(base::BindLambdaForTesting(
[&](ABI::Windows::Devices::Sensors::ILightSensorStatics** sensor_factory)
-> HRESULT { return fake_sensor_factory.CopyTo(sensor_factory); }));
EXPECT_TRUE(sensor->Initialize());
EXPECT_TRUE(sensor->IsUnderlyingWinrtObjectValidForTesting());
// Case: failed to query sensor
fake_sensor_factory->SetGetDefaultReturnCode(E_FAIL);
EXPECT_FALSE(sensor->Initialize());
EXPECT_FALSE(sensor->IsUnderlyingWinrtObjectValidForTesting());
fake_sensor_factory->SetGetDefaultReturnCode(S_OK);
// Case: Sensor does not exist on system
fake_sensor_factory->fake_sensor_ = nullptr;
EXPECT_FALSE(sensor->Initialize());
EXPECT_FALSE(sensor->IsUnderlyingWinrtObjectValidForTesting());
// Case:: failed to activate sensor factory
sensor->InitForTesting(base::BindLambdaForTesting(
[&](ABI::Windows::Devices::Sensors::ILightSensorStatics** sensor_factory)
-> HRESULT { return E_FAIL; }));
EXPECT_FALSE(sensor->Initialize());
EXPECT_FALSE(sensor->IsUnderlyingWinrtObjectValidForTesting());
}
// Tests that PlatformSensorReaderWinrtBase returns the right
// minimum report interval.
TEST_F(PlatformSensorReaderTestWinrt, SensorMinimumReportInterval) {
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::ILightSensorStatics,
ABI::Windows::Devices::Sensors::ILightSensor,
ABI::Windows::Devices::Sensors::LightSensor,
ABI::Windows::Devices::Sensors::ILightSensorReading,
ABI::Windows::Devices::Sensors::ILightSensorReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::LightSensorReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor = CreateAndInitializeSensor<PlatformSensorReaderWinrtLightSensor>(
fake_sensor_factory);
ASSERT_TRUE(sensor);
EXPECT_EQ(sensor->GetMinimalReportingInterval().InMilliseconds(),
kExpectedMinimumReportInterval);
}
// Tests that PlatformSensorReaderWinrtBase returns a 0 report interval
// when it fails to query the sensor.
TEST_F(PlatformSensorReaderTestWinrt, FailedSensorMinimumReportInterval) {
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::ILightSensorStatics,
ABI::Windows::Devices::Sensors::ILightSensor,
ABI::Windows::Devices::Sensors::LightSensor,
ABI::Windows::Devices::Sensors::ILightSensorReading,
ABI::Windows::Devices::Sensors::ILightSensorReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::LightSensorReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
fake_sensor->SetGetMinimumReportIntervalReturnCode(E_FAIL);
auto sensor = CreateAndInitializeSensor<PlatformSensorReaderWinrtLightSensor>(
fake_sensor_factory);
ASSERT_TRUE(sensor);
EXPECT_EQ(sensor->GetMinimalReportingInterval().InMilliseconds(), 0);
}
TEST_F(PlatformSensorReaderTestWinrt, ReadingChangedCallbackAndPostTask) {
// Instead of using PlatformSensorReaderWinrtLightSensor, declare a custom
// implementation that does less and whose sole purpose is to assert that its
// OnReadingChangedCallback() implementation is never called.
struct CustomLightSensor
: public PlatformSensorReaderWinrtBase<
RuntimeClass_Windows_Devices_Sensors_LightSensor,
ABI::Windows::Devices::Sensors::ILightSensorStatics,
ABI::Windows::Devices::Sensors::ILightSensor,
Microsoft::WRL::Implements<
Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>,
ABI::Windows::Foundation::ITypedEventHandler<
ABI::Windows::Devices::Sensors::LightSensor*,
ABI::Windows::Devices::Sensors::
LightSensorReadingChangedEventArgs*>,
Microsoft::WRL::FtmBase>,
ABI::Windows::Devices::Sensors::
ILightSensorReadingChangedEventArgs> {
~CustomLightSensor() override = default;
void OnReadingChangedCallback(
ABI::Windows::Devices::Sensors::ILightSensor*,
ABI::Windows::Devices::Sensors::ILightSensorReadingChangedEventArgs*)
override {
NOTREACHED() << "This function should not have been reached";
}
};
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::ILightSensorStatics,
ABI::Windows::Devices::Sensors::ILightSensor,
ABI::Windows::Devices::Sensors::LightSensor,
ABI::Windows::Devices::Sensors::ILightSensorReading,
ABI::Windows::Devices::Sensors::ILightSensorReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::LightSensorReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
// Instead of using CreateAndInitializeSensor(), for simplicity and for
// better control over |light_sensor|'s lifetime we invert things and create
// the object in the main task runner and invoke StartSensor() from another
// one. The effect on the Reader is the same -- the calls are still made from
// different task runners.
auto light_sensor = std::make_unique<CustomLightSensor>();
light_sensor->InitForTesting(base::BindLambdaForTesting(
[&](ABI::Windows::Devices::Sensors::ILightSensorStatics** sensor_factory)
-> HRESULT { return fake_sensor_factory.CopyTo(sensor_factory); }));
ASSERT_TRUE(light_sensor->Initialize());
base::RunLoop run_loop;
base::ThreadPool::PostTaskAndReply(
FROM_HERE, base::BindLambdaForTesting([&]() {
ASSERT_TRUE(light_sensor->StartSensor(
PlatformSensorConfiguration(kExpectedReportFrequencySet)));
}),
run_loop.QuitClosure());
run_loop.Run();
// The idea here is to rely on the fact that TriggerFakeSensorReading() is
// asynchronous: we call it while it has a valid handler, it schedules a
// task, we destroy the handler object synchronoustly and then it Invoke()s
// the callback, which should never reach
// CustomLightSensor::OnReadingChangedCallback().
Microsoft::WRL::ComPtr<ABI::Windows::Devices::Sensors::ILightSensorReading>
reading = Microsoft::WRL::Make<FakeLightSensorReadingWinrt>(
ABI::Windows::Foundation::DateTime{}, 0.0f);
fake_sensor->TriggerFakeSensorReading(reading);
light_sensor.reset();
task_environment_.RunUntilIdle();
}
// Tests that PlatformSensorReaderWinrtBase converts the timestamp correctly
TEST_F(PlatformSensorReaderTestWinrt, SensorTimestampConversion) {
static constexpr double expectedTimestampDeltaSecs = 19.0;
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::ILightSensorStatics,
ABI::Windows::Devices::Sensors::ILightSensor,
ABI::Windows::Devices::Sensors::LightSensor,
ABI::Windows::Devices::Sensors::ILightSensorReading,
ABI::Windows::Devices::Sensors::ILightSensorReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::LightSensorReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor = CreateAndInitializeSensor<PlatformSensorReaderWinrtLightSensor>(
fake_sensor_factory);
ASSERT_TRUE(sensor);
auto mock_client = std::make_unique<testing::NiceMock<MockClient>>();
sensor->SetClient(mock_client.get());
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
// Trigger a sensor reading at time 0 (epoch), converted timestamp should
// also be 0.
Microsoft::WRL::ComPtr<ABI::Windows::Devices::Sensors::ILightSensorReading>
reading = Microsoft::WRL::Make<FakeLightSensorReadingWinrt>(
ABI::Windows::Foundation::DateTime{}, 0.0f);
{
base::RunLoop run_loop;
EXPECT_CALL(*mock_client, OnReadingUpdated(::testing::_))
.WillOnce(testing::Invoke([&](const SensorReading& reading) {
EXPECT_EQ(reading.als.timestamp, 0.0);
EXPECT_EQ(reading.als.value, 0.0f);
run_loop.Quit();
}));
fake_sensor->TriggerFakeSensorReading(reading);
run_loop.Run();
}
// Verify the reported time stamp has ticked forward
// expectedTimestampDeltaSecs
auto second_timestamp =
base::Seconds(expectedTimestampDeltaSecs).ToWinrtDateTime();
reading =
Microsoft::WRL::Make<FakeLightSensorReadingWinrt>(second_timestamp, 0.0f);
{
base::RunLoop run_loop;
EXPECT_CALL(*mock_client, OnReadingUpdated(::testing::_))
.WillOnce(testing::Invoke([&](const SensorReading& reading) {
EXPECT_EQ(reading.als.timestamp, expectedTimestampDeltaSecs);
EXPECT_EQ(reading.als.value, 0.0f);
run_loop.Quit();
}));
fake_sensor->TriggerFakeSensorReading(reading);
run_loop.Run();
}
}
// Tests that PlatformSensorReaderWinrtBase starts and stops the
// underlying sensor when Start() and Stop() are called.
TEST_F(PlatformSensorReaderTestWinrt, StartStopSensorCallbacks) {
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::ILightSensorStatics,
ABI::Windows::Devices::Sensors::ILightSensor,
ABI::Windows::Devices::Sensors::LightSensor,
ABI::Windows::Devices::Sensors::ILightSensorReading,
ABI::Windows::Devices::Sensors::ILightSensorReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::LightSensorReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor = CreateAndInitializeSensor<PlatformSensorReaderWinrtLightSensor>(
fake_sensor_factory);
ASSERT_TRUE(sensor);
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
EXPECT_TRUE(fake_sensor->IsSensorStarted());
// Calling Start() contiguously should not cause any errors/exceptions
EXPECT_TRUE(sensor->StartSensor(sensor_config));
EXPECT_TRUE(fake_sensor->IsSensorStarted());
sensor->StopSensor();
EXPECT_FALSE(fake_sensor->IsSensorStarted());
// Calling Stop() contiguously should not cause any errors/exceptions
sensor->StopSensor();
EXPECT_FALSE(fake_sensor->IsSensorStarted());
}
// Tests that PlatformSensorReaderWinrtBase stops the underlying sensor
// even if Start() is called without a following Stop() upon destruction.
TEST_F(PlatformSensorReaderTestWinrt, StartWithoutStopSensorCallbacks) {
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::ILightSensorStatics,
ABI::Windows::Devices::Sensors::ILightSensor,
ABI::Windows::Devices::Sensors::LightSensor,
ABI::Windows::Devices::Sensors::ILightSensorReading,
ABI::Windows::Devices::Sensors::ILightSensorReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::LightSensorReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor = CreateAndInitializeSensor<PlatformSensorReaderWinrtLightSensor>(
fake_sensor_factory);
ASSERT_TRUE(sensor);
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
EXPECT_TRUE(fake_sensor->IsSensorStarted());
// *sensor is deleted in |com_sta_task_runner_|, so we need to wait for it to
// happen asynchronously.
sensor.reset();
task_environment_.RunUntilIdle();
EXPECT_FALSE(fake_sensor->IsSensorStarted());
}
// Tests that PlatformSensorReaderWinrtBase::StartSensor() returns false
// when setting the report interval or registering for sensor events fails.
TEST_F(PlatformSensorReaderTestWinrt, FailedSensorStart) {
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::ILightSensorStatics,
ABI::Windows::Devices::Sensors::ILightSensor,
ABI::Windows::Devices::Sensors::LightSensor,
ABI::Windows::Devices::Sensors::ILightSensorReading,
ABI::Windows::Devices::Sensors::ILightSensorReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::LightSensorReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor = CreateAndInitializeSensor<PlatformSensorReaderWinrtLightSensor>(
fake_sensor_factory);
ASSERT_TRUE(sensor);
fake_sensor->SetPutReportIntervalReturnCode(E_FAIL);
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_FALSE(sensor->StartSensor(sensor_config));
fake_sensor->SetPutReportIntervalReturnCode(S_OK);
fake_sensor->SetAddReadingChangedReturnCode(E_FAIL);
EXPECT_FALSE(sensor->StartSensor(sensor_config));
}
// Tests that PlatformSensorReaderWinrtBase::StopSensor() swallows
// unregister sensor change errors.
TEST_F(PlatformSensorReaderTestWinrt, FailedSensorStop) {
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::ILightSensorStatics,
ABI::Windows::Devices::Sensors::ILightSensor,
ABI::Windows::Devices::Sensors::LightSensor,
ABI::Windows::Devices::Sensors::ILightSensorReading,
ABI::Windows::Devices::Sensors::ILightSensorReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::LightSensorReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor = CreateAndInitializeSensor<PlatformSensorReaderWinrtLightSensor>(
fake_sensor_factory);
ASSERT_TRUE(sensor);
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
fake_sensor->SetRemoveReadingChangedReturnCode(E_FAIL);
sensor->StopSensor();
}
// Tests that PlatformSensorReaderWinrtLightSensor does not notify the
// client if an error occurs during sensor sample parsing.
TEST_F(PlatformSensorReaderTestWinrt, FailedLightSensorSampleParse) {
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::ILightSensorStatics,
ABI::Windows::Devices::Sensors::ILightSensor,
ABI::Windows::Devices::Sensors::LightSensor,
ABI::Windows::Devices::Sensors::ILightSensorReading,
ABI::Windows::Devices::Sensors::ILightSensorReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::LightSensorReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor = CreateAndInitializeSensor<PlatformSensorReaderWinrtLightSensor>(
fake_sensor_factory);
ASSERT_TRUE(sensor);
auto mock_client = std::make_unique<testing::NiceMock<MockClient>>();
// This test relies on the NiceMock to work, if the sensor notifies
// the client despite not being able to parse the sensor sample then
// the NiceMock will throw an error as no EXPECT_CALL has been set.
sensor->SetClient(mock_client.get());
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
auto reading = Microsoft::WRL::Make<FakeLightSensorReadingWinrt>(
ABI::Windows::Foundation::DateTime{}, 0.0f);
// We cannot use a base::RunLoop in the checks below because we are expecting
// that MockClient::OnReadingUpdate() does _not_ get called.
reading->SetGetTimestampReturnCode(E_FAIL);
fake_sensor->TriggerFakeSensorReading(reading);
reading->SetGetTimestampReturnCode(S_OK);
reading->SetGetIlluminanceInLuxReturnCode(E_FAIL);
fake_sensor->TriggerFakeSensorReading(reading);
task_environment_.RunUntilIdle();
}
// Tests that PlatformSensorReaderWinrtLightSensor notifies the client
// and gives it the correct sensor data when a new sensor sample arrives.
TEST_F(PlatformSensorReaderTestWinrt, SensorClientNotification) {
static constexpr float expected_lux = 123.0f;
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::ILightSensorStatics,
ABI::Windows::Devices::Sensors::ILightSensor,
ABI::Windows::Devices::Sensors::LightSensor,
ABI::Windows::Devices::Sensors::ILightSensorReading,
ABI::Windows::Devices::Sensors::ILightSensorReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::LightSensorReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor = CreateAndInitializeSensor<PlatformSensorReaderWinrtLightSensor>(
fake_sensor_factory);
ASSERT_TRUE(sensor);
auto mock_client = std::make_unique<testing::NiceMock<MockClient>>();
sensor->SetClient(mock_client.get());
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
auto reading = Microsoft::WRL::Make<FakeLightSensorReadingWinrt>(
ABI::Windows::Foundation::DateTime{}, expected_lux);
{
base::RunLoop run_loop;
EXPECT_CALL(*mock_client, OnReadingUpdated(::testing::_))
.WillOnce(testing::Invoke([&](const SensorReading& reading) {
EXPECT_EQ(expected_lux, reading.als.value);
run_loop.Quit();
}));
fake_sensor->TriggerFakeSensorReading(reading);
run_loop.Run();
}
sensor->StopSensor();
}
// Tests if PlatformSensorReaderWinrtAccelerometer correctly converts sensor
// readings from Windows.Devices.Sensors.Accelerometer.
TEST_F(PlatformSensorReaderTestWinrt, CheckAccelerometerReadingConversion) {
constexpr double expected_x = 0.25;
constexpr double expected_y = -0.25;
constexpr double expected_z = -0.5;
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::IAccelerometerStatics,
ABI::Windows::Devices::Sensors::IAccelerometer,
ABI::Windows::Devices::Sensors::Accelerometer,
ABI::Windows::Devices::Sensors::IAccelerometerReading,
ABI::Windows::Devices::Sensors::IAccelerometerReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::AccelerometerReadingChangedEventArgs>>(
Microsoft::WRL::Make<FakeAccelerometerSensorWinrt>());
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor =
CreateAndInitializeSensor<PlatformSensorReaderWinrtAccelerometer>(
fake_sensor_factory);
ASSERT_TRUE(sensor);
auto mock_client = std::make_unique<testing::NiceMock<MockClient>>();
sensor->SetClient(mock_client.get());
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
auto reading = Microsoft::WRL::Make<FakeAccelerometerReadingWinrt>(
ABI::Windows::Foundation::DateTime{}, expected_x, expected_y, expected_z);
{
base::RunLoop run_loop;
EXPECT_CALL(*mock_client, OnReadingUpdated(::testing::_))
.WillOnce(testing::Invoke([&](const SensorReading& reading) {
EXPECT_EQ(-expected_x * base::kMeanGravityDouble, reading.accel.x);
EXPECT_EQ(-expected_y * base::kMeanGravityDouble, reading.accel.y);
EXPECT_EQ(-expected_z * base::kMeanGravityDouble, reading.accel.z);
run_loop.Quit();
}));
fake_sensor->TriggerFakeSensorReading(reading);
run_loop.Run();
}
sensor->StopSensor();
}
// Tests that PlatformSensorReaderWinrtAccelerometer does not notify the
// client if an error occurs during sensor sample parsing.
TEST_F(PlatformSensorReaderTestWinrt, FailedAccelerometerSampleParse) {
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::IAccelerometerStatics,
ABI::Windows::Devices::Sensors::IAccelerometer,
ABI::Windows::Devices::Sensors::Accelerometer,
ABI::Windows::Devices::Sensors::IAccelerometerReading,
ABI::Windows::Devices::Sensors::IAccelerometerReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::AccelerometerReadingChangedEventArgs>>(
Microsoft::WRL::Make<FakeAccelerometerSensorWinrt>());
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor =
CreateAndInitializeSensor<PlatformSensorReaderWinrtAccelerometer>(
fake_sensor_factory);
ASSERT_TRUE(sensor);
auto mock_client = std::make_unique<testing::NiceMock<MockClient>>();
sensor->SetClient(mock_client.get());
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
auto reading = Microsoft::WRL::Make<FakeAccelerometerReadingWinrt>(
ABI::Windows::Foundation::DateTime{}, 0, 0, 0);
// We cannot use a base::RunLoop in the checks below because we are expecting
// that MockClient::OnReadingUpdate() does _not_ get called.
reading->SetGetTimestampReturnCode(E_FAIL);
fake_sensor->TriggerFakeSensorReading(reading);
reading->SetGetTimestampReturnCode(S_OK);
reading->SetGetXReturnCode(E_FAIL);
fake_sensor->TriggerFakeSensorReading(reading);
reading->SetGetXReturnCode(S_OK);
reading->SetGetYReturnCode(E_FAIL);
fake_sensor->TriggerFakeSensorReading(reading);
reading->SetGetYReturnCode(S_OK);
reading->SetGetZReturnCode(E_FAIL);
fake_sensor->TriggerFakeSensorReading(reading);
task_environment_.RunUntilIdle();
}
// Tests if PlatformSensorReaderWinrtGyrometer correctly converts sensor
// readings from Windows.Devices.Sensors.Gyrometer.
TEST_F(PlatformSensorReaderTestWinrt, CheckGyrometerReadingConversion) {
constexpr double expected_x = 0.0;
constexpr double expected_y = -1.8;
constexpr double expected_z = -98.7;
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::IGyrometerStatics,
ABI::Windows::Devices::Sensors::IGyrometer,
ABI::Windows::Devices::Sensors::Gyrometer,
ABI::Windows::Devices::Sensors::IGyrometerReading,
ABI::Windows::Devices::Sensors::IGyrometerReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::GyrometerReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor = CreateAndInitializeSensor<PlatformSensorReaderWinrtGyrometer>(
fake_sensor_factory);
ASSERT_TRUE(sensor);
auto mock_client = std::make_unique<testing::NiceMock<MockClient>>();
sensor->SetClient(mock_client.get());
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
auto reading = Microsoft::WRL::Make<FakeGyrometerReadingWinrt>(
ABI::Windows::Foundation::DateTime{}, expected_x, expected_y, expected_z);
{
base::RunLoop run_loop;
EXPECT_CALL(*mock_client, OnReadingUpdated(::testing::_))
.WillOnce(testing::Invoke([&](const SensorReading& reading) {
EXPECT_EQ(base::DegToRad(expected_x), reading.gyro.x);
EXPECT_EQ(base::DegToRad(expected_y), reading.gyro.y);
EXPECT_EQ(base::DegToRad(expected_z), reading.gyro.z);
run_loop.Quit();
}));
fake_sensor->TriggerFakeSensorReading(reading);
run_loop.Run();
}
sensor->StopSensor();
}
// Tests that PlatformSensorReaderWinrtGyrometer does not notify the
// client if an error occurs during sensor sample parsing.
TEST_F(PlatformSensorReaderTestWinrt, FailedGyrometerSampleParse) {
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::IGyrometerStatics,
ABI::Windows::Devices::Sensors::IGyrometer,
ABI::Windows::Devices::Sensors::Gyrometer,
ABI::Windows::Devices::Sensors::IGyrometerReading,
ABI::Windows::Devices::Sensors::IGyrometerReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::GyrometerReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor = CreateAndInitializeSensor<PlatformSensorReaderWinrtGyrometer>(
fake_sensor_factory);
ASSERT_TRUE(sensor);
auto mock_client = std::make_unique<testing::NiceMock<MockClient>>();
sensor->SetClient(mock_client.get());
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
auto reading = Microsoft::WRL::Make<FakeGyrometerReadingWinrt>(
ABI::Windows::Foundation::DateTime{}, 0, 0, 0);
// We cannot use a base::RunLoop in the checks below because we are expecting
// that MockClient::OnReadingUpdate() does _not_ get called.
reading->SetGetTimestampReturnCode(E_FAIL);
fake_sensor->TriggerFakeSensorReading(reading);
reading->SetGetTimestampReturnCode(S_OK);
reading->SetGetXReturnCode(E_FAIL);
fake_sensor->TriggerFakeSensorReading(reading);
reading->SetGetXReturnCode(S_OK);
reading->SetGetYReturnCode(E_FAIL);
fake_sensor->TriggerFakeSensorReading(reading);
reading->SetGetYReturnCode(S_OK);
reading->SetGetZReturnCode(E_FAIL);
fake_sensor->TriggerFakeSensorReading(reading);
task_environment_.RunUntilIdle();
}
// Tests if PlatformSensorReaderWinrtMagnetometer correctly converts sensor
// readings from Windows.Sensors.Devices.Magnetometer.
TEST_F(PlatformSensorReaderTestWinrt, CheckMagnetometerReadingConversion) {
constexpr double expected_x = 112.0;
constexpr double expected_y = 112.0;
constexpr double expected_z = 457.0;
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::IMagnetometerStatics,
ABI::Windows::Devices::Sensors::IMagnetometer,
ABI::Windows::Devices::Sensors::Magnetometer,
ABI::Windows::Devices::Sensors::IMagnetometerReading,
ABI::Windows::Devices::Sensors::IMagnetometerReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::MagnetometerReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor =
CreateAndInitializeSensor<PlatformSensorReaderWinrtMagnetometer>(
fake_sensor_factory);
ASSERT_TRUE(sensor);
auto mock_client = std::make_unique<testing::NiceMock<MockClient>>();
sensor->SetClient(mock_client.get());
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
auto reading = Microsoft::WRL::Make<FakeMagnetometerReadingWinrt>(
ABI::Windows::Foundation::DateTime{}, expected_x, expected_y, expected_z);
{
base::RunLoop run_loop;
EXPECT_CALL(*mock_client, OnReadingUpdated(::testing::_))
.WillOnce(testing::Invoke([&](const SensorReading& reading) {
EXPECT_EQ(expected_x, reading.magn.x);
EXPECT_EQ(expected_y, reading.magn.y);
EXPECT_EQ(expected_z, reading.magn.z);
run_loop.Quit();
}));
fake_sensor->TriggerFakeSensorReading(reading);
run_loop.Run();
}
sensor->StopSensor();
}
// Tests that PlatformSensorReaderWinrtMagnetometer does not notify the
// client if an error occurs during sensor sample parsing.
TEST_F(PlatformSensorReaderTestWinrt, FailedMagnetometerSampleParse) {
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::IMagnetometerStatics,
ABI::Windows::Devices::Sensors::IMagnetometer,
ABI::Windows::Devices::Sensors::Magnetometer,
ABI::Windows::Devices::Sensors::IMagnetometerReading,
ABI::Windows::Devices::Sensors::IMagnetometerReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::MagnetometerReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor =
CreateAndInitializeSensor<PlatformSensorReaderWinrtMagnetometer>(
fake_sensor_factory);
ASSERT_TRUE(sensor);
auto mock_client = std::make_unique<testing::NiceMock<MockClient>>();
sensor->SetClient(mock_client.get());
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
auto reading = Microsoft::WRL::Make<FakeMagnetometerReadingWinrt>(
ABI::Windows::Foundation::DateTime{}, 0, 0, 0);
// We cannot use a base::RunLoop in the checks below because we are expecting
// that MockClient::OnReadingUpdate() does _not_ get called.
reading->SetGetTimestampReturnCode(E_FAIL);
fake_sensor->TriggerFakeSensorReading(reading);
reading->SetGetTimestampReturnCode(S_OK);
reading->SetGetXReturnCode(E_FAIL);
fake_sensor->TriggerFakeSensorReading(reading);
reading->SetGetXReturnCode(S_OK);
reading->SetGetYReturnCode(E_FAIL);
fake_sensor->TriggerFakeSensorReading(reading);
reading->SetGetYReturnCode(S_OK);
reading->SetGetZReturnCode(E_FAIL);
fake_sensor->TriggerFakeSensorReading(reading);
task_environment_.RunUntilIdle();
}
// Tests if PlatformSensorReaderWinrtAbsOrientationEulerAngles correctly
// converts sensor readings from Windows.Devices.Sensors.Inclinometer.
TEST_F(PlatformSensorReaderTestWinrt, CheckInclinometerReadingConversion) {
constexpr double expected_x = 10.0;
constexpr double expected_y = 20.0;
constexpr double expected_z = 30.0;
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::IInclinometerStatics,
ABI::Windows::Devices::Sensors::IInclinometer,
ABI::Windows::Devices::Sensors::Inclinometer,
ABI::Windows::Devices::Sensors::IInclinometerReading,
ABI::Windows::Devices::Sensors::IInclinometerReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::InclinometerReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor = CreateAndInitializeSensor<
PlatformSensorReaderWinrtAbsOrientationEulerAngles>(fake_sensor_factory);
ASSERT_TRUE(sensor);
auto mock_client = std::make_unique<testing::NiceMock<MockClient>>();
sensor->SetClient(mock_client.get());
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
auto reading = Microsoft::WRL::Make<FakeInclinometerReadingWinrt>(
ABI::Windows::Foundation::DateTime{}, expected_x, expected_y, expected_z);
{
base::RunLoop run_loop;
EXPECT_CALL(*mock_client, OnReadingUpdated(::testing::_))
.WillOnce(testing::Invoke([&](const SensorReading& reading) {
EXPECT_EQ(expected_x, reading.orientation_euler.x);
EXPECT_EQ(expected_y, reading.orientation_euler.y);
EXPECT_EQ(expected_z, reading.orientation_euler.z);
run_loop.Quit();
}));
fake_sensor->TriggerFakeSensorReading(reading);
run_loop.Run();
}
sensor->StopSensor();
}
// Tests that PlatformSensorReaderWinrtAbsOrientationEulerAngles does not notify
// the client if an error occurs during sensor sample parsing.
TEST_F(PlatformSensorReaderTestWinrt, FailedInclinometerSampleParse) {
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::IInclinometerStatics,
ABI::Windows::Devices::Sensors::IInclinometer,
ABI::Windows::Devices::Sensors::Inclinometer,
ABI::Windows::Devices::Sensors::IInclinometerReading,
ABI::Windows::Devices::Sensors::IInclinometerReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::InclinometerReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor = CreateAndInitializeSensor<
PlatformSensorReaderWinrtAbsOrientationEulerAngles>(fake_sensor_factory);
ASSERT_TRUE(sensor);
auto mock_client = std::make_unique<testing::NiceMock<MockClient>>();
sensor->SetClient(mock_client.get());
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
auto reading = Microsoft::WRL::Make<FakeInclinometerReadingWinrt>(
ABI::Windows::Foundation::DateTime{}, 0, 0, 0);
// We cannot use a base::RunLoop in the checks below because we are expecting
// that MockClient::OnReadingUpdate() does _not_ get called.
reading->SetGetTimestampReturnCode(E_FAIL);
fake_sensor->TriggerFakeSensorReading(reading);
reading->SetGetTimestampReturnCode(S_OK);
reading->SetGetXReturnCode(E_FAIL);
fake_sensor->TriggerFakeSensorReading(reading);
reading->SetGetXReturnCode(S_OK);
reading->SetGetYReturnCode(E_FAIL);
fake_sensor->TriggerFakeSensorReading(reading);
reading->SetGetYReturnCode(S_OK);
reading->SetGetZReturnCode(E_FAIL);
fake_sensor->TriggerFakeSensorReading(reading);
task_environment_.RunUntilIdle();
}
// Tests if PlatformSensorReaderWinrtAbsOrientationQuaternion correctly
// converts sensor readings from Windows.Devices.Sensors.OrientationSensor.
TEST_F(PlatformSensorReaderTestWinrt, CheckOrientationSensorReadingConversion) {
constexpr double expected_w = 11.0;
constexpr double expected_x = 22.0;
constexpr double expected_y = 33.0;
constexpr double expected_z = 44.0;
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::IOrientationSensorStatics,
ABI::Windows::Devices::Sensors::IOrientationSensor,
ABI::Windows::Devices::Sensors::OrientationSensor,
ABI::Windows::Devices::Sensors::IOrientationSensorReading,
ABI::Windows::Devices::Sensors::IOrientationSensorReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::
OrientationSensorReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor = CreateAndInitializeSensor<
PlatformSensorReaderWinrtAbsOrientationQuaternion>(fake_sensor_factory);
ASSERT_TRUE(sensor);
auto mock_client = std::make_unique<testing::NiceMock<MockClient>>();
sensor->SetClient(mock_client.get());
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
auto reading = Microsoft::WRL::Make<FakeOrientationSensorReadingWinrt>(
ABI::Windows::Foundation::DateTime{}, expected_w, expected_x, expected_y,
expected_z);
{
base::RunLoop run_loop;
EXPECT_CALL(*mock_client, OnReadingUpdated(::testing::_))
.WillOnce(testing::Invoke([&](const SensorReading& reading) {
EXPECT_EQ(expected_w, reading.orientation_quat.w);
EXPECT_EQ(expected_x, reading.orientation_quat.x);
EXPECT_EQ(expected_y, reading.orientation_quat.y);
EXPECT_EQ(expected_z, reading.orientation_quat.z);
run_loop.Quit();
}));
fake_sensor->TriggerFakeSensorReading(reading);
run_loop.Run();
}
sensor->StopSensor();
}
// Tests that PlatformSensorReaderWinrtAbsOrientationQuaternion does not notify
// the client if an error occurs during sensor sample parsing.
TEST_F(PlatformSensorReaderTestWinrt, FailedOrientationSampleParse) {
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::IOrientationSensorStatics,
ABI::Windows::Devices::Sensors::IOrientationSensor,
ABI::Windows::Devices::Sensors::OrientationSensor,
ABI::Windows::Devices::Sensors::IOrientationSensorReading,
ABI::Windows::Devices::Sensors::IOrientationSensorReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::
OrientationSensorReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor = CreateAndInitializeSensor<
PlatformSensorReaderWinrtAbsOrientationQuaternion>(fake_sensor_factory);
ASSERT_TRUE(sensor);
auto mock_client = std::make_unique<testing::NiceMock<MockClient>>();
sensor->SetClient(mock_client.get());
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
auto reading = Microsoft::WRL::Make<FakeOrientationSensorReadingWinrt>(
ABI::Windows::Foundation::DateTime{}, 0, 0, 0, 0);
// We cannot use a base::RunLoop in the checks below because we are expecting
// that MockClient::OnReadingUpdate() does _not_ get called.
reading->SetGetTimestampReturnCode(E_FAIL);
fake_sensor->TriggerFakeSensorReading(reading);
reading->SetGetTimestampReturnCode(S_OK);
reading->SetGetQuaternionReturnCode(E_FAIL);
fake_sensor->TriggerFakeSensorReading(reading);
task_environment_.RunUntilIdle();
}
TEST_F(PlatformSensorReaderTestWinrt, LightSensorThresholding) {
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::ILightSensorStatics,
ABI::Windows::Devices::Sensors::ILightSensor,
ABI::Windows::Devices::Sensors::LightSensor,
ABI::Windows::Devices::Sensors::ILightSensorReading,
ABI::Windows::Devices::Sensors::ILightSensorReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::LightSensorReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor = CreateAndInitializeSensor<PlatformSensorReaderWinrtLightSensor>(
fake_sensor_factory);
ASSERT_TRUE(sensor);
auto mock_client = std::make_unique<testing::NiceMock<MockClient>>();
sensor->SetClient(mock_client.get());
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
float last_sent_lux = 1.0f;
auto threshold_helper = [&](bool expect_callback) {
auto reading = Microsoft::WRL::Make<FakeLightSensorReadingWinrt>(
ABI::Windows::Foundation::DateTime{}, last_sent_lux);
if (expect_callback) {
base::RunLoop run_loop;
EXPECT_CALL(*mock_client, OnReadingUpdated(::testing::_))
.WillOnce(base::test::RunClosure(run_loop.QuitClosure()));
fake_sensor->TriggerFakeSensorReading(reading);
run_loop.Run();
} else {
fake_sensor->TriggerFakeSensorReading(reading);
task_environment_.RunUntilIdle();
}
};
// Expect callback, first sample
threshold_helper(true);
// No callback, threshold has not been met
last_sent_lux +=
PlatformSensorReaderWinrtLightSensor::kLuxPercentThreshold * 0.5f;
threshold_helper(false);
// Expect callback, threshold has been met since last reported sample
last_sent_lux +=
PlatformSensorReaderWinrtLightSensor::kLuxPercentThreshold * 0.6f;
threshold_helper(true);
sensor->StopSensor();
}
TEST_F(PlatformSensorReaderTestWinrt, AccelerometerThresholding) {
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::IAccelerometerStatics,
ABI::Windows::Devices::Sensors::IAccelerometer,
ABI::Windows::Devices::Sensors::Accelerometer,
ABI::Windows::Devices::Sensors::IAccelerometerReading,
ABI::Windows::Devices::Sensors::IAccelerometerReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::AccelerometerReadingChangedEventArgs>>(
Microsoft::WRL::Make<FakeAccelerometerSensorWinrt>());
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor =
CreateAndInitializeSensor<PlatformSensorReaderWinrtAccelerometer>(
fake_sensor_factory);
ASSERT_TRUE(sensor);
auto mock_client = std::make_unique<testing::NiceMock<MockClient>>();
sensor->SetClient(mock_client.get());
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
double last_sent_x = 1.0f;
double last_sent_y = 2.0f;
double last_sent_z = 3.0f;
auto threshold_helper = [&](bool expect_callback) {
auto reading = Microsoft::WRL::Make<FakeAccelerometerReadingWinrt>(
ABI::Windows::Foundation::DateTime{}, last_sent_x, last_sent_y,
last_sent_z);
if (expect_callback) {
base::RunLoop run_loop;
EXPECT_CALL(*mock_client, OnReadingUpdated(::testing::_))
.WillOnce(base::test::RunClosure(run_loop.QuitClosure()));
fake_sensor->TriggerFakeSensorReading(reading);
run_loop.Run();
} else {
fake_sensor->TriggerFakeSensorReading(reading);
task_environment_.RunUntilIdle();
}
};
// Expect callback, first sample
threshold_helper(true);
// For each axis, increase its value by an amount lower than the threshold so
// that no callback is invoked, then meet the threshold and do expect a
// callback.
last_sent_x += PlatformSensorReaderWinrtAccelerometer::kAxisThreshold * 0.5f;
threshold_helper(false);
last_sent_x += PlatformSensorReaderWinrtAccelerometer::kAxisThreshold * 0.6f;
threshold_helper(true);
last_sent_y += PlatformSensorReaderWinrtAccelerometer::kAxisThreshold * 0.5f;
threshold_helper(false);
last_sent_y += PlatformSensorReaderWinrtAccelerometer::kAxisThreshold * 0.6f;
threshold_helper(true);
last_sent_z += PlatformSensorReaderWinrtAccelerometer::kAxisThreshold * 0.5f;
threshold_helper(false);
last_sent_z += PlatformSensorReaderWinrtAccelerometer::kAxisThreshold * 0.6f;
threshold_helper(true);
sensor->StopSensor();
}
TEST_F(PlatformSensorReaderTestWinrt, GyrometerThresholding) {
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::IGyrometerStatics,
ABI::Windows::Devices::Sensors::IGyrometer,
ABI::Windows::Devices::Sensors::Gyrometer,
ABI::Windows::Devices::Sensors::IGyrometerReading,
ABI::Windows::Devices::Sensors::IGyrometerReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::GyrometerReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor = CreateAndInitializeSensor<PlatformSensorReaderWinrtGyrometer>(
fake_sensor_factory);
ASSERT_TRUE(sensor);
auto mock_client = std::make_unique<testing::NiceMock<MockClient>>();
sensor->SetClient(mock_client.get());
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
double last_sent_x = 3.0f;
double last_sent_y = 4.0f;
double last_sent_z = 5.0f;
auto threshold_helper = [&](bool expect_callback) {
auto reading = Microsoft::WRL::Make<FakeGyrometerReadingWinrt>(
ABI::Windows::Foundation::DateTime{}, last_sent_x, last_sent_y,
last_sent_z);
if (expect_callback) {
base::RunLoop run_loop;
EXPECT_CALL(*mock_client, OnReadingUpdated(::testing::_))
.WillOnce(base::test::RunClosure(run_loop.QuitClosure()));
fake_sensor->TriggerFakeSensorReading(reading);
run_loop.Run();
} else {
fake_sensor->TriggerFakeSensorReading(reading);
task_environment_.RunUntilIdle();
}
};
// Expect callback, first sample
threshold_helper(true);
// For each axis, increase its value by an amount lower than the threshold so
// that no callback is invoked, then meet the threshold and do expect a
// callback.
last_sent_x += PlatformSensorReaderWinrtGyrometer::kDegreeThreshold * 0.5f;
threshold_helper(false);
last_sent_x += PlatformSensorReaderWinrtGyrometer::kDegreeThreshold * 0.6f;
threshold_helper(true);
last_sent_y += PlatformSensorReaderWinrtGyrometer::kDegreeThreshold * 0.5f;
threshold_helper(false);
last_sent_y += PlatformSensorReaderWinrtGyrometer::kDegreeThreshold * 0.6f;
threshold_helper(true);
last_sent_z += PlatformSensorReaderWinrtGyrometer::kDegreeThreshold * 0.5f;
threshold_helper(false);
last_sent_z += PlatformSensorReaderWinrtGyrometer::kDegreeThreshold * 0.6f;
threshold_helper(true);
sensor->StopSensor();
}
TEST_F(PlatformSensorReaderTestWinrt, MagnetometerThresholding) {
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::IMagnetometerStatics,
ABI::Windows::Devices::Sensors::IMagnetometer,
ABI::Windows::Devices::Sensors::Magnetometer,
ABI::Windows::Devices::Sensors::IMagnetometerReading,
ABI::Windows::Devices::Sensors::IMagnetometerReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::MagnetometerReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor =
CreateAndInitializeSensor<PlatformSensorReaderWinrtMagnetometer>(
fake_sensor_factory);
ASSERT_TRUE(sensor);
auto mock_client = std::make_unique<testing::NiceMock<MockClient>>();
sensor->SetClient(mock_client.get());
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
double last_sent_x = 3.0f;
double last_sent_y = 4.0f;
double last_sent_z = 5.0f;
auto threshold_helper = [&](bool expect_callback) {
auto reading = Microsoft::WRL::Make<FakeMagnetometerReadingWinrt>(
ABI::Windows::Foundation::DateTime{}, last_sent_x, last_sent_y,
last_sent_z);
if (expect_callback) {
base::RunLoop run_loop;
EXPECT_CALL(*mock_client, OnReadingUpdated(::testing::_))
.WillOnce(base::test::RunClosure(run_loop.QuitClosure()));
fake_sensor->TriggerFakeSensorReading(reading);
run_loop.Run();
} else {
fake_sensor->TriggerFakeSensorReading(reading);
task_environment_.RunUntilIdle();
}
};
// Expect callback, first sample
threshold_helper(true);
// For each axis, increase its value by an amount lower than the threshold so
// that no callback is invoked, then meet the threshold and do expect a
// callback.
last_sent_x +=
PlatformSensorReaderWinrtMagnetometer::kMicroteslaThreshold * 0.5f;
threshold_helper(false);
last_sent_x +=
PlatformSensorReaderWinrtMagnetometer::kMicroteslaThreshold * 0.6f;
threshold_helper(true);
last_sent_y +=
PlatformSensorReaderWinrtMagnetometer::kMicroteslaThreshold * 0.5f;
threshold_helper(false);
last_sent_y +=
PlatformSensorReaderWinrtMagnetometer::kMicroteslaThreshold * 0.6f;
threshold_helper(true);
last_sent_z +=
PlatformSensorReaderWinrtMagnetometer::kMicroteslaThreshold * 0.5f;
threshold_helper(false);
last_sent_z +=
PlatformSensorReaderWinrtMagnetometer::kMicroteslaThreshold * 0.6f;
threshold_helper(true);
sensor->StopSensor();
}
TEST_F(PlatformSensorReaderTestWinrt, AbsOrientationEulerThresholding) {
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::IInclinometerStatics,
ABI::Windows::Devices::Sensors::IInclinometer,
ABI::Windows::Devices::Sensors::Inclinometer,
ABI::Windows::Devices::Sensors::IInclinometerReading,
ABI::Windows::Devices::Sensors::IInclinometerReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::InclinometerReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor = CreateAndInitializeSensor<
PlatformSensorReaderWinrtAbsOrientationEulerAngles>(fake_sensor_factory);
ASSERT_TRUE(sensor);
auto mock_client = std::make_unique<testing::NiceMock<MockClient>>();
sensor->SetClient(mock_client.get());
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
double last_sent_x = 3.0f;
double last_sent_y = 4.0f;
double last_sent_z = 5.0f;
auto threshold_helper = [&](bool expect_callback) {
auto reading = Microsoft::WRL::Make<FakeInclinometerReadingWinrt>(
ABI::Windows::Foundation::DateTime{}, last_sent_x, last_sent_y,
last_sent_z);
if (expect_callback) {
base::RunLoop run_loop;
EXPECT_CALL(*mock_client, OnReadingUpdated(::testing::_))
.WillOnce(base::test::RunClosure(run_loop.QuitClosure()));
fake_sensor->TriggerFakeSensorReading(reading);
run_loop.Run();
} else {
fake_sensor->TriggerFakeSensorReading(reading);
task_environment_.RunUntilIdle();
}
};
// Expect callback, first sample
threshold_helper(true);
// For each axis, increase its value by an amount lower than the threshold so
// that no callback is invoked, then meet the threshold and do expect a
// callback.
last_sent_x +=
PlatformSensorReaderWinrtAbsOrientationEulerAngles::kDegreeThreshold *
0.5f;
threshold_helper(false);
last_sent_x +=
PlatformSensorReaderWinrtAbsOrientationEulerAngles::kDegreeThreshold *
0.6f;
threshold_helper(true);
last_sent_y +=
PlatformSensorReaderWinrtAbsOrientationEulerAngles::kDegreeThreshold *
0.5f;
threshold_helper(false);
last_sent_y +=
PlatformSensorReaderWinrtAbsOrientationEulerAngles::kDegreeThreshold *
0.6f;
threshold_helper(true);
last_sent_z +=
PlatformSensorReaderWinrtAbsOrientationEulerAngles::kDegreeThreshold *
0.5f;
threshold_helper(false);
last_sent_z +=
PlatformSensorReaderWinrtAbsOrientationEulerAngles::kDegreeThreshold *
0.6f;
threshold_helper(true);
sensor->StopSensor();
}
TEST_F(PlatformSensorReaderTestWinrt, AbsOrientationQuatThresholding) {
auto fake_sensor_factory = Microsoft::WRL::Make<FakeSensorFactoryWinrt<
ABI::Windows::Devices::Sensors::IOrientationSensorStatics,
ABI::Windows::Devices::Sensors::IOrientationSensor,
ABI::Windows::Devices::Sensors::OrientationSensor,
ABI::Windows::Devices::Sensors::IOrientationSensorReading,
ABI::Windows::Devices::Sensors::IOrientationSensorReadingChangedEventArgs,
ABI::Windows::Devices::Sensors::
OrientationSensorReadingChangedEventArgs>>();
auto fake_sensor = fake_sensor_factory->fake_sensor_;
auto sensor = CreateAndInitializeSensor<
PlatformSensorReaderWinrtAbsOrientationQuaternion>(fake_sensor_factory);
ASSERT_TRUE(sensor);
auto mock_client = std::make_unique<testing::NiceMock<MockClient>>();
sensor->SetClient(mock_client.get());
PlatformSensorConfiguration sensor_config(kExpectedReportFrequencySet);
EXPECT_TRUE(sensor->StartSensor(sensor_config));
double last_sent_rad = 1.0;
auto threshold_helper = [&](bool expect_callback) {
auto quat = gfx::Quaternion(gfx::Vector3dF(1.0, 0, 0), last_sent_rad);
auto reading = Microsoft::WRL::Make<FakeOrientationSensorReadingWinrt>(
ABI::Windows::Foundation::DateTime{}, quat.w(), quat.x(), quat.y(),
quat.z());
if (expect_callback) {
base::RunLoop run_loop;
EXPECT_CALL(*mock_client, OnReadingUpdated(::testing::_))
.WillOnce(base::test::RunClosure(run_loop.QuitClosure()));
fake_sensor->TriggerFakeSensorReading(reading);
run_loop.Run();
} else {
fake_sensor->TriggerFakeSensorReading(reading);
task_environment_.RunUntilIdle();
}
};
// Expect callback, first sample
threshold_helper(true);
// No callback, threshold has not been met
last_sent_rad +=
PlatformSensorReaderWinrtAbsOrientationQuaternion::kRadianThreshold *
0.5f;
threshold_helper(false);
// Expect callback, threshold has been met since last reported sample
last_sent_rad +=
PlatformSensorReaderWinrtAbsOrientationQuaternion::kRadianThreshold *
0.6f;
threshold_helper(true);
sensor->StopSensor();
}
} // namespace device