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