• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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