| 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() : NightLightClient(nullptr /* url_context_getter */) { |
| 68 SetTimerForTesting( |
| 69 base::MakeUnique<base::OneShotTimer>(this /* tick_clock */)); |
| 70 SetClockForTesting(this); |
| 71 } |
| 62 ~FakeNightLightClient() override = default; | 72 ~FakeNightLightClient() override = default; |
| 63 | 73 |
| 74 // base::Clock: |
| 75 base::Time Now() override { return fake_now_; } |
| 76 |
| 77 // base::TickClock: |
| 78 base::TimeTicks NowTicks() override { return fake_now_ticks_; } |
| 79 |
| 80 void set_fake_now(base::Time now) { fake_now_ = now; } |
| 81 void set_fake_now_ticks(base::TimeTicks now_ticks) { |
| 82 fake_now_ticks_ = now_ticks; |
| 83 } |
| 84 |
| 64 void set_position_to_send(const chromeos::Geoposition& position) { | 85 void set_position_to_send(const chromeos::Geoposition& position) { |
| 65 position_to_send_ = position; | 86 position_to_send_ = position; |
| 66 } | 87 } |
| 67 | 88 |
| 89 int geoposition_requests_num() const { return geoposition_requests_num_; } |
| 90 |
| 68 private: | 91 private: |
| 69 // night_light::NightLightClient: | 92 // night_light::NightLightClient: |
| 70 void RequestGeoposition() override { | 93 void RequestGeoposition() override { |
| 71 OnGeoposition(position_to_send_, false, base::TimeDelta()); | 94 OnGeoposition(position_to_send_, false, base::TimeDelta()); |
| 95 ++geoposition_requests_num_; |
| 72 } | 96 } |
| 73 | 97 |
| 98 base::Time fake_now_; |
| 99 base::TimeTicks fake_now_ticks_; |
| 100 |
| 74 // The position to send to the controller the next time OnGeoposition is | 101 // The position to send to the controller the next time OnGeoposition is |
| 75 // invoked. | 102 // invoked. |
| 76 chromeos::Geoposition position_to_send_; | 103 chromeos::Geoposition position_to_send_; |
| 77 | 104 |
| 105 // The number of new geoposition requests that have been triggered. |
| 106 int geoposition_requests_num_ = 0; |
| 107 |
| 78 DISALLOW_COPY_AND_ASSIGN(FakeNightLightClient); | 108 DISALLOW_COPY_AND_ASSIGN(FakeNightLightClient); |
| 79 }; | 109 }; |
| 80 | 110 |
| 81 // Base test fixture. | 111 // Base test fixture. |
| 82 class NightLightClientTest : public testing::Test { | 112 class NightLightClientTest : public testing::Test { |
| 83 public: | 113 public: |
| 84 NightLightClientTest() = default; | 114 NightLightClientTest() = default; |
| 85 ~NightLightClientTest() override = default; | 115 ~NightLightClientTest() override = default; |
| 86 | 116 |
| 87 void SetUp() override { | 117 void SetUp() override { |
| 118 // Deterministic fake time that doesn't change for the sake of testing. |
| 119 client_.set_fake_now(base::Time::Now()); |
| 120 client_.set_fake_now_ticks(base::TimeTicks::Now()); |
| 121 |
| 88 client_.SetNightLightControllerPtrForTesting( | 122 client_.SetNightLightControllerPtrForTesting( |
| 89 controller_.CreateInterfacePtrAndBind()); | 123 controller_.CreateInterfacePtrAndBind()); |
| 90 client_.Start(); | 124 client_.Start(); |
| 91 client_.FlushNightLightControllerForTesting(); | 125 client_.FlushNightLightControllerForTesting(); |
| 92 } | 126 } |
| 93 | 127 |
| 94 base::test::ScopedTaskEnvironment scoped_task_environment_; | 128 base::test::ScopedTaskEnvironment scoped_task_environment_; |
| 95 | 129 |
| 96 FakeNightLightController controller_; | 130 FakeNightLightController controller_; |
| 97 FakeNightLightClient client_; | 131 FakeNightLightClient client_; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 112 client_.FlushNightLightControllerForTesting(); | 146 client_.FlushNightLightControllerForTesting(); |
| 113 EXPECT_TRUE(client_.using_geoposition()); | 147 EXPECT_TRUE(client_.using_geoposition()); |
| 114 | 148 |
| 115 // Client should stop retrieving geopositions when schedule type changes to | 149 // Client should stop retrieving geopositions when schedule type changes to |
| 116 // something else. | 150 // something else. |
| 117 controller_.NotifyScheduleTypeChanged(ScheduleType::kNone); | 151 controller_.NotifyScheduleTypeChanged(ScheduleType::kNone); |
| 118 EXPECT_FALSE(client_.using_geoposition()); | 152 EXPECT_FALSE(client_.using_geoposition()); |
| 119 } | 153 } |
| 120 | 154 |
| 121 // Test that client only pushes valid positions. | 155 // Test that client only pushes valid positions. |
| 122 TEST_F(NightLightClientTest, TestPositionPushes) { | 156 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()); | 157 EXPECT_EQ(0, controller_.position_pushes_num()); |
| 126 chromeos::Geoposition position; | 158 chromeos::Geoposition position; |
| 127 position.latitude = 32.0; | 159 position.latitude = 32.0; |
| 128 position.longitude = 31.0; | 160 position.longitude = 31.0; |
| 129 position.status = chromeos::Geoposition::STATUS_OK; | 161 position.status = chromeos::Geoposition::STATUS_TIMEOUT; |
| 130 position.accuracy = 10; | 162 position.accuracy = 10; |
| 131 position.timestamp = base::Time::Now(); | 163 position.timestamp = base::Time::Now(); |
| 132 client_.set_position_to_send(position); | 164 client_.set_position_to_send(position); |
| 133 controller_.NotifyScheduleTypeChanged(ScheduleType::kSunsetToSunrise); | 165 controller_.NotifyScheduleTypeChanged(ScheduleType::kSunsetToSunrise); |
| 134 scoped_task_environment_.RunUntilIdle(); | 166 scoped_task_environment_.RunUntilIdle(); |
| 135 client_.FlushNightLightControllerForTesting(); | 167 client_.FlushNightLightControllerForTesting(); |
| 136 EXPECT_EQ(1, controller_.position_pushes_num()); | 168 EXPECT_EQ(1, client_.geoposition_requests_num()); |
| 169 EXPECT_EQ(0, controller_.position_pushes_num()); |
| 170 } |
| 137 | 171 |
| 138 // Invalid positions should not be sent. | 172 // Test that successive changes of the schedule type to sunset to sunrise do not |
| 139 position.status = chromeos::Geoposition::STATUS_TIMEOUT; | 173 // trigger repeated geoposition requests. |
| 140 client_.set_position_to_send(position); | 174 TEST_F(NightLightClientTest, TestRepeatedScheduleTypeChanges) { |
| 175 // Start with a valid position, and expect it to be delivered to the |
| 176 // controller. |
| 177 EXPECT_EQ(0, controller_.position_pushes_num()); |
| 178 chromeos::Geoposition position1; |
| 179 position1.latitude = 32.0; |
| 180 position1.longitude = 31.0; |
| 181 position1.status = chromeos::Geoposition::STATUS_OK; |
| 182 position1.accuracy = 10; |
| 183 position1.timestamp = base::Time::Now(); |
| 184 client_.set_position_to_send(position1); |
| 141 controller_.NotifyScheduleTypeChanged(ScheduleType::kSunsetToSunrise); | 185 controller_.NotifyScheduleTypeChanged(ScheduleType::kSunsetToSunrise); |
| 142 scoped_task_environment_.RunUntilIdle(); | 186 scoped_task_environment_.RunUntilIdle(); |
| 143 client_.FlushNightLightControllerForTesting(); | 187 client_.FlushNightLightControllerForTesting(); |
| 188 EXPECT_EQ(1, client_.geoposition_requests_num()); |
| 144 EXPECT_EQ(1, controller_.position_pushes_num()); | 189 EXPECT_EQ(1, controller_.position_pushes_num()); |
| 190 EXPECT_EQ(client_.Now(), client_.last_successful_geo_request_time()); |
| 191 |
| 192 // A new different position just for the sake of comparison with position1 to |
| 193 // make sure that no new requests are triggered and the same old position will |
| 194 // be resent to the controller. |
| 195 chromeos::Geoposition position2; |
| 196 position2.latitude = 100.0; |
| 197 position2.longitude = 200.0; |
| 198 position2.status = chromeos::Geoposition::STATUS_OK; |
| 199 position2.accuracy = 10; |
| 200 position2.timestamp = base::Time::Now(); |
| 201 client_.set_position_to_send(position2); |
| 202 controller_.NotifyScheduleTypeChanged(ScheduleType::kSunsetToSunrise); |
| 203 scoped_task_environment_.RunUntilIdle(); |
| 204 client_.FlushNightLightControllerForTesting(); |
| 205 // No new request has been triggered, however the same old valid position was |
| 206 // pushed to the controller. |
| 207 EXPECT_EQ(1, client_.geoposition_requests_num()); |
| 208 EXPECT_EQ(2, controller_.position_pushes_num()); |
| 209 EXPECT_TRUE(ash::mojom::SimpleGeoposition::New(position1.latitude, |
| 210 position1.longitude) |
| 211 .Equals(controller_.position())); |
| 212 |
| 213 // The timer should be running scheduling a next request that is a |
| 214 // kNextRequestDelayAfterSuccess from the last successful request time. |
| 215 EXPECT_TRUE(client_.timer().IsRunning()); |
| 216 base::TimeDelta expected_delay = |
| 217 client_.last_successful_geo_request_time() + |
| 218 NightLightClient::GetNextRequestDelayAfterSuccessForTesting() - |
| 219 client_.Now(); |
| 220 EXPECT_EQ(expected_delay, client_.timer().GetCurrentDelay()); |
| 145 } | 221 } |
| 146 | 222 |
| 147 } // namespace | 223 } // namespace |
| OLD | NEW |