OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 import hashlib | |
7 import logging | |
8 import os | |
9 import time | |
10 import urllib2 | |
11 | |
12 import pyauto_functional # Must be imported before pyauto | |
13 import pyauto | |
14 import pyauto_utils | |
15 import chromeos_network | |
16 | |
17 | |
18 MAX_WAIT_TIME_IN_MSEC = 15 * 60 * 1000 | |
19 | |
20 | |
21 class WifiDownloadsTest(chromeos_network.PyNetworkUITest): | |
22 """TestCase for ChromeOS Wifi Downloads | |
23 | |
24 This test makes a few assumptions. It needs to have access to the power | |
25 strip used in pyautolib/chromeos/wifi_downloads.py. It also assumes access | |
26 to the server 172.22.12.98:8080. If the server is passed a filname in the | |
27 format <integer>.lf, it will generate a file of size <integer> in KB. In | |
28 addition the name of the file returned is the md5 checksum of the file. | |
29 | |
30 In addition the download times are written to a file in | |
31 /tmp/wifi_download_time.csv. All times are appended to the file if it | |
32 already exists. | |
33 """ | |
34 | |
35 def setUp(self): | |
36 chromeos_network.PyNetworkUITest.setUp(self) | |
37 self.InitWifiPowerStrip() | |
38 # The power strip is a shared resource and if we every crash in the middle | |
39 # of a test we will be in an unknown state. This returns us to 'all off'. | |
40 self.TurnOffAllRouters() | |
41 # Downloading files of a large size, can take a while, bump the timeout | |
42 self.changer = pyauto.PyUITest.ActionTimeoutChanger(self, 4 * 1000 * 60) | |
43 self.log_file_path = '/tmp/wifi_download_time.csv' | |
44 | |
45 def _WriteTimeToFile(self, output_file, router_name, file_size, dl_time): | |
46 """Write or append a time into a csv file. | |
47 | |
48 This method will create or append the amount of time a download took for a | |
49 given filesize and router to a file at the given path. | |
50 | |
51 The format of the output file is as follows: | |
52 <router name A>,<file size A>,time,time,time,time,time,time,time,time | |
53 <router name A>,<file size B>,time,time,time,time,time,time,time,time | |
54 <router name B>,<file size C>,time,time,time,time,time,time,time,time | |
55 | |
56 Args: | |
57 output_file: the complete path of the file to write to | |
58 file_size: the size of the file, this is the row header | |
59 dl_time: the amount of time in seconds | |
60 """ | |
61 file_data = [] | |
62 if os.path.exists(output_file): | |
63 file_handle = open(output_file) | |
64 lines = file_handle.readlines() | |
65 file_handle.close() | |
66 # Convert the file to a full data structure. | |
67 for line in lines: | |
68 values = line.strip().split(',') | |
69 file_data.append(values) | |
70 for values in file_data: | |
71 found_existing_time = False | |
72 if values[0] == router_name and values[1] == file_size: | |
73 values.append('%2.2f' % dl_time) | |
74 found_existing_time = True | |
75 break | |
76 if not found_existing_time: | |
77 new_line = [router_name, file_size, ('%2.2f' % dl_time)] | |
78 file_data.append(new_line) | |
79 else: | |
80 file_data = [[router_name, file_size, ('%2.2f' % dl_time)]] | |
81 # Write the data back out | |
82 file_handle = open(output_file, 'w') | |
83 for line in file_data: | |
84 if len(line) > 2: | |
85 file_handle.write(','.join(line)) | |
86 file_handle.write('\n') | |
87 file_handle.close() | |
88 | |
89 def _Md5Checksum(self, file_path): | |
90 """Returns the md5 checksum of a file at a given path. | |
91 | |
92 Args: | |
93 file_path: The complete path of the file to generate the md5 checksum for. | |
94 """ | |
95 file_handle = open(file_path, 'rb') | |
96 m = hashlib.md5() | |
97 while True: | |
98 data = file_handle.read(8192) | |
99 if not data: | |
100 break | |
101 m.update(data) | |
102 file_handle.close() | |
103 return m.hexdigest() | |
104 | |
105 def _ConnectToRouterAndVerify(self, router_name): | |
106 """Generic routine for connecting to a router. | |
107 | |
108 Args: | |
109 router_name: The name of the router to connect to. | |
110 """ | |
111 router = self.GetRouterConfig(router_name) | |
112 self.RouterPower(router_name, True) | |
113 | |
114 self.assertTrue(self.WaitUntilWifiNetworkAvailable(router['ssid']), | |
115 'Wifi network %s never showed up.' % router['ssid']) | |
116 | |
117 # Verify connect did not have any errors. | |
118 error = self.ConnectToWifiRouter(router_name) | |
119 self.assertFalse(error, 'Failed to connect to wifi network %s. ' | |
120 'Reason: %s.' % (router['ssid'], error)) | |
121 | |
122 # Verify the network we connected to. | |
123 ssid = self.GetConnectedWifi() | |
124 self.assertEqual(ssid, router['ssid'], | |
125 'Did not successfully connect to wifi network %s.' % ssid) | |
126 | |
127 def _DownloadAndVerifyFile(self, download_url): | |
128 """Downloads a file at a given URL and validates it | |
129 | |
130 This method downloads a file from a server whose filename matches the md5 | |
131 checksum. Then we manually generate the md5 and check it against the | |
132 filename. | |
133 | |
134 Args: | |
135 download_url: URL of the file to download. | |
136 | |
137 Returns: | |
138 The download time in seconds. | |
139 """ | |
140 start = time.time() | |
141 # Make a copy of the download directory now to work around segfault | |
142 downloads_dir = self.GetDownloadDirectory().value() | |
143 try: | |
144 self.DownloadAndWaitForStart(download_url) | |
145 except AssertionError: | |
146 # We need to redo this since the external server may not respond the | |
147 # first time. | |
148 logging.info('Could not start download. Retrying ...') | |
149 self.DownloadAndWaitForStart(download_url) | |
150 # Maximum wait time is set as 15 mins as an 100MB file may take somewhere | |
151 # between 8-12 mins to download. | |
152 self.WaitForAllDownloadsToComplete(timeout=MAX_WAIT_TIME_IN_MSEC) | |
153 end = time.time() | |
154 logging.info('Download took %2.2f seconds to complete' % (end - start)) | |
155 downloaded_files = os.listdir(downloads_dir) | |
156 self.assertEquals(len(downloaded_files), 1, | |
157 msg='Expected only one file in the Downloads folder. ' | |
158 'but got this instead: %s' % ', '.join(downloaded_files)) | |
159 filename = os.path.splitext(downloaded_files[0])[0] | |
160 file_path = os.path.join(self.GetDownloadDirectory().value(), | |
161 downloaded_files[0]) | |
162 md5_sum = self._Md5Checksum(file_path) | |
163 md5_url = download_url[:-4] + '.md5' # replacing .slf with .md5 | |
164 md5_file = urllib2.urlopen(md5_url).readlines()[0] | |
165 self.assertTrue(md5_file.rstrip().endswith(md5_sum.encode()), | |
166 msg='Unexpected checksum. The download is incomplete.') | |
167 return end - start | |
168 | |
169 def testDownload1MBFile(self): | |
170 """Test downloading a 1MB file from a wireless router.""" | |
171 download_url = 'http://172.22.12.98:80/downloads/1M.slf' | |
172 router_name = 'Nfiniti' | |
173 self._ConnectToRouterAndVerify(router_name) | |
174 download_time = self._DownloadAndVerifyFile(download_url) | |
175 self._WriteTimeToFile(self.log_file_path, router_name, '1MB', | |
176 download_time) | |
177 self.DisconnectFromWifiNetwork() | |
178 | |
179 def testDownload10MBFile(self): | |
180 """Test downloading a 10MB file from a wireless router.""" | |
181 download_url = 'http://172.22.12.98:80/downloads/10M.slf' | |
182 router_name = 'Linksys_WRT54G2' | |
183 self._ConnectToRouterAndVerify(router_name) | |
184 download_time = self._DownloadAndVerifyFile(download_url) | |
185 self._WriteTimeToFile(self.log_file_path, router_name, '10MB', | |
186 download_time) | |
187 self.DisconnectFromWifiNetwork() | |
188 | |
189 def testDownload100MBFile(self): | |
190 """Test downloading a 100MB file from a wireless router.""" | |
191 download_url = 'http://172.22.12.98:80/downloads/100M.slf' | |
192 router_name = 'Trendnet_639gr_4' | |
193 self._ConnectToRouterAndVerify(router_name) | |
194 download_time = self._DownloadAndVerifyFile(download_url) | |
195 self._WriteTimeToFile(self.log_file_path, router_name, '100MB', | |
196 download_time) | |
197 self.DisconnectFromWifiNetwork() | |
198 | |
199 | |
200 if __name__ == '__main__': | |
201 pyauto_functional.Main() | |
OLD | NEW |