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
17import queue
18import threading
19
20from acts import asserts
21from acts.test_utils.wifi import wifi_constants as wconsts
22from acts.test_utils.wifi.aware import aware_const as aconsts
23from acts.test_utils.wifi.aware import aware_test_utils as autils
24from acts.test_utils.wifi.aware.AwareBaseTest import AwareBaseTest
25
26
27class InfraAssociationStressTest(AwareBaseTest):
28    # Length of test in seconds
29    TEST_DURATION_SECONDS = 300
30
31    # Service name
32    SERVICE_NAME = "GoogleTestServiceXYXYXY"
33
34    def is_associated(self, dut):
35        """Checks whether the device is associated (to any AP).
36
37    Args:
38      dut: Device under test.
39
40    Returns: True if associated (to any AP), False otherwise.
41    """
42        info = dut.droid.wifiGetConnectionInfo()
43        return info is not None and info["supplicant_state"] != "disconnected"
44
45    def wait_for_disassociation(self, q, dut):
46        """Waits for a disassociation event on the specified DUT for the given
47    timeout. Place a result into the queue (False) only if disassociation
48    observed.
49
50    Args:
51      q: The synchronization queue into which to place the results.
52      dut: The device to track.
53    """
54        try:
55            dut.ed.pop_event(wconsts.WIFI_DISCONNECTED,
56                             self.TEST_DURATION_SECONDS)
57            q.put(True)
58        except queue.Empty:
59            pass
60
61    def run_infra_assoc_oob_ndp_stress(self, with_ndp_traffic):
62        """Validates that Wi-Fi Aware NDP does not interfere with infrastructure
63    (AP) association.
64
65    Test assumes (and verifies) that device is already associated to an AP.
66
67    Args:
68      with_ndp_traffic: True to run traffic over the NDP.
69    """
70        init_dut = self.android_devices[0]
71        resp_dut = self.android_devices[1]
72
73        # check that associated and start tracking
74        init_dut.droid.wifiStartTrackingStateChange()
75        resp_dut.droid.wifiStartTrackingStateChange()
76        asserts.assert_true(
77            self.is_associated(init_dut), "DUT is not associated to an AP!")
78        asserts.assert_true(
79            self.is_associated(resp_dut), "DUT is not associated to an AP!")
80
81        # set up NDP
82        (init_req_key, resp_req_key, init_aware_if, resp_aware_if, init_ipv6,
83         resp_ipv6) = autils.create_oob_ndp(init_dut, resp_dut)
84        self.log.info("Interface names: I=%s, R=%s", init_aware_if,
85                      resp_aware_if)
86        self.log.info("Interface addresses (IPv6): I=%s, R=%s", init_ipv6,
87                      resp_ipv6)
88
89        # wait for any disassociation change events
90        q = queue.Queue()
91        init_thread = threading.Thread(
92            target=self.wait_for_disassociation, args=(q, init_dut))
93        resp_thread = threading.Thread(
94            target=self.wait_for_disassociation, args=(q, resp_dut))
95
96        init_thread.start()
97        resp_thread.start()
98
99        any_disassociations = False
100        try:
101            q.get(True, self.TEST_DURATION_SECONDS)
102            any_disassociations = True  # only happens on any disassociation
103        except queue.Empty:
104            pass
105        finally:
106            # TODO: no way to terminate thread (so even if we fast fail we still have
107            # to wait for the full timeout.
108            init_dut.droid.wifiStopTrackingStateChange()
109            resp_dut.droid.wifiStopTrackingStateChange()
110
111        asserts.assert_false(any_disassociations,
112                             "Wi-Fi disassociated during test run")
113
114    ################################################################
115
116    def test_infra_assoc_discovery_stress(self):
117        """Validates that Wi-Fi Aware discovery does not interfere with
118    infrastructure (AP) association.
119
120    Test assumes (and verifies) that device is already associated to an AP.
121    """
122        dut = self.android_devices[0]
123
124        # check that associated and start tracking
125        dut.droid.wifiStartTrackingStateChange()
126        asserts.assert_true(
127            self.is_associated(dut), "DUT is not associated to an AP!")
128
129        # attach
130        session_id = dut.droid.wifiAwareAttach(True)
131        autils.wait_for_event(dut, aconsts.EVENT_CB_ON_ATTACHED)
132
133        # publish
134        p_disc_id = dut.droid.wifiAwarePublish(
135            session_id,
136            autils.create_discovery_config(self.SERVICE_NAME,
137                                           aconsts.PUBLISH_TYPE_UNSOLICITED))
138        autils.wait_for_event(dut, aconsts.SESSION_CB_ON_PUBLISH_STARTED)
139
140        # wait for any disassociation change events
141        any_disassociations = False
142        try:
143            dut.ed.pop_event(wconsts.WIFI_DISCONNECTED,
144                             self.TEST_DURATION_SECONDS)
145            any_disassociations = True
146        except queue.Empty:
147            pass
148        finally:
149            dut.droid.wifiStopTrackingStateChange()
150
151        asserts.assert_false(any_disassociations,
152                             "Wi-Fi disassociated during test run")
153
154    def test_infra_assoc_ndp_no_traffic_stress(self):
155        """Validates that Wi-Fi Aware NDP (with no traffic) does not interfere with
156    infrastructure (AP) association.
157
158    Test assumes (and verifies) that devices are already associated to an AP.
159    """
160        self.run_infra_assoc_oob_ndp_stress(with_ndp_traffic=False)
161