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 <vector>
6
7#include "base/memory/scoped_ptr.h"
8#include "base/strings/string_util.h"
9#include "base/strings/utf_string_conversions.h"
10#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
11#include "content/browser/geolocation/wifi_data_provider_common.h"
12#include "content/browser/geolocation/wifi_data_provider_manager.h"
13#include "testing/gmock/include/gmock/gmock.h"
14#include "testing/gtest/include/gtest/gtest.h"
15
16using testing::_;
17using testing::AtLeast;
18using testing::DoDefault;
19using testing::Invoke;
20using testing::Return;
21
22namespace content {
23
24class MockWlanApi : public WifiDataProviderCommon::WlanApiInterface {
25 public:
26  MockWlanApi() : calls_(0), bool_return_(true) {
27    ANNOTATE_BENIGN_RACE(&calls_, "This is a test-only data race on a counter");
28    ON_CALL(*this, GetAccessPointData(_))
29        .WillByDefault(Invoke(this, &MockWlanApi::GetAccessPointDataInternal));
30  }
31
32  MOCK_METHOD1(GetAccessPointData, bool(WifiData::AccessPointDataSet* data));
33
34  int calls_;
35  bool bool_return_;
36  WifiData::AccessPointDataSet data_out_;
37
38 private:
39  bool GetAccessPointDataInternal(WifiData::AccessPointDataSet* data) {
40    ++calls_;
41    *data = data_out_;
42    return bool_return_;
43  }
44};
45
46class MockPollingPolicy : public WifiPollingPolicy {
47 public:
48  MockPollingPolicy() {
49    ON_CALL(*this,PollingInterval())
50        .WillByDefault(Return(1));
51    ON_CALL(*this,NoWifiInterval())
52        .WillByDefault(Return(1));
53  }
54
55  MOCK_METHOD0(PollingInterval, int());
56  MOCK_METHOD0(NoWifiInterval, int());
57
58  virtual void UpdatePollingInterval(bool) {}
59};
60
61// Stops the specified (nested) message loop when the callback is called.
62class MessageLoopQuitter {
63 public:
64  explicit MessageLoopQuitter(base::MessageLoop* message_loop)
65      : message_loop_to_quit_(message_loop),
66        callback_(base::Bind(&MessageLoopQuitter::OnWifiDataUpdate,
67                             base::Unretained(this))) {
68    CHECK(message_loop_to_quit_ != NULL);
69  }
70
71  void OnWifiDataUpdate() {
72    // Provider should call back on client's thread.
73    EXPECT_EQ(base::MessageLoop::current(), message_loop_to_quit_);
74    message_loop_to_quit_->QuitNow();
75  }
76  base::MessageLoop* message_loop_to_quit_;
77  WifiDataProviderManager::WifiDataUpdateCallback callback_;
78};
79
80class WifiDataProviderCommonWithMock : public WifiDataProviderCommon {
81 public:
82  WifiDataProviderCommonWithMock()
83      : new_wlan_api_(new MockWlanApi),
84        new_polling_policy_(new MockPollingPolicy) {}
85
86  // WifiDataProviderCommon
87  virtual WlanApiInterface* NewWlanApi() OVERRIDE {
88    CHECK(new_wlan_api_ != NULL);
89    return new_wlan_api_.release();
90  }
91  virtual WifiPollingPolicy* NewPollingPolicy() OVERRIDE {
92    CHECK(new_polling_policy_ != NULL);
93    return new_polling_policy_.release();
94  }
95
96  scoped_ptr<MockWlanApi> new_wlan_api_;
97  scoped_ptr<MockPollingPolicy> new_polling_policy_;
98
99 private:
100  virtual ~WifiDataProviderCommonWithMock() {}
101
102  DISALLOW_COPY_AND_ASSIGN(WifiDataProviderCommonWithMock);
103};
104
105WifiDataProvider* CreateWifiDataProviderCommonWithMock() {
106  return new WifiDataProviderCommonWithMock;
107}
108
109// Main test fixture
110class GeolocationWifiDataProviderCommonTest : public testing::Test {
111 public:
112  GeolocationWifiDataProviderCommonTest()
113      : loop_quitter_(&main_message_loop_) {
114  }
115
116  virtual void SetUp() {
117    provider_ = new WifiDataProviderCommonWithMock;
118    wlan_api_ = provider_->new_wlan_api_.get();
119    polling_policy_ = provider_->new_polling_policy_.get();
120    provider_->AddCallback(&loop_quitter_.callback_);
121  }
122  virtual void TearDown() {
123    provider_->RemoveCallback(&loop_quitter_.callback_);
124    provider_->StopDataProvider();
125    provider_ = NULL;
126  }
127
128 protected:
129  base::MessageLoop main_message_loop_;
130  MessageLoopQuitter loop_quitter_;
131  scoped_refptr<WifiDataProviderCommonWithMock> provider_;
132  MockWlanApi* wlan_api_;
133  MockPollingPolicy* polling_policy_;
134};
135
136TEST_F(GeolocationWifiDataProviderCommonTest, CreateDestroy) {
137  // Test fixture members were SetUp correctly.
138  EXPECT_EQ(&main_message_loop_, base::MessageLoop::current());
139  EXPECT_TRUE(NULL != provider_.get());
140  EXPECT_TRUE(NULL != wlan_api_);
141}
142
143TEST_F(GeolocationWifiDataProviderCommonTest, RunNormal) {
144  EXPECT_CALL(*wlan_api_, GetAccessPointData(_))
145      .Times(AtLeast(1));
146  EXPECT_CALL(*polling_policy_, PollingInterval())
147      .Times(AtLeast(1));
148  provider_->StartDataProvider();
149  main_message_loop_.Run();
150  SUCCEED();
151}
152
153TEST_F(GeolocationWifiDataProviderCommonTest, NoWifi){
154  EXPECT_CALL(*polling_policy_, NoWifiInterval())
155      .Times(AtLeast(1));
156  EXPECT_CALL(*wlan_api_, GetAccessPointData(_))
157      .WillRepeatedly(Return(false));
158  provider_->StartDataProvider();
159  main_message_loop_.Run();
160}
161
162TEST_F(GeolocationWifiDataProviderCommonTest, IntermittentWifi){
163  EXPECT_CALL(*polling_policy_, PollingInterval())
164      .Times(AtLeast(1));
165  EXPECT_CALL(*polling_policy_, NoWifiInterval())
166      .Times(1);
167  EXPECT_CALL(*wlan_api_, GetAccessPointData(_))
168      .WillOnce(Return(true))
169      .WillOnce(Return(false))
170      .WillRepeatedly(DoDefault());
171
172  AccessPointData single_access_point;
173  single_access_point.channel = 2;
174  single_access_point.mac_address = 3;
175  single_access_point.radio_signal_strength = 4;
176  single_access_point.signal_to_noise = 5;
177  single_access_point.ssid = base::ASCIIToUTF16("foossid");
178  wlan_api_->data_out_.insert(single_access_point);
179
180  provider_->StartDataProvider();
181  main_message_loop_.Run();
182  main_message_loop_.Run();
183}
184
185#if defined(OS_MACOSX)
186#define MAYBE_DoAnEmptyScan DISABLED_DoAnEmptyScan
187#else
188#define MAYBE_DoAnEmptyScan DoAnEmptyScan
189#endif
190TEST_F(GeolocationWifiDataProviderCommonTest, MAYBE_DoAnEmptyScan) {
191  EXPECT_CALL(*wlan_api_, GetAccessPointData(_))
192      .Times(AtLeast(1));
193  EXPECT_CALL(*polling_policy_, PollingInterval())
194      .Times(AtLeast(1));
195  provider_->StartDataProvider();
196  main_message_loop_.Run();
197  EXPECT_EQ(wlan_api_->calls_, 1);
198  WifiData data;
199  EXPECT_TRUE(provider_->GetData(&data));
200  EXPECT_EQ(0, static_cast<int>(data.access_point_data.size()));
201}
202
203#if defined(OS_MACOSX)
204#define MAYBE_DoScanWithResults DISABLED_DoScanWithResults
205#else
206#define MAYBE_DoScanWithResults DoScanWithResults
207#endif
208TEST_F(GeolocationWifiDataProviderCommonTest, MAYBE_DoScanWithResults) {
209  EXPECT_CALL(*wlan_api_, GetAccessPointData(_))
210      .Times(AtLeast(1));
211  EXPECT_CALL(*polling_policy_, PollingInterval())
212      .Times(AtLeast(1));
213  AccessPointData single_access_point;
214  single_access_point.channel = 2;
215  single_access_point.mac_address = 3;
216  single_access_point.radio_signal_strength = 4;
217  single_access_point.signal_to_noise = 5;
218  single_access_point.ssid = base::ASCIIToUTF16("foossid");
219  wlan_api_->data_out_.insert(single_access_point);
220
221  provider_->StartDataProvider();
222  main_message_loop_.Run();
223  EXPECT_EQ(wlan_api_->calls_, 1);
224  WifiData data;
225  EXPECT_TRUE(provider_->GetData(&data));
226  EXPECT_EQ(1, static_cast<int>(data.access_point_data.size()));
227  EXPECT_EQ(single_access_point.ssid, data.access_point_data.begin()->ssid);
228}
229
230TEST_F(GeolocationWifiDataProviderCommonTest, RegisterUnregister) {
231  MessageLoopQuitter loop_quitter(&main_message_loop_);
232  WifiDataProviderManager::SetFactoryForTesting(
233      CreateWifiDataProviderCommonWithMock);
234  WifiDataProviderManager::Register(&loop_quitter.callback_);
235  main_message_loop_.Run();
236  WifiDataProviderManager::Unregister(&loop_quitter.callback_);
237  WifiDataProviderManager::ResetFactoryForTesting();
238}
239
240}  // namespace content
241