1 #!/usr/bin/python3.4 2 # 3 # Copyright 2017 - The Android Open Source Project 4 # 5 # Licensed under the Apache License, Version 2.0 (the "License"); 6 # you may not use this file except in compliance with the License. 7 # You may obtain a copy of 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, 13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 # See the License for the specific language governing permissions and 15 # limitations under the License. 16 17 import queue 18 import time 19 20 from acts import asserts 21 from acts.test_decorators import test_tracker_info 22 from acts.test_utils.net import connectivity_const as cconsts 23 from acts.test_utils.wifi.aware import aware_const as aconsts 24 from acts.test_utils.wifi.aware import aware_test_utils as autils 25 from acts.test_utils.wifi.aware.AwareBaseTest import AwareBaseTest 26 27 28 class DataPathStressTest(AwareBaseTest): 29 30 # Number of iterations on create/destroy Attach sessions. 31 ATTACH_ITERATIONS = 2 32 33 # Number of iterations on create/destroy NDP in each discovery session. 34 NDP_ITERATIONS = 50 35 36 # Maximum percentage of NDP setup failures over all iterations 37 MAX_FAILURE_PERCENTAGE = 1 38 39 def __init__(self, controllers): 40 AwareBaseTest.__init__(self, controllers) 41 42 ################################################################ 43 44 def run_oob_ndp_stress(self, attach_iterations, ndp_iterations, 45 trigger_failure_on_index=None): 46 """Run NDP (NAN data-path) stress test creating and destroying Aware 47 attach sessions, discovery sessions, and NDPs. 48 49 Args: 50 attach_iterations: Number of attach sessions. 51 ndp_iterations: Number of NDP to be attempted per attach session. 52 trigger_failure_on_index: Trigger a failure on this NDP iteration (the 53 mechanism is to request NDP on Initiator 54 before issuing the requeest on the Responder). 55 If None then no artificial failure triggered. 56 """ 57 init_dut = self.android_devices[0] 58 init_dut.pretty_name = 'Initiator' 59 resp_dut = self.android_devices[1] 60 resp_dut.pretty_name = 'Responder' 61 62 ndp_init_setup_success = 0 63 ndp_init_setup_failures = 0 64 ndp_resp_setup_success = 0 65 ndp_resp_setup_failures = 0 66 67 for attach_iter in range(attach_iterations): 68 init_id = init_dut.droid.wifiAwareAttach(True) 69 autils.wait_for_event(init_dut, aconsts.EVENT_CB_ON_ATTACHED) 70 init_ident_event = autils.wait_for_event( 71 init_dut, aconsts.EVENT_CB_ON_IDENTITY_CHANGED) 72 init_mac = init_ident_event['data']['mac'] 73 time.sleep(self.device_startup_offset) 74 resp_id = resp_dut.droid.wifiAwareAttach(True) 75 autils.wait_for_event(resp_dut, aconsts.EVENT_CB_ON_ATTACHED) 76 resp_ident_event = autils.wait_for_event( 77 resp_dut, aconsts.EVENT_CB_ON_IDENTITY_CHANGED) 78 resp_mac = resp_ident_event['data']['mac'] 79 80 # wait for for devices to synchronize with each other - there are no other 81 # mechanisms to make sure this happens for OOB discovery (except retrying 82 # to execute the data-path request) 83 time.sleep(autils.WAIT_FOR_CLUSTER) 84 85 for ndp_iteration in range(ndp_iterations): 86 if trigger_failure_on_index != ndp_iteration: 87 # Responder: request network 88 resp_req_key = autils.request_network( 89 resp_dut, 90 resp_dut.droid.wifiAwareCreateNetworkSpecifierOob( 91 resp_id, aconsts.DATA_PATH_RESPONDER, init_mac, None)) 92 93 # Wait a minimal amount of time to let the Responder configure itself 94 # and be ready for the request. While calling it first may be 95 # sufficient there are no guarantees that a glitch may slow the 96 # Responder slightly enough to invert the setup order. 97 time.sleep(1) 98 99 # Initiator: request network 100 init_req_key = autils.request_network( 101 init_dut, 102 init_dut.droid.wifiAwareCreateNetworkSpecifierOob( 103 init_id, aconsts.DATA_PATH_INITIATOR, resp_mac, None)) 104 else: 105 # Initiator: request network 106 init_req_key = autils.request_network( 107 init_dut, 108 init_dut.droid.wifiAwareCreateNetworkSpecifierOob( 109 init_id, aconsts.DATA_PATH_INITIATOR, resp_mac, None)) 110 111 # Wait a minimal amount of time to let the Initiator configure itself 112 # to guarantee failure! 113 time.sleep(2) 114 115 # Responder: request network 116 resp_req_key = autils.request_network( 117 resp_dut, 118 resp_dut.droid.wifiAwareCreateNetworkSpecifierOob( 119 resp_id, aconsts.DATA_PATH_RESPONDER, init_mac, None)) 120 121 # Initiator: wait for network formation 122 got_on_available = False 123 got_on_link_props = False 124 while not got_on_available or not got_on_link_props: 125 try: 126 nc_event = init_dut.ed.pop_event(cconsts.EVENT_NETWORK_CALLBACK, 127 autils.EVENT_NDP_TIMEOUT) 128 if nc_event['data'][ 129 cconsts.NETWORK_CB_KEY_EVENT] == cconsts.NETWORK_CB_AVAILABLE: 130 got_on_available = True 131 elif (nc_event['data'][cconsts.NETWORK_CB_KEY_EVENT] == 132 cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED): 133 got_on_link_props = True 134 except queue.Empty: 135 ndp_init_setup_failures = ndp_init_setup_failures + 1 136 init_dut.log.info('[Initiator] Timed out while waiting for ' 137 'EVENT_NETWORK_CALLBACK') 138 break 139 140 if got_on_available and got_on_link_props: 141 ndp_init_setup_success = ndp_init_setup_success + 1 142 143 # Responder: wait for network formation 144 got_on_available = False 145 got_on_link_props = False 146 while not got_on_available or not got_on_link_props: 147 try: 148 nc_event = resp_dut.ed.pop_event(cconsts.EVENT_NETWORK_CALLBACK, 149 autils.EVENT_NDP_TIMEOUT) 150 if nc_event['data'][ 151 cconsts.NETWORK_CB_KEY_EVENT] == cconsts.NETWORK_CB_AVAILABLE: 152 got_on_available = True 153 elif (nc_event['data'][cconsts.NETWORK_CB_KEY_EVENT] == 154 cconsts.NETWORK_CB_LINK_PROPERTIES_CHANGED): 155 got_on_link_props = True 156 except queue.Empty: 157 ndp_resp_setup_failures = ndp_resp_setup_failures + 1 158 init_dut.log.info('[Responder] Timed out while waiting for ' 159 'EVENT_NETWORK_CALLBACK') 160 break 161 162 if got_on_available and got_on_link_props: 163 ndp_resp_setup_success = ndp_resp_setup_success + 1 164 165 # clean-up 166 init_dut.droid.connectivityUnregisterNetworkCallback(init_req_key) 167 resp_dut.droid.connectivityUnregisterNetworkCallback(resp_req_key) 168 169 # clean-up at end of iteration 170 init_dut.droid.wifiAwareDestroy(init_id) 171 resp_dut.droid.wifiAwareDestroy(resp_id) 172 173 results = {} 174 results['ndp_init_setup_success'] = ndp_init_setup_success 175 results['ndp_init_setup_failures'] = ndp_init_setup_failures 176 results['ndp_resp_setup_success'] = ndp_resp_setup_success 177 results['ndp_resp_setup_failures'] = ndp_resp_setup_failures 178 max_failures = ( 179 self.MAX_FAILURE_PERCENTAGE * attach_iterations * ndp_iterations / 100) 180 if max_failures == 0: 181 max_failures = 1 182 if trigger_failure_on_index is not None: 183 max_failures = max_failures + 1 # for the triggered failure 184 asserts.assert_true( 185 (ndp_init_setup_failures + ndp_resp_setup_failures) < (2 * max_failures), 186 'NDP setup failure rate exceeds threshold', extras=results) 187 asserts.explicit_pass("test_oob_ndp_stress* done", extras=results) 188 189 @test_tracker_info(uuid="a20a96ba-e71f-4d31-b850-b88a75381981") 190 def test_oob_ndp_stress(self): 191 """Run NDP (NAN data-path) stress test creating and destroying Aware 192 attach sessions, discovery sessions, and NDPs.""" 193 self.run_oob_ndp_stress(self.ATTACH_ITERATIONS, self.NDP_ITERATIONS) 194 195 @test_tracker_info(uuid="1fb4a383-bf1a-411a-a904-489dd9e29c6a") 196 def test_oob_ndp_stress_failure_case(self): 197 """Run NDP (NAN data-path) stress test creating and destroying Aware 198 attach sessions, discovery sessions, and NDPs. 199 200 Verify recovery from failure by triggering an artifical failure and 201 verifying that all subsequent iterations succeed. 202 """ 203 self.run_oob_ndp_stress(attach_iterations=1, 204 ndp_iterations=10, 205 trigger_failure_on_index=3) 206