| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/night_light/night_light_client.h" | 5 #include "chrome/browser/chromeos/night_light/night_light_client.h" |
| 6 | 6 |
| 7 #include "ash/public/interfaces/night_light_controller.mojom.h" | 7 #include "ash/public/interfaces/night_light_controller.mojom.h" |
| 8 #include "base/test/scoped_task_environment.h" | 8 #include "base/test/scoped_task_environment.h" |
| 9 #include "base/time/clock.h" |
| 10 #include "base/time/tick_clock.h" |
| 9 #include "mojo/public/cpp/bindings/binding.h" | 11 #include "mojo/public/cpp/bindings/binding.h" |
| 10 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
| 11 | 13 |
| 12 namespace { | 14 namespace { |
| 13 | 15 |
| 14 using ScheduleType = ash::mojom::NightLightController::ScheduleType; | 16 using ScheduleType = ash::mojom::NightLightController::ScheduleType; |
| 15 | 17 |
| 16 // A fake implementation of NightLightController for testing. | 18 // A fake implementation of NightLightController for testing. |
| 17 class FakeNightLightController : public ash::mojom::NightLightController { | 19 class FakeNightLightController : public ash::mojom::NightLightController { |
| 18 public: | 20 public: |
| 19 FakeNightLightController() : binding_(this) {} | 21 FakeNightLightController() : binding_(this) {} |
| 20 ~FakeNightLightController() override = default; | 22 ~FakeNightLightController() override = default; |
| 21 | 23 |
| 24 const ash::mojom::SimpleGeopositionPtr& position() const { return position_; } |
| 25 |
| 22 int position_pushes_num() const { return position_pushes_num_; } | 26 int position_pushes_num() const { return position_pushes_num_; } |
| 23 | 27 |
| 24 ash::mojom::NightLightControllerPtr CreateInterfacePtrAndBind() { | 28 ash::mojom::NightLightControllerPtr CreateInterfacePtrAndBind() { |
| 25 ash::mojom::NightLightControllerPtr ptr; | 29 ash::mojom::NightLightControllerPtr ptr; |
| 26 binding_.Bind(mojo::MakeRequest(&ptr)); | 30 binding_.Bind(mojo::MakeRequest(&ptr)); |
| 27 return ptr; | 31 return ptr; |
| 28 } | 32 } |
| 29 | 33 |
| 30 // ash::mojom::NightLightController: | 34 // ash::mojom::NightLightController: |
| 31 void SetCurrentGeoposition( | 35 void SetCurrentGeoposition( |
| (...skipping 17 matching lines...) Expand all Loading... |
| 49 mojo::Binding<ash::mojom::NightLightController> binding_; | 53 mojo::Binding<ash::mojom::NightLightController> binding_; |
| 50 | 54 |
| 51 // The number of times a new position is pushed to this controller. | 55 // The number of times a new position is pushed to this controller. |
| 52 int position_pushes_num_ = 0; | 56 int position_pushes_num_ = 0; |
| 53 | 57 |
| 54 DISALLOW_COPY_AND_ASSIGN(FakeNightLightController); | 58 DISALLOW_COPY_AND_ASSIGN(FakeNightLightController); |
| 55 }; | 59 }; |
| 56 | 60 |
| 57 // A fake implementation of NightLightClient that doesn't perform any actual | 61 // A fake implementation of NightLightClient that doesn't perform any actual |
| 58 // geoposition requests. | 62 // geoposition requests. |
| 59 class FakeNightLightClient : public NightLightClient { | 63 class FakeNightLightClient : public NightLightClient, |
| 64 public base::Clock, |
| 65 public base::TickClock { |
| 60 public: | 66 public: |
| 61 FakeNightLightClient() : NightLightClient(nullptr /* url_context_getter */) {} | 67 FakeNightLightClient() |
| 68 : NightLightClient(nullptr /* url_context_getter */, |
| 69 this /* tick_clock */, |
| 70 this /* clock */) {} |
| 62 ~FakeNightLightClient() override = default; | 71 ~FakeNightLightClient() override = default; |
| 63 | 72 |
| 73 // base::Clock: |
| 74 base::Time Now() override { return fake_now_; } |
| 75 |
| 76 // base::TickClock: |
| 77 base::TimeTicks NowTicks() override { return fake_now_ticks_; } |
| 78 |
| 79 void set_fake_now(base::Time now) { fake_now_ = now; } |
| 80 void set_fake_now_ticks(base::TimeTicks now_ticks) { |
| 81 fake_now_ticks_ = now_ticks; |
| 82 } |
| 83 |
| 64 void set_position_to_send(const chromeos::Geoposition& position) { | 84 void set_position_to_send(const chromeos::Geoposition& position) { |
| 65 position_to_send_ = position; | 85 position_to_send_ = position; |
| 66 } | 86 } |
| 67 | 87 |
| 88 int geoposition_requests_num() const { return geoposition_requests_num_; } |
| 89 |
| 68 private: | 90 private: |
| 69 // night_light::NightLightClient: | 91 // night_light::NightLightClient: |
| 70 void RequestGeoposition() override { | 92 void RequestGeoposition() override { |
| 71 OnGeoposition(position_to_send_, false, base::TimeDelta()); | 93 OnGeoposition(position_to_send_, false, base::TimeDelta()); |
| 94 ++geoposition_requests_num_; |
| 72 } | 95 } |
| 73 | 96 |
| 97 base::Time fake_now_; |
| 98 base::TimeTicks fake_now_ticks_; |
| 99 |
| 74 // The position to send to the controller the next time OnGeoposition is | 100 // The position to send to the controller the next time OnGeoposition is |
| 75 // invoked. | 101 // invoked. |
| 76 chromeos::Geoposition position_to_send_; | 102 chromeos::Geoposition position_to_send_; |
| 77 | 103 |
| 104 // The number of new geoposition requests that have been triggered. |
| 105 int geoposition_requests_num_ = 0; |
| 106 |
| 78 DISALLOW_COPY_AND_ASSIGN(FakeNightLightClient); | 107 DISALLOW_COPY_AND_ASSIGN(FakeNightLightClient); |
| 79 }; | 108 }; |
| 80 | 109 |
| 81 // Base test fixture. | 110 // Base test fixture. |
| 82 class NightLightClientTest : public testing::Test { | 111 class NightLightClientTest : public testing::Test { |
| 83 public: | 112 public: |
| 84 NightLightClientTest() = default; | 113 NightLightClientTest() = default; |
| 85 ~NightLightClientTest() override = default; | 114 ~NightLightClientTest() override = default; |
| 86 | 115 |
| 87 void SetUp() override { | 116 void SetUp() override { |
| 117 // Deterministic fake time that doesn't change for the sake of testing. |
| 118 client_.set_fake_now(base::Time::Now()); |
| 119 client_.set_fake_now_ticks(base::TimeTicks::Now()); |
| 120 |
| 88 client_.SetNightLightControllerPtrForTesting( | 121 client_.SetNightLightControllerPtrForTesting( |
| 89 controller_.CreateInterfacePtrAndBind()); | 122 controller_.CreateInterfacePtrAndBind()); |
| 90 client_.Start(); | 123 client_.Start(); |
| 91 client_.FlushNightLightControllerForTesting(); | 124 client_.FlushNightLightControllerForTesting(); |
| 92 } | 125 } |
| 93 | 126 |
| 94 base::test::ScopedTaskEnvironment scoped_task_environment_; | 127 base::test::ScopedTaskEnvironment scoped_task_environment_; |
| 95 | 128 |
| 96 FakeNightLightController controller_; | 129 FakeNightLightController controller_; |
| 97 FakeNightLightClient client_; | 130 FakeNightLightClient client_; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 112 client_.FlushNightLightControllerForTesting(); | 145 client_.FlushNightLightControllerForTesting(); |
| 113 EXPECT_TRUE(client_.using_geoposition()); | 146 EXPECT_TRUE(client_.using_geoposition()); |
| 114 | 147 |
| 115 // Client should stop retrieving geopositions when schedule type changes to | 148 // Client should stop retrieving geopositions when schedule type changes to |
| 116 // something else. | 149 // something else. |
| 117 controller_.NotifyScheduleTypeChanged(ScheduleType::kNone); | 150 controller_.NotifyScheduleTypeChanged(ScheduleType::kNone); |
| 118 EXPECT_FALSE(client_.using_geoposition()); | 151 EXPECT_FALSE(client_.using_geoposition()); |
| 119 } | 152 } |
| 120 | 153 |
| 121 // Test that client only pushes valid positions. | 154 // Test that client only pushes valid positions. |
| 122 TEST_F(NightLightClientTest, TestPositionPushes) { | 155 TEST_F(NightLightClientTest, TestInvalidPositions) { |
| 123 // Start with a valid position, and expect it to be delivered to the | |
| 124 // controller. | |
| 125 EXPECT_EQ(0, controller_.position_pushes_num()); | 156 EXPECT_EQ(0, controller_.position_pushes_num()); |
| 126 chromeos::Geoposition position; | 157 chromeos::Geoposition position; |
| 127 position.latitude = 32.0; | 158 position.latitude = 32.0; |
| 128 position.longitude = 31.0; | 159 position.longitude = 31.0; |
| 129 position.status = chromeos::Geoposition::STATUS_OK; | 160 position.status = chromeos::Geoposition::STATUS_TIMEOUT; |
| 130 position.accuracy = 10; | 161 position.accuracy = 10; |
| 131 position.timestamp = base::Time::Now(); | 162 position.timestamp = base::Time::Now(); |
| 132 client_.set_position_to_send(position); | 163 client_.set_position_to_send(position); |
| 133 controller_.NotifyScheduleTypeChanged(ScheduleType::kSunsetToSunrise); | 164 controller_.NotifyScheduleTypeChanged(ScheduleType::kSunsetToSunrise); |
| 134 scoped_task_environment_.RunUntilIdle(); | 165 scoped_task_environment_.RunUntilIdle(); |
| 135 client_.FlushNightLightControllerForTesting(); | 166 client_.FlushNightLightControllerForTesting(); |
| 136 EXPECT_EQ(1, controller_.position_pushes_num()); | 167 EXPECT_EQ(1, client_.geoposition_requests_num()); |
| 168 EXPECT_EQ(0, controller_.position_pushes_num()); |
| 169 } |
| 137 | 170 |
| 138 // Invalid positions should not be sent. | 171 // Test that successive changes of the schedule type to sunset to sunrise do not |
| 139 position.status = chromeos::Geoposition::STATUS_TIMEOUT; | 172 // trigger repeated geoposition requests. |
| 140 client_.set_position_to_send(position); | 173 TEST_F(NightLightClientTest, TestRepeatedScheduleTypeChanges) { |
| 174 // Start with a valid position, and expect it to be delivered to the |
| 175 // controller. |
| 176 EXPECT_EQ(0, controller_.position_pushes_num()); |
| 177 chromeos::Geoposition position1; |
| 178 position1.latitude = 32.0; |
| 179 position1.longitude = 31.0; |
| 180 position1.status = chromeos::Geoposition::STATUS_OK; |
| 181 position1.accuracy = 10; |
| 182 position1.timestamp = base::Time::Now(); |
| 183 client_.set_position_to_send(position1); |
| 141 controller_.NotifyScheduleTypeChanged(ScheduleType::kSunsetToSunrise); | 184 controller_.NotifyScheduleTypeChanged(ScheduleType::kSunsetToSunrise); |
| 142 scoped_task_environment_.RunUntilIdle(); | 185 scoped_task_environment_.RunUntilIdle(); |
| 143 client_.FlushNightLightControllerForTesting(); | 186 client_.FlushNightLightControllerForTesting(); |
| 187 EXPECT_EQ(1, client_.geoposition_requests_num()); |
| 144 EXPECT_EQ(1, controller_.position_pushes_num()); | 188 EXPECT_EQ(1, controller_.position_pushes_num()); |
| 189 EXPECT_EQ(client_.Now(), client_.last_successful_geo_request_time()); |
| 190 |
| 191 // A new different position just for the sake of comparison with position1 to |
| 192 // make sure that no new requests are triggered and the same old position will |
| 193 // be resent to the controller. |
| 194 chromeos::Geoposition position2; |
| 195 position2.latitude = 100.0; |
| 196 position2.longitude = 200.0; |
| 197 position2.status = chromeos::Geoposition::STATUS_OK; |
| 198 position2.accuracy = 10; |
| 199 position2.timestamp = base::Time::Now(); |
| 200 client_.set_position_to_send(position2); |
| 201 controller_.NotifyScheduleTypeChanged(ScheduleType::kSunsetToSunrise); |
| 202 scoped_task_environment_.RunUntilIdle(); |
| 203 client_.FlushNightLightControllerForTesting(); |
| 204 // No new request has been triggered, however the same old valid position was |
| 205 // pushed to the controller. |
| 206 EXPECT_EQ(1, client_.geoposition_requests_num()); |
| 207 EXPECT_EQ(2, controller_.position_pushes_num()); |
| 208 EXPECT_TRUE(ash::mojom::SimpleGeoposition::New(position1.latitude, |
| 209 position1.longitude) |
| 210 .Equals(controller_.position())); |
| 211 |
| 212 // The timer should be running scheduling a next request that is a |
| 213 // kNextRequestDelayAfterSuccess from the last successful request time. |
| 214 EXPECT_TRUE(client_.timer().IsRunning()); |
| 215 base::TimeDelta expected_delay = |
| 216 client_.last_successful_geo_request_time() + |
| 217 NightLightClient::GetNextRequestDelayAfterSuccessForTesting() - |
| 218 client_.Now(); |
| 219 EXPECT_EQ(expected_delay, client_.timer().GetCurrentDelay()); |
| 145 } | 220 } |
| 146 | 221 |
| 147 } // namespace | 222 } // namespace |
| OLD | NEW |