blob: 79bff02c6d03f487acd8f6d6464e75a14ec8a0fd [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
Etan Cohenfb7f3b12017-05-19 06:54:03 -070018import time
Etan Cohen872a6be2017-05-16 08:08:15 -070019
20from acts import asserts
21from acts.test_utils.wifi.aware import aware_const as aconsts
22from acts.test_utils.wifi.aware import aware_test_utils as autils
23from acts.test_utils.wifi.aware.AwareBaseTest import AwareBaseTest
24
25
26class DiscoveryTest(AwareBaseTest):
27 """Set of tests for Wi-Fi Aware discovery."""
28
29 # configuration parameters used by tests
30 PAYLOAD_SIZE_MIN = 0
31 PAYLOAD_SIZE_TYPICAL = 1
32 PAYLOAD_SIZE_MAX = 2
33
34 # message strings
35 query_msg = "How are you doing? 你好嗎?"
36 response_msg = "Doing ok - thanks! 做的不錯 - 謝謝!"
37
38 # message re-transmit counter (increases reliability in open-environment)
39 # Note: reliability of message transmission is tested elsewhere
40 msg_retx_count = 5 # hard-coded max value, internal API
41
42 def __init__(self, controllers):
43 AwareBaseTest.__init__(self, controllers)
44
Etan Cohenfb7f3b12017-05-19 06:54:03 -070045 def create_base_config(self, caps, is_publish, ptype, stype, payload_size,
46 ttl, term_ind_on, null_match):
Etan Cohen872a6be2017-05-16 08:08:15 -070047 """Create a base configuration based on input parameters.
48
49 Args:
Etan Cohenfb7f3b12017-05-19 06:54:03 -070050 caps: device capability dictionary
Etan Cohen872a6be2017-05-16 08:08:15 -070051 is_publish: True if a publish config, else False
52 ptype: unsolicited or solicited (used if is_publish is True)
53 stype: passive or active (used if is_publish is False)
54 payload_size: min, typical, max (PAYLOAD_SIZE_xx)
55 ttl: time-to-live configuration (0 - forever)
56 term_ind_on: is termination indication enabled
57 null_match: null-out the middle match filter
58 Returns:
59 publish discovery configuration object.
60 """
61 config = {}
62 if is_publish:
63 config[aconsts.DISCOVERY_KEY_DISCOVERY_TYPE] = ptype
64 else:
65 config[aconsts.DISCOVERY_KEY_DISCOVERY_TYPE] = stype
66 config[aconsts.DISCOVERY_KEY_TTL] = ttl
67 config[aconsts.DISCOVERY_KEY_TERM_CB_ENABLED] = term_ind_on
68 if payload_size == self.PAYLOAD_SIZE_MIN:
69 config[aconsts.DISCOVERY_KEY_SERVICE_NAME] = "a"
70 config[aconsts.DISCOVERY_KEY_SSI] = None
Etan Cohen0bc1cab2017-05-18 15:30:41 -070071 config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST] = []
Etan Cohen872a6be2017-05-16 08:08:15 -070072 elif payload_size == self.PAYLOAD_SIZE_TYPICAL:
73 config[aconsts.DISCOVERY_KEY_SERVICE_NAME] = "GoogleTestServiceX"
74 if is_publish:
75 config[aconsts.DISCOVERY_KEY_SSI] = string.ascii_letters
76 else:
77 config[aconsts.DISCOVERY_KEY_SSI] = string.ascii_letters[::
78 -1] # reverse
79 config[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 return config
84
Etan Cohenfb7f3b12017-05-19 06:54:03 -070085 def create_publish_config(self, caps, ptype, payload_size, ttl, term_ind_on,
Etan Cohen872a6be2017-05-16 08:08:15 -070086 null_match):
87 """Create a publish configuration based on input parameters.
88
89 Args:
Etan Cohenfb7f3b12017-05-19 06:54:03 -070090 caps: device capability dictionary
Etan Cohen872a6be2017-05-16 08:08:15 -070091 ptype: unsolicited or solicited
92 payload_size: min, typical, max (PAYLOAD_SIZE_xx)
93 ttl: time-to-live configuration (0 - forever)
94 term_ind_on: is termination indication enabled
95 null_match: null-out the middle match filter
96 Returns:
97 publish discovery configuration object.
98 """
Etan Cohenfb7f3b12017-05-19 06:54:03 -070099 return self.create_base_config(caps, True, ptype, None, payload_size, ttl,
Etan Cohen872a6be2017-05-16 08:08:15 -0700100 term_ind_on, null_match)
101
Etan Cohenfb7f3b12017-05-19 06:54:03 -0700102 def create_subscribe_config(self, caps, stype, payload_size, ttl, term_ind_on,
Etan Cohen872a6be2017-05-16 08:08:15 -0700103 null_match):
104 """Create a subscribe configuration based on input parameters.
105
106 Args:
Etan Cohenfb7f3b12017-05-19 06:54:03 -0700107 caps: device capability dictionary
Etan Cohen872a6be2017-05-16 08:08:15 -0700108 stype: passive or active
109 payload_size: min, typical, max (PAYLOAD_SIZE_xx)
110 ttl: time-to-live configuration (0 - forever)
111 term_ind_on: is termination indication enabled
112 null_match: null-out the middle match filter
113 Returns:
114 subscribe discovery configuration object.
115 """
Etan Cohenfb7f3b12017-05-19 06:54:03 -0700116 return self.create_base_config(caps, False, None, stype, payload_size, ttl,
Etan Cohen872a6be2017-05-16 08:08:15 -0700117 term_ind_on, null_match)
118
Etan Cohenfb7f3b12017-05-19 06:54:03 -0700119 def positive_discovery_test_utility(self, ptype, stype, payload_size):
Etan Cohen872a6be2017-05-16 08:08:15 -0700120 """Utility which runs a positive discovery test:
Etan Cohenfb7f3b12017-05-19 06:54:03 -0700121 - Discovery (publish/subscribe) with TTL=0 (non-self-terminating)
Etan Cohen872a6be2017-05-16 08:08:15 -0700122 - Exchange messages
123 - Update publish/subscribe
124 - Terminate
125
126 Args:
127 ptype: Publish discovery type
128 stype: Subscribe discovery type
129 payload_size: One of PAYLOAD_SIZE_* constants - MIN, TYPICAL, MAX
Etan Cohen872a6be2017-05-16 08:08:15 -0700130 """
131 p_dut = self.android_devices[0]
Etan Cohenfb7f3b12017-05-19 06:54:03 -0700132 p_dut.pretty_name = "Publisher"
Etan Cohen872a6be2017-05-16 08:08:15 -0700133 s_dut = self.android_devices[1]
Etan Cohenfb7f3b12017-05-19 06:54:03 -0700134 s_dut.pretty_name = "Subscriber"
Etan Cohen872a6be2017-05-16 08:08:15 -0700135
136 # Publisher+Subscriber: attach and wait for confirmation
137 p_id = p_dut.droid.wifiAwareAttach(False)
138 autils.wait_for_event(p_dut, aconsts.EVENT_CB_ON_ATTACHED)
139 s_id = s_dut.droid.wifiAwareAttach(False)
140 autils.wait_for_event(s_dut, aconsts.EVENT_CB_ON_ATTACHED)
141
142 # Publisher: start publish and wait for confirmation
Etan Cohenfb7f3b12017-05-19 06:54:03 -0700143 p_config = self.create_publish_config(
144 p_dut.aware_capabilities,
145 ptype,
146 payload_size,
147 ttl=0,
148 term_ind_on=False,
149 null_match=False)
Etan Cohen872a6be2017-05-16 08:08:15 -0700150 p_disc_id = p_dut.droid.wifiAwarePublish(p_id, p_config)
151 autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_PUBLISH_STARTED)
152
153 # Subscriber: start subscribe and wait for confirmation
Etan Cohenfb7f3b12017-05-19 06:54:03 -0700154 s_config = self.create_subscribe_config(
155 s_dut.aware_capabilities,
156 stype,
157 payload_size,
158 ttl=0,
159 term_ind_on=False,
160 null_match=True)
Etan Cohen872a6be2017-05-16 08:08:15 -0700161 s_disc_id = s_dut.droid.wifiAwareSubscribe(s_id, s_config)
162 autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_SUBSCRIBE_STARTED)
163
164 # Subscriber: wait for service discovery
165 discovery_event = autils.wait_for_event(
166 s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
167 peer_id_on_sub = discovery_event["data"][aconsts.SESSION_CB_KEY_PEER_ID]
168
169 # Subscriber: validate contents of discovery (specifically that getting the
170 # Publisher's SSI and MatchFilter!)
Etan Cohen0bc1cab2017-05-18 15:30:41 -0700171 autils.assert_equal_strings(
Etan Cohen872a6be2017-05-16 08:08:15 -0700172 bytes(discovery_event["data"][
173 aconsts.SESSION_CB_KEY_SERVICE_SPECIFIC_INFO]).decode("utf-8"),
174 p_config[aconsts.DISCOVERY_KEY_SSI],
175 "Discovery mismatch: service specific info (SSI)")
176 asserts.assert_equal(
177 autils.decode_list(
178 discovery_event["data"][aconsts.SESSION_CB_KEY_MATCH_FILTER_LIST]),
179 autils.decode_list(p_config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST]),
180 "Discovery mismatch: match filter")
181
182 # Subscriber: send message to peer (Publisher)
183 s_dut.droid.wifiAwareSendMessage(s_disc_id, peer_id_on_sub,
184 self.get_next_msg_id(), self.query_msg,
185 self.msg_retx_count)
186 autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_MESSAGE_SENT)
187
188 # Publisher: wait for received message
189 pub_rx_msg_event = autils.wait_for_event(
190 p_dut, aconsts.SESSION_CB_ON_MESSAGE_RECEIVED)
191 peer_id_on_pub = pub_rx_msg_event["data"][aconsts.SESSION_CB_KEY_PEER_ID]
192
193 # Publisher: validate contents of message
194 asserts.assert_equal(
195 pub_rx_msg_event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING],
196 self.query_msg, "Subscriber -> Publisher message corrupted")
197
198 # Publisher: send message to peer (Subscriber)
199 p_dut.droid.wifiAwareSendMessage(p_disc_id, peer_id_on_pub,
200 self.get_next_msg_id(), self.response_msg,
201 self.msg_retx_count)
202 autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_MESSAGE_SENT)
203
204 # Subscriber: wait for received message
205 sub_rx_msg_event = autils.wait_for_event(
206 s_dut, aconsts.SESSION_CB_ON_MESSAGE_RECEIVED)
207
208 # Subscriber: validate contents of message
209 asserts.assert_equal(
210 sub_rx_msg_event["data"][aconsts.SESSION_CB_KEY_PEER_ID],
211 peer_id_on_sub,
212 "Subscriber received message from different peer ID then discovery!?")
Etan Cohen0bc1cab2017-05-18 15:30:41 -0700213 autils.assert_equal_strings(
Etan Cohen872a6be2017-05-16 08:08:15 -0700214 sub_rx_msg_event["data"][aconsts.SESSION_CB_KEY_MESSAGE_AS_STRING],
215 self.response_msg, "Publisher -> Subscriber message corrupted")
216
217 # Subscriber: validate that we're not getting another Service Discovery
218 autils.fail_on_event(s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
219
220 # Publisher: update publish and wait for confirmation
221 p_config[aconsts.DISCOVERY_KEY_SSI] = "something else"
222 p_dut.droid.wifiAwareUpdatePublish(p_disc_id, p_config)
223 autils.wait_for_event(p_dut, aconsts.SESSION_CB_ON_SESSION_CONFIG_UPDATED)
224
225 # Subscriber: expect a new service discovery
226 discovery_event = autils.wait_for_event(
227 s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED)
228
229 # Subscriber: validate contents of discovery
Etan Cohen0bc1cab2017-05-18 15:30:41 -0700230 autils.assert_equal_strings(
Etan Cohen872a6be2017-05-16 08:08:15 -0700231 bytes(discovery_event["data"][
232 aconsts.SESSION_CB_KEY_SERVICE_SPECIFIC_INFO]).decode("utf-8"),
233 p_config[aconsts.DISCOVERY_KEY_SSI],
234 "Discovery mismatch (after pub update): service specific info (SSI)")
235 asserts.assert_equal(
236 autils.decode_list(
237 discovery_event["data"][aconsts.SESSION_CB_KEY_MATCH_FILTER_LIST]),
238 autils.decode_list(p_config[aconsts.DISCOVERY_KEY_MATCH_FILTER_LIST]),
239 "Discovery mismatch: match filter")
240
241 # Subscribe: update subscribe and wait for confirmation
Etan Cohenfb7f3b12017-05-19 06:54:03 -0700242 s_config = self.create_subscribe_config(
243 s_dut.aware_capabilities,
244 stype,
245 payload_size,
246 ttl=0,
247 term_ind_on=False,
248 null_match=False)
Etan Cohen872a6be2017-05-16 08:08:15 -0700249 s_dut.droid.wifiAwareUpdateSubscribe(s_disc_id, s_config)
250 autils.wait_for_event(s_dut, aconsts.SESSION_CB_ON_SESSION_CONFIG_UPDATED)
251
Etan Cohen872a6be2017-05-16 08:08:15 -0700252 # Publisher+Subscriber: Terminate sessions
253 p_dut.droid.wifiAwareDestroyDiscoverySession(p_disc_id)
254 s_dut.droid.wifiAwareDestroyDiscoverySession(s_disc_id)
255
Etan Cohenfb7f3b12017-05-19 06:54:03 -0700256 # sleep for timeout period and then verify all 'fail_on_event' together
257 time.sleep(autils.EVENT_TIMEOUT)
258
259 # Subscriber: should not get a new service discovery (no new information)
260 autils.fail_on_event(
261 s_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, timeout=0)
262
263 # Publisher: should never get a service discovery event!
264 autils.fail_on_event(
265 p_dut, aconsts.SESSION_CB_ON_SERVICE_DISCOVERED, timeout=0)
266
267 # Publisher+Subscriber: should not get termination indication (since we're
268 # destroying sessions explicitly)
269 autils.fail_on_event(
270 p_dut, aconsts.SESSION_CB_ON_SESSION_TERMINATED, timeout=0)
271 autils.fail_on_event(
272 s_dut, aconsts.SESSION_CB_ON_SESSION_TERMINATED, timeout=0)
273
274 # verify that there were no other events
275 autils.verify_no_more_events(p_dut)
276 autils.verify_no_more_events(s_dut)
Etan Cohen872a6be2017-05-16 08:08:15 -0700277
278 #######################################
279 # Positive tests key:
280 #
Etan Cohenfb7f3b12017-05-19 06:54:03 -0700281 # names is: test_<pub_type>_<sub_type>_<size>
Etan Cohen872a6be2017-05-16 08:08:15 -0700282 # where:
283 #
284 # pub_type: Type of publish discovery session: unsolicited or solicited.
285 # sub_type: Type of subscribe discovery session: passive or active.
286 # size: Size of payload fields (service name, service specific info, and match
287 # filter: typical, max, or min.
Etan Cohen872a6be2017-05-16 08:08:15 -0700288 #######################################
289
Etan Cohenfb7f3b12017-05-19 06:54:03 -0700290 def test_positive_unsolicited_passive_typical(self):
Etan Cohen872a6be2017-05-16 08:08:15 -0700291 """Functional test case / Discovery test cases / positive test case:
292 - Solicited publish + passive subscribe
293 - Typical payload fields size
Etan Cohen872a6be2017-05-16 08:08:15 -0700294
295 Verifies that discovery and message exchange succeeds.
296 """
297 self.positive_discovery_test_utility(
298 ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
299 stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
Etan Cohenfb7f3b12017-05-19 06:54:03 -0700300 payload_size=self.PAYLOAD_SIZE_TYPICAL)
Etan Cohen0bc1cab2017-05-18 15:30:41 -0700301
Etan Cohenfb7f3b12017-05-19 06:54:03 -0700302 def test_positive_unsolicited_passive_min(self):
Etan Cohen0bc1cab2017-05-18 15:30:41 -0700303 """Functional test case / Discovery test cases / positive test case:
304 - Solicited publish + passive subscribe
305 - Minimal payload fields size
Etan Cohen0bc1cab2017-05-18 15:30:41 -0700306
307 Verifies that discovery and message exchange succeeds.
308 """
309 self.positive_discovery_test_utility(
310 ptype=aconsts.PUBLISH_TYPE_UNSOLICITED,
311 stype=aconsts.SUBSCRIBE_TYPE_PASSIVE,
Etan Cohenfb7f3b12017-05-19 06:54:03 -0700312 payload_size=self.PAYLOAD_SIZE_MIN)
Etan Cohen0bc1cab2017-05-18 15:30:41 -0700313
Etan Cohenfb7f3b12017-05-19 06:54:03 -0700314 def test_positive_solicited_active_typical(self):
Etan Cohen0bc1cab2017-05-18 15:30:41 -0700315 """Functional test case / Discovery test cases / positive test case:
316 - Unsolicited publish + active subscribe
317 - Typical payload fields size
Etan Cohen0bc1cab2017-05-18 15:30:41 -0700318
319 Verifies that discovery and message exchange succeeds.
320 """
321 self.positive_discovery_test_utility(
322 ptype=aconsts.PUBLISH_TYPE_SOLICITED,
323 stype=aconsts.SUBSCRIBE_TYPE_ACTIVE,
Etan Cohenfb7f3b12017-05-19 06:54:03 -0700324 payload_size=self.PAYLOAD_SIZE_TYPICAL)
Etan Cohen0bc1cab2017-05-18 15:30:41 -0700325
Etan Cohenfb7f3b12017-05-19 06:54:03 -0700326 def test_positive_solicited_active_min(self):
Etan Cohen0bc1cab2017-05-18 15:30:41 -0700327 """Functional test case / Discovery test cases / positive test case:
328 - Unsolicited publish + active subscribe
329 - Minimal payload fields size
Etan Cohen0bc1cab2017-05-18 15:30:41 -0700330
331 Verifies that discovery and message exchange succeeds.
332 """
333 self.positive_discovery_test_utility(
334 ptype=aconsts.PUBLISH_TYPE_SOLICITED,
335 stype=aconsts.SUBSCRIBE_TYPE_ACTIVE,
Etan Cohenfb7f3b12017-05-19 06:54:03 -0700336 payload_size=self.PAYLOAD_SIZE_MIN)