• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2013 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include "shill/cellular/active_passive_out_of_credits_detector.h"
18 
19 #include <string>
20 #include <vector>
21 
22 #include <gtest/gtest.h>
23 
24 #include "shill/cellular/mock_cellular.h"
25 #include "shill/cellular/mock_cellular_service.h"
26 #include "shill/cellular/mock_modem_info.h"
27 #include "shill/mock_connection.h"
28 #include "shill/mock_connection_health_checker.h"
29 #include "shill/mock_device_info.h"
30 #include "shill/mock_manager.h"
31 #include "shill/mock_traffic_monitor.h"
32 #include "shill/test_event_dispatcher.h"
33 
34 using base::Bind;
35 using base::Unretained;
36 using std::string;
37 using std::vector;
38 using testing::_;
39 using testing::AnyNumber;
40 using testing::Mock;
41 using testing::NiceMock;
42 using testing::Return;
43 using testing::ReturnPointee;
44 using testing::ReturnRef;
45 using testing::StrictMock;
46 
47 namespace shill {
48 
49 class ActivePassiveOutOfCreditsDetectorTest : public testing::Test {
50  public:
ActivePassiveOutOfCreditsDetectorTest()51   ActivePassiveOutOfCreditsDetectorTest()
52       : modem_info_(nullptr, &dispatcher_, &metrics_, &manager_),
53         device_info_(modem_info_.control_interface(), modem_info_.dispatcher(),
54                      modem_info_.metrics(), modem_info_.manager()),
55         manager_(modem_info_.control_interface(), modem_info_.dispatcher(),
56                  modem_info_.metrics()),
57         metrics_(modem_info_.dispatcher()),
58         cellular_(new NiceMock<MockCellular>(&modem_info_,
59                                              "usb0",
60                                              kAddress,
61                                              3,
62                                              Cellular::kTypeCDMA,
63                                              "",
64                                              "")),
65         service_(new NiceMock<MockCellularService>(&modem_info_, cellular_)),
66         connection_(new NiceMock<MockConnection>(&device_info_)),
67         out_of_credits_detector_(
68             new ActivePassiveOutOfCreditsDetector(
69                 modem_info_.dispatcher(), modem_info_.manager(),
70                 modem_info_.metrics(), service_.get())) {}
71 
SetUp()72   virtual void SetUp() {
73     service_->connection_ = connection_;
74     cellular_->service_ = service_;
75     service_->SetRoamingState(kRoamingStateHome);
76     ON_CALL(*connection_, interface_name())
77         .WillByDefault(ReturnRef(interface_name_));
78     ON_CALL(*connection_, dns_servers())
79         .WillByDefault(ReturnRef(dns_servers_));
80     ON_CALL(manager_, GetPortalCheckURL())
81         .WillByDefault(ReturnRef(portal_check_url_));
82     ON_CALL(*service_, explicitly_disconnected()).WillByDefault(Return(false));
83     ON_CALL(*service_, resume_start_time())
84         .WillByDefault(ReturnRef(resume_start_time_));
85   }
86 
TearDown()87   virtual void TearDown() {
88     cellular_->service_ = nullptr;  // Break circular reference.
89   }
90 
OnConnectionHealthCheckerResult(ConnectionHealthChecker::Result result)91   void OnConnectionHealthCheckerResult(
92       ConnectionHealthChecker::Result result) {}
93 
94  protected:
95   static const char kAddress[];
96 
SetMockServiceState(Service::ConnectState old_state,Service::ConnectState new_state)97   void SetMockServiceState(Service::ConnectState old_state,
98                            Service::ConnectState new_state) {
99     out_of_credits_detector_->NotifyServiceStateChanged(old_state, new_state);
100   }
101 
SetTrafficMonitor(TrafficMonitor * traffic_monitor)102   void SetTrafficMonitor(TrafficMonitor* traffic_monitor) {
103     out_of_credits_detector_->set_traffic_monitor(traffic_monitor);
104   }
105 
SetConnectionHealthChecker(ConnectionHealthChecker * health_checker)106   void SetConnectionHealthChecker(ConnectionHealthChecker* health_checker) {
107     out_of_credits_detector_->set_connection_health_checker(health_checker);
108   }
109 
110   EventDispatcherForTest dispatcher_;
111   MockModemInfo modem_info_;
112   NiceMock<MockDeviceInfo> device_info_;
113   NiceMock<MockManager> manager_;
114   NiceMock<MockMetrics> metrics_;
115   scoped_refptr<NiceMock<MockCellular>> cellular_;
116   scoped_refptr<NiceMock<MockCellularService>> service_;
117   scoped_refptr<NiceMock<MockConnection>> connection_;
118   string interface_name_;
119   vector<string> dns_servers_;
120   string portal_check_url_;
121   base::Time resume_start_time_;
122   std::unique_ptr<ActivePassiveOutOfCreditsDetector> out_of_credits_detector_;
123 };
124 
125 const char ActivePassiveOutOfCreditsDetectorTest::kAddress[] = "000102030405";
126 
TEST_F(ActivePassiveOutOfCreditsDetectorTest,ConnectDisconnectLoopOutOfCreditsDetected)127 TEST_F(ActivePassiveOutOfCreditsDetectorTest,
128     ConnectDisconnectLoopOutOfCreditsDetected) {
129   EXPECT_CALL(*service_, Connect(_, _)).Times(2);
130   SetMockServiceState(Service::kStateIdle, Service::kStateAssociating);
131   SetMockServiceState(Service::kStateAssociating, Service::kStateConnected);
132   SetMockServiceState(Service::kStateConnected, Service::kStateFailure);
133   EXPECT_TRUE(out_of_credits_detector_->IsDetecting());
134   dispatcher_.DispatchPendingEvents();
135   SetMockServiceState(Service::kStateIdle, Service::kStateAssociating);
136   SetMockServiceState(Service::kStateAssociating, Service::kStateConfiguring);
137   SetMockServiceState(Service::kStateConfiguring, Service::kStateIdle);
138   EXPECT_TRUE(out_of_credits_detector_->IsDetecting());
139   dispatcher_.DispatchPendingEvents();
140   SetMockServiceState(Service::kStateIdle, Service::kStateAssociating);
141   SetMockServiceState(Service::kStateAssociating, Service::kStateConnected);
142   SetMockServiceState(Service::kStateConnected, Service::kStateIdle);
143   EXPECT_TRUE(out_of_credits_detector_->out_of_credits());
144   EXPECT_FALSE(out_of_credits_detector_->IsDetecting());
145 }
146 
TEST_F(ActivePassiveOutOfCreditsDetectorTest,ConnectDisconnectLoopDetectionNotSkippedAfterSlowResume)147 TEST_F(ActivePassiveOutOfCreditsDetectorTest,
148     ConnectDisconnectLoopDetectionNotSkippedAfterSlowResume) {
149   resume_start_time_ =
150       base::Time::Now() -
151       base::TimeDelta::FromSeconds(
152       ActivePassiveOutOfCreditsDetector::kOutOfCreditsResumeIgnoreSeconds + 1);
153   EXPECT_CALL(*service_, Connect(_, _)).Times(2);
154   SetMockServiceState(Service::kStateIdle, Service::kStateAssociating);
155   SetMockServiceState(Service::kStateAssociating, Service::kStateFailure);
156   EXPECT_TRUE(out_of_credits_detector_->IsDetecting());
157   dispatcher_.DispatchPendingEvents();
158   SetMockServiceState(Service::kStateIdle, Service::kStateAssociating);
159   SetMockServiceState(Service::kStateAssociating, Service::kStateConfiguring);
160   SetMockServiceState(Service::kStateConfiguring, Service::kStateIdle);
161   EXPECT_TRUE(out_of_credits_detector_->IsDetecting());
162   dispatcher_.DispatchPendingEvents();
163   SetMockServiceState(Service::kStateIdle, Service::kStateAssociating);
164   SetMockServiceState(Service::kStateAssociating, Service::kStateConnected);
165   SetMockServiceState(Service::kStateConnected, Service::kStateIdle);
166   EXPECT_TRUE(out_of_credits_detector_->out_of_credits());
167   EXPECT_FALSE(out_of_credits_detector_->IsDetecting());
168 }
169 
TEST_F(ActivePassiveOutOfCreditsDetectorTest,ConnectDisconnectLoopDetectionSkippedAfterResume)170 TEST_F(ActivePassiveOutOfCreditsDetectorTest,
171     ConnectDisconnectLoopDetectionSkippedAfterResume) {
172   resume_start_time_ = base::Time::Now();
173   ON_CALL(*service_, resume_start_time())
174       .WillByDefault(ReturnRef(resume_start_time_));
175   EXPECT_CALL(*service_, Connect(_, _)).Times(0);
176   SetMockServiceState(Service::kStateIdle, Service::kStateAssociating);
177   SetMockServiceState(Service::kStateAssociating, Service::kStateConnected);
178   SetMockServiceState(Service::kStateConnected, Service::kStateIdle);
179   EXPECT_FALSE(out_of_credits_detector_->out_of_credits());
180   EXPECT_FALSE(out_of_credits_detector_->IsDetecting());
181   // There should not be any pending connect requests but dispatch pending
182   // events anyway to be sure.
183   dispatcher_.DispatchPendingEvents();
184 }
185 
TEST_F(ActivePassiveOutOfCreditsDetectorTest,ConnectDisconnectLoopDetectionSkippedAlreadyOutOfCredits)186 TEST_F(ActivePassiveOutOfCreditsDetectorTest,
187     ConnectDisconnectLoopDetectionSkippedAlreadyOutOfCredits) {
188   EXPECT_CALL(*service_, Connect(_, _)).Times(0);
189   out_of_credits_detector_->ReportOutOfCredits(true);
190   SetMockServiceState(Service::kStateAssociating, Service::kStateConnected);
191   SetMockServiceState(Service::kStateConnected, Service::kStateIdle);
192   EXPECT_FALSE(out_of_credits_detector_->IsDetecting());
193   // There should not be any pending connect requests but dispatch pending
194   // events anyway to be sure.
195   dispatcher_.DispatchPendingEvents();
196 }
197 
TEST_F(ActivePassiveOutOfCreditsDetectorTest,ConnectDisconnectLoopDetectionSkippedExplicitDisconnect)198 TEST_F(ActivePassiveOutOfCreditsDetectorTest,
199     ConnectDisconnectLoopDetectionSkippedExplicitDisconnect) {
200   EXPECT_CALL(*service_, Connect(_, _)).Times(0);
201   SetMockServiceState(Service::kStateIdle, Service::kStateAssociating);
202   SetMockServiceState(Service::kStateAssociating, Service::kStateConnected);
203   EXPECT_CALL(*service_, explicitly_disconnected()).WillOnce(Return(true));
204   SetMockServiceState(Service::kStateConnected, Service::kStateIdle);
205   EXPECT_FALSE(out_of_credits_detector_->out_of_credits());
206   EXPECT_FALSE(out_of_credits_detector_->IsDetecting());
207   // There should not be any pending connect requests but dispatch pending
208   // events anyway to be sure.
209   dispatcher_.DispatchPendingEvents();
210 }
211 
TEST_F(ActivePassiveOutOfCreditsDetectorTest,ConnectDisconnectLoopDetectionConnectionNotDropped)212 TEST_F(ActivePassiveOutOfCreditsDetectorTest,
213     ConnectDisconnectLoopDetectionConnectionNotDropped) {
214   EXPECT_CALL(*service_, Connect(_, _)).Times(0);
215   SetMockServiceState(Service::kStateIdle, Service::kStateAssociating);
216   SetMockServiceState(Service::kStateAssociating, Service::kStateConfiguring);
217   SetMockServiceState(Service::kStateConfiguring, Service::kStateConnected);
218   EXPECT_FALSE(out_of_credits_detector_->out_of_credits());
219   EXPECT_FALSE(out_of_credits_detector_->IsDetecting());
220   // There should not be any pending connect requests but dispatch pending
221   // events anyway to be sure.
222   dispatcher_.DispatchPendingEvents();
223 }
224 
TEST_F(ActivePassiveOutOfCreditsDetectorTest,ConnectDisconnectLoopDetectionIntermittentNetwork)225 TEST_F(ActivePassiveOutOfCreditsDetectorTest,
226     ConnectDisconnectLoopDetectionIntermittentNetwork) {
227   EXPECT_CALL(*service_, Connect(_, _)).Times(0);
228   SetMockServiceState(Service::kStateAssociating, Service::kStateConnected);
229   out_of_credits_detector_->connect_start_time_ =
230       base::Time::Now() -
231       base::TimeDelta::FromSeconds(
232           ActivePassiveOutOfCreditsDetector::
233           kOutOfCreditsConnectionDropSeconds + 1);
234   SetMockServiceState(Service::kStateConnected, Service::kStateIdle);
235   EXPECT_FALSE(out_of_credits_detector_->out_of_credits());
236   EXPECT_FALSE(out_of_credits_detector_->IsDetecting());
237   // There should not be any pending connect requests but dispatch pending
238   // events anyway to be sure.
239   dispatcher_.DispatchPendingEvents();
240 }
241 
TEST_F(ActivePassiveOutOfCreditsDetectorTest,StartTrafficMonitor)242 TEST_F(ActivePassiveOutOfCreditsDetectorTest, StartTrafficMonitor) {
243   MockTrafficMonitor* traffic_monitor = new StrictMock<MockTrafficMonitor>();
244   SetTrafficMonitor(traffic_monitor);  // Passes ownership.
245 
246   // Traffic monitor should only start when the service is connected.
247   EXPECT_CALL(*traffic_monitor, Start()).Times(1);
248   SetMockServiceState(Service::kStateAssociating, Service::kStateConnected);
249   Mock::VerifyAndClearExpectations(traffic_monitor);
250 
251   // Traffic monitor should not start for other state transitions.
252   EXPECT_CALL(*traffic_monitor, Start()).Times(0);
253   EXPECT_CALL(*traffic_monitor, Stop()).Times(AnyNumber());
254   SetMockServiceState(Service::kStateConnected, Service::kStateIdle);
255   SetMockServiceState(Service::kStateIdle, Service::kStateConfiguring);
256   SetMockServiceState(Service::kStateConfiguring, Service::kStateFailure);
257   SetMockServiceState(Service::kStateIdle, Service::kStateAssociating);
258   SetMockServiceState(Service::kStateConfiguring, Service::kStatePortal);
259   SetMockServiceState(Service::kStatePortal, Service::kStateOnline);
260 }
261 
TEST_F(ActivePassiveOutOfCreditsDetectorTest,StopTrafficMonitor)262 TEST_F(ActivePassiveOutOfCreditsDetectorTest, StopTrafficMonitor) {
263   // Traffic monitor should stop when the service is disconnected.
264   MockTrafficMonitor* traffic_monitor = new StrictMock<MockTrafficMonitor>();
265   SetTrafficMonitor(traffic_monitor);  // Passes ownership.
266   EXPECT_CALL(*traffic_monitor, Start());
267   EXPECT_CALL(*traffic_monitor, Stop());
268   SetMockServiceState(Service::kStateAssociating, Service::kStateConnected);
269   SetMockServiceState(Service::kStateConnected, Service::kStateIdle);
270   Mock::VerifyAndClearExpectations(traffic_monitor);
271 
272   EXPECT_CALL(*traffic_monitor, Start());
273   EXPECT_CALL(*traffic_monitor, Stop());
274   SetMockServiceState(Service::kStateIdle, Service::kStateConnected);
275   SetMockServiceState(Service::kStateConnected, Service::kStateFailure);
276   Mock::VerifyAndClearExpectations(traffic_monitor);
277 
278   // Need an additional call to Stop() because |traffic_monitor| destructor
279   // will call stop.
280   EXPECT_CALL(*traffic_monitor, Stop());
281 }
282 
TEST_F(ActivePassiveOutOfCreditsDetectorTest,OnNoNetworkRouting)283 TEST_F(ActivePassiveOutOfCreditsDetectorTest, OnNoNetworkRouting) {
284   // Make sure the connection health checker starts when there is no network
285   // routing.
286   EXPECT_FALSE(out_of_credits_detector_->out_of_credits());
287   MockConnectionHealthChecker* health_checker =
288       new MockConnectionHealthChecker(
289           service_->connection(),
290           modem_info_.dispatcher(),
291           manager_.health_checker_remote_ips(),
292           Bind(&ActivePassiveOutOfCreditsDetectorTest::
293                OnConnectionHealthCheckerResult,
294                Unretained(this)));
295   SetConnectionHealthChecker(health_checker);  // Passes ownership.
296   EXPECT_CALL(*health_checker, Start());
297   out_of_credits_detector_->OnNoNetworkRouting(0);
298   EXPECT_FALSE(out_of_credits_detector_->out_of_credits());
299   Mock::VerifyAndClearExpectations(health_checker);
300 
301   // Make sure connection health checker does not start again if there is a
302   // health check in progress.
303   EXPECT_CALL(*health_checker, health_check_in_progress())
304       .WillOnce(Return(true));
305   EXPECT_CALL(*health_checker, Start()).Times(0);
306   out_of_credits_detector_->OnNoNetworkRouting(0);
307 }
308 
TEST_F(ActivePassiveOutOfCreditsDetectorTest,OnConnectionHealthCheckerResult)309 TEST_F(ActivePassiveOutOfCreditsDetectorTest,
310     OnConnectionHealthCheckerResult) {
311   EXPECT_FALSE(out_of_credits_detector_->out_of_credits());
312   EXPECT_CALL(*service_, Disconnect(_, _)).Times(0);
313   out_of_credits_detector_->OnConnectionHealthCheckerResult(
314       ConnectionHealthChecker::kResultUnknown);
315   EXPECT_FALSE(out_of_credits_detector_->out_of_credits());
316   out_of_credits_detector_->OnConnectionHealthCheckerResult(
317       ConnectionHealthChecker::kResultConnectionFailure);
318   EXPECT_FALSE(out_of_credits_detector_->out_of_credits());
319   Mock::VerifyAndClearExpectations(service_.get());
320 
321   EXPECT_CALL(*service_, Disconnect(_,
322       ::testing::StrEq("out-of-credits"))).
323           Times(1);
324   out_of_credits_detector_->OnConnectionHealthCheckerResult(
325       ConnectionHealthChecker::kResultCongestedTxQueue);
326   EXPECT_TRUE(out_of_credits_detector_->out_of_credits());
327 }
328 
329 }  // namespace shill
330