1 //
2 // Copyright (C) 2015 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/passive_link_monitor.h"
18
19 #include <net/if_arp.h>
20
21 #include <string>
22
23 #include <gtest/gtest.h>
24
25 #include "shill/arp_client_test_helper.h"
26 #include "shill/arp_packet.h"
27 #include "shill/logging.h"
28 #include "shill/mock_arp_client.h"
29 #include "shill/mock_connection.h"
30 #include "shill/mock_control.h"
31 #include "shill/mock_device_info.h"
32 #include "shill/mock_event_dispatcher.h"
33 #include "shill/mock_log.h"
34 #include "shill/net/byte_string.h"
35 #include "shill/net/ip_address.h"
36
37 using base::Bind;
38 using base::Unretained;
39 using std::string;
40 using testing::_;
41 using testing::AnyNumber;
42 using testing::HasSubstr;
43 using testing::Mock;
44 using testing::NiceMock;
45 using testing::Return;
46 using testing::ReturnRef;
47 using testing::StrictMock;
48 using testing::Test;
49
50 namespace shill {
51
52 namespace {
53 const char kInterfaceName[] = "test-interface";
54 const char kLocalIPAddress[] = "10.0.1.1";
55 const uint8_t kLocalMACAddress[] = { 0, 1, 2, 3, 4, 5 };
56 const char kRemoteIPAddress[] = "10.0.1.2";
57 const uint8_t kRemoteMACAddress[] = { 6, 7, 8, 9, 10, 11 };
58 } // namespace
59
60 class ResultCallbackObserver {
61 public:
ResultCallbackObserver()62 ResultCallbackObserver()
63 : result_callback_(
64 Bind(&ResultCallbackObserver::OnResultCallback,
65 Unretained(this))) {}
~ResultCallbackObserver()66 virtual ~ResultCallbackObserver() {}
67
68 MOCK_METHOD1(OnResultCallback, void(bool status));
69
result_callback()70 const PassiveLinkMonitor::ResultCallback result_callback() {
71 return result_callback_;
72 }
73
74 private:
75 PassiveLinkMonitor::ResultCallback result_callback_;
76
77 DISALLOW_COPY_AND_ASSIGN(ResultCallbackObserver);
78 };
79
80 class PassiveLinkMonitorTest : public Test {
81 public:
PassiveLinkMonitorTest()82 PassiveLinkMonitorTest()
83 : device_info_(&control_, nullptr, nullptr, nullptr),
84 connection_(new StrictMock<MockConnection>(&device_info_)),
85 client_(new MockArpClient()),
86 client_test_helper_(client_),
87 link_monitor_(connection_, &dispatcher_, observer_.result_callback()),
88 interface_name_(kInterfaceName) {}
~PassiveLinkMonitorTest()89 virtual ~PassiveLinkMonitorTest() {}
90
SetUp()91 virtual void SetUp() {
92 ScopeLogger::GetInstance()->EnableScopesByName("link");
93 ScopeLogger::GetInstance()->set_verbose_level(4);
94 link_monitor_.arp_client_.reset(client_);
95
96 EXPECT_CALL(*connection_, interface_name())
97 .WillRepeatedly(ReturnRef(interface_name_));
98 }
99
TearDown()100 virtual void TearDown() {
101 ScopeLogger::GetInstance()->EnableScopesByName("-link");
102 ScopeLogger::GetInstance()->set_verbose_level(0);
103 }
104
ReceiveArpPacket(uint16_t operation)105 void ReceiveArpPacket(uint16_t operation) {
106 client_test_helper_.GeneratePacket(
107 operation,
108 IPAddress(kLocalIPAddress),
109 ByteString(kLocalMACAddress, arraysize(kLocalMACAddress)),
110 IPAddress(kRemoteIPAddress),
111 ByteString(kRemoteMACAddress, arraysize(kRemoteMACAddress)));
112 link_monitor_.ReceiveRequest(0);
113 }
114
MonitorCompleted(bool status)115 void MonitorCompleted(bool status) {
116 link_monitor_.MonitorCompleted(status);
117 }
118
InvokeCycleTimeoutHandler()119 void InvokeCycleTimeoutHandler() {
120 link_monitor_.CycleTimeoutHandler();
121 }
122
SetCurrentCycleStats(int num_requests_received,int num_cycles_passed)123 void SetCurrentCycleStats(int num_requests_received, int num_cycles_passed) {
124 link_monitor_.num_requests_received_ = num_requests_received;
125 link_monitor_.num_cycles_passed_ = num_cycles_passed;
126 }
127
VerifyCurrentCycleStats(int num_requests_received,int num_cycles_passed)128 void VerifyCurrentCycleStats(int num_requests_received,
129 int num_cycles_passed) {
130 EXPECT_EQ(num_requests_received, link_monitor_.num_requests_received_);
131 EXPECT_EQ(num_cycles_passed, link_monitor_.num_cycles_passed_);
132 }
133
134 protected:
135 MockEventDispatcher dispatcher_;
136 MockControl control_;
137 NiceMock<MockDeviceInfo> device_info_;
138 ResultCallbackObserver observer_;
139 scoped_refptr<MockConnection> connection_;
140 MockArpClient* client_;
141 ArpClientTestHelper client_test_helper_;
142 PassiveLinkMonitor link_monitor_;
143 const string interface_name_;
144 };
145
TEST_F(PassiveLinkMonitorTest,StartFailedArpClient)146 TEST_F(PassiveLinkMonitorTest, StartFailedArpClient) {
147 EXPECT_CALL(*client_, StartRequestListener()).WillOnce(Return(false));
148 EXPECT_FALSE(link_monitor_.Start(PassiveLinkMonitor::kDefaultMonitorCycles));
149 }
150
TEST_F(PassiveLinkMonitorTest,StartSuccess)151 TEST_F(PassiveLinkMonitorTest, StartSuccess) {
152 EXPECT_CALL(*client_, StartRequestListener()).WillOnce(Return(true));
153 EXPECT_CALL(dispatcher_, CreateReadyHandler(_, IOHandler::kModeInput, _))
154 .Times(1);
155 EXPECT_CALL(dispatcher_, PostDelayedTask(_, _)).Times(1);
156 EXPECT_TRUE(link_monitor_.Start(PassiveLinkMonitor::kDefaultMonitorCycles));
157 }
158
TEST_F(PassiveLinkMonitorTest,Stop)159 TEST_F(PassiveLinkMonitorTest, Stop) {
160 EXPECT_CALL(*client_, Stop()).Times(1);
161 link_monitor_.Stop();
162 Mock::VerifyAndClearExpectations(client_);
163 }
164
TEST_F(PassiveLinkMonitorTest,MonitorCompleted)165 TEST_F(PassiveLinkMonitorTest, MonitorCompleted) {
166 // Monitor failed.
167 EXPECT_CALL(*client_, Stop()).Times(1);
168 EXPECT_CALL(observer_, OnResultCallback(false)).Times(1);
169 MonitorCompleted(false);
170 Mock::VerifyAndClearExpectations(client_);
171 Mock::VerifyAndClearExpectations(&observer_);
172
173 // Monitor succeed.
174 EXPECT_CALL(*client_, Stop()).Times(1);
175 EXPECT_CALL(observer_, OnResultCallback(true)).Times(1);
176 MonitorCompleted(true);
177 Mock::VerifyAndClearExpectations(client_);
178 Mock::VerifyAndClearExpectations(&observer_);
179 }
180
TEST_F(PassiveLinkMonitorTest,ReceiveArpReply)181 TEST_F(PassiveLinkMonitorTest, ReceiveArpReply) {
182 // Setup initial stats.
183 const int kRequestReceived = 0;
184 const int kCurrentCycle = 0;
185 SetCurrentCycleStats(kRequestReceived, kCurrentCycle);
186 ScopedMockLog log;
187 EXPECT_CALL(log, Log(_, _, _)).Times(AnyNumber());
188 EXPECT_CALL(log, Log(_, _, HasSubstr("This is not a request packet")))
189 .Times(1);
190 ReceiveArpPacket(ARPOP_REPLY);
191 // Verify no change in receive count.
192 VerifyCurrentCycleStats(kRequestReceived, kCurrentCycle);
193 Mock::VerifyAndClearExpectations(&log);
194 }
195
TEST_F(PassiveLinkMonitorTest,ReceiveArpRequest)196 TEST_F(PassiveLinkMonitorTest, ReceiveArpRequest) {
197 // Setup initial stats.
198 const int kRequestReceived = 0;
199 const int kCurrentCycle = 0;
200 SetCurrentCycleStats(kRequestReceived, kCurrentCycle);
201
202 EXPECT_CALL(*client_, Stop()).Times(0);
203 ReceiveArpPacket(ARPOP_REQUEST);
204 ReceiveArpPacket(ARPOP_REQUEST);
205 VerifyCurrentCycleStats(kRequestReceived + 2, kCurrentCycle);
206 Mock::VerifyAndClearExpectations(client_);
207 }
208
TEST_F(PassiveLinkMonitorTest,ReceiveAllRequestsForCycle)209 TEST_F(PassiveLinkMonitorTest, ReceiveAllRequestsForCycle) {
210 // 4 ARP requests received in the current cycle so far.
211 const int kRequestReceived = 4;
212 const int kCurrentCycle = 0;
213 SetCurrentCycleStats(kRequestReceived, kCurrentCycle);
214
215 // Received all required requests for a cycle, stop the ARP client.
216 EXPECT_CALL(*client_, Stop()).Times(1);
217 ReceiveArpPacket(ARPOP_REQUEST);
218 Mock::VerifyAndClearExpectations(client_);
219 }
220
TEST_F(PassiveLinkMonitorTest,CycleFailed)221 TEST_F(PassiveLinkMonitorTest, CycleFailed) {
222 // 3 ARP requests received in the current cycle so far.
223 const int kRequestReceived = 3;
224 const int kCurrentCycle = 0;
225 SetCurrentCycleStats(kRequestReceived, kCurrentCycle);
226
227 // Monitor failed for the current cycle, post a task to perform cleanup and
228 // invoke result callback.
229 EXPECT_CALL(*client_, StartRequestListener()).Times(0);
230 EXPECT_CALL(dispatcher_, PostDelayedTask(_, _)).Times(0);
231 EXPECT_CALL(dispatcher_, PostTask(_)).Times(1);
232 InvokeCycleTimeoutHandler();
233 }
234
TEST_F(PassiveLinkMonitorTest,CycleSucceed)235 TEST_F(PassiveLinkMonitorTest, CycleSucceed) {
236 // 5 ARP requests received in the current cycle so far.
237 const int kRequestReceived = 5;
238 const int kCurrentCycle = 0;
239 SetCurrentCycleStats(kRequestReceived, kCurrentCycle);
240
241 // Monitor succeed for the current cycle, post a task to trigger a new cycle.
242 EXPECT_CALL(*client_, StartRequestListener()).WillOnce(Return(true));
243 EXPECT_CALL(dispatcher_, PostDelayedTask(_, _)).Times(1);
244 EXPECT_CALL(dispatcher_, PostTask(_)).Times(0);
245 InvokeCycleTimeoutHandler();
246 // ARP request received count should be resetted.
247 VerifyCurrentCycleStats(0, kCurrentCycle + 1);
248 }
249
TEST_F(PassiveLinkMonitorTest,AllCyclesCompleted)250 TEST_F(PassiveLinkMonitorTest, AllCyclesCompleted) {
251 // 5 ARP requests received in the current cycle so far.
252 const int kRequestReceived = 5;
253 const int kCurrentCycle = PassiveLinkMonitor::kDefaultMonitorCycles - 1;
254 SetCurrentCycleStats(kRequestReceived, kCurrentCycle);
255
256 // Monitor completed all the cycles, post a task to perform cleanup and
257 // invoke result callback.
258 EXPECT_CALL(dispatcher_, PostDelayedTask(_, _)).Times(0);
259 EXPECT_CALL(dispatcher_, PostTask(_)).Times(1);
260 InvokeCycleTimeoutHandler();
261 VerifyCurrentCycleStats(0, PassiveLinkMonitor::kDefaultMonitorCycles);
262 }
263
264 } // namespace shill
265