• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2012 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/link_monitor.h"
18 
19 #include <string>
20 
21 #include <base/bind.h>
22 #include <gtest/gtest.h>
23 
24 #include "shill/logging.h"
25 #include "shill/mock_active_link_monitor.h"
26 #include "shill/mock_connection.h"
27 #include "shill/mock_control.h"
28 #include "shill/mock_device_info.h"
29 #include "shill/mock_event_dispatcher.h"
30 #include "shill/mock_log.h"
31 #include "shill/mock_metrics.h"
32 #include "shill/mock_passive_link_monitor.h"
33 #include "shill/net/byte_string.h"
34 #include "shill/net/mock_time.h"
35 
36 using base::Bind;
37 using base::Unretained;
38 using std::string;
39 using testing::_;
40 using testing::AnyNumber;
41 using testing::HasSubstr;
42 using testing::Invoke;
43 using testing::Mock;
44 using testing::NiceMock;
45 using testing::Return;
46 using testing::ReturnRef;
47 using testing::SetArgumentPointee;
48 using testing::StrictMock;
49 using testing::Test;
50 
51 namespace shill {
52 
53 namespace {
54 const uint8_t kGatewayMACAddress[] = { 0, 1, 2, 3, 4, 5 };
55 }  // namespace
56 
57 class LinkMonitorObserver {
58  public:
LinkMonitorObserver()59   LinkMonitorObserver()
60       : failure_callback_(
61             Bind(&LinkMonitorObserver::OnFailureCallback, Unretained(this))),
62         gateway_change_callback_(
63             Bind(&LinkMonitorObserver::OnGatewayChangeCallback,
64                  Unretained(this))) {}
~LinkMonitorObserver()65   virtual ~LinkMonitorObserver() {}
66 
67   MOCK_METHOD0(OnFailureCallback, void());
68   MOCK_METHOD0(OnGatewayChangeCallback, void());
69 
failure_callback()70   const LinkMonitor::FailureCallback failure_callback() {
71     return failure_callback_;
72   }
73 
gateway_change_callback()74   const LinkMonitor::GatewayChangeCallback gateway_change_callback() {
75     return gateway_change_callback_;
76   }
77 
78  private:
79   LinkMonitor::FailureCallback failure_callback_;
80   LinkMonitor::GatewayChangeCallback gateway_change_callback_;
81 
82   DISALLOW_COPY_AND_ASSIGN(LinkMonitorObserver);
83 };
84 
85 class LinkMonitorTest : public Test {
86  public:
LinkMonitorTest()87   LinkMonitorTest()
88       : metrics_(&dispatcher_),
89         device_info_(&control_, nullptr, nullptr, nullptr),
90         connection_(new StrictMock<MockConnection>(&device_info_)),
91         active_link_monitor_(new MockActiveLinkMonitor()),
92         passive_link_monitor_(new MockPassiveLinkMonitor()),
93         monitor_(connection_,
94                  &dispatcher_,
95                  &metrics_,
96                  &device_info_,
97                  observer_.failure_callback(),
98                  observer_.gateway_change_callback()) {}
~LinkMonitorTest()99   virtual ~LinkMonitorTest() {}
100 
SetUp()101   virtual void SetUp() {
102     monitor_.active_link_monitor_.reset(active_link_monitor_);
103     monitor_.passive_link_monitor_.reset(passive_link_monitor_);
104     monitor_.time_ = &time_;
105 
106     time_val_.tv_sec = 0;
107     time_val_.tv_usec = 0;
108     EXPECT_CALL(time_, GetTimeMonotonic(_))
109         .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
110     EXPECT_CALL(*connection_, technology())
111         .WillRepeatedly(Return(Technology::kEthernet));
112   }
113 
AdvanceTime(int time_ms)114   void AdvanceTime(int time_ms) {
115     struct timeval adv_time = {
116       static_cast<time_t>(time_ms/1000),
117       static_cast<time_t>((time_ms % 1000) * 1000) };
118     timeradd(&time_val_, &adv_time, &time_val_);
119     EXPECT_CALL(time_, GetTimeMonotonic(_))
120         .WillRepeatedly(DoAll(SetArgumentPointee<0>(time_val_), Return(0)));
121   }
122 
SetGatewayMacAddress(const ByteString & gateway_mac_address)123   void SetGatewayMacAddress(const ByteString& gateway_mac_address) {
124     monitor_.gateway_mac_address_ = gateway_mac_address;
125   }
126 
VerifyGatewayMacAddress(const ByteString & gateway_mac_address)127   void VerifyGatewayMacAddress(const ByteString& gateway_mac_address) {
128     EXPECT_TRUE(monitor_.gateway_mac_address_.Equals(gateway_mac_address));
129   }
130 
TriggerActiveLinkMonitorFailure(Metrics::LinkMonitorFailure failure,int broadcast_failure_count,int unicast_failure_count)131   void TriggerActiveLinkMonitorFailure(Metrics::LinkMonitorFailure failure,
132                                        int broadcast_failure_count,
133                                        int unicast_failure_count) {
134     monitor_.OnActiveLinkMonitorFailure(failure,
135                                     broadcast_failure_count,
136                                     unicast_failure_count);
137   }
138 
TriggerActiveLinkMonitorSuccess()139   void TriggerActiveLinkMonitorSuccess() {
140     monitor_.OnActiveLinkMonitorSuccess();
141   }
142 
TriggerPassiveLinkMonitorResultCallback(bool status)143   void TriggerPassiveLinkMonitorResultCallback(bool status) {
144     monitor_.OnPassiveLinkMonitorResultCallback(status);
145   }
146 
147  protected:
148   MockEventDispatcher dispatcher_;
149   StrictMock<MockMetrics> metrics_;
150   MockControl control_;
151   NiceMock<MockDeviceInfo> device_info_;
152   scoped_refptr<MockConnection> connection_;
153   MockTime time_;
154   struct timeval time_val_;
155   MockActiveLinkMonitor* active_link_monitor_;
156   MockPassiveLinkMonitor* passive_link_monitor_;
157   LinkMonitorObserver observer_;
158   LinkMonitor monitor_;
159 };
160 
161 MATCHER_P(IsMacAddress, mac_address, "") {
162   return mac_address.Equals(arg);
163 }
164 
TEST_F(LinkMonitorTest,Start)165 TEST_F(LinkMonitorTest, Start) {
166   EXPECT_CALL(*active_link_monitor_,
167               Start(ActiveLinkMonitor::kDefaultTestPeriodMilliseconds))
168       .WillOnce(Return(false));
169   EXPECT_FALSE(monitor_.Start());
170   Mock::VerifyAndClearExpectations(active_link_monitor_);
171 
172   EXPECT_CALL(*active_link_monitor_,
173               Start(ActiveLinkMonitor::kDefaultTestPeriodMilliseconds))
174       .WillOnce(Return(true));
175   EXPECT_TRUE(monitor_.Start());
176   Mock::VerifyAndClearExpectations(active_link_monitor_);
177 }
178 
TEST_F(LinkMonitorTest,OnAfterResume)179 TEST_F(LinkMonitorTest, OnAfterResume) {
180   ByteString gateway_mac(kGatewayMACAddress, arraysize(kGatewayMACAddress));
181   const bool kGatewayUnicastArpSupport = true;
182   SetGatewayMacAddress(gateway_mac);
183   // Verify gateway settings persist when link monitor is restarted, and
184   // active link monitor is started with fast test period.
185   EXPECT_CALL(*active_link_monitor_, Stop()).Times(1);
186   EXPECT_CALL(*passive_link_monitor_, Stop()).Times(1);
187   EXPECT_CALL(*active_link_monitor_, gateway_supports_unicast_arp())
188       .WillOnce(Return(kGatewayUnicastArpSupport));
189   EXPECT_CALL(*active_link_monitor_,
190               set_gateway_mac_address(IsMacAddress(gateway_mac)));
191   EXPECT_CALL(*active_link_monitor_,
192               set_gateway_supports_unicast_arp(kGatewayUnicastArpSupport));
193   EXPECT_CALL(*active_link_monitor_,
194               Start(ActiveLinkMonitor::kFastTestPeriodMilliseconds));
195   monitor_.OnAfterResume();
196   VerifyGatewayMacAddress(gateway_mac);
197   Mock::VerifyAndClearExpectations(active_link_monitor_);
198   Mock::VerifyAndClearExpectations(passive_link_monitor_);
199 }
200 
TEST_F(LinkMonitorTest,OnActiveLinkMonitorFailure)201 TEST_F(LinkMonitorTest, OnActiveLinkMonitorFailure) {
202   // Start link monitor.
203   EXPECT_CALL(*active_link_monitor_,
204               Start(ActiveLinkMonitor::kDefaultTestPeriodMilliseconds))
205       .WillOnce(Return(true));
206   EXPECT_TRUE(monitor_.Start());
207   Mock::VerifyAndClearExpectations(active_link_monitor_);
208 
209   const int kBroadcastFailureCount = 5;
210   const int kUnicastFailureCount = 3;
211   const int kElapsedTimeMilliseconds = 5000;
212 
213   // Active monitor failed after 5 seconds.
214   EXPECT_CALL(observer_, OnFailureCallback()).Times(1);
215   EXPECT_CALL(metrics_, SendEnumToUMA(
216       HasSubstr("LinkMonitorFailure"),
217       Metrics::kLinkMonitorFailureThresholdReached, _));
218   EXPECT_CALL(metrics_, SendToUMA(
219       HasSubstr("LinkMonitorSecondsToFailure"), kElapsedTimeMilliseconds / 1000,
220       _, _, _));
221   EXPECT_CALL(metrics_, SendToUMA(
222       HasSubstr("BroadcastErrorsAtFailure"), kBroadcastFailureCount,
223       _, _, _));
224   EXPECT_CALL(metrics_, SendToUMA(
225       HasSubstr("UnicastErrorsAtFailure"), kUnicastFailureCount,
226       _, _, _));
227   AdvanceTime(kElapsedTimeMilliseconds);
228   TriggerActiveLinkMonitorFailure(Metrics::kLinkMonitorFailureThresholdReached,
229                                   kBroadcastFailureCount,
230                                   kUnicastFailureCount);
231 }
232 
TEST_F(LinkMonitorTest,OnActiveLinkMonitorSuccess)233 TEST_F(LinkMonitorTest, OnActiveLinkMonitorSuccess) {
234   ByteString gateway_mac(kGatewayMACAddress,
235                                arraysize(kGatewayMACAddress));
236   EXPECT_CALL(*active_link_monitor_, gateway_mac_address())
237       .WillRepeatedly(ReturnRef(gateway_mac));
238 
239   // Active link monitor succeed for the first time, gateway MAC address will be
240   // updated.
241   EXPECT_CALL(observer_, OnGatewayChangeCallback()).Times(1);
242   EXPECT_CALL(*passive_link_monitor_, Start(
243       PassiveLinkMonitor::kDefaultMonitorCycles)).Times(1);
244   TriggerActiveLinkMonitorSuccess();
245   VerifyGatewayMacAddress(gateway_mac);
246   Mock::VerifyAndClearExpectations(&observer_);
247   Mock::VerifyAndClearExpectations(passive_link_monitor_);
248 
249   // Active link monitor succeed again, gateway MAC address not changed.
250   EXPECT_CALL(observer_, OnGatewayChangeCallback()).Times(0);
251   EXPECT_CALL(*passive_link_monitor_, Start(
252       PassiveLinkMonitor::kDefaultMonitorCycles)).Times(1);
253   TriggerActiveLinkMonitorSuccess();
254   VerifyGatewayMacAddress(gateway_mac);
255   Mock::VerifyAndClearExpectations(&observer_);
256   Mock::VerifyAndClearExpectations(passive_link_monitor_);
257 }
258 
TEST_F(LinkMonitorTest,OnPassiveLinkMonitorResultCallback)259 TEST_F(LinkMonitorTest, OnPassiveLinkMonitorResultCallback) {
260   // Active link monitor should start regardless of the result of the passive
261   // link monitor.
262 
263   EXPECT_CALL(*active_link_monitor_,
264               Start(ActiveLinkMonitor::kDefaultTestPeriodMilliseconds));
265   TriggerPassiveLinkMonitorResultCallback(true);
266   Mock::VerifyAndClearExpectations(active_link_monitor_);
267 
268   EXPECT_CALL(*active_link_monitor_,
269               Start(ActiveLinkMonitor::kDefaultTestPeriodMilliseconds));
270   TriggerPassiveLinkMonitorResultCallback(false);
271   Mock::VerifyAndClearExpectations(active_link_monitor_);
272 }
273 
274 }  // namespace shill
275