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