1#  Copyright (C) 2024 The Android Open Source Project
2#
3#  Licensed under the Apache License, Version 2.0 (the "License");
4#  you may not use this file except in compliance with the License.
5#  You may obtain a copy of the License at
6#
7#       http://www.apache.org/licenses/LICENSE-2.0
8#
9#  Unless required by applicable law or agreed to in writing, software
10#  distributed under the License is distributed on an "AS IS" BASIS,
11#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12#  See the License for the specific language governing permissions and
13#  limitations under the License.
14
15# Lint as: python3
16"""Wi-Fi Aware Message test reimplemented in Mobly."""
17import logging
18import string
19import sys
20
21from aware import aware_lib_utils as autils
22from aware import constants
23from mobly import asserts
24from mobly import base_test
25from mobly import records
26from mobly import test_runner
27from mobly import utils
28from mobly.controllers import android_device
29from mobly.controllers.android_device_lib import callback_handler_v2
30
31RUNTIME_PERMISSIONS = (
32    'android.permission.ACCESS_FINE_LOCATION',
33    'android.permission.ACCESS_COARSE_LOCATION',
34    'android.permission.NEARBY_WIFI_DEVICES',
35)
36PACKAGE_NAME = constants.WIFI_AWARE_SNIPPET_PACKAGE_NAME
37_DEFAULT_TIMEOUT = constants.WAIT_WIFI_STATE_TIME_OUT.total_seconds()
38_CALLBACK_NAME = constants.DiscoverySessionCallbackParamsType.CALLBACK_NAME
39_IS_SESSION_INIT = constants.DiscoverySessionCallbackParamsType.IS_SESSION_INIT
40_MESSAGE_SEND_SUCCEEDED = (
41    constants.DiscoverySessionCallbackMethodType.MESSAGE_SEND_SUCCEEDED
42    )
43_MESSAGE_RECEIVED = (
44    constants.DiscoverySessionCallbackMethodType.MESSAGE_RECEIVED
45    )
46_MESSAGE_SEND_RESULT = (
47    constants.DiscoverySessionCallbackMethodType.MESSAGE_SEND_RESULT
48    )
49
50# Publish & Subscribe Config keys.
51_PAYLOAD_SIZE_MIN = 0
52_PAYLOAD_SIZE_TYPICAL = 1
53_PAYLOAD_SIZE_MAX = 2
54_PUBLISH_TYPE_UNSOLICITED = 0
55_PUBLISH_TYPE_SOLICITED = 1
56_SUBSCRIBE_TYPE_PASSIVE = 0
57_SUBSCRIBE_TYPE_ACTIVE = 1
58
59_NUM_MSGS_NO_QUEUE = 10
60# number of messages = mult * queue depth
61_NUM_MSGS_QUEUE_DEPTH_MULT = 2
62
63_CAP_MAX_QUEUED_TRANSMIT_MESSAGES = "maxQueuedTransmitMessages"
64_CAP_MAX_SERVICE_SPECIFIC_INFO_LEN = "maxServiceSpecificInfoLen"
65
66
67class WifiAwareMessageTest(base_test.BaseTestClass):
68    """Wi-Fi Aware test class."""
69
70    # message ID counter to make sure all uses are unique
71    msg_id = 0
72
73    ads: list[android_device.AndroidDevice]
74    publisher: android_device.AndroidDevice
75    subscriber: android_device.AndroidDevice
76
77    def setup_class(self):
78        # Register two Android devices.
79        self.ads = self.register_controller(android_device, min_number=2)
80        self.publisher = self.ads[0]
81        self.subscriber = self.ads[1]
82
83        def setup_device(device: android_device.AndroidDevice):
84            device.load_snippet(
85                'wifi_aware_snippet', PACKAGE_NAME
86            )
87            for permission in RUNTIME_PERMISSIONS:
88                device.adb.shell(['pm', 'grant', PACKAGE_NAME, permission])
89            asserts.abort_all_if(
90                not device.wifi_aware_snippet.wifiAwareIsAvailable(),
91                f'{device} Wi-Fi Aware is not available.',
92            )
93
94        # Set up devices in parallel.
95        utils.concurrent_exec(
96            setup_device,
97            ((self.publisher,), (self.subscriber,)),
98            max_workers=2,
99            raise_on_exception=True,
100        )
101
102    def setup_test(self):
103        for ad in self.ads:
104            autils.control_wifi(ad, True)
105            aware_avail = ad.wifi_aware_snippet.wifiAwareIsAvailable()
106            if not aware_avail:
107                ad.log.info('Aware not available. Waiting ...')
108                state_handler = ad.wifi_aware_snippet.wifiAwareMonitorStateChange()
109                state_handler.waitAndGet(
110                    constants.WifiAwareBroadcast.WIFI_AWARE_AVAILABLE)
111
112    def teardown_test(self):
113        utils.concurrent_exec(
114            self._teardown_test_on_device,
115            ((self.publisher,), (self.subscriber,)),
116            max_workers=2,
117            raise_on_exception=True,
118        )
119        utils.concurrent_exec(
120            lambda d: d.services.create_output_excerpts_all(
121                self.current_test_info),
122            param_list=[[ad] for ad in self.ads],
123            raise_on_exception=True,
124        )
125
126    def _teardown_test_on_device(self, ad: android_device.AndroidDevice) -> None:
127        ad.wifi_aware_snippet.wifiAwareCloseAllWifiAwareSession()
128        autils.reset_device_parameters(ad)
129        autils.validate_forbidden_callbacks(ad)
130        autils.reset_device_statistics(ad)
131
132    def on_fail(self, record: records.TestResult) -> None:
133        android_device.take_bug_reports(self.ads,
134                                        destination =
135                                        self.current_test_info.output_path)
136
137    def _start_attach(self, ad: android_device.AndroidDevice) -> str:
138        """Starts the attach process on the provided device."""
139        handler = ad.wifi_aware_snippet.wifiAwareAttach()
140        attach_event = handler.waitAndGet(
141            event_name = constants.AttachCallBackMethodType.ATTACHED,
142            timeout = _DEFAULT_TIMEOUT,
143        )
144        asserts.assert_true(
145            ad.wifi_aware_snippet.wifiAwareIsSessionAttached(handler.callback_id),
146            f'{ad} attach succeeded, but Wi-Fi Aware session is still null.'
147        )
148        ad.log.info('Attach Wi-Fi Aware session succeeded.')
149        return attach_event.callback_id
150
151    def get_next_msg_id(self):
152        """Increment the message ID and returns the new value.
153        Guarantees that each call to the method returns a unique value.
154
155        Returns: a new message id value.
156        """
157
158        self.msg_id = self.msg_id + 1
159        return self.msg_id
160
161    def assert_equal_strings(self, first, second, msg=None, extras=None):
162        """Assert equality of the string operands.
163            where None is treated as equal to an empty string (''),
164            otherwise fail the test.
165        Error message is "first != second" by default. Additional explanation
166        can be supplied in the message.
167
168        Args:
169            first, seconds: The strings that are evaluated for equality.
170            msg: A string that adds additional info about the failure.
171            extras: An optional field for extra information to be included in
172                    test result.
173        """
174        if first == None:
175            first = ''
176        if second == None:
177            second = ''
178        asserts.assert_equal(first, second, msg, extras)
179
180    def create_msg(self, payload_size, id):
181        """Creates a message string of the specified size containing the id.
182
183        Args:
184            payload_size: The size of the message to create - min (null or
185            empty message), typical, max (based on device capabilities).
186            Use the PAYLOAD_SIZE_xx constants.
187            id: Information to include in the generated message (or None).
188
189        Returns: A string of the requested size, optionally containing the id.
190        """
191        if payload_size == _PAYLOAD_SIZE_MIN:
192            return ""
193        elif payload_size == _PAYLOAD_SIZE_TYPICAL:
194            return "*** ID=%d ***" % id + string.ascii_uppercase
195        else:  # PAYLOAD_SIZE_MAX
196            return "*** ID=%4d ***" % id + "M" * (
197                len(_CAP_MAX_SERVICE_SPECIFIC_INFO_LEN) - 15)
198
199    def create_config(self, is_publish, extra_diff=None):
200        """Create a base configuration based on input parameters.
201
202        Args:
203            is_publish: True for publish, False for subscribe sessions.
204            extra_diff: String to add to service name: allows differentiating
205                        discovery sessions.
206
207        Returns:
208            publish discovery configuration object.
209        """
210        config = {}
211        if is_publish:
212            config[
213                constants.PUBLISH_TYPE] = _PUBLISH_TYPE_UNSOLICITED
214        else:
215            config[
216                constants.SUBSCRIBE_TYPE ] = _SUBSCRIBE_TYPE_PASSIVE
217        config[constants.SERVICE_NAME] = "GoogleTestServiceX" + (
218            extra_diff if extra_diff is not None else "")
219        return config
220
221    def prep_message_exchange(self, extra_diff=None):
222        """Creates a discovery session (publish and subscribe), and waits for
223        service discovery - at that point the sessions are ready for message
224        exchange.
225
226        Args:
227            extra_diff: String to add to service name: allows differentiating
228                        discovery sessions.
229        """
230
231        p_dut = self.ads[0]
232        p_dut.pretty_name = "Publisher"
233        s_dut = self.ads[1]
234        s_dut.pretty_name = "Subscriber"
235        use_id = extra_diff is not None
236        p_id = self._start_attach(p_dut)
237        s_id = self._start_attach(s_dut)
238        p_disc_id = p_dut.wifi_aware_snippet.wifiAwarePublish(
239                p_id, self.create_config(True, extra_diff=extra_diff)
240                )
241        p_dut.log.info('Created the publish session.')
242        p_discovery = p_disc_id.waitAndGet(
243            constants.DiscoverySessionCallbackMethodType.DISCOVER_RESULT)
244        callback_name = p_discovery.data[_CALLBACK_NAME]
245        asserts.assert_equal(
246            constants.DiscoverySessionCallbackMethodType.PUBLISH_STARTED,
247            callback_name,
248            f'{p_dut} publish failed, got callback: {callback_name}.',
249            )
250        # Subscriber: start subscribe and wait for confirmation
251        s_disc_id = s_dut.wifi_aware_snippet.wifiAwareSubscribe(
252                s_id, self.create_config(False, extra_diff=extra_diff)
253                )
254        s_dut.log.info('Created the subscribe session.')
255        s_discovery = s_disc_id.waitAndGet(
256                constants.DiscoverySessionCallbackMethodType.DISCOVER_RESULT,
257                timeout=_DEFAULT_TIMEOUT)
258        callback_name = s_discovery.data[_CALLBACK_NAME]
259        asserts.assert_equal(
260            constants.DiscoverySessionCallbackMethodType.SUBSCRIBE_STARTED,
261            callback_name,
262            f'{s_dut} subscribe failed, got callback: {callback_name}.',
263            )
264        discovered_event = s_disc_id.waitAndGet(
265            constants.DiscoverySessionCallbackMethodType.SERVICE_DISCOVERED)
266        peer_id_on_sub = discovered_event.data[
267            constants.WifiAwareSnippetParams.PEER_ID]
268        return {
269            "p_dut": p_dut,
270            "s_dut": s_dut,
271            "p_id": p_id,
272            "s_id": s_id,
273            "p_disc_id": p_disc_id,
274            "s_disc_id": s_disc_id,
275            "peer_id_on_sub": peer_id_on_sub
276        }
277    def run_message_no_queue(self, payload_size):
278        """Validate L2 message exchange between publisher & subscriber.
279        with no queueing - i.e. wait for an ACK on each message before
280        sending the next message.
281
282        Args:
283            payload_size: min, typical, or max (PAYLOAD_SIZE_xx).
284        """
285        discovery_info = self.prep_message_exchange()
286        p_dut = discovery_info["p_dut"]
287        s_dut = discovery_info["s_dut"]
288        p_disc_id = discovery_info["p_disc_id"]
289        s_disc_id = discovery_info["s_disc_id"]
290        peer_id_on_sub = discovery_info["peer_id_on_sub"]
291        for i in range(_NUM_MSGS_NO_QUEUE):
292            msg = self.create_msg(payload_size, i)
293            msg_id = self.get_next_msg_id()
294            logging.info("msg: %s", msg)
295            s_dut.wifi_aware_snippet.wifiAwareSendMessage(
296                s_disc_id.callback_id, peer_id_on_sub, msg_id, msg
297                )
298            tx_event = s_disc_id.waitAndGet(
299            event_name = _MESSAGE_SEND_RESULT,
300            timeout = _DEFAULT_TIMEOUT,
301            )
302            callback_name = tx_event.data[
303                constants.DiscoverySessionCallbackParamsType.CALLBACK_NAME
304            ]
305            asserts.assert_equal(
306                callback_name,
307                _MESSAGE_SEND_SUCCEEDED,
308                f'{s_dut} failed to send message with an unexpected callback.',
309            )
310            actual_send_message_id = tx_event.data[
311                constants.DiscoverySessionCallbackParamsType.MESSAGE_ID
312            ]
313            asserts.assert_equal(
314                actual_send_message_id,
315                msg_id,
316                f'{s_dut} send message succeeded but message ID mismatched.'
317            )
318            rx_event = p_disc_id.waitAndGet(
319                event_name = _MESSAGE_RECEIVED,
320                timeout = _DEFAULT_TIMEOUT,
321            )
322            received_message_raw = rx_event.data[
323                constants.WifiAwareSnippetParams.RECEIVED_MESSAGE
324            ]
325            received_message = bytes(received_message_raw).decode('utf-8')
326            self.assert_equal_strings(
327                msg,
328                received_message,
329                "Subscriber -> Publisher message %d corrupted" % i)
330        peer_id_on_pub = rx_event.data[
331            constants.WifiAwareSnippetParams.PEER_ID]
332        for i in range(_NUM_MSGS_NO_QUEUE):
333            msg = self.create_msg(payload_size, 1000 + i)
334            msg_id = self.get_next_msg_id()
335
336            p_dut.wifi_aware_snippet.wifiAwareSendMessage(
337                p_disc_id.callback_id, peer_id_on_pub, msg_id, msg)
338            tx_event = p_disc_id.waitAndGet(
339                event_name=_MESSAGE_SEND_RESULT,
340                timeout=_DEFAULT_TIMEOUT,
341                )
342            callback_name = tx_event.data[
343                constants.DiscoverySessionCallbackParamsType.CALLBACK_NAME
344            ]
345            asserts.assert_equal(
346                callback_name,
347                _MESSAGE_SEND_SUCCEEDED,
348                f'{p_dut} failed to send message with an unexpected callback.',
349            )
350            actual_send_message_id = tx_event.data[
351                constants.DiscoverySessionCallbackParamsType.MESSAGE_ID
352            ]
353            asserts.assert_equal(
354                actual_send_message_id,
355                msg_id,
356                f'{p_dut} send message succeeded but message ID mismatched.'
357            )
358            rx_event = s_disc_id.waitAndGet(
359                event_name = _MESSAGE_RECEIVED,
360                timeout = _DEFAULT_TIMEOUT,
361            )
362            received_message_raw = rx_event.data[
363                constants.WifiAwareSnippetParams.RECEIVED_MESSAGE
364            ]
365            received_message = bytes(received_message_raw).decode('utf-8')
366            self.assert_equal_strings(
367                msg,
368                received_message,
369                "Subscriber -> Publisher message %d corrupted" % i)
370
371    def wait_for_messages(self,
372                          tx_msgs,
373                          tx_msg_ids,
374                          tx_disc_id,
375                          rx_disc_id,
376                          tx_dut,
377                          rx_dut,
378                          are_msgs_empty=False):
379        """Validate that all expected messages are transmitted correctly.
380        and received as expected. Method is called after the messages are
381        sent into the transmission queue.
382
383        Note: that message can be transmitted and received out-of-order (
384        which is acceptable and the method handles that correctly).
385
386        Args:
387            tx_msgs: dictionary of transmitted messages
388            tx_msg_ids: dictionary of transmitted message ids
389            tx_disc_id: transmitter discovery session id (None for no
390                        decoration)
391            rx_disc_id: receiver discovery session id (None for no decoration)
392            tx_dut: transmitter device
393            rx_dut: receiver device
394            are_msgs_empty: True if the messages are None or empty (changes dup
395                            detection)
396
397        Returns: the peer ID from any of the received messages
398        """
399        peer_id_on_rx = None
400        still_to_be_tx = len(tx_msg_ids)
401        while still_to_be_tx != 0:
402            tx_event = tx_disc_id.waitAndGet(
403                event_name=_MESSAGE_SEND_RESULT,
404                timeout=_DEFAULT_TIMEOUT,
405                )
406            logging.info("tx_event: %s",tx_event )
407            tx_msg_id = tx_event.data[
408                constants.DiscoverySessionCallbackParamsType.MESSAGE_ID
409                ]
410            logging.info("tx_msg_id: %s",tx_msg_id )
411            logging.info("tx_msg_ids: %s",tx_msg_ids )
412            tx_msg_ids[tx_msg_id] = tx_msg_ids[tx_msg_id] + 1
413            if tx_msg_ids[tx_msg_id] == 1:
414                still_to_be_tx = still_to_be_tx - 1
415            # check for any duplicate transmit notifications
416        asserts.assert_equal(
417            len(tx_msg_ids), sum(tx_msg_ids.values()),
418            "Duplicate transmit message IDs: %s" % tx_msg_ids)
419
420        # wait for all messages to be received
421        still_to_be_rx = len(tx_msg_ids)
422        while still_to_be_rx != 0:
423            rx_event = rx_disc_id.waitAndGet(
424                event_name=_MESSAGE_RECEIVED,
425                timeout=_DEFAULT_TIMEOUT,
426                )
427            peer_id_on_rx = rx_event.data[
428                constants.WifiAwareSnippetParams.PEER_ID
429                ]
430            if are_msgs_empty:
431                still_to_be_rx = still_to_be_rx - 1
432            else:
433                received_message_raw = rx_event.data[
434                    constants.WifiAwareSnippetParams.RECEIVED_MESSAGE
435                    ]
436                rx_msg = bytes(received_message_raw).decode('utf-8')
437                asserts.assert_true(
438                    rx_msg in tx_msgs,
439                    "Received a message we did not send!? -- '%s'" % rx_msg)
440                tx_msgs[rx_msg] = tx_msgs[rx_msg] + 1
441                if tx_msgs[rx_msg] == 1:
442                    still_to_be_rx = still_to_be_rx - 1
443        # check for any duplicate received messages
444        if not are_msgs_empty:
445            asserts.assert_equal(
446                len(tx_msgs), sum(tx_msgs.values()),
447                "Duplicate transmit messages: %s" % tx_msgs)
448        return peer_id_on_rx
449
450    def run_message_with_queue(self, payload_size):
451        """Validate L2 message exchange between publisher & subscriber.
452        with queueing - i.e. transmit all messages and then wait for ACKs.
453
454        Args:
455            payload_size: min, typical, or max (PAYLOAD_SIZE_xx).
456        """
457        discovery_info = self.prep_message_exchange()
458        p_dut = discovery_info["p_dut"]
459        s_dut = discovery_info["s_dut"]
460        p_disc_id = discovery_info["p_disc_id"]
461        s_disc_id = discovery_info["s_disc_id"]
462        peer_id_on_sub = discovery_info["peer_id_on_sub"]
463
464        msgs = {}
465        msg_ids = {}
466        for i in range(
467            _NUM_MSGS_QUEUE_DEPTH_MULT * autils.get_aware_capabilities(s_dut)[_CAP_MAX_QUEUED_TRANSMIT_MESSAGES]):
468            msg = self.create_msg(payload_size, i)
469            msg_id = self.get_next_msg_id()
470            msgs[msg] = 0
471            msg_ids[msg_id] = 0
472            s_dut.wifi_aware_snippet.wifiAwareSendMessage(s_disc_id.callback_id,
473                                                          peer_id_on_sub,
474                                                          msg_id,
475                                                          msg)
476        peer_id_on_pub = self.wait_for_messages(msgs,
477                                                msg_ids,
478                                                s_disc_id,
479                                                p_disc_id,
480                                                s_dut,
481                                                p_dut,
482                                                payload_size
483                                                    ==_PAYLOAD_SIZE_MIN)
484        msgs = {}
485        msg_ids = {}
486        for i in range(
487            _NUM_MSGS_QUEUE_DEPTH_MULT *  autils.get_aware_capabilities(p_dut)[_CAP_MAX_QUEUED_TRANSMIT_MESSAGES]):
488            msg = self.create_msg(payload_size, 1000 + i)
489            msg_id = self.get_next_msg_id()
490            msgs[msg] = 0
491            msg_ids[msg_id] = 0
492            p_dut.wifi_aware_snippet.wifiAwareSendMessage(p_disc_id.callback_id,
493                                                          peer_id_on_pub,
494                                                          msg_id,
495                                                          msg)
496        self.wait_for_messages(msgs, msg_ids,p_disc_id, s_disc_id, p_dut, s_dut,
497                               payload_size == _PAYLOAD_SIZE_MIN)
498    def run_message_multi_session_with_queue(self, payload_size):
499        """Validate L2 message exchange between publishers & subscribers with.
500        queueing - i.e. transmit all messages and then wait for ACKs. Uses 2
501        discovery sessions running concurrently and validates that messages
502        arrive at the correct destination.
503
504        Args:
505            payload_size: min, typical, or max (PAYLOAD_SIZE_xx)
506        """
507        discovery_info1 = self.prep_message_exchange(extra_diff="-111")
508        p_dut = discovery_info1["p_dut"]  # same for both sessions
509        s_dut = discovery_info1["s_dut"]  # same for both sessions
510        p_disc_id1 = discovery_info1["p_disc_id"]
511        s_disc_id1 = discovery_info1["s_disc_id"]
512        peer_id_on_sub1 = discovery_info1["peer_id_on_sub"]
513
514        discovery_info2 = self.prep_message_exchange(extra_diff="-222")
515        p_disc_id2 = discovery_info2["p_disc_id"]
516        s_disc_id2 = discovery_info2["s_disc_id"]
517        peer_id_on_sub2 = discovery_info2["peer_id_on_sub"]
518        msgs1 = {}
519        msg_ids1 = {}
520        msgs2 = {}
521        msg_ids2 = {}
522        for i in range(
523                _NUM_MSGS_QUEUE_DEPTH_MULT * autils.get_aware_capabilities(s_dut)[_CAP_MAX_QUEUED_TRANSMIT_MESSAGES]):
524            msg1 = self.create_msg(payload_size, i)
525            msg_id1 = self.get_next_msg_id()
526            msgs1[msg1] = 0
527            msg_ids1[msg_id1] = 0
528            s_dut.wifi_aware_snippet.wifiAwareSendMessage(s_disc_id1.callback_id,
529                                                          peer_id_on_sub1,
530                                                          msg_id1,
531                                                          msg1)
532            msg2 = self.create_msg(payload_size, 100 + i)
533            msg_id2 = self.get_next_msg_id()
534            msgs2[msg2] = 0
535            msg_ids2[msg_id2] = 0
536            s_dut.wifi_aware_snippet.wifiAwareSendMessage(s_disc_id2.callback_id,
537                                                          peer_id_on_sub2,
538                                                          msg_id2,
539                                                          msg2)
540        peer_id_on_pub1 = self.wait_for_messages(
541            msgs1, msg_ids1, s_disc_id1, p_disc_id1, s_dut, p_dut,
542            payload_size == _PAYLOAD_SIZE_MIN)
543        peer_id_on_pub2 = self.wait_for_messages(
544            msgs2, msg_ids2, s_disc_id2, p_disc_id2, s_dut, p_dut,
545            payload_size == _PAYLOAD_SIZE_MIN)
546        msgs1 = {}
547        msg_ids1 = {}
548        msgs2 = {}
549        msg_ids2 = {}
550        for i in range(
551                _NUM_MSGS_QUEUE_DEPTH_MULT * autils.get_aware_capabilities(p_dut)[_CAP_MAX_QUEUED_TRANSMIT_MESSAGES]):
552            msg1 = self.create_msg(payload_size, 1000 + i)
553            msg_id1 = self.get_next_msg_id()
554            msgs1[msg1] = 0
555            msg_ids1[msg_id1] = 0
556            p_dut.wifi_aware_snippet.wifiAwareSendMessage(p_disc_id1.callback_id,
557                                                          peer_id_on_pub1,
558                                                          msg_id1,
559                                                          msg1)
560            msg2 = self.create_msg(payload_size, 1100 + i)
561            msg_id2 = self.get_next_msg_id()
562            msgs2[msg2] = 0
563            msg_ids2[msg_id2] = 0
564
565            p_dut.wifi_aware_snippet.wifiAwareSendMessage(
566                p_disc_id2.callback_id, peer_id_on_pub2, msg_id2,msg2)
567        self.wait_for_messages(msgs1, msg_ids1, p_disc_id1, s_disc_id1, p_dut,
568                               s_dut, payload_size == _PAYLOAD_SIZE_MIN)
569        self.wait_for_messages(msgs2, msg_ids2, p_disc_id2, s_disc_id2, p_dut,
570                               s_dut, payload_size == _PAYLOAD_SIZE_MIN)
571
572
573    def test_message_no_queue_min(self):
574        """Functional / Message / No queue
575        - Minimal payload size (None or "")
576        """
577        self.run_message_no_queue(_PAYLOAD_SIZE_MIN)
578
579    def test_message_no_queue_typical(self):
580        """Functional / Message / No queue
581        - Typical payload size
582        """
583        self.run_message_no_queue(_PAYLOAD_SIZE_TYPICAL)
584
585    def test_message_no_queue_max(self):
586        """Functional / Message / No queue
587        - Max payload size (based on device capabilities)
588        """
589        self.run_message_no_queue(_PAYLOAD_SIZE_MAX)
590
591    def test_message_with_queue_min(self):
592        """Functional / Message / With queue
593    - Minimal payload size (none or "")
594    """
595        self.run_message_with_queue(_PAYLOAD_SIZE_MIN)
596
597    def test_message_with_queue_typical(self):
598        """Functional / Message / With queue
599    - Typical payload size
600    """
601        self.run_message_with_queue(_PAYLOAD_SIZE_TYPICAL)
602
603    def test_message_with_queue_max(self):
604        """Functional / Message / With queue
605    - Max payload size (based on device capabilities)
606    """
607        self.run_message_with_queue(_PAYLOAD_SIZE_MAX)
608
609    def test_message_with_multiple_discovery_sessions_typical(self):
610        """Functional / Message / Multiple sessions
611
612     Sets up 2 discovery sessions on 2 devices. Sends a message in each
613     direction on each discovery session and verifies that reaches expected
614     destination.
615    """
616        self.run_message_multi_session_with_queue(_PAYLOAD_SIZE_TYPICAL)
617
618if __name__ == '__main__':
619    # Take test args
620    if '--' in sys.argv:
621        index = sys.argv.index('--')
622        sys.argv = sys.argv[:1] + sys.argv[index + 1:]
623
624    test_runner.main()
625