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: 59 LinkMonitorObserver() 60 : failure_callback_( 61 Bind(&LinkMonitorObserver::OnFailureCallback, Unretained(this))), 62 gateway_change_callback_( 63 Bind(&LinkMonitorObserver::OnGatewayChangeCallback, 64 Unretained(this))) {} 65 virtual ~LinkMonitorObserver() {} 66 67 MOCK_METHOD0(OnFailureCallback, void()); 68 MOCK_METHOD0(OnGatewayChangeCallback, void()); 69 70 const LinkMonitor::FailureCallback failure_callback() { 71 return failure_callback_; 72 } 73 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: 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()) {} 99 virtual ~LinkMonitorTest() {} 100 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 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 123 void SetGatewayMacAddress(const ByteString& gateway_mac_address) { 124 monitor_.gateway_mac_address_ = gateway_mac_address; 125 } 126 127 void VerifyGatewayMacAddress(const ByteString& gateway_mac_address) { 128 EXPECT_TRUE(monitor_.gateway_mac_address_.Equals(gateway_mac_address)); 129 } 130 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 139 void TriggerActiveLinkMonitorSuccess() { 140 monitor_.OnActiveLinkMonitorSuccess(); 141 } 142 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 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 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 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 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 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