| // Copyright 2020 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 "chromeos/services/libassistant/device_settings_controller.h" |
| |
| #include <memory> |
| #include <utility> |
| |
| #include "base/command_line.h" |
| #include "base/run_loop.h" |
| #include "base/test/task_environment.h" |
| #include "chromeos/assistant/internal/internal_util.h" |
| #include "chromeos/assistant/internal/proto/google3/assistant/api/client_op/device_args.pb.h" |
| #include "chromeos/services/libassistant/public/mojom/device_settings_delegate.mojom.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace chromeos { |
| namespace assistant { |
| |
| bool operator==(const DeviceSetting& left, const DeviceSetting& right) { |
| return (left.is_supported == right.is_supported) && |
| (left.setting_id == right.setting_id); |
| } |
| |
| void PrintTo(const DeviceSetting& settings, std::ostream* out) { |
| *out << "DeviceSettings {" << std::endl; |
| *out << " setting_id: " << settings.setting_id << std::endl; |
| *out << " is_supported: " << settings.is_supported << std::endl; |
| *out << "}"; |
| } |
| |
| } // namespace assistant |
| } // namespace chromeos |
| |
| namespace chromeos { |
| namespace libassistant { |
| |
| namespace { |
| |
| constexpr double kEpsilon = 0.001; |
| |
| using ::assistant::api::client_op::GetDeviceSettingsArgs; |
| using ::assistant::api::client_op::ModifySettingArgs; |
| using chromeos::assistant::DeviceSetting; |
| using Change = ::assistant::api::client_op::ModifySettingArgs::Change; |
| using Unit = ::assistant::api::client_op::ModifySettingArgs::Unit; |
| using ::testing::AnyNumber; |
| using ::testing::DoubleNear; |
| using ::testing::ElementsAre; |
| using ::testing::FloatNear; |
| using ::testing::Return; |
| using ::testing::StrictMock; |
| |
| constexpr char kWiFi[] = "WIFI"; |
| constexpr char kBluetooth[] = "BLUETOOTH"; |
| constexpr char kScreenBrightness[] = "BRIGHTNESS_LEVEL"; |
| constexpr char kDoNotDisturb[] = "DO_NOT_DISTURB"; |
| constexpr char kNightLight[] = "NIGHT_LIGHT_SWITCH"; |
| constexpr char kSwitchAccess[] = "SWITCH_ACCESS"; |
| |
| // Returns the settings that are always supported. |
| const std::vector<std::string> kAlwaysSupportedSettings = { |
| kWiFi, kBluetooth, kScreenBrightness, |
| kDoNotDisturb, kNightLight, kSwitchAccess, |
| }; |
| |
| class DeviceSettingsDelegateMock : public mojom::DeviceSettingsDelegate { |
| public: |
| // mojom::DeviceSettingsDelegate implementation: |
| void GetScreenBrightnessLevel( |
| GetScreenBrightnessLevelCallback callback) override { |
| std::move(callback).Run( |
| mojom::GetBrightnessResult::New(current_brightness_)); |
| } |
| MOCK_METHOD(void, SetBluetoothEnabled, (bool enabled)); |
| MOCK_METHOD(void, SetDoNotDisturbEnabled, (bool enabled)); |
| MOCK_METHOD(void, SetNightLightEnabled, (bool enabled)); |
| MOCK_METHOD(void, SetScreenBrightnessLevel, (double level, bool gradual)); |
| MOCK_METHOD(void, SetSwitchAccessEnabled, (bool enabled)); |
| MOCK_METHOD(void, SetWifiEnabled, (bool enabled)); |
| |
| mojo::PendingRemote<mojom::DeviceSettingsDelegate> |
| BindNewPipeAndPassRemote() { |
| return receiver_.BindNewPipeAndPassRemote(); |
| } |
| |
| void FlushForTesting() { receiver_.FlushForTesting(); } |
| |
| void set_current_brightness(double value) { current_brightness_ = value; } |
| |
| private: |
| mojo::Receiver<DeviceSettingsDelegate> receiver_{this}; |
| double current_brightness_; |
| }; |
| |
| } // namespace |
| |
| class AssistantDeviceSettingsControllerTest : public testing::Test { |
| public: |
| AssistantDeviceSettingsControllerTest() = default; |
| |
| void SetUp() override { |
| controller().Bind(delegate_mock_.BindNewPipeAndPassRemote()); |
| } |
| |
| DeviceSetting GetSupportedDeviceSettings(const std::string& setting_id) { |
| GetDeviceSettingsArgs args; |
| args.add_setting_ids(setting_id); |
| |
| std::vector<DeviceSetting> result = |
| controller().GetSupportedDeviceSettings(args); |
| EXPECT_EQ(result.size(), 1u); |
| return result[0]; |
| } |
| |
| void ModifySetting(const ModifySettingArgs& args) { |
| controller().OnModifyDeviceSetting(args); |
| delegate_mock().FlushForTesting(); |
| // When we're changing the brightness, we first fetch the current value |
| // and then need to run a callback on the main thread. |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| DeviceSettingsController& controller() { return controller_; } |
| |
| DeviceSettingsDelegateMock& delegate_mock() { return delegate_mock_; } |
| |
| private: |
| base::test::SingleThreadTaskEnvironment environment_; |
| DeviceSettingsController controller_; |
| DeviceSettingsDelegateMock delegate_mock_; |
| }; |
| |
| std::ostream& operator<<(std::ostream& stream, const DeviceSetting& value) { |
| stream << "{ " << value.setting_id << ": " << value.is_supported << "}"; |
| return stream; |
| } |
| |
| TEST_F(AssistantDeviceSettingsControllerTest, |
| GetDeviceSettingsShouldReturnFalseForUnknownSetting) { |
| EXPECT_EQ(GetSupportedDeviceSettings("UNKNOWN_SETTING"), |
| DeviceSetting("UNKNOWN_SETTING", false)); |
| } |
| |
| TEST_F(AssistantDeviceSettingsControllerTest, |
| GetDeviceSettingsShouldReturnTrueForKnownSettings) { |
| for (const std::string& setting : kAlwaysSupportedSettings) { |
| EXPECT_EQ(GetSupportedDeviceSettings(setting), DeviceSetting(setting, true)) |
| << "Error for " << setting; |
| } |
| } |
| |
| TEST_F(AssistantDeviceSettingsControllerTest, |
| GetDeviceSettingsShouldMultipleSettingsAtTheSameTime) { |
| GetDeviceSettingsArgs args; |
| args.add_setting_ids("UNKNOWN_SETTING"); |
| args.add_setting_ids(kWiFi); |
| |
| std::vector<DeviceSetting> result = |
| controller().GetSupportedDeviceSettings(args); |
| |
| EXPECT_THAT(controller().GetSupportedDeviceSettings(args), |
| ElementsAre(DeviceSetting("UNKNOWN_SETTING", false), |
| DeviceSetting(kWiFi, true))); |
| } |
| |
| TEST_F(AssistantDeviceSettingsControllerTest, ShouldTurnWifiOnAndOff) { |
| ModifySettingArgs args; |
| args.set_setting_id(kWiFi); |
| |
| args.set_change(Change::ModifySettingArgs_Change_ON); |
| EXPECT_CALL(delegate_mock(), SetWifiEnabled(true)); |
| ModifySetting(args); |
| |
| args.set_change(Change::ModifySettingArgs_Change_OFF); |
| EXPECT_CALL(delegate_mock(), SetWifiEnabled(false)); |
| ModifySetting(args); |
| } |
| |
| TEST_F(AssistantDeviceSettingsControllerTest, ShouldTurnBluetoothOnAndOff) { |
| ModifySettingArgs args; |
| args.set_setting_id(kBluetooth); |
| |
| args.set_change(Change::ModifySettingArgs_Change_ON); |
| EXPECT_CALL(delegate_mock(), SetBluetoothEnabled(true)); |
| ModifySetting(args); |
| |
| args.set_change(Change::ModifySettingArgs_Change_OFF); |
| EXPECT_CALL(delegate_mock(), SetBluetoothEnabled(false)); |
| ModifySetting(args); |
| } |
| |
| TEST_F(AssistantDeviceSettingsControllerTest, ShouldTurnQuietModeOnAndOff) { |
| ModifySettingArgs args; |
| args.set_setting_id(kDoNotDisturb); |
| |
| args.set_change(Change::ModifySettingArgs_Change_ON); |
| EXPECT_CALL(delegate_mock(), SetDoNotDisturbEnabled(true)); |
| ModifySetting(args); |
| |
| args.set_change(Change::ModifySettingArgs_Change_OFF); |
| EXPECT_CALL(delegate_mock(), SetDoNotDisturbEnabled(false)); |
| ModifySetting(args); |
| } |
| |
| TEST_F(AssistantDeviceSettingsControllerTest, ShouldTurnSwitchAccessOnAndOff) { |
| ModifySettingArgs args; |
| args.set_setting_id(kSwitchAccess); |
| |
| args.set_change(Change::ModifySettingArgs_Change_ON); |
| EXPECT_CALL(delegate_mock(), SetSwitchAccessEnabled(true)); |
| ModifySetting(args); |
| |
| args.set_change(Change::ModifySettingArgs_Change_OFF); |
| EXPECT_CALL(delegate_mock(), SetSwitchAccessEnabled(false)); |
| ModifySetting(args); |
| } |
| |
| TEST_F(AssistantDeviceSettingsControllerTest, ShouldTurnNightLightOnAndOff) { |
| ModifySettingArgs args; |
| args.set_setting_id(kNightLight); |
| |
| args.set_change(Change::ModifySettingArgs_Change_ON); |
| EXPECT_CALL(delegate_mock(), SetNightLightEnabled(true)); |
| ModifySetting(args); |
| |
| args.set_change(Change::ModifySettingArgs_Change_OFF); |
| EXPECT_CALL(delegate_mock(), SetNightLightEnabled(false)); |
| ModifySetting(args); |
| } |
| |
| TEST_F(AssistantDeviceSettingsControllerTest, ShouldSetBrightness) { |
| ModifySettingArgs args; |
| args.set_setting_id(kScreenBrightness); |
| args.set_change(Change::ModifySettingArgs_Change_SET); |
| |
| // Set brightness to 20% |
| args.set_numeric_value(0.2); |
| args.set_unit(Unit::ModifySettingArgs_Unit_RANGE); |
| EXPECT_CALL(delegate_mock(), |
| SetScreenBrightnessLevel(DoubleNear(0.2, kEpsilon), |
| /*gradual=*/true)); |
| ModifySetting(args); |
| |
| // Set brightness to 30. |
| // This will be converted to a percentage |
| args.set_numeric_value(30); |
| args.set_unit(Unit::ModifySettingArgs_Unit_STEP); |
| EXPECT_CALL(delegate_mock(), |
| SetScreenBrightnessLevel(DoubleNear(0.3, kEpsilon), |
| /*gradual=*/true)); |
| ModifySetting(args); |
| } |
| |
| TEST_F(AssistantDeviceSettingsControllerTest, |
| ShouldIncreaseAndDecreaseBrightness) { |
| ModifySettingArgs args; |
| args.set_setting_id(kScreenBrightness); |
| |
| // Increase brightness - this will use a default increment of 10% |
| args.set_change(Change::ModifySettingArgs_Change_INCREASE); |
| args.set_unit(Unit::ModifySettingArgs_Unit_UNKNOWN_UNIT); |
| delegate_mock().set_current_brightness(0.2); |
| EXPECT_CALL(delegate_mock(), |
| SetScreenBrightnessLevel(DoubleNear(0.3, kEpsilon), |
| /*gradual=*/true)); |
| ModifySetting(args); |
| |
| // Decrease brightness - this will use a default decrement of 10% |
| args.set_change(Change::ModifySettingArgs_Change_DECREASE); |
| args.set_unit(Unit::ModifySettingArgs_Unit_UNKNOWN_UNIT); |
| delegate_mock().set_current_brightness(0.2); |
| EXPECT_CALL(delegate_mock(), |
| SetScreenBrightnessLevel(DoubleNear(0.1, kEpsilon), |
| /*gradual=*/true)); |
| ModifySetting(args); |
| } |
| |
| } // namespace libassistant |
| } // namespace chromeos |