blob: 9054aa6dd52c3b848e34f554b9fb7fd0077b25a7 [file] [log] [blame]
# Copyright 2015 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.
"""Ping connection test.
Description
-----------
Tests network connection by pinging a host for a period of time. Then checks
the percentage of successful pings is above some threshold or not.
If moving_window_size is set, it will check the percentage within the moving
window during the test. It always checks the percentage of successful pings for
the whole duration at the end of the test.
Test Procedure
--------------
This is an automated test without user interaction.
Dependency
----------
The program ``ping``.
Examples
--------
To ping 192.168.0.1 every 2 seconds for 10 seconds, and checks the successful
pings are >= 70% at the end of the test (The default values), add this in test
list::
{
"pytest_name": "ping_test",
"args": {
"host": "192.168.0.1"
}
}
To ping 192.168.0.1 every 10 seconds for 120 seconds, and checks the successful
pings are >= 60% at the end of the test::
{
"pytest_name": "ping_test",
"args": {
"duration_secs": 120,
"host": "192.168.0.1",
"interval_secs": 10,
"ping_success_percent": 60
}
}
To ping 192.168.0.1 on interface eth0 every 10 seconds for 120 seconds, checks
the successful pings are >= 70% within the moving window of 5 pings, and also
checks the successful pings are >= 70% overall::
{
"pytest_name": "ping_test",
"args": {
"duration_secs": 120,
"host": "192.168.0.1",
"interface": "eth0",
"interval_secs": 10,
"moving_window_size": 5
}
}
"""
import logging
from cros.factory.test import test_case
from cros.factory.test import test_ui
from cros.factory.utils.arg_utils import Arg
from cros.factory.utils import process_utils
from cros.factory.utils import time_utils
class PingTest(test_case.TestCase):
ARGS = [
Arg('host', str, 'The IP address or hostname to ping.'),
Arg('interface', str, 'Source interface address, may be numeric IP '
'address or name of network device, ex: eth0.',
default=None),
Arg('interval_secs', int, 'The interval in seconds between two '
'consecutive pings.',
default=2),
Arg('duration_secs', int, 'The duration of the ping test in seconds.',
default=10),
Arg('ping_success_percent', int, 'The percentage of successful pings '
'to meet. It will be checked at the end of the test.',
default=70),
Arg('moving_window_size', int, 'The size of the moving window in number '
'of ping attempts. If it is set, the percentage of successful '
'pings will be checked within the moving window in addition to '
'that at the end of the test.',
default=None),
Arg('verbose', bool, 'Dumps stdout of ping commands.',
default=False),
Arg('packet_size', int, 'Specifies the number of data bytes to be sent.',
default=None),
]
ui_class = test_ui.ScrollableLogUI
def _CheckSuccessPercentage(self, success_count, total_count, title=''):
"""Checks the percentage of successful pings is within the range."""
success_percentage = (success_count / total_count) * 100
if success_percentage < self.args.ping_success_percent:
self.FailTask(
'Failed to meet ping success percentage: %.2f%% (expected: %d%%).' % (
success_percentage, self.args.ping_success_percent))
logging.info('%s%.2f%% packets received.', title, success_percentage)
def runTest(self):
"""Tests the network connection by pinging a host for a period of time.
Pings a host and counts the percentage of successful pings at the end of
the test. If moving_window_size is set, it will also check the successful
percentage within the moving window during the ping tests.
"""
window_size = self.args.moving_window_size
moving_queue = []
moving_success_count = 0
total_success_count = 0
total_count = 0
ping_command = 'ping %s -c 1' % self.args.host
if self.args.interface:
ping_command += ' -I %s' % self.args.interface
if self.args.packet_size:
ping_command += ' -s %d' % self.args.packet_size
end_time = time_utils.MonotonicTime() + self.args.duration_secs
while time_utils.MonotonicTime() < end_time:
if self.args.verbose:
p = process_utils.Spawn(ping_command,
shell=True, log=True, read_stdout=True)
logging.info(p.stdout_data)
if total_count % 10 == 0:
self.ui.ClearLog()
self.ui.AppendLog(p.stdout_data + '\n')
else:
p = process_utils.Spawn(ping_command, shell=True, call=True,
ignore_stdout=True, ignore_stderr=True)
result = int(p.returncode == 0)
if window_size is not None:
moving_success_count += result
moving_queue.append(result)
if len(moving_queue) > window_size:
moving_success_count -= moving_queue.pop(0)
if len(moving_queue) == window_size:
self._CheckSuccessPercentage(
moving_success_count, window_size, 'Moving average: ')
total_success_count += result
total_count += 1
self.Sleep(self.args.interval_secs)
self._CheckSuccessPercentage(total_success_count, total_count, 'Overall: ')