1#!/usr/bin/env python3 2# 3# Copyright (C) 2018 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); you may not 6# use this file except in compliance with the License. You may obtain a copy of 7# the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14# License for the specific language governing permissions and limitations under 15# the License. 16""" 17Script for testing various download stress scenarios. 18 19""" 20import threading 21 22from acts import signals 23from acts.controllers.access_point import setup_ap 24from acts.controllers.ap_lib import hostapd_constants 25from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest 26from acts_contrib.test_utils.abstract_devices.wlan_device import create_wlan_device 27from acts_contrib.test_utils.fuchsia import utils 28from acts.utils import rand_ascii_str 29 30 31class DownloadStressTest(WifiBaseTest): 32 # Default number of test iterations here. 33 # Override using parameter in config file. 34 # Eg: "download_stress_test_iterations": "10" 35 num_of_iterations = 3 36 37 # Timeout for download thread in seconds 38 download_timeout_s = 60 * 5 39 40 # Download urls 41 url_20MB = 'http://ipv4.download.thinkbroadband.com/20MB.zip' 42 url_40MB = 'http://ipv4.download.thinkbroadband.com/40MB.zip' 43 url_60MB = 'http://ipv4.download.thinkbroadband.com/60MB.zip' 44 url_512MB = 'http://ipv4.download.thinkbroadband.com/512MB.zip' 45 46 # Constants used in test_one_large_multiple_small_downloads 47 download_small_url = url_20MB 48 download_large_url = url_512MB 49 num_of_small_downloads = 5 50 download_threads_result = [] 51 52 def setup_class(self): 53 super().setup_class() 54 self.ssid = rand_ascii_str(10) 55 self.dut = create_wlan_device(self.fuchsia_devices[0]) 56 self.access_point = self.access_points[0] 57 self.num_of_iterations = int( 58 self.user_params.get("download_stress_test_iterations", 59 self.num_of_iterations)) 60 61 setup_ap(access_point=self.access_point, 62 profile_name='whirlwind', 63 channel=hostapd_constants.AP_DEFAULT_CHANNEL_2G, 64 ssid=self.ssid) 65 self.dut.associate(self.ssid) 66 67 def teardown_test(self): 68 self.download_threads_result.clear() 69 self.dut.disconnect() 70 self.dut.reset_wifi() 71 self.download_ap_logs() 72 self.access_point.stop_all_aps() 73 74 def test_download_small(self): 75 self.log.info("Downloading small file") 76 return self.download_file(self.url_20MB) 77 78 def test_download_large(self): 79 return self.download_file(self.url_512MB) 80 81 def test_continuous_download(self): 82 for x in range(0, self.num_of_iterations): 83 if not self.download_file(self.url_512MB): 84 return False 85 return True 86 87 def download_file(self, url): 88 self.log.info("Start downloading: %s" % url) 89 return utils.http_file_download_by_curl( 90 self.dut.device, 91 url, 92 additional_args='--max-time %d --silent' % self.download_timeout_s) 93 94 def download_thread(self, url): 95 download_status = self.download_file(url) 96 if download_status: 97 self.log.info("Success downloading: %s" % url) 98 else: 99 self.log.info("Failure downloading: %s" % url) 100 101 self.download_threads_result.append(download_status) 102 return download_status 103 104 def test_multi_downloads(self): 105 download_urls = [self.url_20MB, self.url_40MB, self.url_60MB] 106 download_threads = [] 107 108 try: 109 # Start multiple downloads at the same time 110 for index, url in enumerate(download_urls): 111 self.log.info('Create and start thread %d.' % index) 112 t = threading.Thread(target=self.download_thread, args=(url, )) 113 download_threads.append(t) 114 t.start() 115 116 # Wait for all threads to complete or timeout 117 for t in download_threads: 118 t.join(self.download_timeout_s) 119 120 finally: 121 is_alive = False 122 123 for index, t in enumerate(download_threads): 124 if t.isAlive(): 125 t = None 126 is_alive = True 127 128 if is_alive: 129 raise signals.TestFailure('Thread %d timedout' % index) 130 131 for index in range(0, len(self.download_threads_result)): 132 if not self.download_threads_result[index]: 133 self.log.info("Download failed for %d" % index) 134 raise signals.TestFailure('Thread %d failed to download' % 135 index) 136 return False 137 138 return True 139 140 def test_one_large_multiple_small_downloads(self): 141 for index in range(self.num_of_iterations): 142 download_threads = [] 143 try: 144 large_thread = threading.Thread( 145 target=self.download_thread, 146 args=(self.download_large_url, )) 147 download_threads.append(large_thread) 148 large_thread.start() 149 150 for i in range(self.num_of_small_downloads): 151 # Start small file download 152 t = threading.Thread(target=self.download_thread, 153 args=(self.download_small_url, )) 154 download_threads.append(t) 155 t.start() 156 # Wait for thread to exit before starting the next iteration 157 t.join(self.download_timeout_s) 158 159 # Wait for the large file download thread to complete 160 large_thread.join(self.download_timeout_s) 161 162 finally: 163 is_alive = False 164 165 for index, t in enumerate(download_threads): 166 if t.isAlive(): 167 t = None 168 is_alive = True 169 170 if is_alive: 171 raise signals.TestFailure('Thread %d timedout' % index) 172 173 for index in range(0, len(self.download_threads_result)): 174 if not self.download_threads_result[index]: 175 self.log.info("Download failed for %d" % index) 176 raise signals.TestFailure('Thread %d failed to download' % 177 index) 178 return False 179 180 # Clear results before looping again 181 self.download_threads_result.clear() 182 183 return True 184