blob: c86343deee27ce10e33e441ae9b154488e0d548b [file] [log] [blame]
Etan Cohen872a6be2017-05-16 08:08:15 -07001#!/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
18
19from acts import asserts
20from acts.test_utils.wifi.aware import aware_const as aconsts
21from acts.test_utils.wifi.aware import aware_test_utils as autils
22from acts.test_utils.wifi.aware.AwareBaseTest import AwareBaseTest
23
24
25class DiscoveryTest(AwareBaseTest):
26 """Set of tests for Wi-Fi Aware discovery."""
27
28 # configuration parameters used by tests
29 PAYLOAD_SIZE_MIN = 0
30 PAYLOAD_SIZE_TYPICAL = 1
31 PAYLOAD_SIZE_MAX = 2
32
33 # message strings
34 query_msg = "How are you doing? 你好嗎?"
35 response_msg = "Doing ok - thanks! 做的不錯 - 謝謝!"
36
37 # message re-transmit counter (increases reliability in open-environment)
38 # Note: reliability of message transmission is tested elsewhere
39 msg_retx_count = 5 # hard-coded max value, internal API
40
41 def __init__(self, controllers):
42 AwareBaseTest.__init__(self, controllers)
43
44 def create_base_config(self, is_publish, ptype, stype, payload_size, ttl,
45 term_ind_on, null_match):
46 """Create a base configuration based on input parameters.
47
48 Args:
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] = None
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.DISCOVERY_KEY_SSI] = string.ascii_letters[::
76 -1] # reverse
77 config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST] = autils.encode_list(
78 [(10).to_bytes(1, byteorder="big"), "hello there string"
79 if not null_match else None,
80 bytes(range(40))])
81 return config
82
83 def create_publish_config(self, ptype, payload_size, ttl, term_ind_on,
84 null_match):
85 """Create a publish configuration based on input parameters.
86
87 Args:
88 ptype: unsolicited or solicited
89 payload_size: min, typical, max (PAYLOAD_SIZE_xx)
90 ttl: time-to-live configuration (0 - forever)
91 term_ind_on: is termination indication enabled
92 null_match: null-out the middle match filter
93 Returns:
94 publish discovery configuration object.
95 """
96 return self.create_base_config(True, ptype, None, payload_size, ttl,
97 term_ind_on, null_match)
98
99 def create_subscribe_config(self, stype, payload_size, ttl, term_ind_on,
100 null_match):
101 """Create a subscribe configuration based on input parameters.
102
103 Args:
104 stype: passive or active
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 subscribe discovery configuration object.
111 """
112 return self.create_base_config(False, None, stype, payload_size, ttl,
113 term_ind_on, null_match)
114
115 def positive_discovery_test_utility(self, ptype, stype, payload_size, ttl,
116 term_ind_on):
117 """Utility which runs a positive discovery test:
118 - Discovery (publish/subscribe)
119 - Exchange messages
120 - Update publish/subscribe
121 - Terminate
122
123 Args:
124 ptype: Publish discovery type
125 stype: Subscribe discovery type
126 payload_size: One of PAYLOAD_SIZE_* constants - MIN, TYPICAL, MAX
127 ttl: Duration of discovery session, 0 for unlimited
128 term_ind_on: True if a termination indication is wanted, False otherwise
129 """
130 p_dut = self.android_devices[0]
131 s_dut = self.android_devices[1]
132
133 # Publisher+Subscriber: attach and wait for confirmation
134 p_id = p_dut.droid.wifiAwareAttach(False)
135 autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED)
136 s_id = s_dut.droid.wifiAwareAttach(False)
137 autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED)
138
139 # Publisher: start publish and wait for confirmation
140 p_config = self.create_publish_config(ptype, payload_size, ttl, term_ind_on,
141 null_match=False)
142 p_disc_id = p_dut.droid.wifiAwarePublish(p_id, p_config)
143 autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_PUBLISH_STARTED)
144
145 # Subscriber: start subscribe and wait for confirmation
146 s_config = self.create_subscribe_config(stype, payload_size, ttl,
147 term_ind_on, null_match=True)
148 s_disc_id = s_dut.droid.wifiAwareSubscribe(s_id, s_config)
149 autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED)
150
151 # Subscriber: wait for service discovery
152 discovery_event = autils.wait_for_event(
153 s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
154 peer_id_on_sub = discovery_event["data"][aconsts.SESSION_CB_KEY_PEER_ID]
155
156 # Subscriber: validate contents of discovery (specifically that getting the
157 # Publisher's SSI and MatchFilter!)
158 asserts.assert_equal(
159 bytes(discovery_event["data"][
160 aconsts.SESSION_CB_KEY_SERVICE_SPECIFIC_INFO]).decode("utf-8"),
161 p_config[aconsts.DISCOVERY_KEY_SSI],
162 "Discovery mismatch: service specific info (SSI)")
163 asserts.assert_equal(
164 autils.decode_list(
165 discovery_event["data"][aconsts.SESSION_CB_KEY_MATCH_FILTER_LIST]),
166 autils.decode_list(p_config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST]),
167 "Discovery mismatch: match filter")
168
169 # Subscriber: send message to peer (Publisher)
170 s_dut.droid.wifiAwareSendMessage(s_disc_id, peer_id_on_sub,
171 self.get_next_msg_id(), self.query_msg,
172 self.msg_retx_count)
173 autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_MESSAGE_SENT)
174
175 # Publisher: wait for received message
176 pub_rx_msg_event = autils.wait_for_event(
177 p_dut, aconsts.SESSION_CB_ON_MESSAGE_RECEIVED)
178 peer_id_on_pub = pub_rx_msg_event["data"][aconsts.SESSION_CB_KEY_PEER_ID]
179
180 # Publisher: validate contents of message
181 asserts.assert_equal(
182 pub_rx_msg_event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING],
183 self.query_msg, "Subscriber -> Publisher message corrupted")
184
185 # Publisher: send message to peer (Subscriber)
186 p_dut.droid.wifiAwareSendMessage(p_disc_id, peer_id_on_pub,
187 self.get_next_msg_id(), self.response_msg,
188 self.msg_retx_count)
189 autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_MESSAGE_SENT)
190
191 # Subscriber: wait for received message
192 sub_rx_msg_event = autils.wait_for_event(
193 s_dut, aconsts.SESSION_CB_ON_MESSAGE_RECEIVED)
194
195 # Subscriber: validate contents of message
196 asserts.assert_equal(
197 sub_rx_msg_event["data"][aconsts.SESSION_CB_KEY_PEER_ID],
198 peer_id_on_sub,
199 "Subscriber received message from different peer ID then discovery!?")
200 asserts.assert_equal(
201 sub_rx_msg_event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING],
202 self.response_msg, "Publisher -> Subscriber message corrupted")
203
204 # Subscriber: validate that we're not getting another Service Discovery
205 autils.fail_on_event(s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
206
207 # Publisher: update publish and wait for confirmation
208 p_config[aconsts.DISCOVERY_KEY_SSI] = "something else"
209 p_dut.droid.wifiAwareUpdatePublish(p_disc_id, p_config)
210 autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_SESSION_CONFIG_UPDATED)
211
212 # Subscriber: expect a new service discovery
213 discovery_event = autils.wait_for_event(
214 s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
215
216 # Subscriber: validate contents of discovery
217 asserts.assert_equal(
218 bytes(discovery_event["data"][
219 aconsts.SESSION_CB_KEY_SERVICE_SPECIFIC_INFO]).decode("utf-8"),
220 p_config[aconsts.DISCOVERY_KEY_SSI],
221 "Discovery mismatch (after pub update): service specific info (SSI)")
222 asserts.assert_equal(
223 autils.decode_list(
224 discovery_event["data"][aconsts.SESSION_CB_KEY_MATCH_FILTER_LIST]),
225 autils.decode_list(p_config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST]),
226 "Discovery mismatch: match filter")
227
228 # Subscribe: update subscribe and wait for confirmation
229 s_config = self.create_subscribe_config(stype, payload_size, ttl,
230 term_ind_on, null_match=False)
231 s_dut.droid.wifiAwareUpdateSubscribe(s_disc_id, s_config)
232 autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_SESSION_CONFIG_UPDATED)
233
234 # Subscriber: should not get a new service discovery (no new information)
235 autils.fail_on_event(s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
236
237 # Publisher: should never get a service discovery event!
238 autils.fail_on_event(p_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
239
240 # Publisher+Subscriber: Terminate sessions
241 p_dut.droid.wifiAwareDestroyDiscoverySession(p_disc_id)
242 s_dut.droid.wifiAwareDestroyDiscoverySession(s_disc_id)
243
244 # Publisher+Subscriber: Expect (or not) to receive termination indication
245 # Note: if TTL is 0 (i.e. continuous session - which we terminate
246 # explicitly) then do not expect indications no matter the configuration
247 if term_ind_on and ttl != 0:
248 autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_SESSION_TERMINATED)
249 autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_SESSION_TERMINATED)
250 else:
251 autils.fail_on_event(p_dut, aconsts.SESSION_CB_ON_SESSION_TERMINATED)
252 autils.fail_on_event(s_dut, aconsts.SESSION_CB_ON_SESSION_TERMINATED)
253
254 #######################################
255 # Positive tests key:
256 #
257 # names is: test_<pub_type>_<sub_type>_<size>_<lifetime>_<term_ind>,
258 # where:
259 #
260 # pub_type: Type of publish discovery session: unsolicited or solicited.
261 # sub_type: Type of subscribe discovery session: passive or active.
262 # size: Size of payload fields (service name, service specific info, and match
263 # filter: typical, max, or min.
264 # lifetime: Discovery session lifetime: ongoing or limited.
265 # term_ind: Termination indication enabled or disabled: termind or "".
266 # Only relevant for limited lifetime (i.e. TTL != 0).
267 #######################################
268
269 def test_positive_unsolicited_passive_typical_ongoing(self):
270 """Functional test case / Discovery test cases / positive test case:
271 - Solicited publish + passive subscribe
272 - Typical payload fields size
273 - Ongoing lifetime (i.e. no TTL specified)
274
275 Verifies that discovery and message exchange succeeds.
276 """
277 self.positive_discovery_test_utility(
278 ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
279 stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
280 payload_size=self.PAYLOAD_SIZE_TYPICAL,
281 ttl=0,
282 term_ind_on=True) # term_ind_on is irrelevant since ttl=0