OLD | NEW |
| (Empty) |
1 // Copyright (c) 2010 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 <queue> | |
6 | |
7 #include "base/message_loop.h" | |
8 #include "base/synchronization/lock.h" | |
9 #include "base/task.h" | |
10 #include "chrome/browser/device_orientation/data_fetcher.h" | |
11 #include "chrome/browser/device_orientation/orientation.h" | |
12 #include "chrome/browser/device_orientation/provider.h" | |
13 #include "chrome/browser/device_orientation/provider_impl.h" | |
14 #include "testing/gtest/include/gtest/gtest.h" | |
15 | |
16 namespace device_orientation { | |
17 namespace { | |
18 | |
19 // Class for checking expectations on orientation updates from the Provider. | |
20 class UpdateChecker : public Provider::Observer { | |
21 public: | |
22 explicit UpdateChecker(int* expectations_count_ptr) | |
23 : expectations_count_ptr_(expectations_count_ptr) { | |
24 } | |
25 | |
26 // From Provider::Observer. | |
27 virtual void OnOrientationUpdate(const Orientation& orientation) { | |
28 ASSERT_FALSE(expectations_queue_.empty()); | |
29 | |
30 Orientation expected = expectations_queue_.front(); | |
31 expectations_queue_.pop(); | |
32 | |
33 EXPECT_EQ(expected.can_provide_alpha_, orientation.can_provide_alpha_); | |
34 EXPECT_EQ(expected.can_provide_beta_, orientation.can_provide_beta_); | |
35 EXPECT_EQ(expected.can_provide_gamma_, orientation.can_provide_gamma_); | |
36 if (expected.can_provide_alpha_) | |
37 EXPECT_EQ(expected.alpha_, orientation.alpha_); | |
38 if (expected.can_provide_beta_) | |
39 EXPECT_EQ(expected.beta_, orientation.beta_); | |
40 if (expected.can_provide_gamma_) | |
41 EXPECT_EQ(expected.gamma_, orientation.gamma_); | |
42 | |
43 --(*expectations_count_ptr_); | |
44 | |
45 if (*expectations_count_ptr_ == 0) { | |
46 MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); | |
47 } | |
48 } | |
49 | |
50 void AddExpectation(const Orientation& orientation) { | |
51 expectations_queue_.push(orientation); | |
52 ++(*expectations_count_ptr_); | |
53 } | |
54 | |
55 private: | |
56 // Set up by the test fixture, which then blocks while it is accessed | |
57 // from OnOrientationUpdate which is executed on the test fixture's | |
58 // message_loop_. | |
59 int* expectations_count_ptr_; | |
60 std::queue<Orientation> expectations_queue_; | |
61 }; | |
62 | |
63 // Class for injecting test orientation data into the Provider. | |
64 class MockOrientationFactory : public base::RefCounted<MockOrientationFactory> { | |
65 public: | |
66 MockOrientationFactory() { | |
67 EXPECT_FALSE(instance_); | |
68 instance_ = this; | |
69 } | |
70 | |
71 ~MockOrientationFactory() { | |
72 instance_ = NULL; | |
73 } | |
74 | |
75 static DataFetcher* CreateDataFetcher() { | |
76 EXPECT_TRUE(instance_); | |
77 return new MockDataFetcher(instance_); | |
78 } | |
79 | |
80 void SetOrientation(const Orientation& orientation) { | |
81 base::AutoLock auto_lock(lock_); | |
82 orientation_ = orientation; | |
83 } | |
84 | |
85 private: | |
86 // Owned by ProviderImpl. Holds a reference back to MockOrientationFactory. | |
87 class MockDataFetcher : public DataFetcher { | |
88 public: | |
89 explicit MockDataFetcher(MockOrientationFactory* orientation_factory) | |
90 : orientation_factory_(orientation_factory) { } | |
91 | |
92 // From DataFetcher. Called by the Provider. | |
93 virtual bool GetOrientation(Orientation* orientation) { | |
94 base::AutoLock auto_lock(orientation_factory_->lock_); | |
95 *orientation = orientation_factory_->orientation_; | |
96 return true; | |
97 } | |
98 | |
99 private: | |
100 scoped_refptr<MockOrientationFactory> orientation_factory_; | |
101 }; | |
102 | |
103 static MockOrientationFactory* instance_; | |
104 Orientation orientation_; | |
105 base::Lock lock_; | |
106 }; | |
107 | |
108 MockOrientationFactory* MockOrientationFactory::instance_; | |
109 | |
110 // Mock DataFetcher that always fails to provide any orientation data. | |
111 class FailingDataFetcher : public DataFetcher { | |
112 public: | |
113 // Factory method; passed to and called by the ProviderImpl. | |
114 static DataFetcher* Create() { | |
115 return new FailingDataFetcher(); | |
116 } | |
117 | |
118 // From DataFetcher. | |
119 virtual bool GetOrientation(Orientation* orientation) { | |
120 return false; | |
121 } | |
122 | |
123 private: | |
124 FailingDataFetcher() {} | |
125 }; | |
126 | |
127 class DeviceOrientationProviderTest : public testing::Test { | |
128 public: | |
129 DeviceOrientationProviderTest() | |
130 : pending_expectations_(0) { | |
131 } | |
132 | |
133 virtual void TearDown() { | |
134 provider_ = NULL; | |
135 | |
136 // Make sure it is really gone. | |
137 EXPECT_FALSE(Provider::GetInstanceForTests()); | |
138 | |
139 // Clean up in any case, so as to not break subsequent test. | |
140 Provider::SetInstanceForTests(NULL); | |
141 } | |
142 | |
143 // Initialize the test fixture with a ProviderImpl that uses the | |
144 // DataFetcherFactories in the null-terminated factories array. | |
145 void Init(ProviderImpl::DataFetcherFactory* factories) { | |
146 provider_ = new ProviderImpl(factories); | |
147 Provider::SetInstanceForTests(provider_); | |
148 } | |
149 | |
150 // Initialize the test fixture with a ProviderImpl that uses the | |
151 // DataFetcherFactory factory. | |
152 void Init(ProviderImpl::DataFetcherFactory factory) { | |
153 ProviderImpl::DataFetcherFactory factories[] = { factory, NULL }; | |
154 Init(factories); | |
155 } | |
156 | |
157 protected: | |
158 // Number of pending expectations. | |
159 int pending_expectations_; | |
160 | |
161 // Provider instance under test. | |
162 scoped_refptr<Provider> provider_; | |
163 | |
164 // Message loop for the test thread. | |
165 MessageLoop message_loop_; | |
166 }; | |
167 | |
168 TEST_F(DeviceOrientationProviderTest, FailingTest) { | |
169 Init(FailingDataFetcher::Create); | |
170 | |
171 scoped_ptr<UpdateChecker> checker_a( | |
172 new UpdateChecker(&pending_expectations_)); | |
173 scoped_ptr<UpdateChecker> checker_b( | |
174 new UpdateChecker(&pending_expectations_)); | |
175 | |
176 checker_a->AddExpectation(Orientation::Empty()); | |
177 provider_->AddObserver(checker_a.get()); | |
178 MessageLoop::current()->Run(); | |
179 | |
180 checker_b->AddExpectation(Orientation::Empty()); | |
181 provider_->AddObserver(checker_b.get()); | |
182 MessageLoop::current()->Run(); | |
183 } | |
184 | |
185 TEST_F(DeviceOrientationProviderTest, ProviderIsSingleton) { | |
186 Init(FailingDataFetcher::Create); | |
187 | |
188 scoped_refptr<Provider> provider_a(Provider::GetInstance()); | |
189 scoped_refptr<Provider> provider_b(Provider::GetInstance()); | |
190 | |
191 EXPECT_EQ(provider_a.get(), provider_b.get()); | |
192 } | |
193 | |
194 TEST_F(DeviceOrientationProviderTest, BasicPushTest) { | |
195 scoped_refptr<MockOrientationFactory> orientation_factory( | |
196 new MockOrientationFactory()); | |
197 Init(MockOrientationFactory::CreateDataFetcher); | |
198 const Orientation kTestOrientation(true, 1, true, 2, true, 3); | |
199 | |
200 scoped_ptr<UpdateChecker> checker(new UpdateChecker(&pending_expectations_)); | |
201 checker->AddExpectation(kTestOrientation); | |
202 orientation_factory->SetOrientation(kTestOrientation); | |
203 provider_->AddObserver(checker.get()); | |
204 MessageLoop::current()->Run(); | |
205 | |
206 provider_->RemoveObserver(checker.get()); | |
207 } | |
208 | |
209 TEST_F(DeviceOrientationProviderTest, MultipleObserversPushTest) { | |
210 scoped_refptr<MockOrientationFactory> orientation_factory( | |
211 new MockOrientationFactory()); | |
212 Init(MockOrientationFactory::CreateDataFetcher); | |
213 const Orientation kTestOrientations[] = { | |
214 Orientation(true, 1, true, 2, true, 3), | |
215 Orientation(true, 4, true, 5, true, 6), | |
216 Orientation(true, 7, true, 8, true, 9)}; | |
217 | |
218 scoped_ptr<UpdateChecker> checker_a( | |
219 new UpdateChecker(&pending_expectations_)); | |
220 scoped_ptr<UpdateChecker> checker_b( | |
221 new UpdateChecker(&pending_expectations_)); | |
222 scoped_ptr<UpdateChecker> checker_c( | |
223 new UpdateChecker(&pending_expectations_)); | |
224 | |
225 checker_a->AddExpectation(kTestOrientations[0]); | |
226 orientation_factory->SetOrientation(kTestOrientations[0]); | |
227 provider_->AddObserver(checker_a.get()); | |
228 MessageLoop::current()->Run(); | |
229 | |
230 checker_a->AddExpectation(kTestOrientations[1]); | |
231 checker_b->AddExpectation(kTestOrientations[0]); | |
232 checker_b->AddExpectation(kTestOrientations[1]); | |
233 orientation_factory->SetOrientation(kTestOrientations[1]); | |
234 provider_->AddObserver(checker_b.get()); | |
235 MessageLoop::current()->Run(); | |
236 | |
237 provider_->RemoveObserver(checker_a.get()); | |
238 checker_b->AddExpectation(kTestOrientations[2]); | |
239 checker_c->AddExpectation(kTestOrientations[1]); | |
240 checker_c->AddExpectation(kTestOrientations[2]); | |
241 orientation_factory->SetOrientation(kTestOrientations[2]); | |
242 provider_->AddObserver(checker_c.get()); | |
243 MessageLoop::current()->Run(); | |
244 | |
245 provider_->RemoveObserver(checker_b.get()); | |
246 provider_->RemoveObserver(checker_c.get()); | |
247 } | |
248 | |
249 TEST_F(DeviceOrientationProviderTest, ObserverNotRemoved) { | |
250 scoped_refptr<MockOrientationFactory> orientation_factory( | |
251 new MockOrientationFactory()); | |
252 Init(MockOrientationFactory::CreateDataFetcher); | |
253 const Orientation kTestOrientation(true, 1, true, 2, true, 3); | |
254 const Orientation kTestOrientation2(true, 4, true, 5, true, 6); | |
255 | |
256 scoped_ptr<UpdateChecker> checker(new UpdateChecker(&pending_expectations_)); | |
257 checker->AddExpectation(kTestOrientation); | |
258 orientation_factory->SetOrientation(kTestOrientation); | |
259 provider_->AddObserver(checker.get()); | |
260 MessageLoop::current()->Run(); | |
261 | |
262 checker->AddExpectation(kTestOrientation2); | |
263 orientation_factory->SetOrientation(kTestOrientation2); | |
264 MessageLoop::current()->Run(); | |
265 | |
266 // Note that checker is not removed. This should not be a problem. | |
267 } | |
268 | |
269 TEST_F(DeviceOrientationProviderTest, StartFailing) { | |
270 scoped_refptr<MockOrientationFactory> orientation_factory( | |
271 new MockOrientationFactory()); | |
272 Init(MockOrientationFactory::CreateDataFetcher); | |
273 const Orientation kTestOrientation(true, 1, true, 2, true, 3); | |
274 | |
275 scoped_ptr<UpdateChecker> checker_a(new UpdateChecker( | |
276 &pending_expectations_)); | |
277 scoped_ptr<UpdateChecker> checker_b(new UpdateChecker( | |
278 &pending_expectations_)); | |
279 | |
280 orientation_factory->SetOrientation(kTestOrientation); | |
281 checker_a->AddExpectation(kTestOrientation); | |
282 provider_->AddObserver(checker_a.get()); | |
283 MessageLoop::current()->Run(); | |
284 | |
285 checker_a->AddExpectation(Orientation::Empty()); | |
286 orientation_factory->SetOrientation(Orientation::Empty()); | |
287 MessageLoop::current()->Run(); | |
288 | |
289 checker_b->AddExpectation(Orientation::Empty()); | |
290 provider_->AddObserver(checker_b.get()); | |
291 MessageLoop::current()->Run(); | |
292 | |
293 provider_->RemoveObserver(checker_a.get()); | |
294 provider_->RemoveObserver(checker_b.get()); | |
295 } | |
296 | |
297 TEST_F(DeviceOrientationProviderTest, StartStopStart) { | |
298 scoped_refptr<MockOrientationFactory> orientation_factory( | |
299 new MockOrientationFactory()); | |
300 Init(MockOrientationFactory::CreateDataFetcher); | |
301 const Orientation kTestOrientation(true, 1, true, 2, true, 3); | |
302 const Orientation kTestOrientation2(true, 4, true, 5, true, 6); | |
303 | |
304 scoped_ptr<UpdateChecker> checker_a(new UpdateChecker( | |
305 &pending_expectations_)); | |
306 scoped_ptr<UpdateChecker> checker_b(new UpdateChecker( | |
307 &pending_expectations_)); | |
308 | |
309 checker_a->AddExpectation(kTestOrientation); | |
310 orientation_factory->SetOrientation(kTestOrientation); | |
311 provider_->AddObserver(checker_a.get()); | |
312 MessageLoop::current()->Run(); | |
313 | |
314 provider_->RemoveObserver(checker_a.get()); // This stops the Provider. | |
315 | |
316 checker_b->AddExpectation(kTestOrientation2); | |
317 orientation_factory->SetOrientation(kTestOrientation2); | |
318 provider_->AddObserver(checker_b.get()); | |
319 MessageLoop::current()->Run(); | |
320 | |
321 provider_->RemoveObserver(checker_b.get()); | |
322 } | |
323 | |
324 TEST_F(DeviceOrientationProviderTest, SignificantlyDifferent) { | |
325 scoped_refptr<MockOrientationFactory> orientation_factory( | |
326 new MockOrientationFactory()); | |
327 Init(MockOrientationFactory::CreateDataFetcher); | |
328 | |
329 // Values that should be well below or above the implementation's | |
330 // significane threshold. | |
331 const double kInsignificantDifference = 1e-6; | |
332 const double kSignificantDifference = 30; | |
333 const double kAlpha = 4, kBeta = 5, kGamma = 6; | |
334 | |
335 const Orientation first_orientation(true, kAlpha, true, kBeta, true, kGamma); | |
336 | |
337 const Orientation second_orientation(true, kAlpha + kInsignificantDifference, | |
338 true, kBeta + kInsignificantDifference, | |
339 true, kGamma + kInsignificantDifference); | |
340 | |
341 const Orientation third_orientation(true, kAlpha + kSignificantDifference, | |
342 true, kBeta + kSignificantDifference, | |
343 true, kGamma + kSignificantDifference); | |
344 | |
345 scoped_ptr<UpdateChecker> checker_a(new UpdateChecker( | |
346 &pending_expectations_)); | |
347 scoped_ptr<UpdateChecker> checker_b(new UpdateChecker( | |
348 &pending_expectations_)); | |
349 | |
350 | |
351 orientation_factory->SetOrientation(first_orientation); | |
352 checker_a->AddExpectation(first_orientation); | |
353 provider_->AddObserver(checker_a.get()); | |
354 MessageLoop::current()->Run(); | |
355 | |
356 // The observers should not see this insignificantly different orientation. | |
357 orientation_factory->SetOrientation(second_orientation); | |
358 checker_b->AddExpectation(first_orientation); | |
359 provider_->AddObserver(checker_b.get()); | |
360 MessageLoop::current()->Run(); | |
361 | |
362 orientation_factory->SetOrientation(third_orientation); | |
363 checker_a->AddExpectation(third_orientation); | |
364 checker_b->AddExpectation(third_orientation); | |
365 MessageLoop::current()->Run(); | |
366 | |
367 provider_->RemoveObserver(checker_a.get()); | |
368 provider_->RemoveObserver(checker_b.get()); | |
369 } | |
370 | |
371 } // namespace | |
372 | |
373 } // namespace device_orientation | |
OLD | NEW |