#!/usr/bin/env python3 # # Copyright (C) 2018 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy of # the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations under # the License. """ Script for testing various download stress scenarios. """ import os import threading import uuid from acts.base_test import BaseTestClass from acts import signals from acts.controllers.ap_lib import hostapd_constants from acts.test_utils.abstract_devices.utils_lib.wlan_utils import setup_ap_and_associate from acts.test_utils.abstract_devices.wlan_device import create_wlan_device from acts.test_utils.fuchsia import utils from acts.test_utils.tel.tel_test_utils import setup_droid_properties from acts.utils import rand_ascii_str class DownloadStressTest(BaseTestClass): # Default number of test iterations here. # Override using parameter in config file. # Eg: "download_stress_test_iterations": "10" num_of_iterations = 3 # Timeout for download thread in seconds download_timeout_s = 60 * 5 # Download urls url_20MB = 'http://ipv4.download.thinkbroadband.com/20MB.zip' url_40MB = 'http://ipv4.download.thinkbroadband.com/40MB.zip' url_60MB = 'http://ipv4.download.thinkbroadband.com/60MB.zip' url_512MB = 'http://ipv4.download.thinkbroadband.com/512MB.zip' # Constants used in test_one_large_multiple_small_downloads download_small_url = url_20MB download_large_url = url_512MB num_of_small_downloads = 5 download_threads_result = [] def setup_class(self): super().setup_class() self.ssid = rand_ascii_str(10) self.fd = self.fuchsia_devices[0] self.wlan_device = create_wlan_device(self.fd) self.ap = self.access_points[0] self.num_of_iterations = int( self.user_params.get("download_stress_test_iterations", self.num_of_iterations)) setup_ap_and_associate( access_point=self.ap, client=self.wlan_device, profile_name='whirlwind', channel=hostapd_constants.AP_DEFAULT_CHANNEL_2G, ssid=self.ssid) def teardown_test(self): self.download_threads_result.clear() self.wlan_device.disconnect() self.wlan_device.reset_wifi() self.ap.stop_all_aps() def test_download_small(self): self.log.info("Downloading small file") return self.download_file(self.url_20MB) def test_download_large(self): return self.download_file(self.url_512MB) def test_continuous_download(self): for x in range(0, self.num_of_iterations): if not self.download_file(self.url_512MB): return False return True def download_file(self, url): self.log.info("Start downloading: %s" % url) return utils.http_file_download_by_curl( self.fd, url, additional_args='--max-time %d --silent' % self.download_timeout_s) def download_thread(self, url): download_status = self.download_file(url) if download_status: self.log.info("Success downloading: %s" % url) else: self.log.info("Failure downloading: %s" % url) self.download_threads_result.append(download_status) return download_status def test_multi_downloads(self): download_urls = [self.url_20MB, self.url_40MB, self.url_60MB] download_threads = [] try: # Start multiple downloads at the same time for index, url in enumerate(download_urls): self.log.info('Create and start thread %d.' % index) t = threading.Thread(target=self.download_thread, args=(url, )) download_threads.append(t) t.start() # Wait for all threads to complete or timeout for t in download_threads: t.join(self.download_timeout_s) finally: is_alive = False for index, t in enumerate(download_threads): if t.isAlive(): t = None is_alive = True if is_alive: raise signals.TestFailure('Thread %d timedout' % index) for index in range(0, len(self.download_threads_result)): if not self.download_threads_result[index]: self.log.info("Download failed for %d" % index) raise signals.TestFailure( 'Thread %d failed to download' % index) return False return True def test_one_large_multiple_small_downloads(self): for index in range(self.num_of_iterations): download_threads = [] try: large_thread = threading.Thread( target=self.download_thread, args=(self.download_large_url, )) download_threads.append(large_thread) large_thread.start() for i in range(self.num_of_small_downloads): # Start small file download t = threading.Thread( target=self.download_thread, args=(self.download_small_url, )) download_threads.append(t) t.start() # Wait for thread to exit before starting the next iteration t.join(self.download_timeout_s) # Wait for the large file download thread to complete large_thread.join(self.download_timeout_s) finally: is_alive = False for index, t in enumerate(download_threads): if t.isAlive(): t = None is_alive = True if is_alive: raise signals.TestFailure('Thread %d timedout' % index) for index in range(0, len(self.download_threads_result)): if not self.download_threads_result[index]: self.log.info("Download failed for %d" % index) raise signals.TestFailure( 'Thread %d failed to download' % index) return False # Clear results before looping again self.download_threads_result.clear() return True