• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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