|
22 | 22 | import static org.mockito.ArgumentMatchers.any; |
23 | 23 | import static org.mockito.ArgumentMatchers.anyLong; |
24 | 24 | import static org.mockito.ArgumentMatchers.anyString; |
| 25 | +import static org.mockito.ArgumentMatchers.eq; |
25 | 26 | import static org.mockito.ArgumentMatchers.isNull; |
26 | 27 | import static org.mockito.BDDMockito.given; |
27 | 28 | import static org.mockito.BDDMockito.willAnswer; |
|
53 | 54 | import org.assertj.core.api.Condition; |
54 | 55 | import org.eclipse.paho.client.mqttv3.IMqttAsyncClient; |
55 | 56 | import org.eclipse.paho.client.mqttv3.IMqttClient; |
56 | | -import org.eclipse.paho.client.mqttv3.IMqttMessageListener; |
57 | 57 | import org.eclipse.paho.client.mqttv3.IMqttToken; |
58 | 58 | import org.eclipse.paho.client.mqttv3.MqttAsyncClient; |
59 | 59 | import org.eclipse.paho.client.mqttv3.MqttCallback; |
|
65 | 65 | import org.eclipse.paho.client.mqttv3.MqttToken; |
66 | 66 | import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; |
67 | 67 | import org.junit.jupiter.api.Test; |
| 68 | +import org.mockito.ArgumentCaptor; |
68 | 69 | import org.mockito.ArgumentMatchers; |
69 | 70 | import org.mockito.internal.stubbing.answers.CallsRealMethods; |
70 | 71 |
|
@@ -540,8 +541,7 @@ public void testDifferentQos() throws Exception { |
540 | 541 | new DirectFieldAccessor(client).setPropertyValue("aClient", aClient); |
541 | 542 | willAnswer(new CallsRealMethods()).given(client).connect(any(MqttConnectOptions.class)); |
542 | 543 | willAnswer(new CallsRealMethods()).given(client).subscribe(any(String[].class), any(int[].class)); |
543 | | - willAnswer(new CallsRealMethods()).given(client).subscribe(any(String[].class), any(int[].class), |
544 | | - (IMqttMessageListener[]) isNull()); |
| 544 | + willAnswer(new CallsRealMethods()).given(client).subscribe(any(String[].class), any(int[].class), isNull()); |
545 | 545 | willReturn(alwaysComplete).given(aClient).connect(any(MqttConnectOptions.class), any(), any()); |
546 | 546 |
|
547 | 547 | IMqttToken token = mock(IMqttToken.class); |
@@ -572,8 +572,51 @@ public void testDifferentQos() throws Exception { |
572 | 572 | verify(client).disconnectForcibly(5_000L); |
573 | 573 | } |
574 | 574 |
|
| 575 | + @Test |
| 576 | + public void testNoNPEOnReconnectAndStopRaceCondition() throws Exception { |
| 577 | + final IMqttClient client = mock(IMqttClient.class); |
| 578 | + MqttPahoMessageDrivenChannelAdapter adapter = buildAdapterIn(client, null, ConsumerStopAction.UNSUBSCRIBE_NEVER); |
| 579 | + adapter.setRecoveryInterval(10); |
| 580 | + |
| 581 | + MqttException mqttException = new MqttException(MqttException.REASON_CODE_SUBSCRIBE_FAILED); |
| 582 | + |
| 583 | + willThrow(mqttException) |
| 584 | + .given(client) |
| 585 | + .subscribe(any(), ArgumentMatchers.<int[]>any()); |
| 586 | + |
| 587 | + LogAccessor logger = spy(TestUtils.getPropertyValue(adapter, "logger", LogAccessor.class)); |
| 588 | + new DirectFieldAccessor(adapter).setPropertyValue("logger", logger); |
| 589 | + CountDownLatch exceptionLatch = new CountDownLatch(1); |
| 590 | + ArgumentCaptor<MqttException> mqttExceptionArgumentCaptor = ArgumentCaptor.forClass(MqttException.class); |
| 591 | + willAnswer(i -> { |
| 592 | + exceptionLatch.countDown(); |
| 593 | + return null; |
| 594 | + }) |
| 595 | + .given(logger) |
| 596 | + .error(mqttExceptionArgumentCaptor.capture(), eq("Exception while connecting and subscribing")); |
| 597 | + |
| 598 | + ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler(); |
| 599 | + taskScheduler.initialize(); |
| 600 | + adapter.setTaskScheduler(taskScheduler); |
| 601 | + |
| 602 | + adapter.setApplicationEventPublisher(event -> { |
| 603 | + if (event instanceof MqttConnectionFailedEvent) { |
| 604 | + adapter.destroy(); |
| 605 | + } |
| 606 | + }); |
| 607 | + adapter.start(); |
| 608 | + |
| 609 | + assertThat(exceptionLatch.await(10, TimeUnit.SECONDS)).isTrue(); |
| 610 | + assertThat(mqttExceptionArgumentCaptor.getValue()) |
| 611 | + .isNotNull() |
| 612 | + .isSameAs(mqttException); |
| 613 | + |
| 614 | + taskScheduler.destroy(); |
| 615 | + } |
| 616 | + |
575 | 617 | private MqttPahoMessageDrivenChannelAdapter buildAdapterIn(final IMqttClient client, Boolean cleanSession, |
576 | | - ConsumerStopAction action) throws MqttException { |
| 618 | + ConsumerStopAction action) { |
| 619 | + |
577 | 620 | DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory() { |
578 | 621 |
|
579 | 622 | @Override |
@@ -604,7 +647,7 @@ private MqttPahoMessageHandler buildAdapterOut(final IMqttAsyncClient client) { |
604 | 647 | DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory() { |
605 | 648 |
|
606 | 649 | @Override |
607 | | - public IMqttAsyncClient getAsyncClientInstance(String uri, String clientId) throws MqttException { |
| 650 | + public IMqttAsyncClient getAsyncClientInstance(String uri, String clientId) { |
608 | 651 | return client; |
609 | 652 | } |
610 | 653 |
|
|
0 commit comments