1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.wifi.nan; 18 19import static org.hamcrest.core.IsEqual.equalTo; 20import static org.hamcrest.core.IsNull.nullValue; 21import static org.junit.Assert.assertTrue; 22import static org.mockito.Matchers.anyShort; 23import static org.mockito.Matchers.eq; 24import static org.mockito.Mockito.inOrder; 25import static org.mockito.Mockito.mock; 26import static org.mockito.Mockito.verifyNoMoreInteractions; 27import static org.mockito.Mockito.verifyZeroInteractions; 28 29import android.net.wifi.nan.ConfigRequest; 30import android.net.wifi.nan.IWifiNanEventListener; 31import android.net.wifi.nan.IWifiNanSessionListener; 32import android.net.wifi.nan.PublishData; 33import android.net.wifi.nan.PublishSettings; 34import android.net.wifi.nan.SubscribeData; 35import android.net.wifi.nan.SubscribeSettings; 36import android.net.wifi.nan.WifiNanEventListener; 37import android.net.wifi.nan.WifiNanSessionListener; 38import android.test.suitebuilder.annotation.SmallTest; 39import android.util.SparseArray; 40 41import com.android.server.wifi.MockLooper; 42 43import libcore.util.HexEncoding; 44 45import org.junit.Before; 46import org.junit.Rule; 47import org.junit.Test; 48import org.junit.rules.ErrorCollector; 49import org.mockito.ArgumentCaptor; 50import org.mockito.InOrder; 51import org.mockito.Mock; 52import org.mockito.MockitoAnnotations; 53 54import java.lang.reflect.Constructor; 55import java.lang.reflect.Field; 56 57/** 58 * Unit test harness for WifiNanStateManager. 59 */ 60@SmallTest 61public class WifiNanStateManagerTest { 62 private MockLooper mMockLooper; 63 private WifiNanStateManager mDut; 64 @Mock private WifiNanNative mMockNative; 65 66 @Rule 67 public ErrorCollector collector = new ErrorCollector(); 68 69 @Before 70 public void setUp() throws Exception { 71 MockitoAnnotations.initMocks(this); 72 73 mMockLooper = new MockLooper(); 74 75 mDut = installNewNanStateManagerAndResetState(); 76 mDut.start(mMockLooper.getLooper()); 77 78 installMockWifiNanNative(mMockNative); 79 } 80 81 @Test 82 public void testNanEventsDelivered() throws Exception { 83 final int uid = 1005; 84 final int clusterLow1 = 5; 85 final int clusterHigh1 = 100; 86 final int masterPref1 = 111; 87 final int clusterLow2 = 7; 88 final int clusterHigh2 = 155; 89 final int masterPref2 = 0; 90 final int reason = WifiNanSessionListener.FAIL_REASON_NO_RESOURCES; 91 final byte[] someMac = HexEncoding.decode("000102030405".toCharArray(), false); 92 93 ConfigRequest configRequest1 = new ConfigRequest.Builder().setClusterLow(clusterLow1) 94 .setClusterHigh(clusterHigh1).setMasterPreference(masterPref1).build(); 95 96 ConfigRequest configRequest2 = new ConfigRequest.Builder().setClusterLow(clusterLow2) 97 .setClusterHigh(clusterHigh2).setMasterPreference(masterPref2).build(); 98 99 IWifiNanEventListener mockListener = mock(IWifiNanEventListener.class); 100 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 101 InOrder inOrder = inOrder(mockListener, mMockNative); 102 103 mDut.connect(uid, mockListener, 104 WifiNanEventListener.LISTEN_CONFIG_COMPLETED 105 | WifiNanEventListener.LISTEN_CONFIG_FAILED 106 | WifiNanEventListener.LISTEN_IDENTITY_CHANGED 107 | WifiNanEventListener.LISTEN_NAN_DOWN); 108 mDut.requestConfig(uid, configRequest1); 109 mMockLooper.dispatchAll(); 110 111 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest1)); 112 short transactionId1 = transactionId.getValue(); 113 114 mDut.requestConfig(uid, configRequest2); 115 mMockLooper.dispatchAll(); 116 117 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest2)); 118 short transactionId2 = transactionId.getValue(); 119 120 mDut.onClusterChange(WifiNanClientState.CLUSTER_CHANGE_EVENT_STARTED, someMac); 121 mDut.onConfigCompleted(transactionId1); 122 mDut.onConfigFailed(transactionId2, reason); 123 mDut.onInterfaceAddressChange(someMac); 124 mDut.onNanDown(reason); 125 mMockLooper.dispatchAll(); 126 127 inOrder.verify(mockListener).onIdentityChanged(); 128 inOrder.verify(mockListener).onConfigCompleted(configRequest1); 129 inOrder.verify(mockListener).onConfigFailed(configRequest2, reason); 130 inOrder.verify(mockListener).onIdentityChanged(); 131 inOrder.verify(mockListener).onNanDown(reason); 132 verifyNoMoreInteractions(mockListener); 133 134 validateInternalTransactionInfoCleanedUp(transactionId1); 135 validateInternalTransactionInfoCleanedUp(transactionId2); 136 } 137 138 @Test 139 public void testNanEventsNotDelivered() throws Exception { 140 final int uid = 1005; 141 final int clusterLow1 = 5; 142 final int clusterHigh1 = 100; 143 final int masterPref1 = 111; 144 final int clusterLow2 = 7; 145 final int clusterHigh2 = 155; 146 final int masterPref2 = 0; 147 final int reason = WifiNanSessionListener.FAIL_REASON_NO_RESOURCES; 148 final byte[] someMac = HexEncoding.decode("000102030405".toCharArray(), false); 149 150 ConfigRequest configRequest1 = new ConfigRequest.Builder().setClusterLow(clusterLow1) 151 .setClusterHigh(clusterHigh1).setMasterPreference(masterPref1).build(); 152 153 ConfigRequest configRequest2 = new ConfigRequest.Builder().setClusterLow(clusterLow2) 154 .setClusterHigh(clusterHigh2).setMasterPreference(masterPref2).build(); 155 156 IWifiNanEventListener mockListener = mock(IWifiNanEventListener.class); 157 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 158 InOrder inOrder = inOrder(mockListener, mMockNative); 159 160 mDut.connect(uid, mockListener, 0); 161 mDut.requestConfig(uid, configRequest1); 162 mMockLooper.dispatchAll(); 163 164 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest1)); 165 short transactionId1 = transactionId.getValue(); 166 167 mDut.requestConfig(uid, configRequest2); 168 mMockLooper.dispatchAll(); 169 170 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest2)); 171 short transactionId2 = transactionId.getValue(); 172 173 mDut.onClusterChange(WifiNanClientState.CLUSTER_CHANGE_EVENT_JOINED, someMac); 174 mDut.onConfigCompleted(transactionId1); 175 mDut.onConfigFailed(transactionId2, reason); 176 mDut.onInterfaceAddressChange(someMac); 177 mDut.onNanDown(reason); 178 mMockLooper.dispatchAll(); 179 180 verifyZeroInteractions(mockListener); 181 182 validateInternalTransactionInfoCleanedUp(transactionId1); 183 validateInternalTransactionInfoCleanedUp(transactionId2); 184 } 185 186 @Test 187 public void testPublish() throws Exception { 188 final int uid = 1005; 189 final int sessionId = 20; 190 final String serviceName = "some-service-name"; 191 final String ssi = "some much longer and more arbitrary data"; 192 final int publishCount = 7; 193 final int reasonFail = WifiNanSessionListener.FAIL_REASON_NO_RESOURCES; 194 final int reasonTerminate = WifiNanSessionListener.TERMINATE_REASON_DONE; 195 final int publishId1 = 15; 196 final int publishId2 = 22; 197 198 PublishData publishData = new PublishData.Builder().setServiceName(serviceName) 199 .setServiceSpecificInfo(ssi).build(); 200 201 PublishSettings publishSettings = new PublishSettings.Builder() 202 .setPublishType(PublishSettings.PUBLISH_TYPE_UNSOLICITED) 203 .setPublishCount(publishCount).build(); 204 205 IWifiNanSessionListener mockListener = mock(IWifiNanSessionListener.class); 206 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 207 InOrder inOrder = inOrder(mockListener, mMockNative); 208 209 int allEvents = WifiNanSessionListener.LISTEN_PUBLISH_FAIL 210 | WifiNanSessionListener.LISTEN_PUBLISH_TERMINATED 211 | WifiNanSessionListener.LISTEN_SUBSCRIBE_FAIL 212 | WifiNanSessionListener.LISTEN_SUBSCRIBE_TERMINATED 213 | WifiNanSessionListener.LISTEN_MATCH 214 | WifiNanSessionListener.LISTEN_MESSAGE_SEND_SUCCESS 215 | WifiNanSessionListener.LISTEN_MESSAGE_SEND_FAIL 216 | WifiNanSessionListener.LISTEN_MESSAGE_RECEIVED; 217 218 mDut.connect(uid, null, 0); 219 mDut.createSession(uid, sessionId, mockListener, allEvents); 220 221 // publish - fail 222 mDut.publish(uid, sessionId, publishData, publishSettings); 223 mMockLooper.dispatchAll(); 224 225 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishData), 226 eq(publishSettings)); 227 228 mDut.onPublishFail(transactionId.getValue(), reasonFail); 229 mMockLooper.dispatchAll(); 230 231 inOrder.verify(mockListener).onPublishFail(reasonFail); 232 validateInternalTransactionInfoCleanedUp(transactionId.getValue()); 233 234 // publish - success/terminate 235 mDut.publish(uid, sessionId, publishData, publishSettings); 236 mMockLooper.dispatchAll(); 237 238 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishData), 239 eq(publishSettings)); 240 241 mDut.onPublishSuccess(transactionId.getValue(), publishId1); 242 mMockLooper.dispatchAll(); 243 244 mDut.onPublishTerminated(publishId1, reasonTerminate); 245 mMockLooper.dispatchAll(); 246 247 inOrder.verify(mockListener).onPublishTerminated(reasonTerminate); 248 validateInternalTransactionInfoCleanedUp(transactionId.getValue()); 249 250 // re-publish 251 mDut.publish(uid, sessionId, publishData, publishSettings); 252 mMockLooper.dispatchAll(); 253 254 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishData), 255 eq(publishSettings)); 256 257 mDut.onPublishSuccess(transactionId.getValue(), publishId2); 258 mDut.publish(uid, sessionId, publishData, publishSettings); 259 mMockLooper.dispatchAll(); 260 261 validateInternalTransactionInfoCleanedUp(transactionId.getValue()); 262 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(publishId2), 263 eq(publishData), eq(publishSettings)); 264 verifyNoMoreInteractions(mockListener, mMockNative); 265 } 266 267 @Test 268 public void testPublishNoCallbacks() throws Exception { 269 final int uid = 1005; 270 final int sessionId = 20; 271 final String serviceName = "some-service-name"; 272 final String ssi = "some much longer and more arbitrary data"; 273 final int publishCount = 7; 274 final int reasonFail = WifiNanSessionListener.FAIL_REASON_NO_RESOURCES; 275 final int reasonTerminate = WifiNanSessionListener.TERMINATE_REASON_DONE; 276 final int publishId = 15; 277 278 PublishData publishData = new PublishData.Builder().setServiceName(serviceName) 279 .setServiceSpecificInfo(ssi).build(); 280 281 PublishSettings publishSettings = new PublishSettings.Builder() 282 .setPublishType(PublishSettings.PUBLISH_TYPE_UNSOLICITED) 283 .setPublishCount(publishCount).build(); 284 285 IWifiNanSessionListener mockListener = mock(IWifiNanSessionListener.class); 286 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 287 InOrder inOrder = inOrder(mockListener, mMockNative); 288 289 int allEvents = WifiNanSessionListener.LISTEN_PUBLISH_FAIL 290 | WifiNanSessionListener.LISTEN_PUBLISH_TERMINATED 291 | WifiNanSessionListener.LISTEN_SUBSCRIBE_FAIL 292 | WifiNanSessionListener.LISTEN_SUBSCRIBE_TERMINATED 293 | WifiNanSessionListener.LISTEN_MATCH 294 | WifiNanSessionListener.LISTEN_MESSAGE_SEND_SUCCESS 295 | WifiNanSessionListener.LISTEN_MESSAGE_SEND_FAIL 296 | WifiNanSessionListener.LISTEN_MESSAGE_RECEIVED; 297 298 mDut.connect(uid, null, 0); 299 mDut.createSession(uid, sessionId, mockListener, 300 allEvents & ~WifiNanSessionListener.LISTEN_PUBLISH_FAIL 301 & ~WifiNanSessionListener.LISTEN_PUBLISH_TERMINATED); 302 303 // publish - fail 304 mDut.publish(uid, sessionId, publishData, publishSettings); 305 mMockLooper.dispatchAll(); 306 307 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishData), 308 eq(publishSettings)); 309 310 mDut.onPublishFail(transactionId.getValue(), reasonFail); 311 mMockLooper.dispatchAll(); 312 313 validateInternalTransactionInfoCleanedUp(transactionId.getValue()); 314 315 // publish - success/terminate 316 mDut.publish(uid, sessionId, publishData, publishSettings); 317 mMockLooper.dispatchAll(); 318 319 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishData), 320 eq(publishSettings)); 321 322 mDut.onPublishSuccess(transactionId.getValue(), publishId); 323 mMockLooper.dispatchAll(); 324 325 mDut.onPublishTerminated(publishId, reasonTerminate); 326 mMockLooper.dispatchAll(); 327 328 validateInternalTransactionInfoCleanedUp(transactionId.getValue()); 329 verifyNoMoreInteractions(mockListener, mMockNative); 330 } 331 332 @Test 333 public void testSubscribe() throws Exception { 334 final int uid = 1005; 335 final int sessionId = 20; 336 final String serviceName = "some-service-name"; 337 final String ssi = "some much longer and more arbitrary data"; 338 final int subscribeCount = 7; 339 final int reasonFail = WifiNanSessionListener.FAIL_REASON_NO_RESOURCES; 340 final int reasonTerminate = WifiNanSessionListener.TERMINATE_REASON_DONE; 341 final int subscribeId1 = 15; 342 final int subscribeId2 = 10; 343 344 SubscribeData subscribeData = new SubscribeData.Builder().setServiceName(serviceName) 345 .setServiceSpecificInfo(ssi).build(); 346 347 SubscribeSettings subscribeSettings = new SubscribeSettings.Builder() 348 .setSubscribeType(SubscribeSettings.SUBSCRIBE_TYPE_PASSIVE) 349 .setSubscribeCount(subscribeCount).build(); 350 351 IWifiNanSessionListener mockListener = mock(IWifiNanSessionListener.class); 352 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 353 InOrder inOrder = inOrder(mockListener, mMockNative); 354 355 int allEvents = WifiNanSessionListener.LISTEN_PUBLISH_FAIL 356 | WifiNanSessionListener.LISTEN_PUBLISH_TERMINATED 357 | WifiNanSessionListener.LISTEN_SUBSCRIBE_FAIL 358 | WifiNanSessionListener.LISTEN_SUBSCRIBE_TERMINATED 359 | WifiNanSessionListener.LISTEN_MATCH 360 | WifiNanSessionListener.LISTEN_MESSAGE_SEND_SUCCESS 361 | WifiNanSessionListener.LISTEN_MESSAGE_SEND_FAIL 362 | WifiNanSessionListener.LISTEN_MESSAGE_RECEIVED; 363 364 mDut.connect(uid, null, 0); 365 mDut.createSession(uid, sessionId, mockListener, allEvents); 366 367 // subscribe - fail 368 mDut.subscribe(uid, sessionId, subscribeData, subscribeSettings); 369 mMockLooper.dispatchAll(); 370 371 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeData), 372 eq(subscribeSettings)); 373 374 mDut.onSubscribeFail(transactionId.getValue(), reasonFail); 375 mMockLooper.dispatchAll(); 376 377 validateInternalTransactionInfoCleanedUp(transactionId.getValue()); 378 inOrder.verify(mockListener).onSubscribeFail(reasonFail); 379 380 // subscribe - success/terminate 381 mDut.subscribe(uid, sessionId, subscribeData, subscribeSettings); 382 mMockLooper.dispatchAll(); 383 384 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeData), 385 eq(subscribeSettings)); 386 387 mDut.onSubscribeSuccess(transactionId.getValue(), subscribeId1); 388 mMockLooper.dispatchAll(); 389 390 mDut.onSubscribeTerminated(subscribeId1, reasonTerminate); 391 mMockLooper.dispatchAll(); 392 393 validateInternalTransactionInfoCleanedUp(transactionId.getValue()); 394 inOrder.verify(mockListener).onSubscribeTerminated(reasonTerminate); 395 396 // re-subscribe 397 mDut.subscribe(uid, sessionId, subscribeData, subscribeSettings); 398 mMockLooper.dispatchAll(); 399 400 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeData), 401 eq(subscribeSettings)); 402 403 mDut.onSubscribeSuccess(transactionId.getValue(), subscribeId2); 404 mDut.subscribe(uid, sessionId, subscribeData, subscribeSettings); 405 mMockLooper.dispatchAll(); 406 407 validateInternalTransactionInfoCleanedUp(transactionId.getValue()); 408 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(subscribeId2), 409 eq(subscribeData), eq(subscribeSettings)); 410 verifyNoMoreInteractions(mockListener, mMockNative); 411 } 412 413 @Test 414 public void testSubscribeNoCallbacks() throws Exception { 415 final int uid = 1005; 416 final int sessionId = 20; 417 final String serviceName = "some-service-name"; 418 final String ssi = "some much longer and more arbitrary data"; 419 final int subscribeCount = 7; 420 final int reasonFail = WifiNanSessionListener.FAIL_REASON_NO_RESOURCES; 421 final int reasonTerminate = WifiNanSessionListener.TERMINATE_REASON_DONE; 422 final int subscribeId = 15; 423 424 SubscribeData subscribeData = new SubscribeData.Builder().setServiceName(serviceName) 425 .setServiceSpecificInfo(ssi).build(); 426 427 SubscribeSettings subscribeSettings = new SubscribeSettings.Builder() 428 .setSubscribeType(SubscribeSettings.SUBSCRIBE_TYPE_PASSIVE) 429 .setSubscribeCount(subscribeCount).build(); 430 431 IWifiNanSessionListener mockListener = mock(IWifiNanSessionListener.class); 432 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 433 InOrder inOrder = inOrder(mockListener, mMockNative); 434 435 int allEvents = WifiNanSessionListener.LISTEN_PUBLISH_FAIL 436 | WifiNanSessionListener.LISTEN_PUBLISH_TERMINATED 437 | WifiNanSessionListener.LISTEN_SUBSCRIBE_FAIL 438 | WifiNanSessionListener.LISTEN_SUBSCRIBE_TERMINATED 439 | WifiNanSessionListener.LISTEN_MATCH 440 | WifiNanSessionListener.LISTEN_MESSAGE_SEND_SUCCESS 441 | WifiNanSessionListener.LISTEN_MESSAGE_SEND_FAIL 442 | WifiNanSessionListener.LISTEN_MESSAGE_RECEIVED; 443 444 mDut.connect(uid, null, 0); 445 mDut.createSession(uid, sessionId, mockListener, 446 allEvents & ~WifiNanSessionListener.LISTEN_SUBSCRIBE_FAIL 447 & ~WifiNanSessionListener.LISTEN_SUBSCRIBE_TERMINATED); 448 449 // subscribe - fail 450 mDut.subscribe(uid, sessionId, subscribeData, subscribeSettings); 451 mMockLooper.dispatchAll(); 452 453 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeData), 454 eq(subscribeSettings)); 455 456 mDut.onSubscribeFail(transactionId.getValue(), reasonFail); 457 mMockLooper.dispatchAll(); 458 459 validateInternalTransactionInfoCleanedUp(transactionId.getValue()); 460 461 // subscribe - success/terminate 462 mDut.subscribe(uid, sessionId, subscribeData, subscribeSettings); 463 mMockLooper.dispatchAll(); 464 465 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeData), 466 eq(subscribeSettings)); 467 468 mDut.onSubscribeSuccess(transactionId.getValue(), subscribeId); 469 mMockLooper.dispatchAll(); 470 471 mDut.onSubscribeTerminated(subscribeId, reasonTerminate); 472 mMockLooper.dispatchAll(); 473 474 validateInternalTransactionInfoCleanedUp(transactionId.getValue()); 475 verifyNoMoreInteractions(mockListener, mMockNative); 476 } 477 478 @Test 479 public void testMatchAndMessages() throws Exception { 480 final int uid = 1005; 481 final int sessionId = 20; 482 final String serviceName = "some-service-name"; 483 final String ssi = "some much longer and more arbitrary data"; 484 final int subscribeCount = 7; 485 final int reasonFail = WifiNanSessionListener.FAIL_REASON_NO_RESOURCES; 486 final int subscribeId = 15; 487 final int requestorId = 22; 488 final byte[] peerMac = HexEncoding.decode("060708090A0B".toCharArray(), false); 489 final String peerSsi = "some peer ssi data"; 490 final String peerMatchFilter = "filter binary array represented as string"; 491 final String peerMsg = "some message from peer"; 492 final int messageId = 6948; 493 494 SubscribeData subscribeData = new SubscribeData.Builder().setServiceName(serviceName) 495 .setServiceSpecificInfo(ssi).build(); 496 497 SubscribeSettings subscribeSettings = new SubscribeSettings.Builder() 498 .setSubscribeType(SubscribeSettings.SUBSCRIBE_TYPE_PASSIVE) 499 .setSubscribeCount(subscribeCount).build(); 500 501 IWifiNanSessionListener mockListener = mock(IWifiNanSessionListener.class); 502 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 503 InOrder inOrder = inOrder(mockListener, mMockNative); 504 505 int allEvents = WifiNanSessionListener.LISTEN_PUBLISH_FAIL 506 | WifiNanSessionListener.LISTEN_PUBLISH_TERMINATED 507 | WifiNanSessionListener.LISTEN_SUBSCRIBE_FAIL 508 | WifiNanSessionListener.LISTEN_SUBSCRIBE_TERMINATED 509 | WifiNanSessionListener.LISTEN_MATCH 510 | WifiNanSessionListener.LISTEN_MESSAGE_SEND_SUCCESS 511 | WifiNanSessionListener.LISTEN_MESSAGE_SEND_FAIL 512 | WifiNanSessionListener.LISTEN_MESSAGE_RECEIVED; 513 514 mDut.connect(uid, null, 0); 515 mDut.createSession(uid, sessionId, mockListener, allEvents); 516 mDut.subscribe(uid, sessionId, subscribeData, subscribeSettings); 517 mMockLooper.dispatchAll(); 518 519 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeData), 520 eq(subscribeSettings)); 521 522 mDut.onSubscribeSuccess(transactionId.getValue(), subscribeId); 523 mDut.onMatch(subscribeId, requestorId, peerMac, peerSsi.getBytes(), peerSsi.length(), 524 peerMatchFilter.getBytes(), peerMatchFilter.length()); 525 mDut.onMessageReceived(subscribeId, requestorId, peerMac, peerMsg.getBytes(), 526 peerMsg.length()); 527 mMockLooper.dispatchAll(); 528 529 validateInternalTransactionInfoCleanedUp(transactionId.getValue()); 530 inOrder.verify(mockListener).onMatch(requestorId, peerSsi.getBytes(), peerSsi.length(), 531 peerMatchFilter.getBytes(), peerMatchFilter.length()); 532 inOrder.verify(mockListener).onMessageReceived(requestorId, peerMsg.getBytes(), 533 peerMsg.length()); 534 535 mDut.sendMessage(uid, sessionId, requestorId, ssi.getBytes(), ssi.length(), messageId); 536 mMockLooper.dispatchAll(); 537 538 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 539 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(ssi.length())); 540 541 mDut.onMessageSendFail(transactionId.getValue(), reasonFail); 542 mMockLooper.dispatchAll(); 543 544 validateInternalTransactionInfoCleanedUp(transactionId.getValue()); 545 inOrder.verify(mockListener).onMessageSendFail(messageId, reasonFail); 546 547 mDut.sendMessage(uid, sessionId, requestorId, ssi.getBytes(), ssi.length(), messageId); 548 mMockLooper.dispatchAll(); 549 550 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(subscribeId), 551 eq(requestorId), eq(peerMac), eq(ssi.getBytes()), eq(ssi.length())); 552 553 mDut.onMessageSendSuccess(transactionId.getValue()); 554 mMockLooper.dispatchAll(); 555 556 validateInternalTransactionInfoCleanedUp(transactionId.getValue()); 557 inOrder.verify(mockListener).onMessageSendSuccess(messageId); 558 559 verifyNoMoreInteractions(mockListener, mMockNative); 560 } 561 562 /** 563 * Summary: in a single publish session interact with multiple peers 564 * (different MAC addresses). 565 */ 566 @Test 567 public void testMultipleMessageSources() throws Exception { 568 final int uid = 300; 569 final int clusterLow = 7; 570 final int clusterHigh = 7; 571 final int masterPref = 0; 572 final int sessionId = 26; 573 final String serviceName = "some-service-name"; 574 final int publishId = 88; 575 final int peerId1 = 568; 576 final int peerId2 = 873; 577 final byte[] peerMac1 = HexEncoding.decode("000102030405".toCharArray(), false); 578 final byte[] peerMac2 = HexEncoding.decode("060708090A0B".toCharArray(), false); 579 final String msgFromPeer1 = "hey from 000102..."; 580 final String msgFromPeer2 = "hey from 0607..."; 581 final String msgToPeer1 = "hey there 000102..."; 582 final String msgToPeer2 = "hey there 0506..."; 583 final int msgToPeerId1 = 546; 584 final int msgToPeerId2 = 9654; 585 final int reason = WifiNanSessionListener.FAIL_REASON_OTHER; 586 587 ConfigRequest configRequest = new ConfigRequest.Builder().setClusterLow(clusterLow) 588 .setClusterHigh(clusterHigh).setMasterPreference(masterPref).build(); 589 590 PublishData publishData = new PublishData.Builder().setServiceName(serviceName).build(); 591 592 PublishSettings publishSettings = new PublishSettings.Builder() 593 .setPublishType(PublishSettings.PUBLISH_TYPE_UNSOLICITED).build(); 594 595 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 596 IWifiNanEventListener mockListener = mock(IWifiNanEventListener.class); 597 IWifiNanSessionListener mockSessionListener = mock(IWifiNanSessionListener.class); 598 InOrder inOrder = inOrder(mMockNative, mockListener, mockSessionListener); 599 600 int allEvents = WifiNanEventListener.LISTEN_CONFIG_COMPLETED 601 | WifiNanEventListener.LISTEN_CONFIG_FAILED 602 | WifiNanEventListener.LISTEN_IDENTITY_CHANGED 603 | WifiNanEventListener.LISTEN_NAN_DOWN; 604 605 int allSessionEvents = WifiNanSessionListener.LISTEN_PUBLISH_FAIL 606 | WifiNanSessionListener.LISTEN_PUBLISH_TERMINATED 607 | WifiNanSessionListener.LISTEN_SUBSCRIBE_FAIL 608 | WifiNanSessionListener.LISTEN_SUBSCRIBE_TERMINATED 609 | WifiNanSessionListener.LISTEN_MATCH 610 | WifiNanSessionListener.LISTEN_MESSAGE_SEND_SUCCESS 611 | WifiNanSessionListener.LISTEN_MESSAGE_SEND_FAIL 612 | WifiNanSessionListener.LISTEN_MESSAGE_RECEIVED; 613 614 mDut.connect(uid, mockListener, allEvents); 615 mDut.requestConfig(uid, configRequest); 616 mDut.createSession(uid, sessionId, mockSessionListener, allSessionEvents); 617 mDut.publish(uid, sessionId, publishData, publishSettings); 618 mMockLooper.dispatchAll(); 619 620 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest)); 621 short transactionIdConfig = transactionId.getValue(); 622 623 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishData), 624 eq(publishSettings)); 625 short transactionIdPublish = transactionId.getValue(); 626 627 mDut.onConfigCompleted(transactionIdConfig); 628 mDut.onPublishSuccess(transactionIdPublish, publishId); 629 mDut.onMessageReceived(publishId, peerId1, peerMac1, msgFromPeer1.getBytes(), 630 msgFromPeer1.length()); 631 mDut.onMessageReceived(publishId, peerId2, peerMac2, msgFromPeer2.getBytes(), 632 msgFromPeer2.length()); 633 mDut.sendMessage(uid, sessionId, peerId2, msgToPeer2.getBytes(), msgToPeer2.length(), 634 msgToPeerId2); 635 mDut.sendMessage(uid, sessionId, peerId1, msgToPeer1.getBytes(), msgToPeer1.length(), 636 msgToPeerId1); 637 mMockLooper.dispatchAll(); 638 639 validateInternalTransactionInfoCleanedUp(transactionIdConfig); 640 validateInternalTransactionInfoCleanedUp(transactionIdPublish); 641 inOrder.verify(mockListener).onConfigCompleted(configRequest); 642 inOrder.verify(mockSessionListener).onMessageReceived(peerId1, msgFromPeer1.getBytes(), 643 msgFromPeer1.length()); 644 inOrder.verify(mockSessionListener).onMessageReceived(peerId2, msgFromPeer2.getBytes(), 645 msgFromPeer2.length()); 646 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(publishId), eq(peerId2), 647 eq(peerMac2), eq(msgToPeer2.getBytes()), eq(msgToPeer2.length())); 648 short transactionIdMsg2 = transactionId.getValue(); 649 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(publishId), eq(peerId1), 650 eq(peerMac1), eq(msgToPeer1.getBytes()), eq(msgToPeer1.length())); 651 short transactionIdMsg1 = transactionId.getValue(); 652 653 mDut.onMessageSendFail(transactionIdMsg1, reason); 654 mDut.onMessageSendSuccess(transactionIdMsg2); 655 mMockLooper.dispatchAll(); 656 657 validateInternalTransactionInfoCleanedUp(transactionIdMsg1); 658 validateInternalTransactionInfoCleanedUp(transactionIdMsg2); 659 inOrder.verify(mockSessionListener).onMessageSendFail(msgToPeerId1, reason); 660 inOrder.verify(mockSessionListener).onMessageSendSuccess(msgToPeerId2); 661 verifyNoMoreInteractions(mMockNative, mockListener, mockSessionListener); 662 } 663 664 /** 665 * Summary: interact with a peer which changed its identity (MAC address) 666 * but which keeps its requestor instance ID. Should be transparent. 667 */ 668 @Test 669 public void testMessageWhilePeerChangesIdentity() throws Exception { 670 final int uid = 300; 671 final int clusterLow = 7; 672 final int clusterHigh = 7; 673 final int masterPref = 0; 674 final int sessionId = 26; 675 final String serviceName = "some-service-name"; 676 final int publishId = 88; 677 final int peerId = 568; 678 final byte[] peerMacOrig = HexEncoding.decode("000102030405".toCharArray(), false); 679 final byte[] peerMacLater = HexEncoding.decode("060708090A0B".toCharArray(), false); 680 final String msgFromPeer1 = "hey from 000102..."; 681 final String msgFromPeer2 = "hey from 0607..."; 682 final String msgToPeer1 = "hey there 000102..."; 683 final String msgToPeer2 = "hey there 0506..."; 684 final int msgToPeerId1 = 546; 685 final int msgToPeerId2 = 9654; 686 ConfigRequest configRequest = new ConfigRequest.Builder().setClusterLow(clusterLow) 687 .setClusterHigh(clusterHigh).setMasterPreference(masterPref).build(); 688 689 PublishData publishData = new PublishData.Builder().setServiceName(serviceName).build(); 690 691 PublishSettings publishSettings = new PublishSettings.Builder() 692 .setPublishType(PublishSettings.PUBLISH_TYPE_UNSOLICITED).build(); 693 694 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 695 IWifiNanEventListener mockListener = mock(IWifiNanEventListener.class); 696 IWifiNanSessionListener mockSessionListener = mock(IWifiNanSessionListener.class); 697 InOrder inOrder = inOrder(mMockNative, mockListener, mockSessionListener); 698 699 int allEvents = WifiNanEventListener.LISTEN_CONFIG_COMPLETED 700 | WifiNanEventListener.LISTEN_CONFIG_FAILED 701 | WifiNanEventListener.LISTEN_IDENTITY_CHANGED 702 | WifiNanEventListener.LISTEN_NAN_DOWN; 703 704 int allSessionEvents = WifiNanSessionListener.LISTEN_PUBLISH_FAIL 705 | WifiNanSessionListener.LISTEN_PUBLISH_TERMINATED 706 | WifiNanSessionListener.LISTEN_SUBSCRIBE_FAIL 707 | WifiNanSessionListener.LISTEN_SUBSCRIBE_TERMINATED 708 | WifiNanSessionListener.LISTEN_MATCH 709 | WifiNanSessionListener.LISTEN_MESSAGE_SEND_SUCCESS 710 | WifiNanSessionListener.LISTEN_MESSAGE_SEND_FAIL 711 | WifiNanSessionListener.LISTEN_MESSAGE_RECEIVED; 712 713 mDut.connect(uid, mockListener, allEvents); 714 mDut.requestConfig(uid, configRequest); 715 mDut.createSession(uid, sessionId, mockSessionListener, allSessionEvents); 716 mDut.publish(uid, sessionId, publishData, publishSettings); 717 mMockLooper.dispatchAll(); 718 719 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest)); 720 short transactionIdConfig = transactionId.getValue(); 721 722 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishData), 723 eq(publishSettings)); 724 short transactionIdPublish = transactionId.getValue(); 725 726 mDut.onConfigCompleted(transactionIdConfig); 727 mDut.onPublishSuccess(transactionIdPublish, publishId); 728 mDut.onMessageReceived(publishId, peerId, peerMacOrig, msgFromPeer1.getBytes(), 729 msgFromPeer1.length()); 730 mDut.sendMessage(uid, sessionId, peerId, msgToPeer1.getBytes(), msgToPeer1.length(), 731 msgToPeerId1); 732 mMockLooper.dispatchAll(); 733 734 validateInternalTransactionInfoCleanedUp(transactionIdConfig); 735 validateInternalTransactionInfoCleanedUp(transactionIdPublish); 736 inOrder.verify(mockListener).onConfigCompleted(configRequest); 737 inOrder.verify(mockSessionListener).onMessageReceived(peerId, msgFromPeer1.getBytes(), 738 msgFromPeer1.length()); 739 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(publishId), eq(peerId), 740 eq(peerMacOrig), eq(msgToPeer1.getBytes()), eq(msgToPeer1.length())); 741 short transactionIdMsg = transactionId.getValue(); 742 743 mDut.onMessageSendSuccess(transactionIdMsg); 744 mDut.onMessageReceived(publishId, peerId, peerMacLater, msgFromPeer2.getBytes(), 745 msgFromPeer2.length()); 746 mDut.sendMessage(uid, sessionId, peerId, msgToPeer2.getBytes(), msgToPeer2.length(), 747 msgToPeerId2); 748 mMockLooper.dispatchAll(); 749 750 validateInternalTransactionInfoCleanedUp(transactionIdMsg); 751 inOrder.verify(mockSessionListener).onMessageSendSuccess(msgToPeerId1); 752 inOrder.verify(mockSessionListener).onMessageReceived(peerId, msgFromPeer2.getBytes(), 753 msgFromPeer2.length()); 754 inOrder.verify(mMockNative).sendMessage(transactionId.capture(), eq(publishId), eq(peerId), 755 eq(peerMacLater), eq(msgToPeer2.getBytes()), eq(msgToPeer2.length())); 756 transactionIdMsg = transactionId.getValue(); 757 758 mDut.onMessageSendSuccess(transactionIdMsg); 759 mMockLooper.dispatchAll(); 760 761 validateInternalTransactionInfoCleanedUp(transactionIdMsg); 762 inOrder.verify(mockSessionListener).onMessageSendSuccess(msgToPeerId2); 763 764 verifyNoMoreInteractions(mMockNative, mockListener, mockSessionListener); 765 } 766 767 @Test 768 public void testConfigs() throws Exception { 769 final int uid1 = 9999; 770 final int clusterLow1 = 5; 771 final int clusterHigh1 = 100; 772 final int masterPref1 = 111; 773 final int uid2 = 1001; 774 final boolean support5g2 = true; 775 final int clusterLow2 = 7; 776 final int clusterHigh2 = 155; 777 final int masterPref2 = 0; 778 final int uid3 = 55; 779 780 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 781 ArgumentCaptor<ConfigRequest> crCapture = ArgumentCaptor.forClass(ConfigRequest.class); 782 783 ConfigRequest configRequest1 = new ConfigRequest.Builder().setClusterLow(clusterLow1) 784 .setClusterHigh(clusterHigh1).setMasterPreference(masterPref1).build(); 785 786 ConfigRequest configRequest2 = new ConfigRequest.Builder().setSupport5gBand(support5g2) 787 .setClusterLow(clusterLow2).setClusterHigh(clusterHigh2) 788 .setMasterPreference(masterPref2).build(); 789 790 ConfigRequest configRequest3 = new ConfigRequest.Builder().build(); 791 792 IWifiNanEventListener mockListener1 = mock(IWifiNanEventListener.class); 793 IWifiNanEventListener mockListener2 = mock(IWifiNanEventListener.class); 794 IWifiNanEventListener mockListener3 = mock(IWifiNanEventListener.class); 795 796 InOrder inOrder = inOrder(mMockNative, mockListener1, mockListener2, mockListener3); 797 798 mDut.connect(uid1, mockListener1, WifiNanEventListener.LISTEN_CONFIG_COMPLETED); 799 mDut.requestConfig(uid1, configRequest1); 800 mMockLooper.dispatchAll(); 801 802 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 803 crCapture.capture()); 804 collector.checkThat("merge: stage 0", configRequest1, equalTo(crCapture.getValue())); 805 806 mDut.onConfigCompleted(transactionId.getValue()); 807 mMockLooper.dispatchAll(); 808 809 validateInternalTransactionInfoCleanedUp(transactionId.getValue()); 810 inOrder.verify(mockListener1).onConfigCompleted(configRequest1); 811 812 mDut.connect(uid2, mockListener2, WifiNanEventListener.LISTEN_CONFIG_COMPLETED); 813 mDut.requestConfig(uid2, configRequest2); 814 mMockLooper.dispatchAll(); 815 816 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 817 crCapture.capture()); 818 collector.checkThat("merge: stage 1: support 5g", crCapture.getValue().mSupport5gBand, 819 equalTo(true)); 820 collector.checkThat("merge: stage 1: master pref", crCapture.getValue().mMasterPreference, 821 equalTo(Math.max(masterPref1, masterPref2))); 822 collector.checkThat("merge: stage 1: cluster low", crCapture.getValue().mClusterLow, 823 equalTo(Math.min(clusterLow1, clusterLow2))); 824 collector.checkThat("merge: stage 1: cluster high", crCapture.getValue().mClusterHigh, 825 equalTo(Math.max(clusterHigh1, clusterHigh2))); 826 827 mDut.onConfigCompleted(transactionId.getValue()); 828 mMockLooper.dispatchAll(); 829 830 validateInternalTransactionInfoCleanedUp(transactionId.getValue()); 831 inOrder.verify(mockListener1).onConfigCompleted(crCapture.getValue()); 832 833 mDut.connect(uid3, mockListener3, WifiNanEventListener.LISTEN_CONFIG_COMPLETED); 834 mDut.requestConfig(uid3, configRequest3); 835 mMockLooper.dispatchAll(); 836 837 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 838 crCapture.capture()); 839 collector.checkThat("merge: stage 2: support 5g", crCapture.getValue().mSupport5gBand, 840 equalTo(true)); 841 collector.checkThat("merge: stage 2: master pref", crCapture.getValue().mMasterPreference, 842 equalTo(Math.max(masterPref1, masterPref2))); 843 collector.checkThat("merge: stage 2: cluster low", crCapture.getValue().mClusterLow, 844 equalTo(Math.min(clusterLow1, clusterLow2))); 845 collector.checkThat("merge: stage 2: cluster high", crCapture.getValue().mClusterHigh, 846 equalTo(Math.max(clusterHigh1, clusterHigh2))); 847 848 mDut.onConfigCompleted(transactionId.getValue()); 849 mMockLooper.dispatchAll(); 850 851 validateInternalTransactionInfoCleanedUp(transactionId.getValue()); 852 inOrder.verify(mockListener1).onConfigCompleted(crCapture.getValue()); 853 854 mDut.disconnect(uid2); 855 mMockLooper.dispatchAll(); 856 857 validateInternalClientInfoCleanedUp(uid2); 858 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 859 crCapture.capture()); 860 collector.checkThat("merge: stage 3", configRequest1, equalTo(crCapture.getValue())); 861 862 mDut.onConfigCompleted(transactionId.getValue()); 863 mMockLooper.dispatchAll(); 864 865 validateInternalTransactionInfoCleanedUp(transactionId.getValue()); 866 inOrder.verify(mockListener1).onConfigCompleted(crCapture.getValue()); 867 868 mDut.disconnect(uid1); 869 mMockLooper.dispatchAll(); 870 871 validateInternalClientInfoCleanedUp(uid2); 872 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), 873 crCapture.capture()); 874 collector.checkThat("merge: stage 4", configRequest3, equalTo(crCapture.getValue())); 875 876 mDut.onConfigCompleted(transactionId.getValue()); 877 mMockLooper.dispatchAll(); 878 879 validateInternalTransactionInfoCleanedUp(transactionId.getValue()); 880 inOrder.verify(mockListener3).onConfigCompleted(crCapture.getValue()); 881 882 mDut.disconnect(uid3); 883 mMockLooper.dispatchAll(); 884 885 validateInternalClientInfoCleanedUp(uid2); 886 inOrder.verify(mMockNative).disable(anyShort()); 887 888 verifyNoMoreInteractions(mMockNative); 889 } 890 891 /** 892 * Summary: disconnect a client while there are pending transactions. 893 * Validate that no callbacks are called and that internal state is 894 * cleaned-up. 895 */ 896 @Test 897 public void testDisconnectWithPendingTransactions() throws Exception { 898 final int uid = 125; 899 final int clusterLow = 5; 900 final int clusterHigh = 100; 901 final int masterPref = 111; 902 final int sessionId = 20; 903 final String serviceName = "some-service-name"; 904 final String ssi = "some much longer and more arbitrary data"; 905 final int publishCount = 7; 906 final int reason = WifiNanSessionListener.TERMINATE_REASON_DONE; 907 final int publishId = 22; 908 909 ConfigRequest configRequest = new ConfigRequest.Builder().setClusterLow(clusterLow) 910 .setClusterHigh(clusterHigh).setMasterPreference(masterPref).build(); 911 912 PublishData publishData = new PublishData.Builder().setServiceName(serviceName) 913 .setServiceSpecificInfo(ssi).build(); 914 915 PublishSettings publishSettings = new PublishSettings.Builder() 916 .setPublishType(PublishSettings.PUBLISH_TYPE_UNSOLICITED) 917 .setPublishCount(publishCount).build(); 918 919 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 920 IWifiNanEventListener mockListener = mock(IWifiNanEventListener.class); 921 IWifiNanSessionListener mockSessionListener = mock(IWifiNanSessionListener.class); 922 InOrder inOrder = inOrder(mMockNative, mockListener, mockSessionListener); 923 924 int allEvents = WifiNanEventListener.LISTEN_CONFIG_COMPLETED 925 | WifiNanEventListener.LISTEN_CONFIG_FAILED 926 | WifiNanEventListener.LISTEN_IDENTITY_CHANGED 927 | WifiNanEventListener.LISTEN_NAN_DOWN; 928 929 int allSessionEvents = WifiNanSessionListener.LISTEN_PUBLISH_FAIL 930 | WifiNanSessionListener.LISTEN_PUBLISH_TERMINATED 931 | WifiNanSessionListener.LISTEN_SUBSCRIBE_FAIL 932 | WifiNanSessionListener.LISTEN_SUBSCRIBE_TERMINATED 933 | WifiNanSessionListener.LISTEN_MATCH 934 | WifiNanSessionListener.LISTEN_MESSAGE_SEND_SUCCESS 935 | WifiNanSessionListener.LISTEN_MESSAGE_SEND_FAIL 936 | WifiNanSessionListener.LISTEN_MESSAGE_RECEIVED; 937 938 mDut.connect(uid, mockListener, allEvents); 939 mDut.createSession(uid, sessionId, mockSessionListener, allSessionEvents); 940 mDut.requestConfig(uid, configRequest); 941 mDut.publish(uid, sessionId, publishData, publishSettings); 942 mDut.disconnect(uid); 943 mMockLooper.dispatchAll(); 944 945 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest)); 946 short transactionIdConfig = transactionId.getValue(); 947 948 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishData), 949 eq(publishSettings)); 950 short transactionIdPublish = transactionId.getValue(); 951 952 validateInternalClientInfoCleanedUp(uid); 953 validateInternalTransactionInfoCleanedUp(transactionIdPublish); 954 955 mDut.onConfigCompleted(transactionIdConfig); 956 mDut.onPublishSuccess(transactionIdPublish, publishId); 957 mMockLooper.dispatchAll(); 958 959 mDut.onPublishTerminated(publishId, reason); 960 mMockLooper.dispatchAll(); 961 962 verifyZeroInteractions(mockListener, mockSessionListener); 963 } 964 965 /** 966 * Summary: destroy a session while there are pending transactions. Validate 967 * that no callbacks are called and that internal state is cleaned-up. 968 */ 969 @Test 970 public void testDestroySessionWithPendingTransactions() throws Exception { 971 final int uid = 128; 972 final int clusterLow = 15; 973 final int clusterHigh = 192; 974 final int masterPref = 234; 975 final int publishSessionId = 19; 976 final int subscribeSessionId = 24; 977 final String serviceName = "some-service-name"; 978 final String ssi = "some much longer and more arbitrary data"; 979 final int publishCount = 15; 980 final int subscribeCount = 22; 981 final int reason = WifiNanSessionListener.TERMINATE_REASON_DONE; 982 final int publishId = 23; 983 final int subscribeId = 55; 984 985 ConfigRequest configRequest = new ConfigRequest.Builder().setClusterLow(clusterLow) 986 .setClusterHigh(clusterHigh).setMasterPreference(masterPref).build(); 987 988 PublishData publishData = new PublishData.Builder().setServiceName(serviceName) 989 .setServiceSpecificInfo(ssi).build(); 990 991 PublishSettings publishSettings = new PublishSettings.Builder() 992 .setPublishType(PublishSettings.PUBLISH_TYPE_UNSOLICITED) 993 .setPublishCount(publishCount).build(); 994 995 SubscribeData subscribeData = new SubscribeData.Builder().setServiceName(serviceName) 996 .setServiceSpecificInfo(ssi).build(); 997 998 SubscribeSettings subscribeSettings = new SubscribeSettings.Builder() 999 .setSubscribeType(SubscribeSettings.SUBSCRIBE_TYPE_PASSIVE) 1000 .setSubscribeCount(subscribeCount).build(); 1001 1002 ArgumentCaptor<Short> transactionId = ArgumentCaptor.forClass(Short.class); 1003 IWifiNanEventListener mockListener = mock(IWifiNanEventListener.class); 1004 IWifiNanSessionListener mockPublishSessionListener = mock(IWifiNanSessionListener.class); 1005 IWifiNanSessionListener mockSubscribeSessionListener = mock(IWifiNanSessionListener.class); 1006 InOrder inOrder = inOrder(mMockNative, mockListener, mockPublishSessionListener, 1007 mockSubscribeSessionListener); 1008 1009 int allEvents = WifiNanEventListener.LISTEN_CONFIG_COMPLETED 1010 | WifiNanEventListener.LISTEN_CONFIG_FAILED 1011 | WifiNanEventListener.LISTEN_IDENTITY_CHANGED 1012 | WifiNanEventListener.LISTEN_NAN_DOWN; 1013 1014 int allSessionEvents = WifiNanSessionListener.LISTEN_PUBLISH_FAIL 1015 | WifiNanSessionListener.LISTEN_PUBLISH_TERMINATED 1016 | WifiNanSessionListener.LISTEN_SUBSCRIBE_FAIL 1017 | WifiNanSessionListener.LISTEN_SUBSCRIBE_TERMINATED 1018 | WifiNanSessionListener.LISTEN_MATCH 1019 | WifiNanSessionListener.LISTEN_MESSAGE_SEND_SUCCESS 1020 | WifiNanSessionListener.LISTEN_MESSAGE_SEND_FAIL 1021 | WifiNanSessionListener.LISTEN_MESSAGE_RECEIVED; 1022 1023 mDut.connect(uid, mockListener, allEvents); 1024 mDut.requestConfig(uid, configRequest); 1025 mDut.createSession(uid, publishSessionId, mockPublishSessionListener, allSessionEvents); 1026 mDut.publish(uid, publishSessionId, publishData, publishSettings); 1027 mDut.createSession(uid, subscribeSessionId, mockSubscribeSessionListener, allSessionEvents); 1028 mDut.subscribe(uid, subscribeSessionId, subscribeData, subscribeSettings); 1029 mDut.destroySession(uid, publishSessionId); 1030 mMockLooper.dispatchAll(); 1031 1032 inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest)); 1033 short transactionIdConfig = transactionId.getValue(); 1034 1035 inOrder.verify(mMockNative).publish(transactionId.capture(), eq(0), eq(publishData), 1036 eq(publishSettings)); 1037 short transactionIdPublish = transactionId.getValue(); 1038 1039 inOrder.verify(mMockNative).subscribe(transactionId.capture(), eq(0), eq(subscribeData), 1040 eq(subscribeSettings)); 1041 short transactionIdSubscribe = transactionId.getValue(); 1042 1043 validateInternalTransactionInfoCleanedUp(transactionIdPublish); 1044 1045 mDut.onConfigCompleted(transactionIdConfig); 1046 mDut.onPublishSuccess(transactionIdPublish, publishId); 1047 mDut.onSubscribeSuccess(transactionIdSubscribe, subscribeId); 1048 mMockLooper.dispatchAll(); 1049 1050 mDut.onPublishTerminated(publishId, reason); 1051 mDut.destroySession(uid, subscribeSessionId); 1052 mMockLooper.dispatchAll(); 1053 1054 inOrder.verify(mockListener).onConfigCompleted(configRequest); 1055 verifyZeroInteractions(mockPublishSessionListener); 1056 verifyNoMoreInteractions(mockSubscribeSessionListener); 1057 } 1058 1059 @Test 1060 public void testTransactionIdIncrement() { 1061 int loopCount = 100; 1062 1063 short prevId = 0; 1064 for (int i = 0; i < loopCount; ++i) { 1065 short id = mDut.createNextTransactionId(); 1066 if (i != 0) { 1067 assertTrue("Transaction ID incrementing", id > prevId); 1068 } 1069 prevId = id; 1070 } 1071 } 1072 1073 /* 1074 * Tests of internal state of WifiNanStateManager: very limited (not usually 1075 * a good idea). However, these test that the internal state is cleaned-up 1076 * appropriately. Alternatively would cause issues with memory leaks or 1077 * information leak between sessions. 1078 */ 1079 1080 /** 1081 * Utility routine used to validate that the internal state is cleaned-up 1082 * after the specific transaction ID. To be used in every test which 1083 * involves a transaction. 1084 * 1085 * @param transactionId The transaction ID whose state should be erased. 1086 */ 1087 public void validateInternalTransactionInfoCleanedUp(short transactionId) throws Exception { 1088 Object info = getInternalPendingTransactionInfo(mDut, transactionId); 1089 collector.checkThat("Transaction record not cleared up for transactionId=" + transactionId, 1090 info, nullValue()); 1091 } 1092 1093 /** 1094 * Utility routine used to validate that the internal state is cleaned-up 1095 * after a client is disconnected. To be used in every test which terminates 1096 * a client. 1097 * 1098 * @param uid The ID of the client which should be deleted. 1099 */ 1100 public void validateInternalClientInfoCleanedUp(int uid) throws Exception { 1101 WifiNanClientState client = getInternalClientState(mDut, uid); 1102 collector.checkThat("Client record not cleared up for uid=" + uid, client, nullValue()); 1103 } 1104 1105 /* 1106 * Utilities 1107 */ 1108 1109 private static WifiNanStateManager installNewNanStateManagerAndResetState() throws Exception { 1110 Constructor<WifiNanStateManager> ctr = WifiNanStateManager.class.getDeclaredConstructor(); 1111 ctr.setAccessible(true); 1112 WifiNanStateManager nanStateManager = ctr.newInstance(); 1113 1114 Field field = WifiNanStateManager.class.getDeclaredField("sNanStateManagerSingleton"); 1115 field.setAccessible(true); 1116 field.set(null, nanStateManager); 1117 1118 return WifiNanStateManager.getInstance(); 1119 } 1120 1121 private static void installMockWifiNanNative(WifiNanNative obj) throws Exception { 1122 Field field = WifiNanNative.class.getDeclaredField("sWifiNanNativeSingleton"); 1123 field.setAccessible(true); 1124 field.set(null, obj); 1125 } 1126 1127 private static Object getInternalPendingTransactionInfo(WifiNanStateManager dut, 1128 short transactionId) throws Exception { 1129 Field field = WifiNanStateManager.class.getDeclaredField("mPendingResponses"); 1130 field.setAccessible(true); 1131 @SuppressWarnings("unchecked") 1132 SparseArray<Object> pendingResponses = (SparseArray<Object>) field.get(dut); 1133 1134 return pendingResponses.get(transactionId); 1135 } 1136 1137 private static WifiNanClientState getInternalClientState(WifiNanStateManager dut, 1138 int uid) throws Exception { 1139 Field field = WifiNanStateManager.class.getDeclaredField("mClients"); 1140 field.setAccessible(true); 1141 @SuppressWarnings("unchecked") 1142 SparseArray<WifiNanClientState> clients = (SparseArray<WifiNanClientState>) field.get(dut); 1143 1144 return clients.get(uid); 1145 } 1146} 1147 1148