blob: f998934c1b73c0650d498c22b4d0e57ed60af8a3 [file] [log] [blame]
#!/usr/bin/env python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import hashlib
import logging
import os
import time
import urllib2
import pyauto_functional # Must be imported before pyauto
import pyauto
import pyauto_utils
import chromeos_network
MAX_WAIT_TIME_IN_MSEC = 15 * 60 * 1000
class WifiDownloadsTest(chromeos_network.PyNetworkUITest):
"""TestCase for ChromeOS Wifi Downloads
This test makes a few assumptions. It needs to have access to the power
strip used in pyautolib/chromeos/wifi_downloads.py. It also assumes access
to the server 172.22.12.98:8080. If the server is passed a filname in the
format <integer>.lf, it will generate a file of size <integer> in KB. In
addition the name of the file returned is the md5 checksum of the file.
In addition the download times are written to a file in
/tmp/wifi_download_time.csv. All times are appended to the file if it
already exists.
"""
def setUp(self):
chromeos_network.PyNetworkUITest.setUp(self)
self.InitWifiPowerStrip()
# The power strip is a shared resource and if we every crash in the middle
# of a test we will be in an unknown state. This returns us to 'all off'.
self.TurnOffAllRouters()
# Downloading files of a large size, can take a while, bump the timeout
self.changer = pyauto.PyUITest.ActionTimeoutChanger(self, 4 * 1000 * 60)
self.log_file_path = '/tmp/wifi_download_time.csv'
def _WriteTimeToFile(self, output_file, router_name, file_size, dl_time):
"""Write or append a time into a csv file.
This method will create or append the amount of time a download took for a
given filesize and router to a file at the given path.
The format of the output file is as follows:
<router name A>,<file size A>,time,time,time,time,time,time,time,time
<router name A>,<file size B>,time,time,time,time,time,time,time,time
<router name B>,<file size C>,time,time,time,time,time,time,time,time
Args:
output_file: the complete path of the file to write to
file_size: the size of the file, this is the row header
dl_time: the amount of time in seconds
"""
file_data = []
if os.path.exists(output_file):
file_handle = open(output_file)
lines = file_handle.readlines()
file_handle.close()
# Convert the file to a full data structure.
for line in lines:
values = line.strip().split(',')
file_data.append(values)
for values in file_data:
found_existing_time = False
if values[0] == router_name and values[1] == file_size:
values.append('%2.2f' % dl_time)
found_existing_time = True
break
if not found_existing_time:
new_line = [router_name, file_size, ('%2.2f' % dl_time)]
file_data.append(new_line)
else:
file_data = [[router_name, file_size, ('%2.2f' % dl_time)]]
# Write the data back out
file_handle = open(output_file, 'w')
for line in file_data:
if len(line) > 2:
file_handle.write(','.join(line))
file_handle.write('\n')
file_handle.close()
def _Md5Checksum(self, file_path):
"""Returns the md5 checksum of a file at a given path.
Args:
file_path: The complete path of the file to generate the md5 checksum for.
"""
file_handle = open(file_path, 'rb')
m = hashlib.md5()
while True:
data = file_handle.read(8192)
if not data:
break
m.update(data)
file_handle.close()
return m.hexdigest()
def _ConnectToRouterAndVerify(self, router_name):
"""Generic routine for connecting to a router.
Args:
router_name: The name of the router to connect to.
"""
router = self.GetRouterConfig(router_name)
self.RouterPower(router_name, True)
self.assertTrue(self.WaitUntilWifiNetworkAvailable(router['ssid']),
'Wifi network %s never showed up.' % router['ssid'])
# Verify connect did not have any errors.
error = self.ConnectToWifiRouter(router_name)
self.assertFalse(error, 'Failed to connect to wifi network %s. '
'Reason: %s.' % (router['ssid'], error))
# Verify the network we connected to.
ssid = self.GetConnectedWifi()
self.assertEqual(ssid, router['ssid'],
'Did not successfully connect to wifi network %s.' % ssid)
def _DownloadAndVerifyFile(self, download_url):
"""Downloads a file at a given URL and validates it
This method downloads a file from a server whose filename matches the md5
checksum. Then we manually generate the md5 and check it against the
filename.
Args:
download_url: URL of the file to download.
Returns:
The download time in seconds.
"""
start = time.time()
# Make a copy of the download directory now to work around segfault
downloads_dir = self.GetDownloadDirectory().value()
try:
self.DownloadAndWaitForStart(download_url)
except AssertionError:
# We need to redo this since the external server may not respond the
# first time.
logging.info('Could not start download. Retrying ...')
self.DownloadAndWaitForStart(download_url)
# Maximum wait time is set as 15 mins as an 100MB file may take somewhere
# between 8-12 mins to download.
self.WaitForAllDownloadsToComplete(timeout=MAX_WAIT_TIME_IN_MSEC)
end = time.time()
logging.info('Download took %2.2f seconds to complete' % (end - start))
downloaded_files = os.listdir(downloads_dir)
self.assertEquals(len(downloaded_files), 1,
msg='Expected only one file in the Downloads folder. '
'but got this instead: %s' % ', '.join(downloaded_files))
filename = os.path.splitext(downloaded_files[0])[0]
file_path = os.path.join(self.GetDownloadDirectory().value(),
downloaded_files[0])
md5_sum = self._Md5Checksum(file_path)
md5_url = download_url[:-4] + '.md5' # replacing .slf with .md5
md5_file = urllib2.urlopen(md5_url).readlines()[0]
self.assertTrue(md5_file.rstrip().endswith(md5_sum.encode()),
msg='Unexpected checksum. The download is incomplete.')
return end - start
def testDownload1MBFile(self):
"""Test downloading a 1MB file from a wireless router."""
download_url = 'http://172.22.12.98:80/downloads/1M.slf'
router_name = 'Nfiniti'
self._ConnectToRouterAndVerify(router_name)
download_time = self._DownloadAndVerifyFile(download_url)
self._WriteTimeToFile(self.log_file_path, router_name, '1MB',
download_time)
self.DisconnectFromWifiNetwork()
def testDownload10MBFile(self):
"""Test downloading a 10MB file from a wireless router."""
download_url = 'http://172.22.12.98:80/downloads/10M.slf'
router_name = 'Linksys_WRT54G2'
self._ConnectToRouterAndVerify(router_name)
download_time = self._DownloadAndVerifyFile(download_url)
self._WriteTimeToFile(self.log_file_path, router_name, '10MB',
download_time)
self.DisconnectFromWifiNetwork()
def testDownload100MBFile(self):
"""Test downloading a 100MB file from a wireless router."""
download_url = 'http://172.22.12.98:80/downloads/100M.slf'
router_name = 'Trendnet_639gr_4'
self._ConnectToRouterAndVerify(router_name)
download_time = self._DownloadAndVerifyFile(download_url)
self._WriteTimeToFile(self.log_file_path, router_name, '100MB',
download_time)
self.DisconnectFromWifiNetwork()
if __name__ == '__main__':
pyauto_functional.Main()