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 |