OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include <Objbase.h> | |
6 | |
7 #include <algorithm> | |
8 #include <cmath> | |
9 | |
10 #include "base/compiler_specific.h" | |
11 #include "base/logging.h" | |
12 #include "base/memory/scoped_ptr.h" | |
13 #include "base/message_loop/message_loop.h" | |
14 #include "base/time/time.h" | |
15 #include "content/browser/geolocation/win7_location_api_win.h" | |
16 #include "content/public/common/geoposition.h" | |
17 #include "testing/gmock/include/gmock/gmock.h" | |
18 #include "testing/gtest/include/gtest/gtest.h" | |
19 | |
20 using testing::_; | |
21 using testing::AtLeast; | |
22 using testing::DoDefault; | |
23 using testing::Invoke; | |
24 using testing::NiceMock; | |
25 using testing::Return; | |
26 | |
27 namespace content { | |
28 | |
29 class MockLatLongReport : public ILatLongReport { | |
30 public: | |
31 MockLatLongReport() : ref_count_(1) { | |
32 ON_CALL(*this, GetAltitude(_)) | |
33 .WillByDefault(Invoke(this, &MockLatLongReport::GetAltitudeValid)); | |
34 ON_CALL(*this, GetAltitudeError(_)) | |
35 .WillByDefault(Invoke(this, | |
36 &MockLatLongReport::GetAltitudeErrorValid)); | |
37 ON_CALL(*this, GetErrorRadius(_)) | |
38 .WillByDefault(Invoke(this, &MockLatLongReport::GetErrorRadiusValid)); | |
39 ON_CALL(*this, GetLatitude(_)) | |
40 .WillByDefault(Invoke(this, &MockLatLongReport::GetLatitudeValid)); | |
41 ON_CALL(*this, GetLongitude(_)) | |
42 .WillByDefault(Invoke(this, &MockLatLongReport::GetLongitudeValid)); | |
43 ON_CALL(*this, GetValue(_, _)) | |
44 .WillByDefault(Invoke(this, &MockLatLongReport::GetValueValid)); | |
45 ON_CALL(*this, Release()) | |
46 .WillByDefault(Invoke(this, &MockLatLongReport::ReleaseInternal)); | |
47 ON_CALL(*this, AddRef()) | |
48 .WillByDefault(Invoke(this, &MockLatLongReport::AddRefInternal)); | |
49 } | |
50 | |
51 // ILatLongReport | |
52 MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
53 GetAltitude, | |
54 HRESULT(DOUBLE*)); | |
55 MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
56 GetAltitudeError, | |
57 HRESULT(DOUBLE*)); | |
58 MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
59 GetErrorRadius, | |
60 HRESULT(DOUBLE*)); | |
61 MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
62 GetLatitude, | |
63 HRESULT(DOUBLE*)); | |
64 MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
65 GetLongitude, | |
66 HRESULT(DOUBLE*)); | |
67 // ILocationReport | |
68 MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
69 GetSensorID, | |
70 HRESULT(SENSOR_ID*)); | |
71 MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
72 GetTimestamp, | |
73 HRESULT(SYSTEMTIME*)); | |
74 MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
75 GetValue, | |
76 HRESULT(REFPROPERTYKEY, PROPVARIANT*)); | |
77 // IUnknown | |
78 MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
79 QueryInterface, | |
80 HRESULT(REFIID, void**)); | |
81 MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
82 AddRef, | |
83 ULONG()); | |
84 MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
85 Release, | |
86 ULONG()); | |
87 | |
88 HRESULT GetAltitudeValid(DOUBLE* altitude) { | |
89 *altitude = 20.5; | |
90 return S_OK; | |
91 } | |
92 HRESULT GetAltitudeErrorValid(DOUBLE* altitude_error) { | |
93 *altitude_error = 10.0; | |
94 return S_OK; | |
95 } | |
96 HRESULT GetErrorRadiusValid(DOUBLE* error) { | |
97 *error = 5.0; | |
98 return S_OK; | |
99 } | |
100 HRESULT GetLatitudeValid(DOUBLE* latitude) { | |
101 *latitude = 51.0; | |
102 return S_OK; | |
103 } | |
104 HRESULT GetLongitudeValid(DOUBLE* longitude) { | |
105 *longitude = -0.1; | |
106 return S_OK; | |
107 } | |
108 HRESULT GetValueValid(REFPROPERTYKEY prop_key, PROPVARIANT* prop) { | |
109 prop->dblVal = 10.0; | |
110 return S_OK; | |
111 } | |
112 | |
113 private: | |
114 ~MockLatLongReport() {} | |
115 | |
116 ULONG AddRefInternal() { | |
117 return InterlockedIncrement(&ref_count_); | |
118 } | |
119 ULONG ReleaseInternal() { | |
120 LONG new_ref_count = InterlockedDecrement(&ref_count_); | |
121 if (0 == new_ref_count) | |
122 delete this; | |
123 return new_ref_count; | |
124 } | |
125 | |
126 LONG ref_count_; | |
127 }; | |
128 | |
129 class MockReport : public ILocationReport { | |
130 public: | |
131 MockReport() : ref_count_(1) { | |
132 mock_lat_long_report_ = | |
133 new MockLatLongReport(); | |
134 ON_CALL(*this, QueryInterface(_, _)) | |
135 .WillByDefault(Invoke(this, &MockReport::QueryInterfaceValid)); | |
136 ON_CALL(*this, Release()) | |
137 .WillByDefault(Invoke(this, &MockReport::ReleaseInternal)); | |
138 ON_CALL(*this, AddRef()) | |
139 .WillByDefault(Invoke(this, &MockReport::AddRefInternal)); | |
140 } | |
141 | |
142 // ILocationReport | |
143 MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
144 GetSensorID, | |
145 HRESULT(SENSOR_ID*)); | |
146 MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
147 GetTimestamp, | |
148 HRESULT(SYSTEMTIME*)); | |
149 MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
150 GetValue, | |
151 HRESULT(REFPROPERTYKEY, PROPVARIANT*)); | |
152 // IUnknown | |
153 MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
154 QueryInterface, | |
155 HRESULT(REFIID, void**)); | |
156 MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
157 AddRef, | |
158 ULONG()); | |
159 MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
160 Release, | |
161 ULONG()); | |
162 | |
163 MockLatLongReport* mock_lat_long_report_; | |
164 | |
165 private: | |
166 ~MockReport() { | |
167 mock_lat_long_report_->Release(); | |
168 } | |
169 | |
170 ULONG AddRefInternal() { | |
171 return InterlockedIncrement(&ref_count_); | |
172 } | |
173 ULONG ReleaseInternal() { | |
174 LONG new_ref_count = InterlockedDecrement(&ref_count_); | |
175 if (0 == new_ref_count) | |
176 delete this; | |
177 return new_ref_count; | |
178 } | |
179 HRESULT QueryInterfaceValid(REFIID id, void** report) { | |
180 EXPECT_TRUE(id == IID_ILatLongReport); | |
181 *report = reinterpret_cast<ILatLongReport*>(mock_lat_long_report_); | |
182 mock_lat_long_report_->AddRef(); | |
183 return S_OK; | |
184 } | |
185 | |
186 LONG ref_count_; | |
187 }; | |
188 | |
189 class MockLocation : public ILocation { | |
190 public: | |
191 MockLocation() : ref_count_(1) { | |
192 mock_report_ = new MockReport(); | |
193 ON_CALL(*this, SetDesiredAccuracy(_, _)) | |
194 .WillByDefault(Return(S_OK)); | |
195 ON_CALL(*this, GetReport(_, _)) | |
196 .WillByDefault(Invoke(this, &MockLocation::GetReportValid)); | |
197 ON_CALL(*this, RequestPermissions(_, _, _, _)) | |
198 .WillByDefault(Return(S_OK)); | |
199 ON_CALL(*this, AddRef()) | |
200 .WillByDefault(Invoke(this, &MockLocation::AddRefInternal)); | |
201 ON_CALL(*this, Release()) | |
202 .WillByDefault(Invoke(this, &MockLocation::ReleaseInternal)); | |
203 } | |
204 | |
205 // ILocation | |
206 MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
207 GetDesiredAccuracy, | |
208 HRESULT(REFIID, LOCATION_DESIRED_ACCURACY*)); | |
209 MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
210 GetReport, | |
211 HRESULT(REFIID, ILocationReport**)); | |
212 MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
213 GetReportInterval, | |
214 HRESULT(REFIID, DWORD*)); | |
215 MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
216 GetReportStatus, | |
217 HRESULT(REFIID, LOCATION_REPORT_STATUS*)); | |
218 MOCK_METHOD4_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
219 RequestPermissions, | |
220 HRESULT(HWND, IID*, ULONG, BOOL)); | |
221 MOCK_METHOD3_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
222 RegisterForReport, | |
223 HRESULT(ILocationEvents*, REFIID, DWORD)); | |
224 MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
225 SetDesiredAccuracy, | |
226 HRESULT(REFIID, LOCATION_DESIRED_ACCURACY)); | |
227 MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
228 SetReportInterval, | |
229 HRESULT(REFIID, DWORD)); | |
230 MOCK_METHOD1_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
231 UnregisterForReport, | |
232 HRESULT(REFIID)); | |
233 // IUnknown | |
234 MOCK_METHOD2_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
235 QueryInterface, | |
236 HRESULT(REFIID, void**)); | |
237 MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
238 AddRef, | |
239 ULONG()); | |
240 MOCK_METHOD0_WITH_CALLTYPE(STDMETHODCALLTYPE, | |
241 Release, | |
242 ULONG()); | |
243 | |
244 MockReport* mock_report_; | |
245 | |
246 protected: | |
247 ~MockLocation() { | |
248 mock_report_->Release(); | |
249 } | |
250 | |
251 private: | |
252 HRESULT GetReportValid(REFIID report_type, | |
253 ILocationReport** location_report) { | |
254 *location_report = reinterpret_cast<ILocationReport*>(mock_report_); | |
255 mock_report_->AddRef(); | |
256 return S_OK; | |
257 } | |
258 ULONG AddRefInternal() { | |
259 return InterlockedIncrement(&ref_count_); | |
260 } | |
261 ULONG ReleaseInternal() { | |
262 LONG new_ref_count = InterlockedDecrement(&ref_count_); | |
263 if (0 == new_ref_count) | |
264 delete this; | |
265 return new_ref_count; | |
266 } | |
267 | |
268 LONG ref_count_; | |
269 }; | |
270 | |
271 | |
272 HRESULT __stdcall MockPropVariantToDoubleFunction(REFPROPVARIANT propvarIn, | |
273 DOUBLE *pdblRet) { | |
274 CHECK_EQ(10.0, propvarIn.dblVal); | |
275 *pdblRet = 10.0; | |
276 return S_OK; | |
277 } | |
278 | |
279 // TODO(allanwoj): Either make mock classes into NiceMock classes | |
280 // or check every mock method call. | |
281 class GeolocationApiWin7Tests : public testing::Test { | |
282 public: | |
283 GeolocationApiWin7Tests() { | |
284 } | |
285 virtual void SetUp() { | |
286 api_.reset(CreateMock()); | |
287 report_ = locator_->mock_report_; | |
288 lat_long_report_ = report_->mock_lat_long_report_; | |
289 } | |
290 virtual void TearDown() { | |
291 locator_->Release(); | |
292 api_.reset(); | |
293 } | |
294 ~GeolocationApiWin7Tests() { | |
295 } | |
296 protected: | |
297 Win7LocationApi* CreateMock() { | |
298 NiceMock<MockLocation>* locator = new NiceMock<MockLocation>(); | |
299 locator_ = locator; | |
300 return Win7LocationApi::CreateForTesting(&MockPropVariantToDoubleFunction, | |
301 locator); | |
302 } | |
303 | |
304 scoped_ptr<Win7LocationApi> api_; | |
305 MockLatLongReport* lat_long_report_; | |
306 NiceMock<MockLocation>* locator_; | |
307 MockReport* report_; | |
308 }; | |
309 | |
310 TEST_F(GeolocationApiWin7Tests, PermissionDenied) { | |
311 EXPECT_CALL(*locator_, GetReport(_, _)) | |
312 .Times(AtLeast(1)) | |
313 .WillRepeatedly(Return(E_ACCESSDENIED)); | |
314 Geoposition position; | |
315 api_->GetPosition(&position); | |
316 EXPECT_EQ(Geoposition::ERROR_CODE_PERMISSION_DENIED, | |
317 position.error_code); | |
318 } | |
319 | |
320 TEST_F(GeolocationApiWin7Tests, GetValidPosition) { | |
321 EXPECT_CALL(*locator_, GetReport(_, _)) | |
322 .Times(AtLeast(1)); | |
323 Geoposition position; | |
324 api_->GetPosition(&position); | |
325 EXPECT_TRUE(position.Validate()); | |
326 } | |
327 | |
328 TEST_F(GeolocationApiWin7Tests, GetInvalidPosition) { | |
329 EXPECT_CALL(*lat_long_report_, GetLatitude(_)) | |
330 .Times(AtLeast(1)) | |
331 .WillRepeatedly(Return(HRESULT_FROM_WIN32(ERROR_NO_DATA))); | |
332 EXPECT_CALL(*locator_, GetReport(_, _)) | |
333 .Times(AtLeast(1)); | |
334 Geoposition position; | |
335 api_->GetPosition(&position); | |
336 EXPECT_FALSE(position.Validate()); | |
337 } | |
338 | |
339 } // namespace content | |
OLD | NEW |