| // Copyright (c) 2013 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "shill/traffic_monitor.h" |
| |
| #include <base/bind.h> |
| #include <base/stringprintf.h> |
| #include <gtest/gtest.h> |
| #include <netinet/in.h> |
| |
| #include "shill/mock_device.h" |
| #include "shill/mock_connection_info_reader.h" |
| #include "shill/mock_event_dispatcher.h" |
| #include "shill/mock_ipconfig.h" |
| #include "shill/mock_socket_info_reader.h" |
| #include "shill/nice_mock_control.h" |
| |
| using base::Bind; |
| using base::StringPrintf; |
| using base::Unretained; |
| using std::string; |
| using std::vector; |
| using testing::_; |
| using testing::Mock; |
| using testing::NiceMock; |
| using testing::Return; |
| using testing::ReturnRef; |
| using testing::Test; |
| |
| namespace shill { |
| |
| class TrafficMonitorTest : public Test { |
| public: |
| static const string kLocalIpAddr; |
| static const uint16 kLocalPort1; |
| static const uint16 kLocalPort2; |
| static const uint16 kLocalPort3; |
| static const uint16 kLocalPort4; |
| static const uint16 kLocalPort5; |
| static const string kRemoteIpAddr; |
| static const uint16 kRemotePort; |
| static const uint64 kTxQueueLength1; |
| static const uint64 kTxQueueLength2; |
| static const uint64 kTxQueueLength3; |
| static const uint64 kTxQueueLength4; |
| |
| TrafficMonitorTest() |
| : device_(new MockDevice(&control_, |
| &dispatcher_, |
| reinterpret_cast<Metrics *>(NULL), |
| reinterpret_cast<Manager *>(NULL), |
| "netdev0", |
| "00:11:22:33:44:55", |
| 1)), |
| ipconfig_(new MockIPConfig(&control_, "netdev0")), |
| mock_socket_info_reader_(new MockSocketInfoReader), |
| mock_connection_info_reader_(new MockConnectionInfoReader), |
| monitor_(device_, &dispatcher_), |
| local_addr_(IPAddress::kFamilyIPv4), |
| remote_addr_(IPAddress::kFamilyIPv4) { |
| local_addr_.SetAddressFromString(kLocalIpAddr); |
| remote_addr_.SetAddressFromString(kRemoteIpAddr); |
| } |
| |
| MOCK_METHOD0(OnNoOutgoingPackets, void()); |
| |
| protected: |
| virtual void SetUp() { |
| monitor_.socket_info_reader_.reset( |
| mock_socket_info_reader_); // Passes ownership |
| monitor_.connection_info_reader_.reset( |
| mock_connection_info_reader_); // Passes ownership |
| |
| device_->set_ipconfig(ipconfig_); |
| ipconfig_properties_.address = kLocalIpAddr; |
| EXPECT_CALL(*ipconfig_.get(), properties()) |
| .WillRepeatedly(ReturnRef(ipconfig_properties_)); |
| } |
| |
| void VerifyStopped() { |
| EXPECT_TRUE(monitor_.sample_traffic_callback_.IsCancelled()); |
| EXPECT_EQ(0, monitor_.accummulated_congested_tx_queues_samples_); |
| } |
| |
| void VerifyStarted() { |
| EXPECT_FALSE(monitor_.sample_traffic_callback_.IsCancelled()); |
| } |
| |
| void SetupMockSocketInfos(const vector<SocketInfo> &socket_infos) { |
| mock_socket_infos_ = socket_infos; |
| EXPECT_CALL(*mock_socket_info_reader_, LoadTcpSocketInfo(_)) |
| .WillRepeatedly( |
| Invoke(this, &TrafficMonitorTest::MockLoadTcpSocketInfo)); |
| } |
| |
| void SetupMockConnectionInfos( |
| const vector<ConnectionInfo> &connection_infos) { |
| mock_connection_infos_ = connection_infos; |
| EXPECT_CALL(*mock_connection_info_reader_, LoadConnectionInfo(_)) |
| .WillRepeatedly( |
| Invoke(this, &TrafficMonitorTest::MockLoadConnectionInfo)); |
| } |
| |
| bool MockLoadTcpSocketInfo(vector<SocketInfo> *info_list) { |
| *info_list = mock_socket_infos_; |
| return true; |
| } |
| |
| bool MockLoadConnectionInfo(vector<ConnectionInfo> *info_list) { |
| *info_list = mock_connection_infos_; |
| return true; |
| } |
| |
| string FormatIPPort(const IPAddress &ip, const uint16 port) { |
| return StringPrintf("%s:%d", ip.ToString().c_str(), port); |
| } |
| |
| NiceMockControl control_; |
| NiceMock<MockEventDispatcher> dispatcher_; |
| scoped_refptr<MockDevice> device_; |
| scoped_refptr<MockIPConfig> ipconfig_; |
| IPConfig::Properties ipconfig_properties_; |
| MockSocketInfoReader *mock_socket_info_reader_; |
| MockConnectionInfoReader *mock_connection_info_reader_; |
| TrafficMonitor monitor_; |
| vector<SocketInfo> mock_socket_infos_; |
| vector<ConnectionInfo> mock_connection_infos_; |
| IPAddress local_addr_; |
| IPAddress remote_addr_; |
| }; |
| |
| // static |
| const string TrafficMonitorTest::kLocalIpAddr = "127.0.0.1"; |
| const uint16 TrafficMonitorTest::kLocalPort1 = 1234; |
| const uint16 TrafficMonitorTest::kLocalPort2 = 2345; |
| const uint16 TrafficMonitorTest::kLocalPort3 = 3456; |
| const uint16 TrafficMonitorTest::kLocalPort4 = 4567; |
| const uint16 TrafficMonitorTest::kLocalPort5 = 4567; |
| const string TrafficMonitorTest::kRemoteIpAddr = "192.168.1.1"; |
| const uint16 TrafficMonitorTest::kRemotePort = 5678; |
| const uint64 TrafficMonitorTest::kTxQueueLength1 = 111; |
| const uint64 TrafficMonitorTest::kTxQueueLength2 = 222; |
| const uint64 TrafficMonitorTest::kTxQueueLength3 = 333; |
| const uint64 TrafficMonitorTest::kTxQueueLength4 = 444; |
| |
| TEST_F(TrafficMonitorTest, StartAndStop) { |
| // Stop without start |
| monitor_.Stop(); |
| VerifyStopped(); |
| |
| // Normal start |
| monitor_.Start(); |
| VerifyStarted(); |
| |
| // Stop after start |
| monitor_.Stop(); |
| VerifyStopped(); |
| |
| // Stop again without start |
| monitor_.Stop(); |
| VerifyStopped(); |
| } |
| |
| TEST_F(TrafficMonitorTest, BuildIPPortToTxQueueLengthValid) { |
| vector<SocketInfo> socket_infos; |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateEstablished, |
| local_addr_, |
| TrafficMonitorTest::kLocalPort1, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| TrafficMonitorTest::kTxQueueLength1, |
| 0, |
| SocketInfo::kTimerStateRetransmitTimerPending)); |
| TrafficMonitor::IPPortToTxQueueLengthMap tx_queue_lengths; |
| monitor_.BuildIPPortToTxQueueLength(socket_infos, &tx_queue_lengths); |
| EXPECT_EQ(1, tx_queue_lengths.size()); |
| string ip_port = FormatIPPort(local_addr_, TrafficMonitorTest::kLocalPort1); |
| EXPECT_EQ(TrafficMonitorTest::kTxQueueLength1, tx_queue_lengths[ip_port]); |
| } |
| |
| TEST_F(TrafficMonitorTest, BuildIPPortToTxQueueLengthInvalidDevice) { |
| vector<SocketInfo> socket_infos; |
| IPAddress foreign_ip_addr(IPAddress::kFamilyIPv4); |
| foreign_ip_addr.SetAddressFromString("192.167.1.1"); |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateEstablished, |
| foreign_ip_addr, |
| TrafficMonitorTest::kLocalPort1, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| TrafficMonitorTest::kTxQueueLength1, |
| 0, |
| SocketInfo::kTimerStateRetransmitTimerPending)); |
| TrafficMonitor::IPPortToTxQueueLengthMap tx_queue_lengths; |
| monitor_.BuildIPPortToTxQueueLength(socket_infos, &tx_queue_lengths); |
| EXPECT_EQ(0, tx_queue_lengths.size()); |
| } |
| |
| TEST_F(TrafficMonitorTest, BuildIPPortToTxQueueLengthZero) { |
| vector<SocketInfo> socket_infos; |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateEstablished, |
| local_addr_, |
| TrafficMonitorTest::kLocalPort1, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| 0, |
| 0, |
| SocketInfo::kTimerStateRetransmitTimerPending)); |
| TrafficMonitor::IPPortToTxQueueLengthMap tx_queue_lengths; |
| monitor_.BuildIPPortToTxQueueLength(socket_infos, &tx_queue_lengths); |
| EXPECT_EQ(0, tx_queue_lengths.size()); |
| } |
| |
| TEST_F(TrafficMonitorTest, BuildIPPortToTxQueueLengthInvalidConnectionState) { |
| vector<SocketInfo> socket_infos; |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateSynSent, |
| local_addr_, |
| TrafficMonitorTest::kLocalPort1, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| TrafficMonitorTest::kTxQueueLength1, |
| 0, |
| SocketInfo::kTimerStateRetransmitTimerPending)); |
| TrafficMonitor::IPPortToTxQueueLengthMap tx_queue_lengths; |
| monitor_.BuildIPPortToTxQueueLength(socket_infos, &tx_queue_lengths); |
| EXPECT_EQ(0, tx_queue_lengths.size()); |
| } |
| |
| TEST_F(TrafficMonitorTest, BuildIPPortToTxQueueLengthInvalidTimerState) { |
| vector<SocketInfo> socket_infos; |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateEstablished, |
| local_addr_, |
| TrafficMonitorTest::kLocalPort1, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| TrafficMonitorTest::kTxQueueLength1, |
| 0, |
| SocketInfo::kTimerStateNoTimerPending)); |
| TrafficMonitor::IPPortToTxQueueLengthMap tx_queue_lengths; |
| monitor_.BuildIPPortToTxQueueLength(socket_infos, &tx_queue_lengths); |
| EXPECT_EQ(0, tx_queue_lengths.size()); |
| } |
| |
| TEST_F(TrafficMonitorTest, BuildIPPortToTxQueueLengthMultipleEntries) { |
| vector<SocketInfo> socket_infos; |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateSynSent, |
| local_addr_, |
| TrafficMonitorTest::kLocalPort1, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| TrafficMonitorTest::kTxQueueLength1, |
| 0, |
| SocketInfo::kTimerStateNoTimerPending)); |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateEstablished, |
| local_addr_, |
| TrafficMonitorTest::kLocalPort2, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| TrafficMonitorTest::kTxQueueLength2, |
| 0, |
| SocketInfo::kTimerStateRetransmitTimerPending)); |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateEstablished, |
| local_addr_, |
| TrafficMonitorTest::kLocalPort3, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| TrafficMonitorTest::kTxQueueLength3, |
| 0, |
| SocketInfo::kTimerStateRetransmitTimerPending)); |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateEstablished, |
| local_addr_, |
| TrafficMonitorTest::kLocalPort4, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| TrafficMonitorTest::kTxQueueLength4, |
| 0, |
| SocketInfo::kTimerStateNoTimerPending)); |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateEstablished, |
| local_addr_, |
| TrafficMonitorTest::kLocalPort5, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| 0, |
| 0, |
| SocketInfo::kTimerStateRetransmitTimerPending)); |
| TrafficMonitor::IPPortToTxQueueLengthMap tx_queue_lengths; |
| monitor_.BuildIPPortToTxQueueLength(socket_infos, &tx_queue_lengths); |
| EXPECT_EQ(2, tx_queue_lengths.size()); |
| string ip_port = FormatIPPort(local_addr_, TrafficMonitorTest::kLocalPort2); |
| EXPECT_EQ(kTxQueueLength2, tx_queue_lengths[ip_port]); |
| ip_port = FormatIPPort(local_addr_, TrafficMonitorTest::kLocalPort3); |
| EXPECT_EQ(kTxQueueLength3, tx_queue_lengths[ip_port]); |
| } |
| |
| TEST_F(TrafficMonitorTest, SampleTrafficStuckTxQueueSameQueueLength) { |
| vector<SocketInfo> socket_infos; |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateEstablished, |
| local_addr_, |
| TrafficMonitorTest::kLocalPort1, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| TrafficMonitorTest::kTxQueueLength1, |
| 0, |
| SocketInfo::kTimerStateRetransmitTimerPending)); |
| SetupMockSocketInfos(socket_infos); |
| monitor_.set_tcp_out_traffic_not_routed_callback( |
| Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); |
| EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); |
| monitor_.SampleTraffic(); |
| Mock::VerifyAndClearExpectations(this); |
| |
| // Mimic same queue length by using same mock socket info. |
| EXPECT_CALL(*this, OnNoOutgoingPackets()); |
| monitor_.SampleTraffic(); |
| Mock::VerifyAndClearExpectations(this); |
| |
| // Perform another sampling pass and make sure the callback is only |
| // triggered once. |
| EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); |
| monitor_.SampleTraffic(); |
| } |
| |
| TEST_F(TrafficMonitorTest, SampleTrafficStuckTxQueueIncreasingQueueLength) { |
| vector<SocketInfo> socket_infos; |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateEstablished, |
| local_addr_, |
| TrafficMonitorTest::kLocalPort1, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| TrafficMonitorTest::kTxQueueLength1, |
| 0, |
| SocketInfo::kTimerStateRetransmitTimerPending)); |
| SetupMockSocketInfos(socket_infos); |
| monitor_.set_tcp_out_traffic_not_routed_callback( |
| Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); |
| EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); |
| monitor_.SampleTraffic(); |
| Mock::VerifyAndClearExpectations(this); |
| |
| socket_infos.clear(); |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateEstablished, |
| local_addr_, |
| TrafficMonitorTest::kLocalPort1, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| TrafficMonitorTest::kTxQueueLength1 + 1, |
| 0, |
| SocketInfo::kTimerStateRetransmitTimerPending)); |
| SetupMockSocketInfos(socket_infos); |
| EXPECT_CALL(*this, OnNoOutgoingPackets()); |
| monitor_.SampleTraffic(); |
| } |
| |
| TEST_F(TrafficMonitorTest, SampleTrafficStuckTxQueueVariousQueueLengths) { |
| vector<SocketInfo> socket_infos; |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateEstablished, |
| local_addr_, |
| TrafficMonitorTest::kLocalPort1, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| TrafficMonitorTest::kTxQueueLength2, |
| 0, |
| SocketInfo::kTimerStateRetransmitTimerPending)); |
| SetupMockSocketInfos(socket_infos); |
| monitor_.set_tcp_out_traffic_not_routed_callback( |
| Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); |
| EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); |
| monitor_.SampleTraffic(); |
| Mock::VerifyAndClearExpectations(this); |
| |
| socket_infos.clear(); |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateEstablished, |
| local_addr_, |
| TrafficMonitorTest::kLocalPort1, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| TrafficMonitorTest::kTxQueueLength1, |
| 0, |
| SocketInfo::kTimerStateRetransmitTimerPending)); |
| SetupMockSocketInfos(socket_infos); |
| EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); |
| monitor_.SampleTraffic(); |
| Mock::VerifyAndClearExpectations(this); |
| |
| socket_infos.clear(); |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateEstablished, |
| local_addr_, |
| TrafficMonitorTest::kLocalPort1, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| TrafficMonitorTest::kTxQueueLength2, |
| 0, |
| SocketInfo::kTimerStateRetransmitTimerPending)); |
| SetupMockSocketInfos(socket_infos); |
| EXPECT_CALL(*this, OnNoOutgoingPackets()); |
| monitor_.SampleTraffic(); |
| } |
| |
| TEST_F(TrafficMonitorTest, SampleTrafficUnstuckTxQueueZeroQueueLength) { |
| vector<SocketInfo> socket_infos; |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateEstablished, |
| local_addr_, |
| TrafficMonitorTest::kLocalPort1, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| TrafficMonitorTest::kTxQueueLength1, |
| 0, |
| SocketInfo::kTimerStateRetransmitTimerPending)); |
| SetupMockSocketInfos(socket_infos); |
| monitor_.set_tcp_out_traffic_not_routed_callback( |
| Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); |
| EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); |
| monitor_.SampleTraffic(); |
| |
| socket_infos.clear(); |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateEstablished, |
| local_addr_, |
| TrafficMonitorTest::kLocalPort1, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| 0, |
| 0, |
| SocketInfo::kTimerStateRetransmitTimerPending)); |
| SetupMockSocketInfos(socket_infos); |
| monitor_.SampleTraffic(); |
| EXPECT_EQ(0, monitor_.accummulated_congested_tx_queues_samples_); |
| } |
| |
| TEST_F(TrafficMonitorTest, SampleTrafficUnstuckTxQueueNoConnection) { |
| vector<SocketInfo> socket_infos; |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateEstablished, |
| local_addr_, |
| TrafficMonitorTest::kLocalPort1, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| TrafficMonitorTest::kTxQueueLength1, |
| 0, |
| SocketInfo::kTimerStateRetransmitTimerPending)); |
| SetupMockSocketInfos(socket_infos); |
| monitor_.set_tcp_out_traffic_not_routed_callback( |
| Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); |
| EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); |
| monitor_.SampleTraffic(); |
| |
| socket_infos.clear(); |
| SetupMockSocketInfos(socket_infos); |
| monitor_.SampleTraffic(); |
| EXPECT_EQ(0, monitor_.accummulated_congested_tx_queues_samples_); |
| } |
| |
| TEST_F(TrafficMonitorTest, SampleTrafficUnstuckTxQueueStateChanged) { |
| vector<SocketInfo> socket_infos; |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateEstablished, |
| local_addr_, |
| TrafficMonitorTest::kLocalPort1, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| TrafficMonitorTest::kTxQueueLength1, |
| 0, |
| SocketInfo::kTimerStateRetransmitTimerPending)); |
| SetupMockSocketInfos(socket_infos); |
| monitor_.set_tcp_out_traffic_not_routed_callback( |
| Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); |
| EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); |
| monitor_.SampleTraffic(); |
| |
| socket_infos.clear(); |
| socket_infos.push_back( |
| SocketInfo(SocketInfo::kConnectionStateClose, |
| local_addr_, |
| TrafficMonitorTest::kLocalPort1, |
| remote_addr_, |
| TrafficMonitorTest::kRemotePort, |
| 0, |
| 0, |
| SocketInfo::kTimerStateNoTimerPending)); |
| SetupMockSocketInfos(socket_infos); |
| monitor_.SampleTraffic(); |
| EXPECT_EQ(0, monitor_.accummulated_congested_tx_queues_samples_); |
| } |
| |
| TEST_F(TrafficMonitorTest, SampleTrafficDnsTimedOut) { |
| vector<ConnectionInfo> connection_infos; |
| connection_infos.push_back( |
| ConnectionInfo(IPPROTO_UDP, |
| TrafficMonitor::kDnsTimedOutThresholdSeconds - 1, |
| true, local_addr_, TrafficMonitorTest::kLocalPort1, |
| remote_addr_, TrafficMonitor::kDnsPort, |
| remote_addr_, TrafficMonitor::kDnsPort, |
| local_addr_, TrafficMonitorTest::kLocalPort1)); |
| SetupMockConnectionInfos(connection_infos); |
| monitor_.set_tcp_out_traffic_not_routed_callback( |
| Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); |
| // Make sure the no routing event is not fired before the threshold is |
| // exceeded. |
| EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); |
| for (int count = 1; count < TrafficMonitor::kMinimumFailedSamplesToTrigger; |
| ++count) { |
| monitor_.SampleTraffic(); |
| } |
| Mock::VerifyAndClearExpectations(this); |
| |
| // This call should cause the threshold to exceed. |
| EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(1); |
| monitor_.SampleTraffic(); |
| Mock::VerifyAndClearExpectations(this); |
| |
| // Make sure the event is only fired once. |
| EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); |
| monitor_.SampleTraffic(); |
| } |
| |
| TEST_F(TrafficMonitorTest, SampleTrafficDnsOutstanding) { |
| vector<ConnectionInfo> connection_infos; |
| connection_infos.push_back( |
| ConnectionInfo(IPPROTO_UDP, |
| TrafficMonitor::kDnsTimedOutThresholdSeconds + 1, |
| true, local_addr_, TrafficMonitorTest::kLocalPort1, |
| remote_addr_, TrafficMonitor::kDnsPort, |
| remote_addr_, TrafficMonitor::kDnsPort, |
| local_addr_, TrafficMonitorTest::kLocalPort1)); |
| SetupMockConnectionInfos(connection_infos); |
| monitor_.set_tcp_out_traffic_not_routed_callback( |
| Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); |
| EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); |
| for (int count = 0; count < TrafficMonitor::kMinimumFailedSamplesToTrigger; |
| ++count) { |
| monitor_.SampleTraffic(); |
| } |
| } |
| |
| TEST_F(TrafficMonitorTest, SampleTrafficDnsSuccessful) { |
| vector<ConnectionInfo> connection_infos; |
| connection_infos.push_back( |
| ConnectionInfo(IPPROTO_UDP, |
| TrafficMonitor::kDnsTimedOutThresholdSeconds - 1, |
| false, local_addr_, TrafficMonitorTest::kLocalPort1, |
| remote_addr_, TrafficMonitor::kDnsPort, |
| remote_addr_, TrafficMonitor::kDnsPort, |
| local_addr_, TrafficMonitorTest::kLocalPort1)); |
| SetupMockConnectionInfos(connection_infos); |
| monitor_.set_tcp_out_traffic_not_routed_callback( |
| Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); |
| EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); |
| for (int count = 1; count < TrafficMonitor::kMinimumFailedSamplesToTrigger; |
| ++count) { |
| monitor_.SampleTraffic(); |
| } |
| } |
| |
| TEST_F(TrafficMonitorTest, SampleTrafficDnsFailureThenSuccess) { |
| vector<ConnectionInfo> connection_infos; |
| connection_infos.push_back( |
| ConnectionInfo(IPPROTO_UDP, |
| TrafficMonitor::kDnsTimedOutThresholdSeconds - 1, |
| true, local_addr_, TrafficMonitorTest::kLocalPort1, |
| remote_addr_, TrafficMonitor::kDnsPort, |
| remote_addr_, TrafficMonitor::kDnsPort, |
| local_addr_, TrafficMonitorTest::kLocalPort1)); |
| SetupMockConnectionInfos(connection_infos); |
| monitor_.set_tcp_out_traffic_not_routed_callback( |
| Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); |
| EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); |
| for (int count = 1; count < TrafficMonitor::kMinimumFailedSamplesToTrigger; |
| ++count) { |
| monitor_.SampleTraffic(); |
| } |
| Mock::VerifyAndClearExpectations(this); |
| |
| connection_infos.clear(); |
| connection_infos.push_back( |
| ConnectionInfo(IPPROTO_UDP, |
| TrafficMonitor::kDnsTimedOutThresholdSeconds - 1, |
| false, local_addr_, TrafficMonitorTest::kLocalPort1, |
| remote_addr_, TrafficMonitor::kDnsPort, |
| remote_addr_, TrafficMonitor::kDnsPort, |
| local_addr_, TrafficMonitorTest::kLocalPort1)); |
| SetupMockConnectionInfos(connection_infos); |
| EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); |
| monitor_.SampleTraffic(); |
| EXPECT_EQ(0, monitor_.accummulated_dns_failures_samples_); |
| } |
| |
| TEST_F(TrafficMonitorTest, SampleTrafficDnsTimedOutInvalidProtocol) { |
| vector<ConnectionInfo> connection_infos; |
| connection_infos.push_back( |
| ConnectionInfo(IPPROTO_TCP, |
| TrafficMonitor::kDnsTimedOutThresholdSeconds - 1, |
| true, local_addr_, TrafficMonitorTest::kLocalPort1, |
| remote_addr_, TrafficMonitor::kDnsPort, |
| remote_addr_, TrafficMonitor::kDnsPort, |
| local_addr_, TrafficMonitorTest::kLocalPort1)); |
| SetupMockConnectionInfos(connection_infos); |
| monitor_.set_tcp_out_traffic_not_routed_callback( |
| Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); |
| EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); |
| for (int count = 0; count < TrafficMonitor::kMinimumFailedSamplesToTrigger; |
| ++count) { |
| monitor_.SampleTraffic(); |
| } |
| } |
| |
| TEST_F(TrafficMonitorTest, SampleTrafficDnsTimedOutInvalidSourceIp) { |
| vector<ConnectionInfo> connection_infos; |
| connection_infos.push_back( |
| ConnectionInfo(IPPROTO_UDP, |
| TrafficMonitor::kDnsTimedOutThresholdSeconds - 1, |
| true, remote_addr_, TrafficMonitorTest::kLocalPort1, |
| remote_addr_, TrafficMonitor::kDnsPort, |
| remote_addr_, TrafficMonitor::kDnsPort, |
| remote_addr_, TrafficMonitorTest::kLocalPort1)); |
| SetupMockConnectionInfos(connection_infos); |
| monitor_.set_tcp_out_traffic_not_routed_callback( |
| Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); |
| EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); |
| for (int count = 0; count < TrafficMonitor::kMinimumFailedSamplesToTrigger; |
| ++count) { |
| monitor_.SampleTraffic(); |
| } |
| } |
| |
| TEST_F(TrafficMonitorTest, SampleTrafficDnsTimedOutOutsideTimeWindow) { |
| vector<ConnectionInfo> connection_infos; |
| connection_infos.push_back( |
| ConnectionInfo(IPPROTO_UDP, |
| TrafficMonitor::kDnsTimedOutThresholdSeconds - |
| TrafficMonitor::kSamplingIntervalMilliseconds / 1000, |
| true, remote_addr_, TrafficMonitorTest::kLocalPort1, |
| remote_addr_, TrafficMonitor::kDnsPort, |
| remote_addr_, TrafficMonitor::kDnsPort, |
| remote_addr_, TrafficMonitorTest::kLocalPort1)); |
| SetupMockConnectionInfos(connection_infos); |
| monitor_.set_tcp_out_traffic_not_routed_callback( |
| Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); |
| EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); |
| for (int count = 0; count < TrafficMonitor::kMinimumFailedSamplesToTrigger; |
| ++count) { |
| monitor_.SampleTraffic(); |
| } |
| } |
| |
| TEST_F(TrafficMonitorTest, SampleTrafficNonDnsTimedOut) { |
| const uint16 kNonDnsPort = 54; |
| vector<ConnectionInfo> connection_infos; |
| connection_infos.push_back( |
| ConnectionInfo(IPPROTO_UDP, |
| TrafficMonitor::kDnsTimedOutThresholdSeconds - 1, |
| true, local_addr_, TrafficMonitorTest::kLocalPort1, |
| remote_addr_, kNonDnsPort, |
| remote_addr_, kNonDnsPort, |
| local_addr_, TrafficMonitorTest::kLocalPort1)); |
| SetupMockConnectionInfos(connection_infos); |
| monitor_.set_tcp_out_traffic_not_routed_callback( |
| Bind(&TrafficMonitorTest::OnNoOutgoingPackets, Unretained(this))); |
| EXPECT_CALL(*this, OnNoOutgoingPackets()).Times(0); |
| for (int count = 0; count < TrafficMonitor::kMinimumFailedSamplesToTrigger; |
| ++count) { |
| monitor_.SampleTraffic(); |
| } |
| } |
| |
| TEST_F(TrafficMonitorTest, SampleTrafficDnsStatsReset) { |
| vector<ConnectionInfo> connection_infos; |
| SetupMockConnectionInfos(connection_infos); |
| monitor_.accummulated_dns_failures_samples_ = 1; |
| monitor_.SampleTraffic(); |
| EXPECT_EQ(0, monitor_.accummulated_dns_failures_samples_); |
| } |
| |
| } // namespace shill |