Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2449)

Unified Diff: device/generic_sensor/platform_sensor_and_provider_unittest_win.cc

Issue 2898433002: Revert of Move //device/generic_sensor to be part of the internal implementation of the Device Service. (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: device/generic_sensor/platform_sensor_and_provider_unittest_win.cc
diff --git a/device/generic_sensor/platform_sensor_and_provider_unittest_win.cc b/device/generic_sensor/platform_sensor_and_provider_unittest_win.cc
new file mode 100644
index 0000000000000000000000000000000000000000..fbe917fe68b439ac74b5a8aab3f7751f6668909b
--- /dev/null
+++ b/device/generic_sensor/platform_sensor_and_provider_unittest_win.cc
@@ -0,0 +1,723 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <SensorsApi.h>
+#include <objbase.h>
+#include <propvarutil.h>
+#include <sensors.h>
+
+#include "base/bind.h"
+#include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/win/iunknown_impl.h"
+#include "base/win/scoped_propvariant.h"
+#include "device/generic_sensor/generic_sensor_consts.h"
+#include "device/generic_sensor/platform_sensor_provider_win.h"
+#include "device/generic_sensor/public/interfaces/sensor_provider.mojom.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::IsNull;
+using ::testing::NiceMock;
+using ::testing::NotNull;
+using ::testing::Return;
+using ::testing::WithArgs;
+
+namespace device {
+
+using mojom::SensorType;
+
+template <class Interface>
+class MockCOMInterface : public Interface, public base::win::IUnknownImpl {
+ public:
+ // IUnknown interface
+ ULONG STDMETHODCALLTYPE AddRef() override { return IUnknownImpl::AddRef(); }
+ ULONG STDMETHODCALLTYPE Release() override { return IUnknownImpl::Release(); }
+
+ STDMETHODIMP QueryInterface(REFIID riid, void** ppv) override {
+ if (riid == __uuidof(Interface)) {
+ *ppv = static_cast<Interface*>(this);
+ AddRef();
+ return S_OK;
+ }
+ return IUnknownImpl::QueryInterface(riid, ppv);
+ }
+
+ protected:
+ ~MockCOMInterface() override = default;
+};
+
+// Mock class for ISensorManager COM interface.
+class MockISensorManager : public MockCOMInterface<ISensorManager> {
+ public:
+ // ISensorManager interface
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ GetSensorsByCategory,
+ HRESULT(REFSENSOR_CATEGORY_ID category,
+ ISensorCollection** sensors_found));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ GetSensorsByType,
+ HRESULT(REFSENSOR_TYPE_ID sensor_id,
+ ISensorCollection** sensors_found));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ GetSensorByID,
+ HRESULT(REFSENSOR_ID sensor_id, ISensor** sensor));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ SetEventSink,
+ HRESULT(ISensorManagerEvents* event_sink));
+ MOCK_METHOD3_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ RequestPermissions,
+ HRESULT(HWND parent,
+ ISensorCollection* sensors,
+ BOOL is_modal));
+
+ protected:
+ ~MockISensorManager() override = default;
+};
+
+// Mock class for ISensorCollection COM interface.
+class MockISensorCollection : public MockCOMInterface<ISensorCollection> {
+ public:
+ // ISensorCollection interface
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ GetAt,
+ HRESULT(ULONG index, ISensor** sensor));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ GetCount,
+ HRESULT(ULONG* count));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, Add, HRESULT(ISensor* sensor));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ Remove,
+ HRESULT(ISensor* sensor));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ RemoveByID,
+ HRESULT(REFSENSOR_ID sensor_id));
+ MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, Clear, HRESULT());
+
+ protected:
+ ~MockISensorCollection() override = default;
+};
+
+// Mock class for ISensor COM interface.
+class MockISensor : public MockCOMInterface<ISensor> {
+ public:
+ // ISensor interface
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, GetID, HRESULT(SENSOR_ID* id));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ GetCategory,
+ HRESULT(SENSOR_CATEGORY_ID* category));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ GetType,
+ HRESULT(SENSOR_TYPE_ID* type));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ GetFriendlyName,
+ HRESULT(BSTR* name));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ GetProperty,
+ HRESULT(REFPROPERTYKEY key,
+ PROPVARIANT* property));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ GetProperties,
+ HRESULT(IPortableDeviceKeyCollection* keys,
+ IPortableDeviceValues** properties));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ GetSupportedDataFields,
+ HRESULT(IPortableDeviceKeyCollection** data));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ SetProperties,
+ HRESULT(IPortableDeviceValues* properties,
+ IPortableDeviceValues** results));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ SupportsDataField,
+ HRESULT(REFPROPERTYKEY key,
+ VARIANT_BOOL* is_supported));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ GetState,
+ HRESULT(SensorState* state));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ GetData,
+ HRESULT(ISensorDataReport** data_report));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ SupportsEvent,
+ HRESULT(REFGUID event_guid,
+ VARIANT_BOOL* is_supported));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ GetEventInterest,
+ HRESULT(GUID** values, ULONG* count));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ SetEventInterest,
+ HRESULT(GUID* values, ULONG count));
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ SetEventSink,
+ HRESULT(ISensorEvents* pEvents));
+
+ protected:
+ ~MockISensor() override = default;
+};
+
+// Mock class for ISensorDataReport COM interface.
+class MockISensorDataReport : public MockCOMInterface<ISensorDataReport> {
+ public:
+ // ISensorDataReport interface
+ MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ GetTimestamp,
+ HRESULT(SYSTEMTIME* timestamp));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ GetSensorValue,
+ HRESULT(REFPROPERTYKEY key, PROPVARIANT* value));
+ MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE,
+ GetSensorValues,
+ HRESULT(IPortableDeviceKeyCollection* keys,
+ IPortableDeviceValues** values));
+
+ protected:
+ ~MockISensorDataReport() override = default;
+};
+
+// Class that provides test harness support for generic sensor adaptation for
+// Windows platform. Testing is mainly done by mocking main COM interfaces that
+// are used to communicate with Sensors API.
+// MockISensorManager - mocks ISensorManager and responsible for fetching
+// list of supported sensors.
+// MockISensorCollection - mocks collection of ISensor objects.
+// MockISensor - mocks ISensor intrface.
+// MockISensorDataReport - mocks IDataReport interface that is used to deliver
+// data in OnDataUpdated event.
+class PlatformSensorAndProviderTestWin : public ::testing::Test {
+ public:
+ void SetUp() override {
+ sensor_ = new NiceMock<MockISensor>();
+ sensor_collection_ = new NiceMock<MockISensorCollection>();
+ sensor_manager_ = new NiceMock<MockISensorManager>();
+ base::win::ScopedComPtr<ISensorManager> manager;
+ sensor_manager_->QueryInterface(IID_PPV_ARGS(&manager));
+
+ // Overrides default ISensorManager with mocked interface.
+ PlatformSensorProviderWin::GetInstance()->SetSensorManagerForTesting(
+ manager);
+ }
+
+ void TearDown() override {
+ base::win::ScopedComPtr<ISensorManager> null_manager;
+ PlatformSensorProviderWin::GetInstance()->SetSensorManagerForTesting(
+ null_manager);
+ }
+
+ protected:
+ void SensorCreated(scoped_refptr<PlatformSensor> sensor) {
+ platform_sensor_ = sensor;
+ run_loop_->Quit();
+ }
+
+ // Sensor creation is asynchronous, therefore inner loop is used to wait for
+ // PlatformSensorProvider::CreateSensorCallback completion.
+ scoped_refptr<PlatformSensor> CreateSensor(mojom::SensorType type) {
+ run_loop_ = base::MakeUnique<base::RunLoop>();
+ PlatformSensorProviderWin::GetInstance()->CreateSensor(
+ type, base::Bind(&PlatformSensorAndProviderTestWin::SensorCreated,
+ base::Unretained(this)));
+ run_loop_->Run();
+ scoped_refptr<PlatformSensor> sensor;
+ sensor.swap(platform_sensor_);
+ run_loop_ = nullptr;
+ return sensor;
+ }
+
+ // Listening the sensor is asynchronous, therefore inner loop is used to wait
+ // for SetEventSink to be called.
+ bool StartListening(scoped_refptr<PlatformSensor> sensor,
+ PlatformSensor::Client* client,
+ const PlatformSensorConfiguration& config) {
+ run_loop_ = base::MakeUnique<base::RunLoop>();
+ bool ret = sensor->StartListening(client, config);
+ run_loop_->Run();
+ run_loop_ = nullptr;
+ return ret;
+ }
+
+ void QuitInnerLoop() { run_loop_->Quit(); }
+
+ // Sets sensor with REFSENSOR_TYPE_ID |sensor| to be supported by mocked
+ // ISensorMager and it will be present in ISensorCollection.
+ void SetSupportedSensor(REFSENSOR_TYPE_ID sensor) {
+ // Returns mock ISensorCollection.
+ EXPECT_CALL(*sensor_manager_, GetSensorsByType(sensor, _))
+ .WillOnce(Invoke(
+ [this](REFSENSOR_TYPE_ID type, ISensorCollection** collection) {
+ sensor_collection_->QueryInterface(
+ __uuidof(ISensorCollection),
+ reinterpret_cast<void**>(collection));
+ return S_OK;
+ }));
+
+ // Returns number of ISensor objects in ISensorCollection, at the moment
+ // only one ISensor interface instance is suported.
+ EXPECT_CALL(*sensor_collection_, GetCount(_))
+ .WillOnce(Invoke([](ULONG* count) {
+ *count = 1;
+ return S_OK;
+ }));
+
+ // Returns ISensor interface instance at index 0.
+ EXPECT_CALL(*sensor_collection_, GetAt(0, _))
+ .WillOnce(Invoke([this](ULONG index, ISensor** sensor) {
+ sensor_->QueryInterface(__uuidof(ISensor),
+ reinterpret_cast<void**>(sensor));
+ return S_OK;
+ }));
+
+ // Handles |SetEventSink| call that is used to subscribe to sensor events
+ // through ISensorEvents interface. ISensorEvents is stored and attached to
+ // |sensor_events_| that is used later to generate fake error, state and
+ // data change events.
+ ON_CALL(*sensor_, SetEventSink(NotNull()))
+ .WillByDefault(Invoke([this](ISensorEvents* events) {
+ events->AddRef();
+ sensor_events_.Attach(events);
+ if (this->run_loop_) {
+ message_loop_.task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&PlatformSensorAndProviderTestWin::QuitInnerLoop,
+ base::Unretained(this)));
+ }
+ return S_OK;
+ }));
+
+ // When |SetEventSink| is called with nullptr, it means that client is no
+ // longer interested in sensor events and ISensorEvents can be released.
+ ON_CALL(*sensor_, SetEventSink(IsNull()))
+ .WillByDefault(Invoke([this](ISensorEvents* events) {
+ sensor_events_.Reset();
+ if (this->run_loop_) {
+ message_loop_.task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&PlatformSensorAndProviderTestWin::QuitInnerLoop,
+ base::Unretained(this)));
+ }
+ return S_OK;
+ }));
+ }
+
+ // Sets minimal reporting frequency for the mock sensor.
+ void SetSupportedReportingFrequency(double frequency) {
+ ON_CALL(*sensor_, GetProperty(SENSOR_PROPERTY_MIN_REPORT_INTERVAL, _))
+ .WillByDefault(
+ Invoke([frequency](REFPROPERTYKEY key, PROPVARIANT* pProperty) {
+ pProperty->vt = VT_UI4;
+ pProperty->ulVal =
+ (1 / frequency) * base::Time::kMillisecondsPerSecond;
+ return S_OK;
+ }));
+ }
+
+ // Generates OnLeave event, e.g. when sensor is disconnected.
+ void GenerateLeaveEvent() {
+ if (!sensor_events_)
+ return;
+ sensor_events_->OnLeave(SENSOR_ID());
+ }
+
+ // Generates OnStateChangedLeave event.
+ void GenerateStateChangeEvent(SensorState state) {
+ if (!sensor_events_)
+ return;
+ sensor_events_->OnStateChanged(sensor_.get(), state);
+ }
+
+ struct PropertyKeyCompare {
+ bool operator()(REFPROPERTYKEY a, REFPROPERTYKEY b) const {
+ if (a.fmtid == b.fmtid)
+ return a.pid < b.pid;
+ return false;
+ }
+ };
+
+ using SensorData =
+ std::map<PROPERTYKEY, const PROPVARIANT*, PropertyKeyCompare>;
+
+ // Generates OnDataUpdated event and creates ISensorDataReport with fake
+ // |value| for property with |key|.
+ void GenerateDataUpdatedEvent(const SensorData& values) {
+ if (!sensor_events_)
+ return;
+
+ // MockISensorDataReport implements IUnknown that provides ref counting.
+ // IUnknown::QueryInterface increases refcount if an object implements
+ // requested interface. ScopedComPtr wraps received interface and destructs
+ // it when there are not more references.
+ auto* mock_report = new NiceMock<MockISensorDataReport>();
+ base::win::ScopedComPtr<ISensorDataReport> data_report;
+ mock_report->QueryInterface(IID_PPV_ARGS(&data_report));
+
+ EXPECT_CALL(*mock_report, GetTimestamp(_))
+ .WillOnce(Invoke([](SYSTEMTIME* timestamp) {
+ GetSystemTime(timestamp);
+ return S_OK;
+ }));
+
+ EXPECT_CALL(*mock_report, GetSensorValue(_, _))
+ .WillRepeatedly(WithArgs<0, 1>(
+ Invoke([&values](REFPROPERTYKEY key, PROPVARIANT* variant) {
+ auto it = values.find(key);
+ if (it == values.end())
+ return E_FAIL;
+
+ PropVariantCopy(variant, it->second);
+ return S_OK;
+ })));
+
+ sensor_events_->OnDataUpdated(sensor_.get(), data_report.Get());
+ }
+
+ scoped_refptr<MockISensorManager> sensor_manager_;
+ scoped_refptr<MockISensorCollection> sensor_collection_;
+ scoped_refptr<MockISensor> sensor_;
+ base::win::ScopedComPtr<ISensorEvents> sensor_events_;
+ base::MessageLoop message_loop_;
+ scoped_refptr<PlatformSensor> platform_sensor_;
+ // Inner run loop used to wait for async sensor creation callback.
+ std::unique_ptr<base::RunLoop> run_loop_;
+};
+
+// Mock for PlatformSensor's client interface that is used to deliver
+// error and data changes notifications.
+class MockPlatformSensorClient : public PlatformSensor::Client {
+ public:
+ MockPlatformSensorClient() = default;
+ explicit MockPlatformSensorClient(scoped_refptr<PlatformSensor> sensor)
+ : sensor_(sensor) {
+ if (sensor_)
+ sensor_->AddClient(this);
+
+ ON_CALL(*this, IsNotificationSuspended()).WillByDefault(Return(false));
+ }
+
+ ~MockPlatformSensorClient() override {
+ if (sensor_)
+ sensor_->RemoveClient(this);
+ }
+
+ // PlatformSensor::Client interface.
+ MOCK_METHOD0(OnSensorReadingChanged, void());
+ MOCK_METHOD0(OnSensorError, void());
+ MOCK_METHOD0(IsNotificationSuspended, bool());
+
+ private:
+ scoped_refptr<PlatformSensor> sensor_;
+};
+
+// Tests that PlatformSensorManager returns null sensor when sensor
+// is not implemented.
+TEST_F(PlatformSensorAndProviderTestWin, SensorIsNotImplemented) {
+ EXPECT_CALL(*sensor_manager_, GetSensorsByType(SENSOR_TYPE_PRESSURE, _))
+ .Times(0);
+ EXPECT_FALSE(CreateSensor(SensorType::PRESSURE));
+}
+
+// Tests that PlatformSensorManager returns null sensor when sensor
+// is implemented, but not supported by the hardware.
+TEST_F(PlatformSensorAndProviderTestWin, SensorIsNotSupported) {
+ EXPECT_CALL(*sensor_manager_, GetSensorsByType(SENSOR_TYPE_AMBIENT_LIGHT, _))
+ .WillOnce(Invoke([](REFSENSOR_TYPE_ID, ISensorCollection** result) {
+ *result = nullptr;
+ return E_FAIL;
+ }));
+
+ EXPECT_FALSE(CreateSensor(SensorType::AMBIENT_LIGHT));
+}
+
+// Tests that PlatformSensorManager returns correct sensor when sensor
+// is supported by the hardware.
+TEST_F(PlatformSensorAndProviderTestWin, SensorIsSupported) {
+ SetSupportedSensor(SENSOR_TYPE_AMBIENT_LIGHT);
+ auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
+ EXPECT_TRUE(sensor);
+ EXPECT_EQ(SensorType::AMBIENT_LIGHT, sensor->GetType());
+}
+
+// Tests that PlatformSensor::StartListening fails when provided reporting
+// frequency is above hardware capabilities.
+TEST_F(PlatformSensorAndProviderTestWin, StartFails) {
+ SetSupportedReportingFrequency(1);
+ SetSupportedSensor(SENSOR_TYPE_AMBIENT_LIGHT);
+
+ auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
+ EXPECT_TRUE(sensor);
+
+ auto client = base::MakeUnique<NiceMock<MockPlatformSensorClient>>(sensor);
+ PlatformSensorConfiguration configuration(10);
+ EXPECT_FALSE(sensor->StartListening(client.get(), configuration));
+}
+
+// Tests that PlatformSensor::StartListening succeeds and notification about
+// modified sensor reading is sent to the PlatformSensor::Client interface.
+TEST_F(PlatformSensorAndProviderTestWin, SensorStarted) {
+ SetSupportedReportingFrequency(10);
+ SetSupportedSensor(SENSOR_TYPE_AMBIENT_LIGHT);
+
+ EXPECT_CALL(*sensor_, SetEventSink(NotNull())).Times(1);
+ EXPECT_CALL(*sensor_, SetEventSink(IsNull())).Times(1);
+ EXPECT_CALL(*sensor_, SetProperties(NotNull(), _))
+ .WillRepeatedly(Invoke(
+ [](IPortableDeviceValues* props, IPortableDeviceValues** result) {
+ ULONG value = 0;
+ HRESULT hr = props->GetUnsignedIntegerValue(
+ SENSOR_PROPERTY_CURRENT_REPORT_INTERVAL, &value);
+ EXPECT_TRUE(SUCCEEDED(hr));
+ // 10Hz is 100msec
+ EXPECT_THAT(value, 100);
+ return hr;
+ }));
+
+ auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
+ EXPECT_TRUE(sensor);
+
+ auto client = base::MakeUnique<NiceMock<MockPlatformSensorClient>>(sensor);
+ PlatformSensorConfiguration configuration(10);
+ EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
+
+ EXPECT_CALL(*client, OnSensorReadingChanged()).Times(1);
+ base::win::ScopedPropVariant pvLux;
+ InitPropVariantFromDouble(3.14, pvLux.Receive());
+ GenerateDataUpdatedEvent({{SENSOR_DATA_TYPE_LIGHT_LEVEL_LUX, pvLux.ptr()}});
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(sensor->StopListening(client.get(), configuration));
+}
+
+// Tests that OnSensorError is called when sensor is disconnected.
+TEST_F(PlatformSensorAndProviderTestWin, SensorRemoved) {
+ SetSupportedSensor(SENSOR_TYPE_AMBIENT_LIGHT);
+ auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
+ EXPECT_TRUE(sensor);
+
+ auto client = base::MakeUnique<NiceMock<MockPlatformSensorClient>>(sensor);
+ PlatformSensorConfiguration configuration(10);
+ EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
+ EXPECT_CALL(*client, OnSensorError()).Times(1);
+
+ GenerateLeaveEvent();
+ base::RunLoop().RunUntilIdle();
+}
+
+// Tests that OnSensorError is called when sensor is in an error state.
+TEST_F(PlatformSensorAndProviderTestWin, SensorStateChangedToError) {
+ SetSupportedSensor(SENSOR_TYPE_AMBIENT_LIGHT);
+ auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
+ EXPECT_TRUE(sensor);
+
+ auto client = base::MakeUnique<NiceMock<MockPlatformSensorClient>>(sensor);
+ PlatformSensorConfiguration configuration(10);
+ EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
+ EXPECT_CALL(*client, OnSensorError()).Times(1);
+
+ GenerateStateChangeEvent(SENSOR_STATE_ERROR);
+ base::RunLoop().RunUntilIdle();
+}
+
+// Tests that OnSensorError is not called when sensor is in a ready state.
+TEST_F(PlatformSensorAndProviderTestWin, SensorStateChangedToReady) {
+ SetSupportedSensor(SENSOR_TYPE_AMBIENT_LIGHT);
+ auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
+ EXPECT_TRUE(sensor);
+
+ auto client = base::MakeUnique<NiceMock<MockPlatformSensorClient>>(sensor);
+ PlatformSensorConfiguration configuration(10);
+ EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
+ EXPECT_CALL(*client, OnSensorError()).Times(0);
+
+ GenerateStateChangeEvent(SENSOR_STATE_READY);
+ base::RunLoop().RunUntilIdle();
+}
+
+// Tests that GetMaximumSupportedFrequency provides correct value.
+TEST_F(PlatformSensorAndProviderTestWin, GetMaximumSupportedFrequency) {
+ SetSupportedReportingFrequency(20);
+ SetSupportedSensor(SENSOR_TYPE_AMBIENT_LIGHT);
+ auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
+ EXPECT_TRUE(sensor);
+ EXPECT_THAT(sensor->GetMaximumSupportedFrequency(), 20);
+}
+
+// Tests that GetMaximumSupportedFrequency returns fallback value.
+TEST_F(PlatformSensorAndProviderTestWin, GetMaximumSupportedFrequencyFallback) {
+ SetSupportedReportingFrequency(0);
+ SetSupportedSensor(SENSOR_TYPE_AMBIENT_LIGHT);
+ auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
+ EXPECT_TRUE(sensor);
+ EXPECT_THAT(sensor->GetMaximumSupportedFrequency(), 5);
+}
+
+// Tests that Accelerometer readings are correctly converted.
+TEST_F(PlatformSensorAndProviderTestWin, CheckAccelerometerReadingConversion) {
+ mojo::ScopedSharedBufferHandle handle =
+ PlatformSensorProviderWin::GetInstance()->CloneSharedBufferHandle();
+ mojo::ScopedSharedBufferMapping mapping = handle->MapAtOffset(
+ sizeof(SensorReadingSharedBuffer),
+ SensorReadingSharedBuffer::GetOffset(SensorType::ACCELEROMETER));
+
+ SetSupportedSensor(SENSOR_TYPE_ACCELEROMETER_3D);
+ auto sensor = CreateSensor(SensorType::ACCELEROMETER);
+ EXPECT_TRUE(sensor);
+
+ auto client = base::MakeUnique<NiceMock<MockPlatformSensorClient>>(sensor);
+ PlatformSensorConfiguration configuration(10);
+ EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
+ EXPECT_CALL(*client, OnSensorReadingChanged()).Times(1);
+
+ double x_accel = 0.25;
+ double y_accel = -0.25;
+ double z_accel = -0.5;
+
+ base::win::ScopedPropVariant pvX, pvY, pvZ;
+ InitPropVariantFromDouble(x_accel, pvX.Receive());
+ InitPropVariantFromDouble(y_accel, pvY.Receive());
+ InitPropVariantFromDouble(z_accel, pvZ.Receive());
+
+ GenerateDataUpdatedEvent({{SENSOR_DATA_TYPE_ACCELERATION_X_G, pvX.ptr()},
+ {SENSOR_DATA_TYPE_ACCELERATION_Y_G, pvY.ptr()},
+ {SENSOR_DATA_TYPE_ACCELERATION_Z_G, pvZ.ptr()}});
+
+ base::RunLoop().RunUntilIdle();
+ SensorReadingSharedBuffer* buffer =
+ static_cast<SensorReadingSharedBuffer*>(mapping.get());
+ EXPECT_THAT(buffer->reading.values[0], -x_accel * kMeanGravity);
+ EXPECT_THAT(buffer->reading.values[1], -y_accel * kMeanGravity);
+ EXPECT_THAT(buffer->reading.values[2], -z_accel * kMeanGravity);
+ EXPECT_TRUE(sensor->StopListening(client.get(), configuration));
+}
+
+// Tests that Gyroscope readings are correctly converted.
+TEST_F(PlatformSensorAndProviderTestWin, CheckGyroscopeReadingConversion) {
+ mojo::ScopedSharedBufferHandle handle =
+ PlatformSensorProviderWin::GetInstance()->CloneSharedBufferHandle();
+ mojo::ScopedSharedBufferMapping mapping = handle->MapAtOffset(
+ sizeof(SensorReadingSharedBuffer),
+ SensorReadingSharedBuffer::GetOffset(SensorType::GYROSCOPE));
+
+ SetSupportedSensor(SENSOR_TYPE_GYROMETER_3D);
+ auto sensor = CreateSensor(SensorType::GYROSCOPE);
+ EXPECT_TRUE(sensor);
+
+ auto client = base::MakeUnique<NiceMock<MockPlatformSensorClient>>(sensor);
+ PlatformSensorConfiguration configuration(10);
+ EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
+ EXPECT_CALL(*client, OnSensorReadingChanged()).Times(1);
+
+ double x_ang_accel = 0.0;
+ double y_ang_accel = -1.8;
+ double z_ang_accel = -98.7;
+
+ base::win::ScopedPropVariant pvX, pvY, pvZ;
+ InitPropVariantFromDouble(x_ang_accel, pvX.Receive());
+ InitPropVariantFromDouble(y_ang_accel, pvY.Receive());
+ InitPropVariantFromDouble(z_ang_accel, pvZ.Receive());
+
+ GenerateDataUpdatedEvent(
+ {{SENSOR_DATA_TYPE_ANGULAR_VELOCITY_X_DEGREES_PER_SECOND, pvX.ptr()},
+ {SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Y_DEGREES_PER_SECOND, pvY.ptr()},
+ {SENSOR_DATA_TYPE_ANGULAR_VELOCITY_Z_DEGREES_PER_SECOND, pvZ.ptr()}});
+
+ base::RunLoop().RunUntilIdle();
+ SensorReadingSharedBuffer* buffer =
+ static_cast<SensorReadingSharedBuffer*>(mapping.get());
+ EXPECT_THAT(buffer->reading.values[0], -x_ang_accel * kRadiansInDegrees);
+ EXPECT_THAT(buffer->reading.values[1], -y_ang_accel * kRadiansInDegrees);
+ EXPECT_THAT(buffer->reading.values[2], -z_ang_accel * kRadiansInDegrees);
+ EXPECT_TRUE(sensor->StopListening(client.get(), configuration));
+}
+
+// Tests that Magnetometer readings are correctly converted.
+TEST_F(PlatformSensorAndProviderTestWin, CheckMagnetometerReadingConversion) {
+ mojo::ScopedSharedBufferHandle handle =
+ PlatformSensorProviderWin::GetInstance()->CloneSharedBufferHandle();
+ mojo::ScopedSharedBufferMapping mapping = handle->MapAtOffset(
+ sizeof(SensorReadingSharedBuffer),
+ SensorReadingSharedBuffer::GetOffset(SensorType::MAGNETOMETER));
+
+ SetSupportedSensor(SENSOR_TYPE_COMPASS_3D);
+ auto sensor = CreateSensor(SensorType::MAGNETOMETER);
+ EXPECT_TRUE(sensor);
+
+ auto client = base::MakeUnique<NiceMock<MockPlatformSensorClient>>(sensor);
+ PlatformSensorConfiguration configuration(10);
+ EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
+ EXPECT_CALL(*client, OnSensorReadingChanged()).Times(1);
+
+ double x_magn_field = 112.0;
+ double y_magn_field = -162.0;
+ double z_magn_field = 457.0;
+
+ base::win::ScopedPropVariant pvX, pvY, pvZ;
+ InitPropVariantFromDouble(x_magn_field, pvX.Receive());
+ InitPropVariantFromDouble(y_magn_field, pvY.Receive());
+ InitPropVariantFromDouble(z_magn_field, pvZ.Receive());
+
+ GenerateDataUpdatedEvent(
+ {{SENSOR_DATA_TYPE_MAGNETIC_FIELD_STRENGTH_X_MILLIGAUSS, pvX.ptr()},
+ {SENSOR_DATA_TYPE_MAGNETIC_FIELD_STRENGTH_Y_MILLIGAUSS, pvY.ptr()},
+ {SENSOR_DATA_TYPE_MAGNETIC_FIELD_STRENGTH_Z_MILLIGAUSS, pvZ.ptr()}});
+
+ base::RunLoop().RunUntilIdle();
+ SensorReadingSharedBuffer* buffer =
+ static_cast<SensorReadingSharedBuffer*>(mapping.get());
+ EXPECT_THAT(buffer->reading.values[0],
+ -x_magn_field * kMicroteslaInMilligauss);
+ EXPECT_THAT(buffer->reading.values[1],
+ -y_magn_field * kMicroteslaInMilligauss);
+ EXPECT_THAT(buffer->reading.values[2],
+ -z_magn_field * kMicroteslaInMilligauss);
+ EXPECT_TRUE(sensor->StopListening(client.get(), configuration));
+}
+
+// Tests that AbsoluteOrientation sensor readings are correctly converted.
+TEST_F(PlatformSensorAndProviderTestWin,
+ CheckDeviceOrientationReadingConversion) {
+ mojo::ScopedSharedBufferHandle handle =
+ PlatformSensorProviderWin::GetInstance()->CloneSharedBufferHandle();
+ mojo::ScopedSharedBufferMapping mapping = handle->MapAtOffset(
+ sizeof(SensorReadingSharedBuffer),
+ SensorReadingSharedBuffer::GetOffset(SensorType::ABSOLUTE_ORIENTATION));
+
+ SetSupportedSensor(SENSOR_TYPE_AGGREGATED_DEVICE_ORIENTATION);
+ auto sensor = CreateSensor(SensorType::ABSOLUTE_ORIENTATION);
+ EXPECT_TRUE(sensor);
+
+ auto client = base::MakeUnique<NiceMock<MockPlatformSensorClient>>(sensor);
+ PlatformSensorConfiguration configuration(10);
+ EXPECT_TRUE(StartListening(sensor, client.get(), configuration));
+ EXPECT_CALL(*client, OnSensorReadingChanged()).Times(1);
+
+ double x = -0.5;
+ double y = -0.5;
+ double z = 0.5;
+ double w = 0.5;
+ float quat_elements[4] = {x, y, z, w};
+
+ base::win::ScopedPropVariant pvQuat;
+
+ // The SENSOR_DATA_TYPE_QUATERNION property has [VT_VECTOR | VT_UI1] type.
+ // https://msdn.microsoft.com/en-us/library/windows/hardware/dn265187(v=vs.85).aspx
+ // Helper functions e.g., InitVariantFromDoubleArray cannot be used for its
+ // intialization and the only way to initialize it, is to use
+ // InitPropVariantFromGUIDAsBuffer with quaternion format GUID.
+ InitPropVariantFromGUIDAsBuffer(SENSOR_DATA_TYPE_QUATERNION.fmtid,
+ pvQuat.Receive());
+ memcpy(pvQuat.get().caub.pElems, &quat_elements, sizeof(quat_elements));
+ GenerateDataUpdatedEvent({{SENSOR_DATA_TYPE_QUATERNION, pvQuat.ptr()}});
+
+ base::RunLoop().RunUntilIdle();
+ SensorReadingSharedBuffer* buffer =
+ static_cast<SensorReadingSharedBuffer*>(mapping.get());
+
+ EXPECT_THAT(buffer->reading.values[0], -x);
+ EXPECT_THAT(buffer->reading.values[1], -y);
+ EXPECT_THAT(buffer->reading.values[2], -z);
+ EXPECT_THAT(buffer->reading.values[3], w);
+ EXPECT_TRUE(sensor->StopListening(client.get(), configuration));
+}
+
+} // namespace device
« no previous file with comments | « device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc ('k') | device/generic_sensor/platform_sensor_android.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698