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 string 18import time 19 20from acts import asserts 21from acts.test_decorators import test_tracker_info 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 DiscoveryTest(AwareBaseTest): 28 """Set of tests for Wi-Fi Aware discovery.""" 29 30 # configuration parameters used by tests 31 PAYLOAD_SIZE_MIN = 0 32 PAYLOAD_SIZE_TYPICAL = 1 33 PAYLOAD_SIZE_MAX = 2 34 35 # message strings 36 query_msg = "How are you doing? 你好嗎?" 37 response_msg = "Doing ok - thanks! 做的不錯 - 謝謝!" 38 39 # message re-transmit counter (increases reliability in open-environment) 40 # Note: reliability of message transmission is tested elsewhere 41 msg_retx_count = 5 # hard-coded max value, internal API 42 43 def __init__(self, controllers): 44 AwareBaseTest.__init__(self, controllers) 45 46 def create_base_config(self, caps, is_publish, ptype, stype, payload_size, 47 ttl, term_ind_on, null_match): 48 """Create a base configuration based on input parameters. 49 50 Args: 51 caps: device capability dictionary 52 is_publish: True if a publish config, else False 53 ptype: unsolicited or solicited (used if is_publish is True) 54 stype: passive or active (used if is_publish is False) 55 payload_size: min, typical, max (PAYLOAD_SIZE_xx) 56 ttl: time-to-live configuration (0 - forever) 57 term_ind_on: is termination indication enabled 58 null_match: null-out the middle match filter 59 Returns: 60 publish discovery configuration object. 61 """ 62 config = {} 63 if is_publish: 64 config[aconsts.DISCOVERY_KEY_DISCOVERY_TYPE] = ptype 65 else: 66 config[aconsts.DISCOVERY_KEY_DISCOVERY_TYPE] = stype 67 config[aconsts.DISCOVERY_KEY_TTL] = ttl 68 config[aconsts.DISCOVERY_KEY_TERM_CB_ENABLED] = term_ind_on 69 if payload_size == self.PAYLOAD_SIZE_MIN: 70 config[aconsts.DISCOVERY_KEY_SERVICE_NAME] = "a" 71 config[aconsts.DISCOVERY_KEY_SSI] = None 72 config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST] = [] 73 elif payload_size == self.PAYLOAD_SIZE_TYPICAL: 74 config[aconsts.DISCOVERY_KEY_SERVICE_NAME] = "GoogleTestServiceX" 75 if is_publish: 76 config[aconsts.DISCOVERY_KEY_SSI] = string.ascii_letters 77 else: 78 config[aconsts. 79 DISCOVERY_KEY_SSI] = string.ascii_letters[:: 80 -1] # reverse 81 config[ 82 aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST] = autils.encode_list( 83 [(10).to_bytes(1, byteorder="big"), "hello there string" 84 if not null_match else None, 85 bytes(range(40))]) 86 else: # PAYLOAD_SIZE_MAX 87 config[aconsts.DISCOVERY_KEY_SERVICE_NAME] = "VeryLong" + "X" * ( 88 caps[aconsts.CAP_MAX_SERVICE_NAME_LEN] - 8) 89 config[aconsts.DISCOVERY_KEY_SSI] = ( 90 "P" if is_publish else 91 "S") * caps[aconsts.CAP_MAX_SERVICE_SPECIFIC_INFO_LEN] 92 mf = autils.construct_max_match_filter( 93 caps[aconsts.CAP_MAX_MATCH_FILTER_LEN]) 94 if null_match: 95 mf[2] = None 96 config[aconsts. 97 DISCOVERY_KEY_MATCH_FILTER_LIST] = autils.encode_list(mf) 98 99 return config 100 101 def create_publish_config(self, caps, ptype, payload_size, ttl, 102 term_ind_on, null_match): 103 """Create a publish configuration based on input parameters. 104 105 Args: 106 caps: device capability dictionary 107 ptype: unsolicited or solicited 108 payload_size: min, typical, max (PAYLOAD_SIZE_xx) 109 ttl: time-to-live configuration (0 - forever) 110 term_ind_on: is termination indication enabled 111 null_match: null-out the middle match filter 112 Returns: 113 publish discovery configuration object. 114 """ 115 return self.create_base_config(caps, True, ptype, None, payload_size, 116 ttl, term_ind_on, null_match) 117 118 def create_subscribe_config(self, caps, stype, payload_size, ttl, 119 term_ind_on, null_match): 120 """Create a subscribe configuration based on input parameters. 121 122 Args: 123 caps: device capability dictionary 124 stype: passive or active 125 payload_size: min, typical, max (PAYLOAD_SIZE_xx) 126 ttl: time-to-live configuration (0 - forever) 127 term_ind_on: is termination indication enabled 128 null_match: null-out the middle match filter 129 Returns: 130 subscribe discovery configuration object. 131 """ 132 return self.create_base_config(caps, False, None, stype, payload_size, 133 ttl, term_ind_on, null_match) 134 135 def positive_discovery_test_utility(self, ptype, stype, payload_size): 136 """Utility which runs a positive discovery test: 137 - Discovery (publish/subscribe) with TTL=0 (non-self-terminating) 138 - Exchange messages 139 - Update publish/subscribe 140 - Terminate 141 142 Args: 143 ptype: Publish discovery type 144 stype: Subscribe discovery type 145 payload_size: One of PAYLOAD_SIZE_* constants - MIN, TYPICAL, MAX 146 """ 147 p_dut = self.android_devices[0] 148 p_dut.pretty_name = "Publisher" 149 s_dut = self.android_devices[1] 150 s_dut.pretty_name = "Subscriber" 151 152 # Publisher+Subscriber: attach and wait for confirmation 153 p_id = p_dut.droid.wifiAwareAttach(False) 154 autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED) 155 time.sleep(self.device_startup_offset) 156 s_id = s_dut.droid.wifiAwareAttach(False) 157 autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED) 158 159 # Publisher: start publish and wait for confirmation 160 p_config = self.create_publish_config( 161 p_dut.aware_capabilities, 162 ptype, 163 payload_size, 164 ttl=0, 165 term_ind_on=False, 166 null_match=False) 167 p_disc_id = p_dut.droid.wifiAwarePublish(p_id, p_config) 168 autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_PUBLISH_STARTED) 169 170 # Subscriber: start subscribe and wait for confirmation 171 s_config = self.create_subscribe_config( 172 s_dut.aware_capabilities, 173 stype, 174 payload_size, 175 ttl=0, 176 term_ind_on=False, 177 null_match=True) 178 s_disc_id = s_dut.droid.wifiAwareSubscribe(s_id, s_config) 179 autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED) 180 181 # Subscriber: wait for service discovery 182 discovery_event = autils.wait_for_event( 183 s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED) 184 peer_id_on_sub = discovery_event["data"][ 185 aconsts.SESSION_CB_KEY_PEER_ID] 186 187 # Subscriber: validate contents of discovery: 188 # - SSI: publisher's 189 # - Match filter: UNSOLICITED - publisher, SOLICITED - subscriber 190 autils.assert_equal_strings( 191 bytes(discovery_event["data"][ 192 aconsts.SESSION_CB_KEY_SERVICE_SPECIFIC_INFO]).decode("utf-8"), 193 p_config[aconsts.DISCOVERY_KEY_SSI], 194 "Discovery mismatch: service specific info (SSI)") 195 asserts.assert_equal( 196 autils.decode_list(discovery_event["data"][ 197 aconsts.SESSION_CB_KEY_MATCH_FILTER_LIST]), 198 autils.decode_list( 199 p_config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST] 200 if ptype == aconsts.PUBLISH_TYPE_UNSOLICITED else s_config[ 201 aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST]), 202 "Discovery mismatch: match filter") 203 204 # Subscriber: send message to peer (Publisher) 205 s_dut.droid.wifiAwareSendMessage(s_disc_id, peer_id_on_sub, 206 self.get_next_msg_id(), 207 self.query_msg, self.msg_retx_count) 208 autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_MESSAGE_SENT) 209 210 # Publisher: wait for received message 211 pub_rx_msg_event = autils.wait_for_event( 212 p_dut, aconsts.SESSION_CB_ON_MESSAGE_RECEIVED) 213 peer_id_on_pub = pub_rx_msg_event["data"][ 214 aconsts.SESSION_CB_KEY_PEER_ID] 215 216 # Publisher: validate contents of message 217 asserts.assert_equal( 218 pub_rx_msg_event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING], 219 self.query_msg, "Subscriber -> Publisher message corrupted") 220 221 # Publisher: send message to peer (Subscriber) 222 p_dut.droid.wifiAwareSendMessage(p_disc_id, peer_id_on_pub, 223 self.get_next_msg_id(), 224 self.response_msg, 225 self.msg_retx_count) 226 autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_MESSAGE_SENT) 227 228 # Subscriber: wait for received message 229 sub_rx_msg_event = autils.wait_for_event( 230 s_dut, aconsts.SESSION_CB_ON_MESSAGE_RECEIVED) 231 232 # Subscriber: validate contents of message 233 asserts.assert_equal( 234 sub_rx_msg_event["data"][aconsts.SESSION_CB_KEY_PEER_ID], 235 peer_id_on_sub, 236 "Subscriber received message from different peer ID then discovery!?" 237 ) 238 autils.assert_equal_strings( 239 sub_rx_msg_event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING], 240 self.response_msg, "Publisher -> Subscriber message corrupted") 241 242 # Subscriber: validate that we're not getting another Service Discovery 243 autils.fail_on_event(s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED) 244 245 # Publisher: update publish and wait for confirmation 246 p_config[aconsts.DISCOVERY_KEY_SSI] = "something else" 247 p_dut.droid.wifiAwareUpdatePublish(p_disc_id, p_config) 248 autils.wait_for_event(p_dut, 249 aconsts.SESSION_CB_ON_SESSION_CONFIG_UPDATED) 250 251 # Subscriber: expect a new service discovery 252 discovery_event = autils.wait_for_event( 253 s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED) 254 255 # Subscriber: validate contents of discovery 256 autils.assert_equal_strings( 257 bytes(discovery_event["data"][ 258 aconsts.SESSION_CB_KEY_SERVICE_SPECIFIC_INFO]).decode("utf-8"), 259 p_config[aconsts.DISCOVERY_KEY_SSI], 260 "Discovery mismatch (after pub update): service specific info (SSI)" 261 ) 262 asserts.assert_equal( 263 autils.decode_list(discovery_event["data"][ 264 aconsts.SESSION_CB_KEY_MATCH_FILTER_LIST]), 265 autils.decode_list( 266 p_config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST] 267 if ptype == aconsts.PUBLISH_TYPE_UNSOLICITED else s_config[ 268 aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST]), 269 "Discovery mismatch: match filter") 270 asserts.assert_equal( 271 peer_id_on_sub, 272 discovery_event["data"][aconsts.SESSION_CB_KEY_PEER_ID], 273 "Peer ID changed when publish was updated!?") 274 275 # Subscribe: update subscribe and wait for confirmation 276 s_config = self.create_subscribe_config( 277 s_dut.aware_capabilities, 278 stype, 279 payload_size, 280 ttl=0, 281 term_ind_on=False, 282 null_match=False) 283 s_dut.droid.wifiAwareUpdateSubscribe(s_disc_id, s_config) 284 autils.wait_for_event(s_dut, 285 aconsts.SESSION_CB_ON_SESSION_CONFIG_UPDATED) 286 287 # Publisher+Subscriber: Terminate sessions 288 p_dut.droid.wifiAwareDestroyDiscoverySession(p_disc_id) 289 s_dut.droid.wifiAwareDestroyDiscoverySession(s_disc_id) 290 291 # sleep for timeout period and then verify all 'fail_on_event' together 292 time.sleep(autils.EVENT_TIMEOUT) 293 294 # verify that there were no other events 295 autils.verify_no_more_events(p_dut, timeout=0) 296 autils.verify_no_more_events(s_dut, timeout=0) 297 298 # verify that forbidden callbacks aren't called 299 autils.validate_forbidden_callbacks(p_dut, {aconsts.CB_EV_MATCH: 0}) 300 301 def verify_discovery_session_term(self, dut, disc_id, config, is_publish, 302 term_ind_on): 303 """Utility to verify that the specified discovery session has terminated (by 304 waiting for the TTL and then attempting to reconfigure). 305 306 Args: 307 dut: device under test 308 disc_id: discovery id for the existing session 309 config: configuration of the existing session 310 is_publish: True if the configuration was publish, False if subscribe 311 term_ind_on: True if a termination indication is expected, False otherwise 312 """ 313 # Wait for session termination 314 if term_ind_on: 315 autils.wait_for_event( 316 dut, 317 autils.decorate_event(aconsts.SESSION_CB_ON_SESSION_TERMINATED, 318 disc_id)) 319 else: 320 # can't defer wait to end since in any case have to wait for session to 321 # expire 322 autils.fail_on_event( 323 dut, 324 autils.decorate_event(aconsts.SESSION_CB_ON_SESSION_TERMINATED, 325 disc_id)) 326 327 # Validate that session expired by trying to configure it (expect failure) 328 config[aconsts.DISCOVERY_KEY_SSI] = "something else" 329 if is_publish: 330 dut.droid.wifiAwareUpdatePublish(disc_id, config) 331 else: 332 dut.droid.wifiAwareUpdateSubscribe(disc_id, config) 333 334 # The response to update discovery session is: 335 # term_ind_on=True: session was cleaned-up so won't get an explicit failure, but won't get a 336 # success either. Can check for no SESSION_CB_ON_SESSION_CONFIG_UPDATED but 337 # will defer to the end of the test (no events on queue). 338 # term_ind_on=False: session was not cleaned-up (yet). So expect 339 # SESSION_CB_ON_SESSION_CONFIG_FAILED. 340 if not term_ind_on: 341 autils.wait_for_event( 342 dut, 343 autils.decorate_event( 344 aconsts.SESSION_CB_ON_SESSION_CONFIG_FAILED, disc_id)) 345 346 def positive_ttl_test_utility(self, is_publish, ptype, stype, term_ind_on): 347 """Utility which runs a positive discovery session TTL configuration test 348 349 Iteration 1: Verify session started with TTL 350 Iteration 2: Verify session started without TTL and reconfigured with TTL 351 Iteration 3: Verify session started with (long) TTL and reconfigured with 352 (short) TTL 353 354 Args: 355 is_publish: True if testing publish, False if testing subscribe 356 ptype: Publish discovery type (used if is_publish is True) 357 stype: Subscribe discovery type (used if is_publish is False) 358 term_ind_on: Configuration of termination indication 359 """ 360 SHORT_TTL = 5 # 5 seconds 361 LONG_TTL = 100 # 100 seconds 362 dut = self.android_devices[0] 363 364 # Attach and wait for confirmation 365 id = dut.droid.wifiAwareAttach(False) 366 autils.wait_for_event(dut, aconsts.EVENT_CB_ON_ATTACHED) 367 368 # Iteration 1: Start discovery session with TTL 369 config = self.create_base_config( 370 dut.aware_capabilities, is_publish, ptype, stype, 371 self.PAYLOAD_SIZE_TYPICAL, SHORT_TTL, term_ind_on, False) 372 if is_publish: 373 disc_id = dut.droid.wifiAwarePublish(id, config, True) 374 autils.wait_for_event( 375 dut, 376 autils.decorate_event(aconsts.SESSION_CB_ON_PUBLISH_STARTED, 377 disc_id)) 378 else: 379 disc_id = dut.droid.wifiAwareSubscribe(id, config, True) 380 autils.wait_for_event( 381 dut, 382 autils.decorate_event(aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, 383 disc_id)) 384 385 # Wait for session termination & verify 386 self.verify_discovery_session_term(dut, disc_id, config, is_publish, 387 term_ind_on) 388 389 # Iteration 2: Start a discovery session without TTL 390 config = self.create_base_config( 391 dut.aware_capabilities, is_publish, ptype, stype, 392 self.PAYLOAD_SIZE_TYPICAL, 0, term_ind_on, False) 393 if is_publish: 394 disc_id = dut.droid.wifiAwarePublish(id, config, True) 395 autils.wait_for_event( 396 dut, 397 autils.decorate_event(aconsts.SESSION_CB_ON_PUBLISH_STARTED, 398 disc_id)) 399 else: 400 disc_id = dut.droid.wifiAwareSubscribe(id, config, True) 401 autils.wait_for_event( 402 dut, 403 autils.decorate_event(aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, 404 disc_id)) 405 406 # Update with a TTL 407 config = self.create_base_config( 408 dut.aware_capabilities, is_publish, ptype, stype, 409 self.PAYLOAD_SIZE_TYPICAL, SHORT_TTL, term_ind_on, False) 410 if is_publish: 411 dut.droid.wifiAwareUpdatePublish(disc_id, config) 412 else: 413 dut.droid.wifiAwareUpdateSubscribe(disc_id, config) 414 autils.wait_for_event( 415 dut, 416 autils.decorate_event(aconsts.SESSION_CB_ON_SESSION_CONFIG_UPDATED, 417 disc_id)) 418 419 # Wait for session termination & verify 420 self.verify_discovery_session_term(dut, disc_id, config, is_publish, 421 term_ind_on) 422 423 # Iteration 3: Start a discovery session with (long) TTL 424 config = self.create_base_config( 425 dut.aware_capabilities, is_publish, ptype, stype, 426 self.PAYLOAD_SIZE_TYPICAL, LONG_TTL, term_ind_on, False) 427 if is_publish: 428 disc_id = dut.droid.wifiAwarePublish(id, config, True) 429 autils.wait_for_event( 430 dut, 431 autils.decorate_event(aconsts.SESSION_CB_ON_PUBLISH_STARTED, 432 disc_id)) 433 else: 434 disc_id = dut.droid.wifiAwareSubscribe(id, config, True) 435 autils.wait_for_event( 436 dut, 437 autils.decorate_event(aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED, 438 disc_id)) 439 440 # Update with a TTL 441 config = self.create_base_config( 442 dut.aware_capabilities, is_publish, ptype, stype, 443 self.PAYLOAD_SIZE_TYPICAL, SHORT_TTL, term_ind_on, False) 444 if is_publish: 445 dut.droid.wifiAwareUpdatePublish(disc_id, config) 446 else: 447 dut.droid.wifiAwareUpdateSubscribe(disc_id, config) 448 autils.wait_for_event( 449 dut, 450 autils.decorate_event(aconsts.SESSION_CB_ON_SESSION_CONFIG_UPDATED, 451 disc_id)) 452 453 # Wait for session termination & verify 454 self.verify_discovery_session_term(dut, disc_id, config, is_publish, 455 term_ind_on) 456 457 # verify that there were no other events 458 autils.verify_no_more_events(dut) 459 460 # verify that forbidden callbacks aren't called 461 if not term_ind_on: 462 autils.validate_forbidden_callbacks( 463 dut, { 464 aconsts.CB_EV_PUBLISH_TERMINATED: 0, 465 aconsts.CB_EV_SUBSCRIBE_TERMINATED: 0 466 }) 467 468 def discovery_mismatch_test_utility(self, 469 is_expected_to_pass, 470 p_type, 471 s_type, 472 p_service_name=None, 473 s_service_name=None, 474 p_mf_1=None, 475 s_mf_1=None): 476 """Utility which runs the negative discovery test for mismatched service 477 configs. 478 479 Args: 480 is_expected_to_pass: True if positive test, False if negative 481 p_type: Publish discovery type 482 s_type: Subscribe discovery type 483 p_service_name: Publish service name (or None to leave unchanged) 484 s_service_name: Subscribe service name (or None to leave unchanged) 485 p_mf_1: Publish match filter element [1] (or None to leave unchanged) 486 s_mf_1: Subscribe match filter element [1] (or None to leave unchanged) 487 """ 488 p_dut = self.android_devices[0] 489 p_dut.pretty_name = "Publisher" 490 s_dut = self.android_devices[1] 491 s_dut.pretty_name = "Subscriber" 492 493 # create configurations 494 p_config = self.create_publish_config( 495 p_dut.aware_capabilities, 496 p_type, 497 self.PAYLOAD_SIZE_TYPICAL, 498 ttl=0, 499 term_ind_on=False, 500 null_match=False) 501 if p_service_name is not None: 502 p_config[aconsts.DISCOVERY_KEY_SERVICE_NAME] = p_service_name 503 if p_mf_1 is not None: 504 p_config[ 505 aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST] = autils.encode_list( 506 [(10).to_bytes(1, byteorder="big"), p_mf_1, 507 bytes(range(40))]) 508 s_config = self.create_publish_config( 509 s_dut.aware_capabilities, 510 s_type, 511 self.PAYLOAD_SIZE_TYPICAL, 512 ttl=0, 513 term_ind_on=False, 514 null_match=False) 515 if s_service_name is not None: 516 s_config[aconsts.DISCOVERY_KEY_SERVICE_NAME] = s_service_name 517 if s_mf_1 is not None: 518 s_config[ 519 aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST] = autils.encode_list( 520 [(10).to_bytes(1, byteorder="big"), s_mf_1, 521 bytes(range(40))]) 522 523 p_id = p_dut.droid.wifiAwareAttach(False) 524 autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED) 525 time.sleep(self.device_startup_offset) 526 s_id = s_dut.droid.wifiAwareAttach(False) 527 autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED) 528 529 # Publisher: start publish and wait for confirmation 530 p_disc_id = p_dut.droid.wifiAwarePublish(p_id, p_config) 531 autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_PUBLISH_STARTED) 532 533 # Subscriber: start subscribe and wait for confirmation 534 s_disc_id = s_dut.droid.wifiAwareSubscribe(s_id, s_config) 535 autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED) 536 537 # Subscriber: fail on service discovery 538 if is_expected_to_pass: 539 autils.wait_for_event(s_dut, 540 aconsts.SESSION_CB_ON_SERVICE_DISCOVERED) 541 else: 542 autils.fail_on_event(s_dut, 543 aconsts.SESSION_CB_ON_SERVICE_DISCOVERED) 544 545 # Publisher+Subscriber: Terminate sessions 546 p_dut.droid.wifiAwareDestroyDiscoverySession(p_disc_id) 547 s_dut.droid.wifiAwareDestroyDiscoverySession(s_disc_id) 548 549 # verify that there were no other events (including terminations) 550 time.sleep(autils.EVENT_TIMEOUT) 551 autils.verify_no_more_events(p_dut, timeout=0) 552 autils.verify_no_more_events(s_dut, timeout=0) 553 554 ####################################### 555 # Positive tests key: 556 # 557 # names is: test_<pub_type>_<sub_type>_<size> 558 # where: 559 # 560 # pub_type: Type of publish discovery session: unsolicited or solicited. 561 # sub_type: Type of subscribe discovery session: passive or active. 562 # size: Size of payload fields (service name, service specific info, and match 563 # filter: typical, max, or min. 564 ####################################### 565 566 @test_tracker_info(uuid="954ebbde-ed2b-4f04-9e68-88239187d69d") 567 def test_positive_unsolicited_passive_typical(self): 568 """Functional test case / Discovery test cases / positive test case: 569 - Solicited publish + passive subscribe 570 - Typical payload fields size 571 572 Verifies that discovery and message exchange succeeds. 573 """ 574 self.positive_discovery_test_utility( 575 ptype=aconsts.PUBLISH_TYPE_UNSOLICITED, 576 stype=aconsts.SUBSCRIBE_TYPE_PASSIVE, 577 payload_size=self.PAYLOAD_SIZE_TYPICAL) 578 579 @test_tracker_info(uuid="67fb22bb-6985-4345-95a4-90b76681a58b") 580 def test_positive_unsolicited_passive_min(self): 581 """Functional test case / Discovery test cases / positive test case: 582 - Solicited publish + passive subscribe 583 - Minimal payload fields size 584 585 Verifies that discovery and message exchange succeeds. 586 """ 587 self.positive_discovery_test_utility( 588 ptype=aconsts.PUBLISH_TYPE_UNSOLICITED, 589 stype=aconsts.SUBSCRIBE_TYPE_PASSIVE, 590 payload_size=self.PAYLOAD_SIZE_MIN) 591 592 @test_tracker_info(uuid="a02a47b9-41bb-47bb-883b-921024a2c30d") 593 def test_positive_unsolicited_passive_max(self): 594 """Functional test case / Discovery test cases / positive test case: 595 - Solicited publish + passive subscribe 596 - Maximal payload fields size 597 598 Verifies that discovery and message exchange succeeds. 599 """ 600 self.positive_discovery_test_utility( 601 ptype=aconsts.PUBLISH_TYPE_UNSOLICITED, 602 stype=aconsts.SUBSCRIBE_TYPE_PASSIVE, 603 payload_size=self.PAYLOAD_SIZE_MAX) 604 605 @test_tracker_info(uuid="586c657f-2388-4e7a-baee-9bce2f3d1a16") 606 def test_positive_solicited_active_typical(self): 607 """Functional test case / Discovery test cases / positive test case: 608 - Unsolicited publish + active subscribe 609 - Typical payload fields size 610 611 Verifies that discovery and message exchange succeeds. 612 """ 613 self.positive_discovery_test_utility( 614 ptype=aconsts.PUBLISH_TYPE_SOLICITED, 615 stype=aconsts.SUBSCRIBE_TYPE_ACTIVE, 616 payload_size=self.PAYLOAD_SIZE_TYPICAL) 617 618 @test_tracker_info(uuid="5369e4ff-f406-48c5-b41a-df38ec340146") 619 def test_positive_solicited_active_min(self): 620 """Functional test case / Discovery test cases / positive test case: 621 - Unsolicited publish + active subscribe 622 - Minimal payload fields size 623 624 Verifies that discovery and message exchange succeeds. 625 """ 626 self.positive_discovery_test_utility( 627 ptype=aconsts.PUBLISH_TYPE_SOLICITED, 628 stype=aconsts.SUBSCRIBE_TYPE_ACTIVE, 629 payload_size=self.PAYLOAD_SIZE_MIN) 630 631 @test_tracker_info(uuid="634c6eb8-2c4f-42bd-9bbb-d874d0ec22f3") 632 def test_positive_solicited_active_max(self): 633 """Functional test case / Discovery test cases / positive test case: 634 - Unsolicited publish + active subscribe 635 - Maximal payload fields size 636 637 Verifies that discovery and message exchange succeeds. 638 """ 639 self.positive_discovery_test_utility( 640 ptype=aconsts.PUBLISH_TYPE_SOLICITED, 641 stype=aconsts.SUBSCRIBE_TYPE_ACTIVE, 642 payload_size=self.PAYLOAD_SIZE_MAX) 643 644 ####################################### 645 # TTL tests key: 646 # 647 # names is: test_ttl_<pub_type|sub_type>_<term_ind> 648 # where: 649 # 650 # pub_type: Type of publish discovery session: unsolicited or solicited. 651 # sub_type: Type of subscribe discovery session: passive or active. 652 # term_ind: ind_on or ind_off 653 ####################################### 654 655 @test_tracker_info(uuid="9d7e758e-e0e2-4550-bcee-bfb6a2bff63e") 656 def test_ttl_unsolicited_ind_on(self): 657 """Functional test case / Discovery test cases / TTL test case: 658 - Unsolicited publish 659 - Termination indication enabled 660 """ 661 self.positive_ttl_test_utility( 662 is_publish=True, 663 ptype=aconsts.PUBLISH_TYPE_UNSOLICITED, 664 stype=None, 665 term_ind_on=True) 666 667 @test_tracker_info(uuid="48fd69bc-cc2a-4f65-a0a1-63d7c1720702") 668 def test_ttl_unsolicited_ind_off(self): 669 """Functional test case / Discovery test cases / TTL test case: 670 - Unsolicited publish 671 - Termination indication disabled 672 """ 673 self.positive_ttl_test_utility( 674 is_publish=True, 675 ptype=aconsts.PUBLISH_TYPE_UNSOLICITED, 676 stype=None, 677 term_ind_on=False) 678 679 @test_tracker_info(uuid="afb75fc1-9ba7-446a-b5ed-7cd37ab51b1c") 680 def test_ttl_solicited_ind_on(self): 681 """Functional test case / Discovery test cases / TTL test case: 682 - Solicited publish 683 - Termination indication enabled 684 """ 685 self.positive_ttl_test_utility( 686 is_publish=True, 687 ptype=aconsts.PUBLISH_TYPE_SOLICITED, 688 stype=None, 689 term_ind_on=True) 690 691 @test_tracker_info(uuid="703311a6-e444-4055-94ee-ea9b9b71799e") 692 def test_ttl_solicited_ind_off(self): 693 """Functional test case / Discovery test cases / TTL test case: 694 - Solicited publish 695 - Termination indication disabled 696 """ 697 self.positive_ttl_test_utility( 698 is_publish=True, 699 ptype=aconsts.PUBLISH_TYPE_SOLICITED, 700 stype=None, 701 term_ind_on=False) 702 703 @test_tracker_info(uuid="38a541c4-ff55-4387-87b7-4d940489da9d") 704 def test_ttl_passive_ind_on(self): 705 """Functional test case / Discovery test cases / TTL test case: 706 - Passive subscribe 707 - Termination indication enabled 708 """ 709 self.positive_ttl_test_utility( 710 is_publish=False, 711 ptype=None, 712 stype=aconsts.SUBSCRIBE_TYPE_PASSIVE, 713 term_ind_on=True) 714 715 @test_tracker_info(uuid="ba971e12-b0ca-417c-a1b5-9451598de47d") 716 def test_ttl_passive_ind_off(self): 717 """Functional test case / Discovery test cases / TTL test case: 718 - Passive subscribe 719 - Termination indication disabled 720 """ 721 self.positive_ttl_test_utility( 722 is_publish=False, 723 ptype=None, 724 stype=aconsts.SUBSCRIBE_TYPE_PASSIVE, 725 term_ind_on=False) 726 727 @test_tracker_info(uuid="7b5d96f2-2415-4b98-9a51-32957f0679a0") 728 def test_ttl_active_ind_on(self): 729 """Functional test case / Discovery test cases / TTL test case: 730 - Active subscribe 731 - Termination indication enabled 732 """ 733 self.positive_ttl_test_utility( 734 is_publish=False, 735 ptype=None, 736 stype=aconsts.SUBSCRIBE_TYPE_ACTIVE, 737 term_ind_on=True) 738 739 @test_tracker_info(uuid="c9268eca-0a30-42dd-8e6c-b8b0b84697fb") 740 def test_ttl_active_ind_off(self): 741 """Functional test case / Discovery test cases / TTL test case: 742 - Active subscribe 743 - Termination indication disabled 744 """ 745 self.positive_ttl_test_utility( 746 is_publish=False, 747 ptype=None, 748 stype=aconsts.SUBSCRIBE_TYPE_ACTIVE, 749 term_ind_on=False) 750 751 ####################################### 752 # Mismatched service name tests key: 753 # 754 # names is: test_mismatch_service_name_<pub_type>_<sub_type> 755 # where: 756 # 757 # pub_type: Type of publish discovery session: unsolicited or solicited. 758 # sub_type: Type of subscribe discovery session: passive or active. 759 ####################################### 760 761 @test_tracker_info(uuid="175415e9-7d07-40d0-95f0-3a5f91ea4711") 762 def test_mismatch_service_name_unsolicited_passive(self): 763 """Functional test case / Discovery test cases / Mismatch service name 764 - Unsolicited publish 765 - Passive subscribe 766 """ 767 self.discovery_mismatch_test_utility( 768 is_expected_to_pass=False, 769 p_type=aconsts.PUBLISH_TYPE_UNSOLICITED, 770 s_type=aconsts.SUBSCRIBE_TYPE_PASSIVE, 771 p_service_name="GoogleTestServiceXXX", 772 s_service_name="GoogleTestServiceYYY") 773 774 @test_tracker_info(uuid="c22a54ce-9e46-47a5-ac44-831faf93d317") 775 def test_mismatch_service_name_solicited_active(self): 776 """Functional test case / Discovery test cases / Mismatch service name 777 - Solicited publish 778 - Active subscribe 779 """ 780 self.discovery_mismatch_test_utility( 781 is_expected_to_pass=False, 782 p_type=aconsts.PUBLISH_TYPE_SOLICITED, 783 s_type=aconsts.SUBSCRIBE_TYPE_ACTIVE, 784 p_service_name="GoogleTestServiceXXX", 785 s_service_name="GoogleTestServiceYYY") 786 787 ####################################### 788 # Mismatched discovery session type tests key: 789 # 790 # names is: test_mismatch_service_type_<pub_type>_<sub_type> 791 # where: 792 # 793 # pub_type: Type of publish discovery session: unsolicited or solicited. 794 # sub_type: Type of subscribe discovery session: passive or active. 795 ####################################### 796 797 @test_tracker_info(uuid="4806f631-d9eb-45fd-9e75-24674962770f") 798 def test_mismatch_service_type_unsolicited_active(self): 799 """Functional test case / Discovery test cases / Mismatch service name 800 - Unsolicited publish 801 - Active subscribe 802 """ 803 self.discovery_mismatch_test_utility( 804 is_expected_to_pass=True, 805 p_type=aconsts.PUBLISH_TYPE_UNSOLICITED, 806 s_type=aconsts.SUBSCRIBE_TYPE_ACTIVE) 807 808 @test_tracker_info(uuid="12d648fd-b8fa-4c0f-9467-95e2366047de") 809 def test_mismatch_service_type_solicited_passive(self): 810 """Functional test case / Discovery test cases / Mismatch service name 811 - Unsolicited publish 812 - Active subscribe 813 """ 814 self.discovery_mismatch_test_utility( 815 is_expected_to_pass=False, 816 p_type=aconsts.PUBLISH_TYPE_SOLICITED, 817 s_type=aconsts.SUBSCRIBE_TYPE_PASSIVE) 818 819 ####################################### 820 # Mismatched discovery match filter tests key: 821 # 822 # names is: test_mismatch_match_filter_<pub_type>_<sub_type> 823 # where: 824 # 825 # pub_type: Type of publish discovery session: unsolicited or solicited. 826 # sub_type: Type of subscribe discovery session: passive or active. 827 ####################################### 828 829 @test_tracker_info(uuid="d98454cb-64af-4266-8fed-f0b545a2d7c4") 830 def test_mismatch_match_filter_unsolicited_passive(self): 831 """Functional test case / Discovery test cases / Mismatch match filter 832 - Unsolicited publish 833 - Passive subscribe 834 """ 835 self.discovery_mismatch_test_utility( 836 is_expected_to_pass=False, 837 p_type=aconsts.PUBLISH_TYPE_UNSOLICITED, 838 s_type=aconsts.SUBSCRIBE_TYPE_PASSIVE, 839 p_mf_1="hello there string", 840 s_mf_1="goodbye there string") 841 842 @test_tracker_info(uuid="663c1008-ae11-4e1a-87c7-c311d83f481c") 843 def test_mismatch_match_filter_solicited_active(self): 844 """Functional test case / Discovery test cases / Mismatch match filter 845 - Solicited publish 846 - Active subscribe 847 """ 848 self.discovery_mismatch_test_utility( 849 is_expected_to_pass=False, 850 p_type=aconsts.PUBLISH_TYPE_SOLICITED, 851 s_type=aconsts.SUBSCRIBE_TYPE_ACTIVE, 852 p_mf_1="hello there string", 853 s_mf_1="goodbye there string") 854 855 ####################################### 856 # Multiple concurrent services 857 ####################################### 858 859 def run_multiple_concurrent_services(self, type_x, type_y): 860 """Validate multiple identical discovery services running on both devices: 861 - DUT1 & DUT2 running Publish for X 862 - DUT1 & DUT2 running Publish for Y 863 - DUT1 Subscribes for X 864 - DUT2 Subscribes for Y 865 Message exchanges. 866 867 Note: test requires that devices support 2 publish sessions concurrently. 868 The test will be skipped if the devices are not capable. 869 870 Args: 871 type_x, type_y: A list of [ptype, stype] of the publish and subscribe 872 types for services X and Y respectively. 873 """ 874 dut1 = self.android_devices[0] 875 dut2 = self.android_devices[1] 876 877 X_SERVICE_NAME = "ServiceXXX" 878 Y_SERVICE_NAME = "ServiceYYY" 879 880 asserts.skip_if( 881 dut1.aware_capabilities[aconsts.CAP_MAX_PUBLISHES] < 2 882 or dut2.aware_capabilities[aconsts.CAP_MAX_PUBLISHES] < 2, 883 "Devices do not support 2 publish sessions") 884 885 # attach and wait for confirmation 886 id1 = dut1.droid.wifiAwareAttach(False) 887 autils.wait_for_event(dut1, aconsts.EVENT_CB_ON_ATTACHED) 888 time.sleep(self.device_startup_offset) 889 id2 = dut2.droid.wifiAwareAttach(False) 890 autils.wait_for_event(dut2, aconsts.EVENT_CB_ON_ATTACHED) 891 892 # DUT1 & DUT2: start publishing both X & Y services and wait for 893 # confirmations 894 dut1_x_pid = dut1.droid.wifiAwarePublish( 895 id1, autils.create_discovery_config(X_SERVICE_NAME, type_x[0])) 896 event = autils.wait_for_event(dut1, 897 aconsts.SESSION_CB_ON_PUBLISH_STARTED) 898 asserts.assert_equal(event["data"][aconsts.SESSION_CB_KEY_SESSION_ID], 899 dut1_x_pid, 900 "Unexpected DUT1 X publish session discovery ID") 901 902 dut1_y_pid = dut1.droid.wifiAwarePublish( 903 id1, autils.create_discovery_config(Y_SERVICE_NAME, type_y[0])) 904 event = autils.wait_for_event(dut1, 905 aconsts.SESSION_CB_ON_PUBLISH_STARTED) 906 asserts.assert_equal(event["data"][aconsts.SESSION_CB_KEY_SESSION_ID], 907 dut1_y_pid, 908 "Unexpected DUT1 Y publish session discovery ID") 909 910 dut2_x_pid = dut2.droid.wifiAwarePublish( 911 id2, autils.create_discovery_config(X_SERVICE_NAME, type_x[0])) 912 event = autils.wait_for_event(dut2, 913 aconsts.SESSION_CB_ON_PUBLISH_STARTED) 914 asserts.assert_equal(event["data"][aconsts.SESSION_CB_KEY_SESSION_ID], 915 dut2_x_pid, 916 "Unexpected DUT2 X publish session discovery ID") 917 918 dut2_y_pid = dut2.droid.wifiAwarePublish( 919 id2, autils.create_discovery_config(Y_SERVICE_NAME, type_y[0])) 920 event = autils.wait_for_event(dut2, 921 aconsts.SESSION_CB_ON_PUBLISH_STARTED) 922 asserts.assert_equal(event["data"][aconsts.SESSION_CB_KEY_SESSION_ID], 923 dut2_y_pid, 924 "Unexpected DUT2 Y publish session discovery ID") 925 926 # DUT1: start subscribing for X 927 dut1_x_sid = dut1.droid.wifiAwareSubscribe( 928 id1, autils.create_discovery_config(X_SERVICE_NAME, type_x[1])) 929 autils.wait_for_event(dut1, aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED) 930 931 # DUT2: start subscribing for Y 932 dut2_y_sid = dut2.droid.wifiAwareSubscribe( 933 id2, autils.create_discovery_config(Y_SERVICE_NAME, type_y[1])) 934 autils.wait_for_event(dut2, aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED) 935 936 # DUT1 & DUT2: wait for service discovery 937 event = autils.wait_for_event(dut1, 938 aconsts.SESSION_CB_ON_SERVICE_DISCOVERED) 939 asserts.assert_equal( 940 event["data"][aconsts.SESSION_CB_KEY_SESSION_ID], dut1_x_sid, 941 "Unexpected DUT1 X subscribe session discovery ID") 942 dut1_peer_id_for_dut2_x = event["data"][aconsts.SESSION_CB_KEY_PEER_ID] 943 944 event = autils.wait_for_event(dut2, 945 aconsts.SESSION_CB_ON_SERVICE_DISCOVERED) 946 asserts.assert_equal( 947 event["data"][aconsts.SESSION_CB_KEY_SESSION_ID], dut2_y_sid, 948 "Unexpected DUT2 Y subscribe session discovery ID") 949 dut2_peer_id_for_dut1_y = event["data"][aconsts.SESSION_CB_KEY_PEER_ID] 950 951 # DUT1.X send message to DUT2 952 x_msg = "Hello X on DUT2!" 953 dut1.droid.wifiAwareSendMessage(dut1_x_sid, dut1_peer_id_for_dut2_x, 954 self.get_next_msg_id(), x_msg, 955 self.msg_retx_count) 956 autils.wait_for_event(dut1, aconsts.SESSION_CB_ON_MESSAGE_SENT) 957 event = autils.wait_for_event(dut2, 958 aconsts.SESSION_CB_ON_MESSAGE_RECEIVED) 959 asserts.assert_equal( 960 event["data"][aconsts.SESSION_CB_KEY_SESSION_ID], dut2_x_pid, 961 "Unexpected publish session ID on DUT2 for meesage " 962 "received on service X") 963 asserts.assert_equal( 964 event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING], x_msg, 965 "Message on service X from DUT1 to DUT2 not received correctly") 966 967 # DUT2.Y send message to DUT1 968 y_msg = "Hello Y on DUT1!" 969 dut2.droid.wifiAwareSendMessage(dut2_y_sid, dut2_peer_id_for_dut1_y, 970 self.get_next_msg_id(), y_msg, 971 self.msg_retx_count) 972 autils.wait_for_event(dut2, aconsts.SESSION_CB_ON_MESSAGE_SENT) 973 event = autils.wait_for_event(dut1, 974 aconsts.SESSION_CB_ON_MESSAGE_RECEIVED) 975 asserts.assert_equal( 976 event["data"][aconsts.SESSION_CB_KEY_SESSION_ID], dut1_y_pid, 977 "Unexpected publish session ID on DUT1 for meesage " 978 "received on service Y") 979 asserts.assert_equal( 980 event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING], y_msg, 981 "Message on service Y from DUT2 to DUT1 not received correctly") 982 983 @test_tracker_info(uuid="eef80cf3-1fd2-4526-969b-6af2dce785d7") 984 def test_multiple_concurrent_services_both_unsolicited_passive(self): 985 """Validate multiple concurrent discovery sessions running on both devices. 986 - DUT1 & DUT2 running Publish for X 987 - DUT1 & DUT2 running Publish for Y 988 - DUT1 Subscribes for X 989 - DUT2 Subscribes for Y 990 Message exchanges. 991 992 Both sessions are Unsolicited/Passive. 993 994 Note: test requires that devices support 2 publish sessions concurrently. 995 The test will be skipped if the devices are not capable. 996 """ 997 self.run_multiple_concurrent_services( 998 type_x=[ 999 aconsts.PUBLISH_TYPE_UNSOLICITED, 1000 aconsts.SUBSCRIBE_TYPE_PASSIVE 1001 ], 1002 type_y=[ 1003 aconsts.PUBLISH_TYPE_UNSOLICITED, 1004 aconsts.SUBSCRIBE_TYPE_PASSIVE 1005 ]) 1006 1007 @test_tracker_info(uuid="46739f04-ab2b-4556-b1a4-9aa2774869b5") 1008 def test_multiple_concurrent_services_both_solicited_active(self): 1009 """Validate multiple concurrent discovery sessions running on both devices. 1010 - DUT1 & DUT2 running Publish for X 1011 - DUT1 & DUT2 running Publish for Y 1012 - DUT1 Subscribes for X 1013 - DUT2 Subscribes for Y 1014 Message exchanges. 1015 1016 Both sessions are Solicited/Active. 1017 1018 Note: test requires that devices support 2 publish sessions concurrently. 1019 The test will be skipped if the devices are not capable. 1020 """ 1021 self.run_multiple_concurrent_services( 1022 type_x=[ 1023 aconsts.PUBLISH_TYPE_SOLICITED, aconsts.SUBSCRIBE_TYPE_ACTIVE 1024 ], 1025 type_y=[ 1026 aconsts.PUBLISH_TYPE_SOLICITED, aconsts.SUBSCRIBE_TYPE_ACTIVE 1027 ]) 1028 1029 @test_tracker_info(uuid="5f8f7fd2-4a0e-4cca-8cbb-6d54353f2baa") 1030 def test_multiple_concurrent_services_mix_unsolicited_solicited(self): 1031 """Validate multiple concurrent discovery sessions running on both devices. 1032 - DUT1 & DUT2 running Publish for X 1033 - DUT1 & DUT2 running Publish for Y 1034 - DUT1 Subscribes for X 1035 - DUT2 Subscribes for Y 1036 Message exchanges. 1037 1038 Session A is Unsolicited/Passive. 1039 Session B is Solicited/Active. 1040 1041 Note: test requires that devices support 2 publish sessions concurrently. 1042 The test will be skipped if the devices are not capable. 1043 """ 1044 self.run_multiple_concurrent_services( 1045 type_x=[ 1046 aconsts.PUBLISH_TYPE_UNSOLICITED, 1047 aconsts.SUBSCRIBE_TYPE_PASSIVE 1048 ], 1049 type_y=[ 1050 aconsts.PUBLISH_TYPE_SOLICITED, aconsts.SUBSCRIBE_TYPE_ACTIVE 1051 ]) 1052 1053 ######################################################### 1054 1055 @test_tracker_info(uuid="908ec896-fc7a-4ee4-b633-a2f042b74448") 1056 def test_upper_lower_service_name_equivalence(self): 1057 """Validate that Service Name is case-insensitive. Publish a service name 1058 with mixed case, subscribe to the same service name with alternative case 1059 and verify that discovery happens.""" 1060 p_dut = self.android_devices[0] 1061 s_dut = self.android_devices[1] 1062 1063 pub_service_name = "GoogleAbCdEf" 1064 sub_service_name = "GoogleaBcDeF" 1065 1066 autils.create_discovery_pair( 1067 p_dut, 1068 s_dut, 1069 p_config=autils.create_discovery_config( 1070 pub_service_name, aconsts.PUBLISH_TYPE_UNSOLICITED), 1071 s_config=autils.create_discovery_config( 1072 sub_service_name, aconsts.SUBSCRIBE_TYPE_PASSIVE), 1073 device_startup_offset=self.device_startup_offset) 1074