| #!/usr/bin/python3.4 |
| # |
| # Copyright 2017 - 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. |
| |
| import string |
| import time |
| |
| from acts import asserts |
| from acts.test_decorators import test_tracker_info |
| from acts_contrib.test_utils.wifi.aware import aware_const as aconsts |
| from acts_contrib.test_utils.wifi.aware import aware_test_utils as autils |
| from acts_contrib.test_utils.wifi.aware.AwareBaseTest import AwareBaseTest |
| from acts_contrib.test_utils.wifi.WifiBaseTest import WifiBaseTest |
| |
| |
| class DiscoveryTest(AwareBaseTest): |
| """Set of tests for Wi-Fi Aware discovery.""" |
| |
| # configuration parameters used by tests |
| PAYLOAD_SIZE_MIN = 0 |
| PAYLOAD_SIZE_TYPICAL = 1 |
| PAYLOAD_SIZE_MAX = 2 |
| |
| # message strings |
| query_msg = "How are you doing? 你好嗎?" |
| response_msg = "Doing ok - thanks! 做的不錯 - 謝謝!" |
| |
| # message re-transmit counter (increases reliability in open-environment) |
| # Note: reliability of message transmission is tested elsewhere |
| msg_retx_count = 5 # hard-coded max value, internal API |
| |
| def create_base_config(self, caps, is_publish, ptype, stype, payload_size, |
| ttl, term_ind_on, null_match): |
| """Create a base configuration based on input parameters. |
| |
| Args: |
| caps: device capability dictionary |
| is_publish: True if a publish config, else False |
| ptype: unsolicited or solicited (used if is_publish is True) |
| stype: passive or active (used if is_publish is False) |
| payload_size: min, typical, max (PAYLOAD_SIZE_xx) |
| ttl: time-to-live configuration (0 - forever) |
| term_ind_on: is termination indication enabled |
| null_match: null-out the middle match filter |
| Returns: |
| publish discovery configuration object. |
| """ |
| config = {} |
| if is_publish: |
| config[aconsts.DISCOVERY_KEY_DISCOVERY_TYPE] = ptype |
| else: |
| config[aconsts.DISCOVERY_KEY_DISCOVERY_TYPE] = stype |
| config[aconsts.DISCOVERY_KEY_TTL] = ttl |
| config[aconsts.DISCOVERY_KEY_TERM_CB_ENABLED] = term_ind_on |
| if payload_size == self.PAYLOAD_SIZE_MIN: |
| config[aconsts.DISCOVERY_KEY_SERVICE_NAME] = "a" |
| config[aconsts.DISCOVERY_KEY_SSI] = None |
| config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST] = [] |
| elif payload_size == self.PAYLOAD_SIZE_TYPICAL: |
| config[aconsts.DISCOVERY_KEY_SERVICE_NAME] = "GoogleTestServiceX" |
| if is_publish: |
| config[aconsts.DISCOVERY_KEY_SSI] = string.ascii_letters |
| else: |
| config[aconsts. |
| DISCOVERY_KEY_SSI] = string.ascii_letters[:: |
| -1] # reverse |
| config[ |
| aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST] = autils.encode_list( |
| [(10).to_bytes(1, byteorder="big"), "hello there string" |
| if not null_match else None, |
| bytes(range(40))]) |
| else: # PAYLOAD_SIZE_MAX |
| config[aconsts.DISCOVERY_KEY_SERVICE_NAME] = "VeryLong" + "X" * ( |
| caps[aconsts.CAP_MAX_SERVICE_NAME_LEN] - 8) |
| config[aconsts.DISCOVERY_KEY_SSI] = ( |
| "P" if is_publish else |
| "S") * caps[aconsts.CAP_MAX_SERVICE_SPECIFIC_INFO_LEN] |
| mf = autils.construct_max_match_filter( |
| caps[aconsts.CAP_MAX_MATCH_FILTER_LEN]) |
| if null_match: |
| mf[2] = None |
| config[aconsts. |
| DISCOVERY_KEY_MATCH_FILTER_LIST] = autils.encode_list(mf) |
| |
| return config |
| |
| def create_publish_config(self, caps, ptype, payload_size, ttl, |
| term_ind_on, null_match): |
| """Create a publish configuration based on input parameters. |
| |
| Args: |
| caps: device capability dictionary |
| ptype: unsolicited or solicited |
| payload_size: min, typical, max (PAYLOAD_SIZE_xx) |
| ttl: time-to-live configuration (0 - forever) |
| term_ind_on: is termination indication enabled |
| null_match: null-out the middle match filter |
| Returns: |
| publish discovery configuration object. |
| """ |
| return self.create_base_config(caps, True, ptype, None, payload_size, |
| ttl, term_ind_on, null_match) |
| |
| def create_subscribe_config(self, caps, stype, payload_size, ttl, |
| term_ind_on, null_match): |
| """Create a subscribe configuration based on input parameters. |
| |
| Args: |
| caps: device capability dictionary |
| stype: passive or active |
| payload_size: min, typical, max (PAYLOAD_SIZE_xx) |
| ttl: time-to-live configuration (0 - forever) |
| term_ind_on: is termination indication enabled |
| null_match: null-out the middle match filter |
| Returns: |
| subscribe discovery configuration object. |
| """ |
| return self.create_base_config(caps, False, None, stype, payload_size, |
| ttl, term_ind_on, null_match) |
| |
| def positive_discovery_test_utility(self, ptype, stype, payload_size): |
| """Utility which runs a positive discovery test: |
| - Discovery (publish/subscribe) with TTL=0 (non-self-terminating) |
| - Exchange messages |
| - Update publish/subscribe |
| - Terminate |
| |
| Args: |
| ptype: Publish discovery type |
| stype: Subscribe discovery type |
| payload_size: One of PAYLOAD_SIZE_* constants - MIN, TYPICAL, MAX |
| """ |
| p_dut = self.android_devices[0] |
| p_dut.pretty_name = "Publisher" |
| s_dut = self.android_devices[1] |
| s_dut.pretty_name = "Subscriber" |
| |
| # Publisher+Subscriber: attach and wait for confirmation |
| p_id = p_dut.droid.wifiAwareAttach(False) |
| autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED) |
| time.sleep(self.device_startup_offset) |
| s_id = s_dut.droid.wifiAwareAttach(False) |
| autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED) |
| |
| # Publisher: start publish and wait for confirmation |
| p_config = self.create_publish_config( |
| p_dut.aware_capabilities, |
| ptype, |
| payload_size, |
| ttl=0, |
| term_ind_on=False, |
| null_match=False) |
| p_disc_id = p_dut.droid.wifiAwarePublish(p_id, p_config) |
| autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_PUBLISH_STARTED) |
| |
| # Subscriber: start subscribe and wait for confirmation |
| s_config = self.create_subscribe_config( |
| s_dut.aware_capabilities, |
| stype, |
| payload_size, |
| ttl=0, |
| term_ind_on=False, |
| null_match=True) |
| s_disc_id = s_dut.droid.wifiAwareSubscribe(s_id, s_config) |
| autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED) |
| |
| # Subscriber: wait for service discovery |
| discovery_event = autils.wait_for_event( |
| s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED) |
| peer_id_on_sub = discovery_event["data"][ |
| aconsts.SESSION_CB_KEY_PEER_ID] |
| |
| # Subscriber: validate contents of discovery: |
| # - SSI: publisher's |
| # - Match filter: UNSOLICITED - publisher, SOLICITED - subscriber |
| autils.assert_equal_strings( |
| bytes(discovery_event["data"][ |
| aconsts.SESSION_CB_KEY_SERVICE_SPECIFIC_INFO]).decode("utf-8"), |
| p_config[aconsts.DISCOVERY_KEY_SSI], |
| "Discovery mismatch: service specific info (SSI)") |
| asserts.assert_equal( |
| autils.decode_list(discovery_event["data"][ |
| aconsts.SESSION_CB_KEY_MATCH_FILTER_LIST]), |
| autils.decode_list( |
| p_config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST] |
| if ptype == aconsts.PUBLISH_TYPE_UNSOLICITED else s_config[ |
| aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST]), |
| "Discovery mismatch: match filter") |
| |
| # Subscriber: send message to peer (Publisher) |
| s_dut.droid.wifiAwareSendMessage(s_disc_id, peer_id_on_sub, |
| self.get_next_msg_id(), |
| self.query_msg, self.msg_retx_count) |
| autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_MESSAGE_SENT) |
| |
| # Publisher: wait for received message |
| pub_rx_msg_event = autils.wait_for_event( |
| p_dut, aconsts.SESSION_CB_ON_MESSAGE_RECEIVED) |
| peer_id_on_pub = pub_rx_msg_event["data"][ |
| aconsts.SESSION_CB_KEY_PEER_ID] |
| |
| # Publisher: validate contents of message |
| asserts.assert_equal( |
| pub_rx_msg_event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING], |
| self.query_msg, "Subscriber -> Publisher message corrupted") |
| |
| # Publisher: send message to peer (Subscriber) |
| p_dut.droid.wifiAwareSendMessage(p_disc_id, peer_id_on_pub, |
| self.get_next_msg_id(), |
| self.response_msg, |
| self.msg_retx_count) |
| autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_MESSAGE_SENT) |
| |
| # Subscriber: wait for received message |
| sub_rx_msg_event = autils.wait_for_event( |
| s_dut, aconsts.SESSION_CB_ON_MESSAGE_RECEIVED) |
| |
| # Subscriber: validate contents of message |
| asserts.assert_equal( |
| sub_rx_msg_event["data"][aconsts.SESSION_CB_KEY_PEER_ID], |
| peer_id_on_sub, |
| "Subscriber received message from different peer ID then discovery!?" |
| ) |
| autils.assert_equal_strings( |
| sub_rx_msg_event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING], |
| self.response_msg, "Publisher -> Subscriber message corrupted") |
| |
| # Subscriber: validate that we're not getting another Service Discovery |
| autils.fail_on_event(s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED) |
| |
| # Publisher: update publish and wait for confirmation |
| p_config[aconsts.DISCOVERY_KEY_SSI] = "something else" |
| p_dut.droid.wifiAwareUpdatePublish(p_disc_id, p_config) |
| autils.wait_for_event(p_dut, |
| aconsts.SESSION_CB_ON_SESSION_CONFIG_UPDATED) |
| |
| # Subscriber: expect a new service discovery |
| discovery_event = autils.wait_for_event( |
| s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED) |
| |
| # Subscriber: validate contents of discovery |
| autils.assert_equal_strings( |
| bytes(discovery_event["data"][ |
| aconsts.SESSION_CB_KEY_SERVICE_SPECIFIC_INFO]).decode("utf-8"), |
| p_config[aconsts.DISCOVERY_KEY_SSI], |
| "Discovery mismatch (after pub update): service specific info (SSI)" |
| ) |
| asserts.assert_equal( |
| autils.decode_list(discovery_event["data"][ |
| aconsts.SESSION_CB_KEY_MATCH_FILTER_LIST]), |
| autils.decode_list( |
| p_config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST] |
| if ptype == aconsts.PUBLISH_TYPE_UNSOLICITED else s_config[ |
| aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST]), |
| "Discovery mismatch: match filter") |
| asserts.assert_equal( |
| peer_id_on_sub, |
| discovery_event["data"][aconsts.SESSION_CB_KEY_PEER_ID], |
| "Peer ID changed when publish was updated!?") |
| |
| # Subscribe: update subscribe and wait for confirmation |
| s_config = self.create_subscribe_config( |
| s_dut.aware_capabilities, |
| stype, |
| payload_size, |
| ttl=0, |
| term_ind_on=False, |
| null_match=False) |
| s_dut.droid.wifiAwareUpdateSubscribe(s_disc_id, s_config) |
| autils.wait_for_event(s_dut, |
| aconsts.SESSION_CB_ON_SESSION_CONFIG_UPDATED) |
| |
| # Publisher+Subscriber: Terminate sessions |
| p_dut.droid.wifiAwareDestroyDiscoverySession(p_disc_id) |
| s_dut.droid.wifiAwareDestroyDiscoverySession(s_disc_id) |
| |
| autils.wait_for_event(p_dut, |
| aconsts.SESSION_CB_ON_SESSION_TERMINATED) |
| autils.wait_for_event(s_dut, |
| aconsts.SESSION_CB_ON_SESSION_TERMINATED) |
| |
| |
| # verify that there were no other events |
| autils.verify_no_more_events(p_dut, timeout=0) |
| autils.verify_no_more_events(s_dut, timeout=0) |
| |
| # verify that forbidden callbacks aren't called |
| autils.validate_forbidden_callbacks(p_dut, {aconsts.CB_EV_MATCH: 0}) |
| |
| def verify_discovery_session_term(self, dut, disc_id, config, is_publish, |
| term_ind_on): |
| """Utility to verify that the specified discovery session has terminated (by |
| waiting for the TTL and then attempting to reconfigure). |
| |
| Args: |
| dut: device under test |
| disc_id: discovery id for the existing session |
| config: configuration of the existing session |
| is_publish: True if the configuration was publish, False if subscribe |
| term_ind_on: True if a termination indication is expected, False otherwise |
| """ |
| # Wait for session termination |
| if term_ind_on: |
| autils.wait_for_event( |
| dut, |
| autils.decorate_event(aconsts.SESSION_CB_ON_SESSION_TERMINATED, |
| disc_id)) |
| else: |
| # can't defer wait to end since in any case have to wait for session to |
| # expire |
| autils.fail_on_event( |
| dut, |
| autils.decorate_event(aconsts.SESSION_CB_ON_SESSION_TERMINATED, |
| disc_id)) |
| |
| # Validate that session expired by trying to configure it (expect failure) |
| config[aconsts.DISCOVERY_KEY_SSI] = "something else" |
| if is_publish: |
| dut.droid.wifiAwareUpdatePublish(disc_id, config) |
| else: |
| dut.droid.wifiAwareUpdateSubscribe(disc_id, config) |
| |
| # The response to update discovery session is: |
| # term_ind_on=True: session was cleaned-up so won't get an explicit failure, but won't get a |
| # success either. Can check for no SESSION_CB_ON_SESSION_CONFIG_UPDATED but |
| # will defer to the end of the test (no events on queue). |
| # term_ind_on=False: session was not cleaned-up (yet). So expect |
| # SESSION_CB_ON_SESSION_CONFIG_FAILED. |
| if not term_ind_on: |
| autils.wait_for_event( |
| dut, |
| autils.decorate_event( |
| aconsts.SESSION_CB_ON_SESSION_CONFIG_FAILED, disc_id)) |
| |
| def positive_ttl_test_utility(self, is_publish, ptype, stype, term_ind_on): |
| """Utility which runs a positive discovery session TTL configuration test |
| |
| Iteration 1: Verify session started with TTL |
| Iteration 2: Verify session started without TTL and reconfigured with TTL |
| Iteration 3: Verify session started with (long) TTL and reconfigured with |
| (short) TTL |
| |
| Args: |
| is_publish: True if testing publish, False if testing subscribe |
| ptype: Publish discovery type (used if is_publish is True) |
| stype: Subscribe discovery type (used if is_publish is False) |
| term_ind_on: Configuration of termination indication |
| """ |
| SHORT_TTL = 5 # 5 seconds |
| LONG_TTL = 100 # 100 seconds |
| dut = self.android_devices[0] |
| |
| # Attach and wait for confirmation |
| id = dut.droid.wifiAwareAttach(False) |
| autils.wait_for_event(dut, aconsts.EVENT_CB_ON_ATTACHED) |
| |
| # Iteration 1: Start discovery session with TTL |
| config = self.create_base_config( |
| dut.aware_capabilities, is_publish, ptype, stype, |
| self.PAYLOAD_SIZE_TYPICAL, SHORT_TTL, term_ind_on, False) |
| if is_publish: |
| disc_id = dut.droid.wifiAwarePublish(id, config, True) |
| autils.wait_for_event( |
| dut, |
| autils.decorate_event(aconsts.SESSION_CB_ON_PUBLISH_STARTED, |
| disc_id)) |
| else: |
| disc_id = dut.droid.wifiAwareSubscribe(id, config, True) |
| autils.wait_for_event( |
| dut, |
| autils.decorate_event(aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, |
| disc_id)) |
| |
| # Wait for session termination & verify |
| self.verify_discovery_session_term(dut, disc_id, config, is_publish, |
| term_ind_on) |
| |
| # Iteration 2: Start a discovery session without TTL |
| config = self.create_base_config( |
| dut.aware_capabilities, is_publish, ptype, stype, |
| self.PAYLOAD_SIZE_TYPICAL, 0, term_ind_on, False) |
| if is_publish: |
| disc_id = dut.droid.wifiAwarePublish(id, config, True) |
| autils.wait_for_event( |
| dut, |
| autils.decorate_event(aconsts.SESSION_CB_ON_PUBLISH_STARTED, |
| disc_id)) |
| else: |
| disc_id = dut.droid.wifiAwareSubscribe(id, config, True) |
| autils.wait_for_event( |
| dut, |
| autils.decorate_event(aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, |
| disc_id)) |
| |
| # Update with a TTL |
| config = self.create_base_config( |
| dut.aware_capabilities, is_publish, ptype, stype, |
| self.PAYLOAD_SIZE_TYPICAL, SHORT_TTL, term_ind_on, False) |
| if is_publish: |
| dut.droid.wifiAwareUpdatePublish(disc_id, config) |
| else: |
| dut.droid.wifiAwareUpdateSubscribe(disc_id, config) |
| autils.wait_for_event( |
| dut, |
| autils.decorate_event(aconsts.SESSION_CB_ON_SESSION_CONFIG_UPDATED, |
| disc_id)) |
| |
| # Wait for session termination & verify |
| self.verify_discovery_session_term(dut, disc_id, config, is_publish, |
| term_ind_on) |
| |
| # Iteration 3: Start a discovery session with (long) TTL |
| config = self.create_base_config( |
| dut.aware_capabilities, is_publish, ptype, stype, |
| self.PAYLOAD_SIZE_TYPICAL, LONG_TTL, term_ind_on, False) |
| if is_publish: |
| disc_id = dut.droid.wifiAwarePublish(id, config, True) |
| autils.wait_for_event( |
| dut, |
| autils.decorate_event(aconsts.SESSION_CB_ON_PUBLISH_STARTED, |
| disc_id)) |
| else: |
| disc_id = dut.droid.wifiAwareSubscribe(id, config, True) |
| autils.wait_for_event( |
| dut, |
| autils.decorate_event(aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, |
| disc_id)) |
| |
| # Update with a TTL |
| config = self.create_base_config( |
| dut.aware_capabilities, is_publish, ptype, stype, |
| self.PAYLOAD_SIZE_TYPICAL, SHORT_TTL, term_ind_on, False) |
| if is_publish: |
| dut.droid.wifiAwareUpdatePublish(disc_id, config) |
| else: |
| dut.droid.wifiAwareUpdateSubscribe(disc_id, config) |
| autils.wait_for_event( |
| dut, |
| autils.decorate_event(aconsts.SESSION_CB_ON_SESSION_CONFIG_UPDATED, |
| disc_id)) |
| |
| # Wait for session termination & verify |
| self.verify_discovery_session_term(dut, disc_id, config, is_publish, |
| term_ind_on) |
| |
| # verify that there were no other events |
| autils.verify_no_more_events(dut) |
| |
| # verify that forbidden callbacks aren't called |
| if not term_ind_on: |
| autils.validate_forbidden_callbacks( |
| dut, { |
| aconsts.CB_EV_PUBLISH_TERMINATED: 0, |
| aconsts.CB_EV_SUBSCRIBE_TERMINATED: 0 |
| }) |
| |
| def discovery_mismatch_test_utility(self, |
| is_expected_to_pass, |
| p_type, |
| s_type, |
| p_service_name=None, |
| s_service_name=None, |
| p_mf_1=None, |
| s_mf_1=None): |
| """Utility which runs the negative discovery test for mismatched service |
| configs. |
| |
| Args: |
| is_expected_to_pass: True if positive test, False if negative |
| p_type: Publish discovery type |
| s_type: Subscribe discovery type |
| p_service_name: Publish service name (or None to leave unchanged) |
| s_service_name: Subscribe service name (or None to leave unchanged) |
| p_mf_1: Publish match filter element [1] (or None to leave unchanged) |
| s_mf_1: Subscribe match filter element [1] (or None to leave unchanged) |
| """ |
| p_dut = self.android_devices[0] |
| p_dut.pretty_name = "Publisher" |
| s_dut = self.android_devices[1] |
| s_dut.pretty_name = "Subscriber" |
| |
| # create configurations |
| p_config = self.create_publish_config( |
| p_dut.aware_capabilities, |
| p_type, |
| self.PAYLOAD_SIZE_TYPICAL, |
| ttl=0, |
| term_ind_on=False, |
| null_match=False) |
| if p_service_name is not None: |
| p_config[aconsts.DISCOVERY_KEY_SERVICE_NAME] = p_service_name |
| if p_mf_1 is not None: |
| p_config[ |
| aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST] = autils.encode_list( |
| [(10).to_bytes(1, byteorder="big"), p_mf_1, |
| bytes(range(40))]) |
| s_config = self.create_publish_config( |
| s_dut.aware_capabilities, |
| s_type, |
| self.PAYLOAD_SIZE_TYPICAL, |
| ttl=0, |
| term_ind_on=False, |
| null_match=False) |
| if s_service_name is not None: |
| s_config[aconsts.DISCOVERY_KEY_SERVICE_NAME] = s_service_name |
| if s_mf_1 is not None: |
| s_config[ |
| aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST] = autils.encode_list( |
| [(10).to_bytes(1, byteorder="big"), s_mf_1, |
| bytes(range(40))]) |
| |
| p_id = p_dut.droid.wifiAwareAttach(False) |
| autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED) |
| time.sleep(self.device_startup_offset) |
| s_id = s_dut.droid.wifiAwareAttach(False) |
| autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED) |
| |
| # Publisher: start publish and wait for confirmation |
| p_disc_id = p_dut.droid.wifiAwarePublish(p_id, p_config) |
| autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_PUBLISH_STARTED) |
| |
| # Subscriber: start subscribe and wait for confirmation |
| s_disc_id = s_dut.droid.wifiAwareSubscribe(s_id, s_config) |
| autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED) |
| |
| # Subscriber: fail on service discovery |
| if is_expected_to_pass: |
| autils.wait_for_event(s_dut, |
| aconsts.SESSION_CB_ON_SERVICE_DISCOVERED) |
| else: |
| autils.fail_on_event(s_dut, |
| aconsts.SESSION_CB_ON_SERVICE_DISCOVERED) |
| |
| # Publisher+Subscriber: Terminate sessions |
| p_dut.droid.wifiAwareDestroyDiscoverySession(p_disc_id) |
| s_dut.droid.wifiAwareDestroyDiscoverySession(s_disc_id) |
| autils.wait_for_event(p_dut, |
| aconsts.SESSION_CB_ON_SESSION_TERMINATED) |
| autils.wait_for_event(s_dut, |
| aconsts.SESSION_CB_ON_SESSION_TERMINATED) |
| |
| # verify that there were no other events (including terminations) |
| autils.verify_no_more_events(p_dut, timeout=0) |
| autils.verify_no_more_events(s_dut, timeout=0) |
| |
| ####################################### |
| # Positive tests key: |
| # |
| # names is: test_<pub_type>_<sub_type>_<size> |
| # where: |
| # |
| # pub_type: Type of publish discovery session: unsolicited or solicited. |
| # sub_type: Type of subscribe discovery session: passive or active. |
| # size: Size of payload fields (service name, service specific info, and match |
| # filter: typical, max, or min. |
| ####################################### |
| |
| @test_tracker_info(uuid="954ebbde-ed2b-4f04-9e68-88239187d69d") |
| @WifiBaseTest.wifi_test_wrap |
| def test_positive_unsolicited_passive_typical(self): |
| """Functional test case / Discovery test cases / positive test case: |
| - Solicited publish + passive subscribe |
| - Typical payload fields size |
| |
| Verifies that discovery and message exchange succeeds. |
| """ |
| self.positive_discovery_test_utility( |
| ptype=aconsts.PUBLISH_TYPE_UNSOLICITED, |
| stype=aconsts.SUBSCRIBE_TYPE_PASSIVE, |
| payload_size=self.PAYLOAD_SIZE_TYPICAL) |
| |
| @test_tracker_info(uuid="67fb22bb-6985-4345-95a4-90b76681a58b") |
| def test_positive_unsolicited_passive_min(self): |
| """Functional test case / Discovery test cases / positive test case: |
| - Solicited publish + passive subscribe |
| - Minimal payload fields size |
| |
| Verifies that discovery and message exchange succeeds. |
| """ |
| self.positive_discovery_test_utility( |
| ptype=aconsts.PUBLISH_TYPE_UNSOLICITED, |
| stype=aconsts.SUBSCRIBE_TYPE_PASSIVE, |
| payload_size=self.PAYLOAD_SIZE_MIN) |
| |
| @test_tracker_info(uuid="a02a47b9-41bb-47bb-883b-921024a2c30d") |
| def test_positive_unsolicited_passive_max(self): |
| """Functional test case / Discovery test cases / positive test case: |
| - Solicited publish + passive subscribe |
| - Maximal payload fields size |
| |
| Verifies that discovery and message exchange succeeds. |
| """ |
| self.positive_discovery_test_utility( |
| ptype=aconsts.PUBLISH_TYPE_UNSOLICITED, |
| stype=aconsts.SUBSCRIBE_TYPE_PASSIVE, |
| payload_size=self.PAYLOAD_SIZE_MAX) |
| |
| @test_tracker_info(uuid="586c657f-2388-4e7a-baee-9bce2f3d1a16") |
| def test_positive_solicited_active_typical(self): |
| """Functional test case / Discovery test cases / positive test case: |
| - Unsolicited publish + active subscribe |
| - Typical payload fields size |
| |
| Verifies that discovery and message exchange succeeds. |
| """ |
| self.positive_discovery_test_utility( |
| ptype=aconsts.PUBLISH_TYPE_SOLICITED, |
| stype=aconsts.SUBSCRIBE_TYPE_ACTIVE, |
| payload_size=self.PAYLOAD_SIZE_TYPICAL) |
| |
| @test_tracker_info(uuid="5369e4ff-f406-48c5-b41a-df38ec340146") |
| def test_positive_solicited_active_min(self): |
| """Functional test case / Discovery test cases / positive test case: |
| - Unsolicited publish + active subscribe |
| - Minimal payload fields size |
| |
| Verifies that discovery and message exchange succeeds. |
| """ |
| self.positive_discovery_test_utility( |
| ptype=aconsts.PUBLISH_TYPE_SOLICITED, |
| stype=aconsts.SUBSCRIBE_TYPE_ACTIVE, |
| payload_size=self.PAYLOAD_SIZE_MIN) |
| |
| @test_tracker_info(uuid="634c6eb8-2c4f-42bd-9bbb-d874d0ec22f3") |
| def test_positive_solicited_active_max(self): |
| """Functional test case / Discovery test cases / positive test case: |
| - Unsolicited publish + active subscribe |
| - Maximal payload fields size |
| |
| Verifies that discovery and message exchange succeeds. |
| """ |
| self.positive_discovery_test_utility( |
| ptype=aconsts.PUBLISH_TYPE_SOLICITED, |
| stype=aconsts.SUBSCRIBE_TYPE_ACTIVE, |
| payload_size=self.PAYLOAD_SIZE_MAX) |
| |
| ####################################### |
| # TTL tests key: |
| # |
| # names is: test_ttl_<pub_type|sub_type>_<term_ind> |
| # where: |
| # |
| # pub_type: Type of publish discovery session: unsolicited or solicited. |
| # sub_type: Type of subscribe discovery session: passive or active. |
| # term_ind: ind_on or ind_off |
| ####################################### |
| |
| @test_tracker_info(uuid="9d7e758e-e0e2-4550-bcee-bfb6a2bff63e") |
| def test_ttl_unsolicited_ind_on(self): |
| """Functional test case / Discovery test cases / TTL test case: |
| - Unsolicited publish |
| - Termination indication enabled |
| """ |
| self.positive_ttl_test_utility( |
| is_publish=True, |
| ptype=aconsts.PUBLISH_TYPE_UNSOLICITED, |
| stype=None, |
| term_ind_on=True) |
| |
| @test_tracker_info(uuid="48fd69bc-cc2a-4f65-a0a1-63d7c1720702") |
| def test_ttl_unsolicited_ind_off(self): |
| """Functional test case / Discovery test cases / TTL test case: |
| - Unsolicited publish |
| - Termination indication disabled |
| """ |
| self.positive_ttl_test_utility( |
| is_publish=True, |
| ptype=aconsts.PUBLISH_TYPE_UNSOLICITED, |
| stype=None, |
| term_ind_on=False) |
| |
| @test_tracker_info(uuid="afb75fc1-9ba7-446a-b5ed-7cd37ab51b1c") |
| def test_ttl_solicited_ind_on(self): |
| """Functional test case / Discovery test cases / TTL test case: |
| - Solicited publish |
| - Termination indication enabled |
| """ |
| self.positive_ttl_test_utility( |
| is_publish=True, |
| ptype=aconsts.PUBLISH_TYPE_SOLICITED, |
| stype=None, |
| term_ind_on=True) |
| |
| @test_tracker_info(uuid="703311a6-e444-4055-94ee-ea9b9b71799e") |
| def test_ttl_solicited_ind_off(self): |
| """Functional test case / Discovery test cases / TTL test case: |
| - Solicited publish |
| - Termination indication disabled |
| """ |
| self.positive_ttl_test_utility( |
| is_publish=True, |
| ptype=aconsts.PUBLISH_TYPE_SOLICITED, |
| stype=None, |
| term_ind_on=False) |
| |
| @test_tracker_info(uuid="38a541c4-ff55-4387-87b7-4d940489da9d") |
| def test_ttl_passive_ind_on(self): |
| """Functional test case / Discovery test cases / TTL test case: |
| - Passive subscribe |
| - Termination indication enabled |
| """ |
| self.positive_ttl_test_utility( |
| is_publish=False, |
| ptype=None, |
| stype=aconsts.SUBSCRIBE_TYPE_PASSIVE, |
| term_ind_on=True) |
| |
| @test_tracker_info(uuid="ba971e12-b0ca-417c-a1b5-9451598de47d") |
| def test_ttl_passive_ind_off(self): |
| """Functional test case / Discovery test cases / TTL test case: |
| - Passive subscribe |
| - Termination indication disabled |
| """ |
| self.positive_ttl_test_utility( |
| is_publish=False, |
| ptype=None, |
| stype=aconsts.SUBSCRIBE_TYPE_PASSIVE, |
| term_ind_on=False) |
| |
| @test_tracker_info(uuid="7b5d96f2-2415-4b98-9a51-32957f0679a0") |
| def test_ttl_active_ind_on(self): |
| """Functional test case / Discovery test cases / TTL test case: |
| - Active subscribe |
| - Termination indication enabled |
| """ |
| self.positive_ttl_test_utility( |
| is_publish=False, |
| ptype=None, |
| stype=aconsts.SUBSCRIBE_TYPE_ACTIVE, |
| term_ind_on=True) |
| |
| @test_tracker_info(uuid="c9268eca-0a30-42dd-8e6c-b8b0b84697fb") |
| def test_ttl_active_ind_off(self): |
| """Functional test case / Discovery test cases / TTL test case: |
| - Active subscribe |
| - Termination indication disabled |
| """ |
| self.positive_ttl_test_utility( |
| is_publish=False, |
| ptype=None, |
| stype=aconsts.SUBSCRIBE_TYPE_ACTIVE, |
| term_ind_on=False) |
| |
| ####################################### |
| # Mismatched service name tests key: |
| # |
| # names is: test_mismatch_service_name_<pub_type>_<sub_type> |
| # where: |
| # |
| # pub_type: Type of publish discovery session: unsolicited or solicited. |
| # sub_type: Type of subscribe discovery session: passive or active. |
| ####################################### |
| |
| @test_tracker_info(uuid="175415e9-7d07-40d0-95f0-3a5f91ea4711") |
| def test_mismatch_service_name_unsolicited_passive(self): |
| """Functional test case / Discovery test cases / Mismatch service name |
| - Unsolicited publish |
| - Passive subscribe |
| """ |
| self.discovery_mismatch_test_utility( |
| is_expected_to_pass=False, |
| p_type=aconsts.PUBLISH_TYPE_UNSOLICITED, |
| s_type=aconsts.SUBSCRIBE_TYPE_PASSIVE, |
| p_service_name="GoogleTestServiceXXX", |
| s_service_name="GoogleTestServiceYYY") |
| |
| @test_tracker_info(uuid="c22a54ce-9e46-47a5-ac44-831faf93d317") |
| def test_mismatch_service_name_solicited_active(self): |
| """Functional test case / Discovery test cases / Mismatch service name |
| - Solicited publish |
| - Active subscribe |
| """ |
| self.discovery_mismatch_test_utility( |
| is_expected_to_pass=False, |
| p_type=aconsts.PUBLISH_TYPE_SOLICITED, |
| s_type=aconsts.SUBSCRIBE_TYPE_ACTIVE, |
| p_service_name="GoogleTestServiceXXX", |
| s_service_name="GoogleTestServiceYYY") |
| |
| ####################################### |
| # Mismatched discovery session type tests key: |
| # |
| # names is: test_mismatch_service_type_<pub_type>_<sub_type> |
| # where: |
| # |
| # pub_type: Type of publish discovery session: unsolicited or solicited. |
| # sub_type: Type of subscribe discovery session: passive or active. |
| ####################################### |
| |
| @test_tracker_info(uuid="4806f631-d9eb-45fd-9e75-24674962770f") |
| def test_mismatch_service_type_unsolicited_active(self): |
| """Functional test case / Discovery test cases / Mismatch service name |
| - Unsolicited publish |
| - Active subscribe |
| """ |
| self.discovery_mismatch_test_utility( |
| is_expected_to_pass=True, |
| p_type=aconsts.PUBLISH_TYPE_UNSOLICITED, |
| s_type=aconsts.SUBSCRIBE_TYPE_ACTIVE) |
| |
| @test_tracker_info(uuid="12d648fd-b8fa-4c0f-9467-95e2366047de") |
| def test_mismatch_service_type_solicited_passive(self): |
| """Functional test case / Discovery test cases / Mismatch service name |
| - Unsolicited publish |
| - Active subscribe |
| """ |
| self.discovery_mismatch_test_utility( |
| is_expected_to_pass=False, |
| p_type=aconsts.PUBLISH_TYPE_SOLICITED, |
| s_type=aconsts.SUBSCRIBE_TYPE_PASSIVE) |
| |
| ####################################### |
| # Mismatched discovery match filter tests key: |
| # |
| # names is: test_mismatch_match_filter_<pub_type>_<sub_type> |
| # where: |
| # |
| # pub_type: Type of publish discovery session: unsolicited or solicited. |
| # sub_type: Type of subscribe discovery session: passive or active. |
| ####################################### |
| |
| @test_tracker_info(uuid="d98454cb-64af-4266-8fed-f0b545a2d7c4") |
| def test_mismatch_match_filter_unsolicited_passive(self): |
| """Functional test case / Discovery test cases / Mismatch match filter |
| - Unsolicited publish |
| - Passive subscribe |
| """ |
| self.discovery_mismatch_test_utility( |
| is_expected_to_pass=False, |
| p_type=aconsts.PUBLISH_TYPE_UNSOLICITED, |
| s_type=aconsts.SUBSCRIBE_TYPE_PASSIVE, |
| p_mf_1="hello there string", |
| s_mf_1="goodbye there string") |
| |
| @test_tracker_info(uuid="663c1008-ae11-4e1a-87c7-c311d83f481c") |
| def test_mismatch_match_filter_solicited_active(self): |
| """Functional test case / Discovery test cases / Mismatch match filter |
| - Solicited publish |
| - Active subscribe |
| """ |
| self.discovery_mismatch_test_utility( |
| is_expected_to_pass=False, |
| p_type=aconsts.PUBLISH_TYPE_SOLICITED, |
| s_type=aconsts.SUBSCRIBE_TYPE_ACTIVE, |
| p_mf_1="hello there string", |
| s_mf_1="goodbye there string") |
| |
| ####################################### |
| # Multiple concurrent services |
| ####################################### |
| |
| def run_multiple_concurrent_services(self, type_x, type_y): |
| """Validate multiple identical discovery services running on both devices: |
| - DUT1 & DUT2 running Publish for X |
| - DUT1 & DUT2 running Publish for Y |
| - DUT1 Subscribes for X |
| - DUT2 Subscribes for Y |
| Message exchanges. |
| |
| Note: test requires that devices support 2 publish sessions concurrently. |
| The test will be skipped if the devices are not capable. |
| |
| Args: |
| type_x, type_y: A list of [ptype, stype] of the publish and subscribe |
| types for services X and Y respectively. |
| """ |
| dut1 = self.android_devices[0] |
| dut2 = self.android_devices[1] |
| |
| X_SERVICE_NAME = "ServiceXXX" |
| Y_SERVICE_NAME = "ServiceYYY" |
| |
| asserts.skip_if( |
| dut1.aware_capabilities[aconsts.CAP_MAX_PUBLISHES] < 2 |
| or dut2.aware_capabilities[aconsts.CAP_MAX_PUBLISHES] < 2, |
| "Devices do not support 2 publish sessions") |
| |
| # attach and wait for confirmation |
| id1 = dut1.droid.wifiAwareAttach(False) |
| autils.wait_for_event(dut1, aconsts.EVENT_CB_ON_ATTACHED) |
| time.sleep(self.device_startup_offset) |
| id2 = dut2.droid.wifiAwareAttach(False) |
| autils.wait_for_event(dut2, aconsts.EVENT_CB_ON_ATTACHED) |
| |
| # DUT1 & DUT2: start publishing both X & Y services and wait for |
| # confirmations |
| dut1_x_pid = dut1.droid.wifiAwarePublish( |
| id1, autils.create_discovery_config(X_SERVICE_NAME, type_x[0])) |
| event = autils.wait_for_event(dut1, |
| aconsts.SESSION_CB_ON_PUBLISH_STARTED) |
| asserts.assert_equal(event["data"][aconsts.SESSION_CB_KEY_SESSION_ID], |
| dut1_x_pid, |
| "Unexpected DUT1 X publish session discovery ID") |
| |
| dut1_y_pid = dut1.droid.wifiAwarePublish( |
| id1, autils.create_discovery_config(Y_SERVICE_NAME, type_y[0])) |
| event = autils.wait_for_event(dut1, |
| aconsts.SESSION_CB_ON_PUBLISH_STARTED) |
| asserts.assert_equal(event["data"][aconsts.SESSION_CB_KEY_SESSION_ID], |
| dut1_y_pid, |
| "Unexpected DUT1 Y publish session discovery ID") |
| |
| dut2_x_pid = dut2.droid.wifiAwarePublish( |
| id2, autils.create_discovery_config(X_SERVICE_NAME, type_x[0])) |
| event = autils.wait_for_event(dut2, |
| aconsts.SESSION_CB_ON_PUBLISH_STARTED) |
| asserts.assert_equal(event["data"][aconsts.SESSION_CB_KEY_SESSION_ID], |
| dut2_x_pid, |
| "Unexpected DUT2 X publish session discovery ID") |
| |
| dut2_y_pid = dut2.droid.wifiAwarePublish( |
| id2, autils.create_discovery_config(Y_SERVICE_NAME, type_y[0])) |
| event = autils.wait_for_event(dut2, |
| aconsts.SESSION_CB_ON_PUBLISH_STARTED) |
| asserts.assert_equal(event["data"][aconsts.SESSION_CB_KEY_SESSION_ID], |
| dut2_y_pid, |
| "Unexpected DUT2 Y publish session discovery ID") |
| |
| # DUT1: start subscribing for X |
| dut1_x_sid = dut1.droid.wifiAwareSubscribe( |
| id1, autils.create_discovery_config(X_SERVICE_NAME, type_x[1])) |
| autils.wait_for_event(dut1, aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED) |
| |
| # DUT2: start subscribing for Y |
| dut2_y_sid = dut2.droid.wifiAwareSubscribe( |
| id2, autils.create_discovery_config(Y_SERVICE_NAME, type_y[1])) |
| autils.wait_for_event(dut2, aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED) |
| |
| # DUT1 & DUT2: wait for service discovery |
| event = autils.wait_for_event(dut1, |
| aconsts.SESSION_CB_ON_SERVICE_DISCOVERED) |
| asserts.assert_equal( |
| event["data"][aconsts.SESSION_CB_KEY_SESSION_ID], dut1_x_sid, |
| "Unexpected DUT1 X subscribe session discovery ID") |
| dut1_peer_id_for_dut2_x = event["data"][aconsts.SESSION_CB_KEY_PEER_ID] |
| |
| event = autils.wait_for_event(dut2, |
| aconsts.SESSION_CB_ON_SERVICE_DISCOVERED) |
| asserts.assert_equal( |
| event["data"][aconsts.SESSION_CB_KEY_SESSION_ID], dut2_y_sid, |
| "Unexpected DUT2 Y subscribe session discovery ID") |
| dut2_peer_id_for_dut1_y = event["data"][aconsts.SESSION_CB_KEY_PEER_ID] |
| |
| # DUT1.X send message to DUT2 |
| x_msg = "Hello X on DUT2!" |
| dut1.droid.wifiAwareSendMessage(dut1_x_sid, dut1_peer_id_for_dut2_x, |
| self.get_next_msg_id(), x_msg, |
| self.msg_retx_count) |
| autils.wait_for_event(dut1, aconsts.SESSION_CB_ON_MESSAGE_SENT) |
| event = autils.wait_for_event(dut2, |
| aconsts.SESSION_CB_ON_MESSAGE_RECEIVED) |
| asserts.assert_equal( |
| event["data"][aconsts.SESSION_CB_KEY_SESSION_ID], dut2_x_pid, |
| "Unexpected publish session ID on DUT2 for meesage " |
| "received on service X") |
| asserts.assert_equal( |
| event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING], x_msg, |
| "Message on service X from DUT1 to DUT2 not received correctly") |
| |
| # DUT2.Y send message to DUT1 |
| y_msg = "Hello Y on DUT1!" |
| dut2.droid.wifiAwareSendMessage(dut2_y_sid, dut2_peer_id_for_dut1_y, |
| self.get_next_msg_id(), y_msg, |
| self.msg_retx_count) |
| autils.wait_for_event(dut2, aconsts.SESSION_CB_ON_MESSAGE_SENT) |
| event = autils.wait_for_event(dut1, |
| aconsts.SESSION_CB_ON_MESSAGE_RECEIVED) |
| asserts.assert_equal( |
| event["data"][aconsts.SESSION_CB_KEY_SESSION_ID], dut1_y_pid, |
| "Unexpected publish session ID on DUT1 for meesage " |
| "received on service Y") |
| asserts.assert_equal( |
| event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING], y_msg, |
| "Message on service Y from DUT2 to DUT1 not received correctly") |
| |
| @test_tracker_info(uuid="eef80cf3-1fd2-4526-969b-6af2dce785d7") |
| def test_multiple_concurrent_services_both_unsolicited_passive(self): |
| """Validate multiple concurrent discovery sessions running on both devices. |
| - DUT1 & DUT2 running Publish for X |
| - DUT1 & DUT2 running Publish for Y |
| - DUT1 Subscribes for X |
| - DUT2 Subscribes for Y |
| Message exchanges. |
| |
| Both sessions are Unsolicited/Passive. |
| |
| Note: test requires that devices support 2 publish sessions concurrently. |
| The test will be skipped if the devices are not capable. |
| """ |
| self.run_multiple_concurrent_services( |
| type_x=[ |
| aconsts.PUBLISH_TYPE_UNSOLICITED, |
| aconsts.SUBSCRIBE_TYPE_PASSIVE |
| ], |
| type_y=[ |
| aconsts.PUBLISH_TYPE_UNSOLICITED, |
| aconsts.SUBSCRIBE_TYPE_PASSIVE |
| ]) |
| |
| @test_tracker_info(uuid="46739f04-ab2b-4556-b1a4-9aa2774869b5") |
| def test_multiple_concurrent_services_both_solicited_active(self): |
| """Validate multiple concurrent discovery sessions running on both devices. |
| - DUT1 & DUT2 running Publish for X |
| - DUT1 & DUT2 running Publish for Y |
| - DUT1 Subscribes for X |
| - DUT2 Subscribes for Y |
| Message exchanges. |
| |
| Both sessions are Solicited/Active. |
| |
| Note: test requires that devices support 2 publish sessions concurrently. |
| The test will be skipped if the devices are not capable. |
| """ |
| self.run_multiple_concurrent_services( |
| type_x=[ |
| aconsts.PUBLISH_TYPE_SOLICITED, aconsts.SUBSCRIBE_TYPE_ACTIVE |
| ], |
| type_y=[ |
| aconsts.PUBLISH_TYPE_SOLICITED, aconsts.SUBSCRIBE_TYPE_ACTIVE |
| ]) |
| |
| @test_tracker_info(uuid="5f8f7fd2-4a0e-4cca-8cbb-6d54353f2baa") |
| def test_multiple_concurrent_services_mix_unsolicited_solicited(self): |
| """Validate multiple concurrent discovery sessions running on both devices. |
| - DUT1 & DUT2 running Publish for X |
| - DUT1 & DUT2 running Publish for Y |
| - DUT1 Subscribes for X |
| - DUT2 Subscribes for Y |
| Message exchanges. |
| |
| Session A is Unsolicited/Passive. |
| Session B is Solicited/Active. |
| |
| Note: test requires that devices support 2 publish sessions concurrently. |
| The test will be skipped if the devices are not capable. |
| """ |
| self.run_multiple_concurrent_services( |
| type_x=[ |
| aconsts.PUBLISH_TYPE_UNSOLICITED, |
| aconsts.SUBSCRIBE_TYPE_PASSIVE |
| ], |
| type_y=[ |
| aconsts.PUBLISH_TYPE_SOLICITED, aconsts.SUBSCRIBE_TYPE_ACTIVE |
| ]) |
| |
| ######################################################### |
| |
| @test_tracker_info(uuid="908ec896-fc7a-4ee4-b633-a2f042b74448") |
| def test_upper_lower_service_name_equivalence(self): |
| """Validate that Service Name is case-insensitive. Publish a service name |
| with mixed case, subscribe to the same service name with alternative case |
| and verify that discovery happens.""" |
| p_dut = self.android_devices[0] |
| s_dut = self.android_devices[1] |
| |
| pub_service_name = "GoogleAbCdEf" |
| sub_service_name = "GoogleaBcDeF" |
| |
| autils.create_discovery_pair( |
| p_dut, |
| s_dut, |
| p_config=autils.create_discovery_config( |
| pub_service_name, aconsts.PUBLISH_TYPE_UNSOLICITED), |
| s_config=autils.create_discovery_config( |
| sub_service_name, aconsts.SUBSCRIBE_TYPE_PASSIVE), |
| device_startup_offset=self.device_startup_offset) |
| |
| ########################################################## |
| |
| def exchange_messages(self, p_dut, p_disc_id, s_dut, s_disc_id, peer_id_on_sub, session_name): |
| """ |
| Exchange message between Publisher and Subscriber on target discovery session |
| |
| Args: |
| p_dut: Publisher device |
| p_disc_id: Publish discovery session id |
| s_dut: Subscriber device |
| s_disc_id: Subscribe discovery session id |
| peer_id_on_sub: Peer ID of the Publisher as seen on the Subscriber |
| session_name: dictionary of discovery session name base on role("pub" or "sub") |
| {role: {disc_id: name}} |
| """ |
| msg_template = "Hello {} from {} !" |
| |
| # Message send from Subscriber to Publisher |
| s_to_p_msg = msg_template.format(session_name["pub"][p_disc_id], |
| session_name["sub"][s_disc_id]) |
| s_dut.droid.wifiAwareSendMessage(s_disc_id, |
| peer_id_on_sub, |
| self.get_next_msg_id(), |
| s_to_p_msg, |
| self.msg_retx_count) |
| autils.wait_for_event(s_dut, |
| autils.decorate_event(aconsts.SESSION_CB_ON_MESSAGE_SENT, s_disc_id)) |
| event = autils.wait_for_event(p_dut, |
| autils.decorate_event(aconsts.SESSION_CB_ON_MESSAGE_RECEIVED, |
| p_disc_id)) |
| asserts.assert_equal( |
| event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING], s_to_p_msg, |
| "Message on service %s from Subscriber to Publisher " |
| "not received correctly" % session_name["pub"][p_disc_id]) |
| peer_id_on_pub = event["data"][aconsts.SESSION_CB_KEY_PEER_ID] |
| |
| # Message send from Publisher to Subscriber |
| p_to_s_msg = msg_template.format(session_name["sub"][s_disc_id], |
| session_name["pub"][p_disc_id]) |
| p_dut.droid.wifiAwareSendMessage(p_disc_id, |
| peer_id_on_pub, |
| self.get_next_msg_id(), p_to_s_msg, |
| self.msg_retx_count) |
| autils.wait_for_event( |
| p_dut, autils.decorate_event(aconsts.SESSION_CB_ON_MESSAGE_SENT, p_disc_id)) |
| event = autils.wait_for_event(s_dut, |
| autils.decorate_event(aconsts.SESSION_CB_ON_MESSAGE_RECEIVED, |
| s_disc_id)) |
| asserts.assert_equal( |
| event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING], p_to_s_msg, |
| "Message on service %s from Publisher to Subscriber" |
| "not received correctly" % session_name["sub"][s_disc_id]) |
| |
| def run_multiple_concurrent_services_same_name_diff_ssi(self, type_x, type_y): |
| """Validate same service name with multiple service specific info on publisher |
| and subscriber can see all service |
| |
| - p_dut running Publish X and Y |
| - s_dut running subscribe A and B |
| - subscribe A find X and Y |
| - subscribe B find X and Y |
| |
| Message exchanges: |
| - A to X and X to A |
| - B to X and X to B |
| - A to Y and Y to A |
| - B to Y and Y to B |
| |
| Note: test requires that publisher device support 2 publish sessions concurrently, |
| and subscriber device support 2 subscribe sessions concurrently. |
| The test will be skipped if the devices are not capable. |
| |
| Args: |
| type_x, type_y: A list of [ptype, stype] of the publish and subscribe |
| types for services X and Y respectively. |
| """ |
| p_dut = self.android_devices[0] |
| s_dut = self.android_devices[1] |
| |
| asserts.skip_if( |
| p_dut.aware_capabilities[aconsts.CAP_MAX_PUBLISHES] < 2 |
| or s_dut.aware_capabilities[aconsts.CAP_MAX_SUBSCRIBES] < 2, |
| "Devices do not support 2 publish sessions or 2 subscribe sessions") |
| |
| SERVICE_NAME = "ServiceName" |
| X_SERVICE_SSI = "ServiceSpecificInfoXXX" |
| Y_SERVICE_SSI = "ServiceSpecificInfoYYY" |
| use_id = True |
| |
| # attach and wait for confirmation |
| p_id = p_dut.droid.wifiAwareAttach(False, None, use_id) |
| autils.wait_for_event(p_dut, autils.decorate_event(aconsts.EVENT_CB_ON_ATTACHED, p_id)) |
| time.sleep(self.device_startup_offset) |
| s_id = s_dut.droid.wifiAwareAttach(False, None, use_id) |
| autils.wait_for_event(s_dut, autils.decorate_event(aconsts.EVENT_CB_ON_ATTACHED, s_id)) |
| |
| # Publisher: start publishing both X & Y services and wait for confirmations |
| p_disc_id_x = p_dut.droid.wifiAwarePublish( |
| p_id, autils.create_discovery_config(SERVICE_NAME, type_x[0], X_SERVICE_SSI), use_id) |
| event = autils.wait_for_event(p_dut, |
| autils.decorate_event( |
| aconsts.SESSION_CB_ON_PUBLISH_STARTED, p_disc_id_x)) |
| |
| p_disc_id_y = p_dut.droid.wifiAwarePublish( |
| p_id, autils.create_discovery_config(SERVICE_NAME, type_x[0], Y_SERVICE_SSI), use_id) |
| event = autils.wait_for_event(p_dut, |
| autils.decorate_event( |
| aconsts.SESSION_CB_ON_PUBLISH_STARTED, p_disc_id_y)) |
| |
| # Subscriber: start subscribe session A |
| s_disc_id_a = s_dut.droid.wifiAwareSubscribe( |
| s_id, autils.create_discovery_config(SERVICE_NAME, type_x[1]), use_id) |
| autils.wait_for_event(s_dut, autils.decorate_event( |
| aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, s_disc_id_a)) |
| |
| # Subscriber: start subscribe session B |
| s_disc_id_b = s_dut.droid.wifiAwareSubscribe( |
| p_id, autils.create_discovery_config(SERVICE_NAME, type_y[1]), use_id) |
| autils.wait_for_event(s_dut, autils.decorate_event( |
| aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, s_disc_id_b)) |
| |
| session_name = {"pub": {p_disc_id_x: "X", p_disc_id_y: "Y"}, |
| "sub": {s_disc_id_a: "A", s_disc_id_b: "B"}} |
| |
| # Subscriber: subscribe session A & B wait for service discovery |
| # Number of results on each session should be exactly 2 |
| results_a = {} |
| for i in range(2): |
| event = autils.wait_for_event(s_dut, autils.decorate_event( |
| aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, s_disc_id_a)) |
| results_a[ |
| bytes(event["data"][ |
| aconsts.SESSION_CB_KEY_SERVICE_SPECIFIC_INFO]).decode('utf-8')] = event |
| autils.fail_on_event(s_dut, autils.decorate_event( |
| aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, s_disc_id_a)) |
| |
| results_b = {} |
| for i in range(2): |
| event = autils.wait_for_event(s_dut, autils.decorate_event( |
| aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, s_disc_id_b)) |
| results_b[ |
| bytes(event["data"][ |
| aconsts.SESSION_CB_KEY_SERVICE_SPECIFIC_INFO]).decode('utf-8')] = event |
| autils.fail_on_event(s_dut, autils.decorate_event( |
| aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, s_disc_id_b)) |
| |
| s_a_peer_id_for_p_x = results_a[X_SERVICE_SSI]["data"][aconsts.SESSION_CB_KEY_PEER_ID] |
| s_a_peer_id_for_p_y = results_a[Y_SERVICE_SSI]["data"][aconsts.SESSION_CB_KEY_PEER_ID] |
| s_b_peer_id_for_p_x = results_b[X_SERVICE_SSI]["data"][aconsts.SESSION_CB_KEY_PEER_ID] |
| s_b_peer_id_for_p_y = results_b[Y_SERVICE_SSI]["data"][aconsts.SESSION_CB_KEY_PEER_ID] |
| |
| # Message exchange between Publisher and Subscribe |
| self.exchange_messages(p_dut, p_disc_id_x, |
| s_dut, s_disc_id_a, s_a_peer_id_for_p_x, session_name) |
| |
| self.exchange_messages(p_dut, p_disc_id_x, |
| s_dut, s_disc_id_b, s_b_peer_id_for_p_x, session_name) |
| |
| self.exchange_messages(p_dut, p_disc_id_y, |
| s_dut, s_disc_id_a, s_a_peer_id_for_p_y, session_name) |
| |
| self.exchange_messages(p_dut, p_disc_id_y, |
| s_dut, s_disc_id_b, s_b_peer_id_for_p_y, session_name) |
| |
| # Check no more messages |
| time.sleep(autils.EVENT_TIMEOUT) |
| autils.verify_no_more_events(p_dut, timeout=0) |
| autils.verify_no_more_events(s_dut, timeout=0) |
| |
| ########################################################## |
| |
| @test_tracker_info(uuid="78d89d63-1cbc-47f6-a8fc-74057fea655e") |
| def test_multiple_concurrent_services_diff_ssi_unsolicited_passive(self): |
| """Multi service test on same service name but different Service Specific Info |
| - Unsolicited publish |
| - Passive subscribe |
| """ |
| self.run_multiple_concurrent_services_same_name_diff_ssi( |
| type_x=[aconsts.PUBLISH_TYPE_UNSOLICITED, aconsts.SUBSCRIBE_TYPE_PASSIVE], |
| type_y=[aconsts.PUBLISH_TYPE_UNSOLICITED, aconsts.SUBSCRIBE_TYPE_PASSIVE]) |
| |
| @test_tracker_info(uuid="5d349491-48e4-4ca1-a8af-7afb44e7bcbc") |
| def test_multiple_concurrent_services_diff_ssi_solicited_active(self): |
| """Multi service test on same service name but different Service Specific Info |
| - Solicited publish |
| - Active subscribe |
| """ |
| self.run_multiple_concurrent_services_same_name_diff_ssi( |
| type_x=[aconsts.PUBLISH_TYPE_SOLICITED, aconsts.SUBSCRIBE_TYPE_ACTIVE], |
| type_y=[aconsts.PUBLISH_TYPE_SOLICITED, aconsts.SUBSCRIBE_TYPE_ACTIVE]) |
| |
| def run_service_discovery_on_service_lost(self, p_type, s_type): |
| """ |
| Validate service lost callback will be receive on subscriber, when publisher stopped publish |
| - p_dut running Publish |
| - s_dut running subscribe |
| - s_dut discover p_dut |
| - p_dut stop publish |
| - s_dut receive service lost callback |
| |
| Args: |
| p_type: Publish discovery type |
| s_type: Subscribe discovery type |
| """ |
| p_dut = self.android_devices[0] |
| p_dut.pretty_name = "Publisher" |
| s_dut = self.android_devices[1] |
| s_dut.pretty_name = "Subscriber" |
| |
| asserts.skip_if(not s_dut.droid.isSdkAtLeastS(), |
| "R build and below do not have onServiceLost API.") |
| |
| # Publisher+Subscriber: attach and wait for confirmation |
| p_id = p_dut.droid.wifiAwareAttach(False) |
| autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED) |
| time.sleep(self.device_startup_offset) |
| s_id = s_dut.droid.wifiAwareAttach(False) |
| autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED) |
| |
| # Publisher: start publish and wait for confirmation |
| p_config = self.create_publish_config( |
| p_dut.aware_capabilities, |
| p_type, |
| self.PAYLOAD_SIZE_TYPICAL, |
| ttl=0, |
| term_ind_on=False, |
| null_match=False) |
| p_disc_id = p_dut.droid.wifiAwarePublish(p_id, p_config) |
| autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_PUBLISH_STARTED) |
| |
| # Subscriber: start subscribe and wait for confirmation |
| s_config = self.create_subscribe_config( |
| s_dut.aware_capabilities, |
| s_type, |
| self.PAYLOAD_SIZE_TYPICAL, |
| ttl=0, |
| term_ind_on=False, |
| null_match=True) |
| s_disc_id = s_dut.droid.wifiAwareSubscribe(s_id, s_config) |
| autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED) |
| |
| # Subscriber: wait for service discovery |
| discovery_event = autils.wait_for_event( |
| s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED) |
| peer_id_on_sub = discovery_event["data"][ |
| aconsts.SESSION_CB_KEY_PEER_ID] |
| |
| # Publisher+Subscriber: Terminate sessions |
| p_dut.droid.wifiAwareDestroyDiscoverySession(p_disc_id) |
| time.sleep(10) |
| service_lost_event = autils.wait_for_event( |
| s_dut, aconsts.SESSION_CB_ON_SERVICE_LOST) |
| asserts.assert_equal(peer_id_on_sub, |
| service_lost_event["data"][aconsts.SESSION_CB_KEY_PEER_ID]) |
| asserts.assert_equal(aconsts.REASON_PEER_NOT_VISIBLE, |
| service_lost_event["data"][aconsts.SESSION_CB_KEY_LOST_REASON]) |
| |
| s_dut.droid.wifiAwareDestroyDiscoverySession(s_disc_id) |
| |
| @test_tracker_info(uuid="b1894ce3-8692-478b-a96f-db2797e22caa") |
| def test_service_discovery_on_service_lost_unsolicited_passive(self): |
| """ |
| Test service discovery lost with unsolicited publish and passive subscribe |
| """ |
| self.run_service_discovery_on_service_lost(aconsts.PUBLISH_TYPE_UNSOLICITED, |
| aconsts.SUBSCRIBE_TYPE_PASSIVE) |
| |
| @test_tracker_info(uuid="4470d897-223a-4f9f-b21f-4061943137dd") |
| def test_service_discovery_on_service_lost_solicited_active(self): |
| """ |
| Test service discovery lost with solicited publish and active subscribe |
| """ |
| self.run_service_discovery_on_service_lost(aconsts.PUBLISH_TYPE_SOLICITED, |
| aconsts.SUBSCRIBE_TYPE_ACTIVE) |