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