| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "content/browser/browser_thread_impl.h" | 5 #include "content/browser/browser_thread_impl.h" |
| 6 #include "content/browser/geolocation/gps_location_provider_linux.h" | 6 #include "content/browser/geolocation/gps_location_provider_linux.h" |
| 7 #include "content/browser/geolocation/libgps_wrapper_linux.h" | 7 #include "content/browser/geolocation/libgps_wrapper_linux.h" |
| 8 #include "testing/gtest/include/gtest/gtest.h" | 8 #include "testing/gtest/include/gtest/gtest.h" |
| 9 | 9 |
| 10 #include "base/bind.h" |
| 11 |
| 10 using content::BrowserThread; | 12 using content::BrowserThread; |
| 11 using content::BrowserThreadImpl; | 13 using content::BrowserThreadImpl; |
| 12 | 14 |
| 13 struct gps_data_t { | |
| 14 }; | |
| 15 | |
| 16 namespace { | 15 namespace { |
| 17 class MockLibGps : public LibGps { | 16 class MockLibGps : public LibGps { |
| 18 public: | 17 public: |
| 19 MockLibGps(); | 18 MockLibGps(); |
| 20 ~MockLibGps(); | 19 ~MockLibGps(); |
| 21 | 20 |
| 22 virtual bool StartStreaming() { | |
| 23 ++start_streaming_calls_; | |
| 24 return start_streaming_ret_; | |
| 25 } | |
| 26 virtual bool DataWaiting() { | |
| 27 EXPECT_GT(start_streaming_calls_, 0); | |
| 28 ++data_waiting_calls_; | |
| 29 // Toggle the return value, so the poll loop will exit once per test step. | |
| 30 return (data_waiting_calls_ & 1) != 0; | |
| 31 } | |
| 32 virtual bool GetPositionIfFixed(Geoposition* position) { | 21 virtual bool GetPositionIfFixed(Geoposition* position) { |
| 33 CHECK(position); | 22 CHECK(position); |
| 34 EXPECT_GT(start_streaming_calls_, 0); | |
| 35 EXPECT_GT(data_waiting_calls_, 0); | |
| 36 ++get_position_calls_; | 23 ++get_position_calls_; |
| 37 *position = get_position_; | 24 *position = get_position_; |
| 38 return get_position_ret_; | 25 return get_position_ret_; |
| 26 } |
| 39 | 27 |
| 28 static int gps_open_stub(const char*, const char*, struct gps_data_t*) { |
| 29 CHECK(g_instance_); |
| 30 g_instance_->gps_open_calls_++; |
| 31 return g_instance_->gps_open_ret_; |
| 40 } | 32 } |
| 41 int start_streaming_calls_; | 33 |
| 42 bool start_streaming_ret_; | 34 static int gps_close_stub(struct gps_data_t*) { |
| 43 int data_waiting_calls_; | 35 return 0; |
| 36 } |
| 37 |
| 38 static int gps_read_stub(struct gps_data_t*) { |
| 39 CHECK(g_instance_); |
| 40 g_instance_->gps_read_calls_++; |
| 41 return g_instance_->gps_read_ret_; |
| 42 } |
| 43 |
| 44 int get_position_calls_; | 44 int get_position_calls_; |
| 45 bool get_position_ret_; |
| 46 int gps_open_calls_; |
| 47 int gps_open_ret_; |
| 48 int gps_read_calls_; |
| 49 int gps_read_ret_; |
| 45 Geoposition get_position_; | 50 Geoposition get_position_; |
| 46 bool get_position_ret_; | |
| 47 static MockLibGps* g_instance_; | 51 static MockLibGps* g_instance_; |
| 48 }; | 52 }; |
| 49 | 53 |
| 50 class LocaionProviderListenerLoopQuitter | 54 class LocaionProviderListenerLoopQuitter |
| 51 : public LocationProviderBase::ListenerInterface { | 55 : public LocationProviderBase::ListenerInterface { |
| 52 // LocationProviderBase::ListenerInterface | 56 // LocationProviderBase::ListenerInterface |
| 53 virtual void LocationUpdateAvailable(LocationProviderBase* provider) { | 57 virtual void LocationUpdateAvailable(LocationProviderBase* provider) { |
| 54 MessageLoop::current()->Quit(); | 58 MessageLoop::current()->Quit(); |
| 55 } | 59 } |
| 56 }; | 60 }; |
| 57 | 61 |
| 58 class GeolocationGpsProviderLinuxTests : public testing::Test { | 62 class GeolocationGpsProviderLinuxTests : public testing::Test { |
| 59 public: | 63 public: |
| 60 GeolocationGpsProviderLinuxTests(); | 64 GeolocationGpsProviderLinuxTests(); |
| 61 ~GeolocationGpsProviderLinuxTests(); | 65 ~GeolocationGpsProviderLinuxTests(); |
| 62 | 66 |
| 63 static LibGps* NewMockLibGps() { | 67 static LibGps* NewMockLibGps() { |
| 64 return new MockLibGps; | 68 return new MockLibGps(); |
| 65 } | 69 } |
| 66 static LibGps* NoLibGpsFactory() { | 70 static LibGps* NoLibGpsFactory() { |
| 67 return NULL; | 71 return NULL; |
| 68 } | 72 } |
| 69 | 73 |
| 70 protected: | 74 protected: |
| 71 MessageLoop message_loop_; | 75 MessageLoop message_loop_; |
| 72 BrowserThreadImpl ui_thread_; | 76 BrowserThreadImpl ui_thread_; |
| 73 LocaionProviderListenerLoopQuitter location_listener_; | 77 LocaionProviderListenerLoopQuitter location_listener_; |
| 74 scoped_ptr<GpsLocationProviderLinux> provider_; | 78 scoped_ptr<GpsLocationProviderLinux> provider_; |
| 75 }; | 79 }; |
| 76 | 80 |
| 77 gps_data_t* gps_open_stub(const char*, const char*) { | |
| 78 // Need to return a non-NULL value here to indicate success, however we don't | |
| 79 // need (or want) a valid pointer as it should never be dereferenced. | |
| 80 return static_cast<gps_data_t*>(NULL) + 1; | |
| 81 } | |
| 82 int gps_close_stub(gps_data_t*) { | |
| 83 return 0; | |
| 84 } | |
| 85 int gps_poll_stub(gps_data_t*) { | |
| 86 return 0; | |
| 87 } | |
| 88 // v2.90+ | |
| 89 int gps_stream_stub(gps_data_t*, unsigned int, void*) { | |
| 90 return 0; | |
| 91 } | |
| 92 bool gps_waiting_stub(gps_data_t*) { | |
| 93 return 0; | |
| 94 } | |
| 95 | |
| 96 void CheckValidPosition(const Geoposition& expected, | 81 void CheckValidPosition(const Geoposition& expected, |
| 97 const Geoposition& actual) { | 82 const Geoposition& actual) { |
| 98 EXPECT_TRUE(actual.IsValidFix()); | 83 EXPECT_TRUE(actual.IsValidFix()); |
| 99 EXPECT_DOUBLE_EQ(expected.latitude, actual.latitude); | 84 EXPECT_DOUBLE_EQ(expected.latitude, actual.latitude); |
| 100 EXPECT_DOUBLE_EQ(expected.longitude, actual.longitude); | 85 EXPECT_DOUBLE_EQ(expected.longitude, actual.longitude); |
| 101 EXPECT_DOUBLE_EQ(expected.accuracy, actual.accuracy); | 86 EXPECT_DOUBLE_EQ(expected.accuracy, actual.accuracy); |
| 102 } | 87 } |
| 103 | 88 |
| 104 MockLibGps* MockLibGps::g_instance_ = NULL; | 89 MockLibGps* MockLibGps::g_instance_ = NULL; |
| 105 | 90 |
| 106 MockLibGps::MockLibGps() | 91 MockLibGps::MockLibGps() |
| 107 : LibGps(new LibGpsLibraryWrapper(NULL, | 92 : LibGps(NULL, gps_open_stub, gps_close_stub, gps_read_stub), |
| 108 gps_open_stub, | |
| 109 gps_close_stub, | |
| 110 gps_poll_stub, | |
| 111 gps_stream_stub, | |
| 112 gps_waiting_stub)), | |
| 113 start_streaming_calls_(0), | |
| 114 start_streaming_ret_(true), | |
| 115 data_waiting_calls_(0), | |
| 116 get_position_calls_(0), | 93 get_position_calls_(0), |
| 117 get_position_ret_(true) { | 94 get_position_ret_(true), |
| 95 gps_open_calls_(0), |
| 96 gps_open_ret_(0), |
| 97 gps_read_calls_(0), |
| 98 gps_read_ret_(0) { |
| 118 get_position_.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; | 99 get_position_.error_code = Geoposition::ERROR_CODE_POSITION_UNAVAILABLE; |
| 119 EXPECT_FALSE(g_instance_); | 100 EXPECT_FALSE(g_instance_); |
| 120 g_instance_ = this; | 101 g_instance_ = this; |
| 121 } | 102 } |
| 122 | 103 |
| 123 MockLibGps::~MockLibGps() { | 104 MockLibGps::~MockLibGps() { |
| 124 EXPECT_EQ(this, g_instance_); | 105 EXPECT_EQ(this, g_instance_); |
| 125 g_instance_ = NULL; | 106 g_instance_ = NULL; |
| 126 } | 107 } |
| 127 | 108 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 140 ASSERT_TRUE(provider_.get()); | 121 ASSERT_TRUE(provider_.get()); |
| 141 const bool ok = provider_->StartProvider(true); | 122 const bool ok = provider_->StartProvider(true); |
| 142 EXPECT_FALSE(ok); | 123 EXPECT_FALSE(ok); |
| 143 Geoposition position; | 124 Geoposition position; |
| 144 provider_->GetPosition(&position); | 125 provider_->GetPosition(&position); |
| 145 EXPECT_TRUE(position.IsInitialized()); | 126 EXPECT_TRUE(position.IsInitialized()); |
| 146 EXPECT_FALSE(position.IsValidFix()); | 127 EXPECT_FALSE(position.IsValidFix()); |
| 147 EXPECT_EQ(Geoposition::ERROR_CODE_POSITION_UNAVAILABLE, position.error_code); | 128 EXPECT_EQ(Geoposition::ERROR_CODE_POSITION_UNAVAILABLE, position.error_code); |
| 148 } | 129 } |
| 149 | 130 |
| 131 #if defined(OS_CHROMEOS) |
| 132 |
| 150 TEST_F(GeolocationGpsProviderLinuxTests, GetPosition) { | 133 TEST_F(GeolocationGpsProviderLinuxTests, GetPosition) { |
| 151 ASSERT_TRUE(provider_.get()); | 134 ASSERT_TRUE(provider_.get()); |
| 152 const bool ok = provider_->StartProvider(true); | 135 const bool ok = provider_->StartProvider(true); |
| 153 EXPECT_TRUE(ok); | 136 EXPECT_TRUE(ok); |
| 154 ASSERT_TRUE(MockLibGps::g_instance_); | 137 ASSERT_TRUE(MockLibGps::g_instance_); |
| 155 EXPECT_EQ(0, MockLibGps::g_instance_->start_streaming_calls_); | |
| 156 EXPECT_EQ(0, MockLibGps::g_instance_->data_waiting_calls_); | |
| 157 EXPECT_EQ(0, MockLibGps::g_instance_->get_position_calls_); | 138 EXPECT_EQ(0, MockLibGps::g_instance_->get_position_calls_); |
| 139 EXPECT_EQ(0, MockLibGps::g_instance_->gps_open_calls_); |
| 140 EXPECT_EQ(0, MockLibGps::g_instance_->gps_read_calls_); |
| 158 Geoposition position; | 141 Geoposition position; |
| 159 provider_->GetPosition(&position); | 142 provider_->GetPosition(&position); |
| 160 EXPECT_TRUE(position.IsInitialized()); | 143 EXPECT_TRUE(position.IsInitialized()); |
| 161 EXPECT_FALSE(position.IsValidFix()); | 144 EXPECT_FALSE(position.IsValidFix()); |
| 162 EXPECT_EQ(Geoposition::ERROR_CODE_POSITION_UNAVAILABLE, position.error_code); | 145 EXPECT_EQ(Geoposition::ERROR_CODE_POSITION_UNAVAILABLE, position.error_code); |
| 163 MockLibGps::g_instance_->get_position_.error_code = | 146 MockLibGps::g_instance_->get_position_.error_code = |
| 164 Geoposition::ERROR_CODE_NONE; | 147 Geoposition::ERROR_CODE_NONE; |
| 165 MockLibGps::g_instance_->get_position_.latitude = 4.5; | 148 MockLibGps::g_instance_->get_position_.latitude = 4.5; |
| 166 MockLibGps::g_instance_->get_position_.longitude = -34.1; | 149 MockLibGps::g_instance_->get_position_.longitude = -34.1; |
| 167 MockLibGps::g_instance_->get_position_.accuracy = 345; | 150 MockLibGps::g_instance_->get_position_.accuracy = 345; |
| 168 MockLibGps::g_instance_->get_position_.timestamp = | 151 MockLibGps::g_instance_->get_position_.timestamp = |
| 169 base::Time::FromDoubleT(200); | 152 base::Time::FromDoubleT(200); |
| 170 EXPECT_TRUE(MockLibGps::g_instance_->get_position_.IsValidFix()); | 153 EXPECT_TRUE(MockLibGps::g_instance_->get_position_.IsValidFix()); |
| 171 | |
| 172 MessageLoop::current()->Run(); | 154 MessageLoop::current()->Run(); |
| 173 EXPECT_GT(MockLibGps::g_instance_->start_streaming_calls_, 0); | |
| 174 EXPECT_GT(MockLibGps::g_instance_->data_waiting_calls_, 0); | |
| 175 EXPECT_EQ(1, MockLibGps::g_instance_->get_position_calls_); | 155 EXPECT_EQ(1, MockLibGps::g_instance_->get_position_calls_); |
| 156 EXPECT_EQ(1, MockLibGps::g_instance_->gps_open_calls_); |
| 157 EXPECT_EQ(1, MockLibGps::g_instance_->gps_read_calls_); |
| 176 provider_->GetPosition(&position); | 158 provider_->GetPosition(&position); |
| 177 CheckValidPosition(MockLibGps::g_instance_->get_position_, position); | 159 CheckValidPosition(MockLibGps::g_instance_->get_position_, position); |
| 178 | 160 |
| 179 // Movement. This will block for up to half a second. | 161 // Movement. This will block for up to half a second. |
| 180 MockLibGps::g_instance_->get_position_.latitude += 0.01; | 162 MockLibGps::g_instance_->get_position_.latitude += 0.01; |
| 181 MessageLoop::current()->Run(); | 163 MessageLoop::current()->Run(); |
| 182 provider_->GetPosition(&position); | 164 provider_->GetPosition(&position); |
| 183 EXPECT_EQ(2, MockLibGps::g_instance_->get_position_calls_); | 165 EXPECT_EQ(2, MockLibGps::g_instance_->get_position_calls_); |
| 166 EXPECT_EQ(1, MockLibGps::g_instance_->gps_open_calls_); |
| 167 EXPECT_EQ(2, MockLibGps::g_instance_->gps_read_calls_); |
| 184 CheckValidPosition(MockLibGps::g_instance_->get_position_, position); | 168 CheckValidPosition(MockLibGps::g_instance_->get_position_, position); |
| 185 } | 169 } |
| 186 | 170 |
| 187 // TODO(joth): Add a test for LibGps::Start() returning false (i.e. gpsd not | 171 class EnableGpsOpenTask : public Task { |
| 188 // running). Need to work around the 10s reconnect delay (either by injecting | 172 public: |
| 189 // a shorter retry interval, or adapt MessageLoop / Time::Now to be more test | 173 virtual void Run() { |
| 190 // friendly). | 174 CHECK(MockLibGps::g_instance_); |
| 175 MockLibGps::g_instance_->gps_open_ret_ = 0; |
| 176 } |
| 177 }; |
| 178 |
| 179 TEST_F(GeolocationGpsProviderLinuxTests, LibGpsReconnect) { |
| 180 // Setup gpsd reconnect interval to be 1000ms to speed up test. |
| 181 provider_->SetGpsdReconnectIntervalMillis(1000); |
| 182 provider_->SetPollPeriodMovingMillis(200); |
| 183 const bool ok = provider_->StartProvider(true); |
| 184 EXPECT_TRUE(ok); |
| 185 ASSERT_TRUE(MockLibGps::g_instance_); |
| 186 // Let gps_open() fails, and so will LibGps::Start(). |
| 187 // Reconnect will happen in 1000ms. |
| 188 MockLibGps::g_instance_->gps_open_ret_ = 1; |
| 189 Geoposition position; |
| 190 MockLibGps::g_instance_->get_position_.error_code = |
| 191 Geoposition::ERROR_CODE_NONE; |
| 192 MockLibGps::g_instance_->get_position_.latitude = 4.5; |
| 193 MockLibGps::g_instance_->get_position_.longitude = -34.1; |
| 194 MockLibGps::g_instance_->get_position_.accuracy = 345; |
| 195 MockLibGps::g_instance_->get_position_.timestamp = |
| 196 base::Time::FromDoubleT(200); |
| 197 EXPECT_TRUE(MockLibGps::g_instance_->get_position_.IsValidFix()); |
| 198 // This task makes gps_open() and LibGps::Start() to succeed after |
| 199 // 1500ms. |
| 200 MessageLoop::current()->PostDelayedTask( |
| 201 FROM_HERE, new EnableGpsOpenTask(), 1500); |
| 202 MessageLoop::current()->Run(); |
| 203 provider_->GetPosition(&position); |
| 204 EXPECT_TRUE(position.IsInitialized()); |
| 205 EXPECT_TRUE(position.IsValidFix()); |
| 206 // 3 gps_open() calls are expected (2 failures and 1 success) |
| 207 EXPECT_EQ(1, MockLibGps::g_instance_->get_position_calls_); |
| 208 EXPECT_EQ(3, MockLibGps::g_instance_->gps_open_calls_); |
| 209 EXPECT_EQ(1, MockLibGps::g_instance_->gps_read_calls_); |
| 210 } |
| 211 |
| 212 #endif // #if defined(OS_CHROMEOS) |
| 191 | 213 |
| 192 } // namespace | 214 } // namespace |
| OLD | NEW |