1 package software.amazon.awssdk.crt.test; 2 3 import org.junit.Assume; 4 import org.junit.Test; 5 import static org.junit.Assert.assertNotNull; 6 import static org.junit.Assert.assertTrue; 7 import static org.junit.Assert.assertEquals; 8 import static org.junit.Assert.fail; 9 10 import software.amazon.awssdk.crt.*; 11 import software.amazon.awssdk.crt.auth.credentials.CredentialsProvider; 12 import software.amazon.awssdk.crt.auth.credentials.CognitoCredentialsProvider.CognitoCredentialsProviderBuilder; 13 import software.amazon.awssdk.crt.auth.credentials.DefaultChainCredentialsProvider.DefaultChainCredentialsProviderBuilder; 14 import software.amazon.awssdk.crt.auth.credentials.StaticCredentialsProvider.StaticCredentialsProviderBuilder; 15 import software.amazon.awssdk.crt.auth.credentials.X509CredentialsProvider.X509CredentialsProviderBuilder; 16 import software.amazon.awssdk.crt.auth.signing.AwsSigningConfig; 17 import software.amazon.awssdk.crt.auth.signing.AwsSigningConfig.AwsSigningAlgorithm; 18 import software.amazon.awssdk.crt.http.HttpProxyOptions; 19 import software.amazon.awssdk.crt.http.HttpProxyOptions.HttpProxyConnectionType; 20 import software.amazon.awssdk.crt.io.ClientBootstrap; 21 import software.amazon.awssdk.crt.io.EventLoopGroup; 22 import software.amazon.awssdk.crt.io.HostResolver; 23 import software.amazon.awssdk.crt.io.Pkcs11Lib; 24 import software.amazon.awssdk.crt.io.SocketOptions; 25 import software.amazon.awssdk.crt.io.TlsContext; 26 import software.amazon.awssdk.crt.io.TlsContextOptions; 27 import software.amazon.awssdk.crt.io.TlsContextPkcs11Options; 28 import software.amazon.awssdk.crt.io.ExponentialBackoffRetryOptions.JitterMode; 29 import software.amazon.awssdk.crt.mqtt5.*; 30 import software.amazon.awssdk.crt.mqtt5.Mqtt5ClientOptions.ClientOfflineQueueBehavior; 31 import software.amazon.awssdk.crt.mqtt5.Mqtt5ClientOptions.ClientSessionBehavior; 32 import software.amazon.awssdk.crt.mqtt5.Mqtt5ClientOptions.ExtendedValidationAndFlowControlOptions; 33 import software.amazon.awssdk.crt.mqtt5.Mqtt5ClientOptions.LifecycleEvents; 34 import software.amazon.awssdk.crt.mqtt5.Mqtt5ClientOptions.Mqtt5ClientOptionsBuilder; 35 import software.amazon.awssdk.crt.mqtt5.Mqtt5ClientOptions.PublishEvents; 36 import software.amazon.awssdk.crt.mqtt5.packets.*; 37 import software.amazon.awssdk.crt.mqtt5.packets.ConnectPacket.ConnectPacketBuilder; 38 import software.amazon.awssdk.crt.mqtt5.packets.DisconnectPacket.DisconnectPacketBuilder; 39 import software.amazon.awssdk.crt.mqtt5.packets.DisconnectPacket.DisconnectReasonCode; 40 import software.amazon.awssdk.crt.mqtt5.packets.PublishPacket.PublishPacketBuilder; 41 import software.amazon.awssdk.crt.mqtt5.packets.SubscribePacket.SubscribePacketBuilder; 42 import software.amazon.awssdk.crt.mqtt5.packets.UnsubscribePacket.UnsubscribePacketBuilder; 43 import software.amazon.awssdk.crt.mqtt5.packets.SubscribePacket.RetainHandlingType; 44 45 import java.util.ArrayList; 46 import java.util.Random; 47 import java.util.UUID; 48 import java.util.concurrent.CompletableFuture; 49 import java.util.concurrent.TimeUnit; 50 import java.util.function.Consumer; 51 52 /* For environment variable setup, see SetupCrossCICrtEnvironment in the CRT builder */ 53 public class Mqtt5ClientTest extends Mqtt5ClientTestFixture { 54 Mqtt5ClientTest()55 public Mqtt5ClientTest() { 56 } 57 58 /** 59 * ============================================================ 60 * CREATION TEST CASES 61 * ============================================================ 62 */ 63 64 /* Happy path. Minimal creation and cleanup */ 65 @Test New_UC1()66 public void New_UC1() { 67 skipIfNetworkUnavailable(); 68 Assume.assumeNotNull(AWS_TEST_MQTT5_DIRECT_MQTT_HOST, AWS_TEST_MQTT5_DIRECT_MQTT_PORT); 69 try { 70 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder( 71 AWS_TEST_MQTT5_DIRECT_MQTT_HOST, 72 Long.parseLong(AWS_TEST_MQTT5_DIRECT_MQTT_PORT)); 73 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 74 assertNotNull(client); 75 } 76 } catch (Exception ex) { 77 fail(ex.getMessage()); 78 } 79 } 80 81 /* Maximum creation and cleanup */ 82 @Test New_UC2()83 public void New_UC2() { 84 skipIfNetworkUnavailable(); 85 Assume.assumeNotNull( 86 AWS_TEST_MQTT5_DIRECT_MQTT_HOST, AWS_TEST_MQTT5_DIRECT_MQTT_PORT, 87 AWS_TEST_MQTT5_BASIC_AUTH_USERNAME, AWS_TEST_MQTT5_BASIC_AUTH_PASSWORD, 88 AWS_TEST_MQTT5_PROXY_HOST, AWS_TEST_MQTT5_PROXY_PORT); 89 try { 90 91 try ( 92 EventLoopGroup elg = new EventLoopGroup(1); 93 HostResolver hr = new HostResolver(elg); 94 ClientBootstrap bootstrap = new ClientBootstrap(elg, hr); 95 SocketOptions socketOptions = new SocketOptions(); 96 ) { 97 98 PublishPacketBuilder willPacketBuilder = new PublishPacketBuilder(); 99 willPacketBuilder.withQOS(QOS.AT_LEAST_ONCE).withPayload("Hello World".getBytes()).withTopic("test/topic"); 100 101 ConnectPacketBuilder connectBuilder = new ConnectPacketBuilder(); 102 connectBuilder.withClientId("MQTT5 CRT") 103 .withKeepAliveIntervalSeconds(1000L) 104 .withMaximumPacketSizeBytes(1000L) 105 .withPassword(AWS_TEST_MQTT5_BASIC_AUTH_PASSWORD.getBytes()) 106 .withReceiveMaximum(1000L) 107 .withRequestProblemInformation(true) 108 .withRequestResponseInformation(true) 109 .withSessionExpiryIntervalSeconds(1000L) 110 .withUsername(AWS_TEST_MQTT5_BASIC_AUTH_USERNAME) 111 .withWill(willPacketBuilder.build()) 112 .withWillDelayIntervalSeconds(1000L); 113 114 ArrayList<UserProperty> userProperties = new ArrayList<UserProperty>(); 115 userProperties.add(new UserProperty("Hello", "World")); 116 connectBuilder.withUserProperties(userProperties); 117 118 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder( 119 AWS_TEST_MQTT5_DIRECT_MQTT_HOST, 120 Long.parseLong(AWS_TEST_MQTT5_DIRECT_MQTT_PORT)); 121 builder.withBootstrap(bootstrap) 122 .withConnackTimeoutMs(100L) 123 .withConnectOptions(connectBuilder.build()) 124 .withExtendedValidationAndFlowControlOptions(ExtendedValidationAndFlowControlOptions.NONE) 125 .withLifecycleEvents(new LifecycleEvents() { 126 @Override 127 public void onAttemptingConnect(Mqtt5Client client, OnAttemptingConnectReturn onAttemptingConnectReturn) {} 128 129 @Override 130 public void onConnectionSuccess(Mqtt5Client client, OnConnectionSuccessReturn onConnectionSuccessReturn) {} 131 132 @Override 133 public void onConnectionFailure(Mqtt5Client client, OnConnectionFailureReturn onConnectionFailureReturn) {} 134 135 @Override 136 public void onDisconnection(Mqtt5Client client, OnDisconnectionReturn onDisconnectionReturn) {} 137 138 @Override 139 public void onStopped(Mqtt5Client client, OnStoppedReturn onStoppedReturn) {} 140 }) 141 .withMaxReconnectDelayMs(1000L) 142 .withMinConnectedTimeToResetReconnectDelayMs(1000L) 143 .withMinReconnectDelayMs(1000L) 144 .withOfflineQueueBehavior(ClientOfflineQueueBehavior.FAIL_ALL_ON_DISCONNECT) 145 .withAckTimeoutSeconds(1000L) 146 .withPingTimeoutMs(1000L) 147 .withPublishEvents(new PublishEvents() { 148 @Override 149 public void onMessageReceived(Mqtt5Client client, PublishReturn publishReturn) {} 150 }) 151 .withRetryJitterMode(JitterMode.Default) 152 .withSessionBehavior(ClientSessionBehavior.CLEAN) 153 .withSocketOptions(socketOptions); 154 // Skip websocket and TLS options - those are all different tests 155 156 HttpProxyOptions proxyOptions = new HttpProxyOptions(); 157 proxyOptions.setHost(AWS_TEST_MQTT5_PROXY_HOST); 158 proxyOptions.setPort((Integer.parseInt(AWS_TEST_MQTT5_PROXY_PORT))); 159 proxyOptions.setConnectionType(HttpProxyConnectionType.Tunneling); 160 builder.withHttpProxyOptions(proxyOptions); 161 162 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 163 assertNotNull(client); 164 } 165 } 166 167 } catch (Exception ex) { 168 fail(ex.getMessage()); 169 } 170 } 171 172 /* Minimal memory check */ 173 @Test New_UC3()174 public void New_UC3() { 175 skipIfNetworkUnavailable(); 176 Assume.assumeNotNull(AWS_TEST_MQTT5_DIRECT_MQTT_HOST, AWS_TEST_MQTT5_DIRECT_MQTT_PORT); 177 try { 178 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder( 179 AWS_TEST_MQTT5_DIRECT_MQTT_HOST, 180 Long.parseLong(AWS_TEST_MQTT5_DIRECT_MQTT_PORT)); 181 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 182 assertNotNull(client); 183 } 184 } catch (Exception ex) { 185 fail(ex.getMessage()); 186 } 187 CrtResource.waitForNoResources(); 188 } 189 190 /* Maximum memory test */ 191 @Test New_UC4()192 public void New_UC4() { 193 skipIfNetworkUnavailable(); 194 Assume.assumeNotNull( 195 AWS_TEST_MQTT5_DIRECT_MQTT_HOST, AWS_TEST_MQTT5_DIRECT_MQTT_PORT, 196 AWS_TEST_MQTT5_BASIC_AUTH_USERNAME, AWS_TEST_MQTT5_BASIC_AUTH_PASSWORD, 197 AWS_TEST_MQTT5_PROXY_HOST, AWS_TEST_MQTT5_PROXY_PORT); 198 try { 199 try ( 200 EventLoopGroup elg = new EventLoopGroup(1); 201 HostResolver hr = new HostResolver(elg); 202 ClientBootstrap bootstrap = new ClientBootstrap(elg, hr); 203 SocketOptions socketOptions = new SocketOptions(); 204 ) { 205 PublishPacketBuilder willPacketBuilder = new PublishPacketBuilder(); 206 willPacketBuilder.withQOS(QOS.AT_LEAST_ONCE).withPayload("Hello World".getBytes()).withTopic("test/topic"); 207 208 ConnectPacketBuilder connectBuilder = new ConnectPacketBuilder(); 209 connectBuilder.withClientId("MQTT5 CRT"); 210 connectBuilder.withKeepAliveIntervalSeconds(1000L); 211 connectBuilder.withMaximumPacketSizeBytes(1000L); 212 connectBuilder.withPassword(AWS_TEST_MQTT5_BASIC_AUTH_PASSWORD.getBytes()); 213 connectBuilder.withReceiveMaximum(1000L); 214 connectBuilder.withRequestProblemInformation(true); 215 connectBuilder.withRequestResponseInformation(true); 216 connectBuilder.withSessionExpiryIntervalSeconds(1000L); 217 connectBuilder.withUsername(AWS_TEST_MQTT5_BASIC_AUTH_USERNAME); 218 connectBuilder.withWill(willPacketBuilder.build()); 219 connectBuilder.withWillDelayIntervalSeconds(1000L); 220 221 ArrayList<UserProperty> userProperties = new ArrayList<UserProperty>(); 222 userProperties.add(new UserProperty("Hello", "World")); 223 connectBuilder.withUserProperties(userProperties); 224 225 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder( 226 AWS_TEST_MQTT5_DIRECT_MQTT_HOST, 227 Long.parseLong(AWS_TEST_MQTT5_DIRECT_MQTT_PORT)); 228 builder.withBootstrap(bootstrap) 229 .withConnackTimeoutMs(1000L) 230 .withConnectOptions(connectBuilder.build()) 231 .withExtendedValidationAndFlowControlOptions(ExtendedValidationAndFlowControlOptions.NONE) 232 .withLifecycleEvents(new LifecycleEvents() { 233 @Override 234 public void onAttemptingConnect(Mqtt5Client client, OnAttemptingConnectReturn onAttemptingConnectReturn) {} 235 236 @Override 237 public void onConnectionSuccess(Mqtt5Client client, OnConnectionSuccessReturn onConnectionSuccessReturn) {} 238 239 @Override 240 public void onConnectionFailure(Mqtt5Client client, OnConnectionFailureReturn onConnectionFailureReturn) {} 241 242 @Override 243 public void onDisconnection(Mqtt5Client client, OnDisconnectionReturn onDisconnectionReturn) {} 244 245 @Override 246 public void onStopped(Mqtt5Client client, OnStoppedReturn onStoppedReturn) {} 247 }) 248 .withMaxReconnectDelayMs(1000L) 249 .withMinConnectedTimeToResetReconnectDelayMs(1000L) 250 .withMinReconnectDelayMs(1000L) 251 .withOfflineQueueBehavior(ClientOfflineQueueBehavior.FAIL_ALL_ON_DISCONNECT) 252 .withAckTimeoutSeconds(1000L) 253 .withPingTimeoutMs(1000L) 254 .withPublishEvents(new PublishEvents() { 255 @Override 256 public void onMessageReceived(Mqtt5Client client, PublishReturn publishReturn) {} 257 }) 258 .withRetryJitterMode(JitterMode.Default) 259 .withSessionBehavior(ClientSessionBehavior.CLEAN) 260 .withSocketOptions(socketOptions); 261 // Skip websocket and TLS options - those are all different tests 262 263 HttpProxyOptions proxyOptions = new HttpProxyOptions(); 264 proxyOptions.setHost(AWS_TEST_MQTT5_PROXY_HOST); 265 proxyOptions.setPort((Integer.parseInt(AWS_TEST_MQTT5_PROXY_PORT))); 266 proxyOptions.setConnectionType(HttpProxyConnectionType.Tunneling); 267 builder.withHttpProxyOptions(proxyOptions); 268 269 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 270 assertNotNull(client); 271 } 272 } 273 274 } catch (Exception ex) { 275 fail(ex.getMessage()); 276 } 277 278 CrtResource.waitForNoResources(); 279 } 280 281 /** 282 * ============================================================ 283 * DIRECT CONNECT TEST CASES 284 * ============================================================ 285 */ 286 287 /* Happy path. Direct connection with minimal configuration */ 288 @Test ConnDC_UC1()289 public void ConnDC_UC1() { 290 skipIfNetworkUnavailable(); 291 Assume.assumeNotNull(AWS_TEST_MQTT5_DIRECT_MQTT_HOST, AWS_TEST_MQTT5_DIRECT_MQTT_PORT); 292 try { 293 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 294 295 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder( 296 AWS_TEST_MQTT5_DIRECT_MQTT_HOST, 297 Long.parseLong(AWS_TEST_MQTT5_DIRECT_MQTT_PORT)); 298 builder.withLifecycleEvents(events); 299 300 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 301 client.start(); 302 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 303 client.stop(); 304 } 305 306 } catch (Exception ex) { 307 fail(ex.getMessage()); 308 } 309 } 310 311 /* Direct connection with basic authentication */ 312 @Test ConnDC_UC2()313 public void ConnDC_UC2() { 314 skipIfNetworkUnavailable(); 315 Assume.assumeNotNull( 316 AWS_TEST_MQTT5_DIRECT_MQTT_BASIC_AUTH_HOST, AWS_TEST_MQTT5_DIRECT_MQTT_BASIC_AUTH_PORT, 317 AWS_TEST_MQTT5_BASIC_AUTH_USERNAME, AWS_TEST_MQTT5_BASIC_AUTH_PASSWORD); 318 try { 319 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 320 321 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder( 322 AWS_TEST_MQTT5_DIRECT_MQTT_BASIC_AUTH_HOST, 323 Long.parseLong(AWS_TEST_MQTT5_DIRECT_MQTT_BASIC_AUTH_PORT)); 324 builder.withLifecycleEvents(events); 325 326 ConnectPacketBuilder connectOptions = new ConnectPacketBuilder(); 327 connectOptions.withUsername(AWS_TEST_MQTT5_BASIC_AUTH_USERNAME).withPassword(AWS_TEST_MQTT5_BASIC_AUTH_PASSWORD.getBytes()); 328 builder.withConnectOptions(connectOptions.build()); 329 330 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 331 client.start(); 332 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 333 client.stop(); 334 } 335 } catch (Exception ex) { 336 fail(ex.getMessage()); 337 } 338 } 339 340 /* Direct connection with TLS */ 341 @Test ConnDC_UC3()342 public void ConnDC_UC3() { 343 skipIfNetworkUnavailable(); 344 Assume.assumeNotNull(AWS_TEST_MQTT5_DIRECT_MQTT_TLS_HOST, AWS_TEST_MQTT5_DIRECT_MQTT_TLS_PORT); 345 try { 346 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 347 348 try (TlsContextOptions tlsOptions = TlsContextOptions.createDefaultClient()) { 349 tlsOptions.withVerifyPeer(false); 350 try (TlsContext tlsContext = new TlsContext(tlsOptions)) { 351 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder( 352 AWS_TEST_MQTT5_DIRECT_MQTT_TLS_HOST, Long.parseLong(AWS_TEST_MQTT5_DIRECT_MQTT_TLS_PORT)); 353 builder.withLifecycleEvents(events); 354 builder.withTlsContext(tlsContext); 355 356 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 357 client.start(); 358 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 359 client.stop(); 360 } 361 } 362 } 363 } catch (Exception ex) { 364 fail(ex.getMessage()); 365 } 366 } 367 368 /* Direct connection with mTLS */ 369 @Test ConnDC_UC4()370 public void ConnDC_UC4() { 371 skipIfNetworkUnavailable(); 372 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 373 try { 374 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 375 376 try ( 377 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 378 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 379 TlsContext tlsContext = new TlsContext(tlsOptions); 380 ) { 381 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 382 builder.withLifecycleEvents(events); 383 builder.withTlsContext(tlsContext); 384 385 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 386 client.start(); 387 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 388 client.stop(); 389 } 390 } 391 } catch (Exception ex) { 392 fail(ex.getMessage()); 393 } 394 } 395 396 /* Direct connection with HttpProxyOptions */ 397 @Test ConnDC_UC5()398 public void ConnDC_UC5() { 399 skipIfNetworkUnavailable(); 400 Assume.assumeNotNull( 401 AWS_TEST_MQTT5_DIRECT_MQTT_TLS_HOST, AWS_TEST_MQTT5_DIRECT_MQTT_TLS_PORT, 402 AWS_TEST_MQTT5_PROXY_HOST, AWS_TEST_MQTT5_PROXY_PORT); 403 try { 404 405 try ( 406 EventLoopGroup elg = new EventLoopGroup(1); 407 HostResolver hr = new HostResolver(elg); 408 ClientBootstrap bootstrap = new ClientBootstrap(elg, hr); 409 ) { 410 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 411 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder( 412 AWS_TEST_MQTT5_DIRECT_MQTT_TLS_HOST, Long.parseLong(AWS_TEST_MQTT5_DIRECT_MQTT_TLS_PORT)); 413 builder.withLifecycleEvents(events); 414 builder.withBootstrap(bootstrap); 415 416 HttpProxyOptions proxyOptions = new HttpProxyOptions(); 417 proxyOptions.setHost(AWS_TEST_MQTT5_PROXY_HOST); 418 proxyOptions.setPort(Integer.parseInt(AWS_TEST_MQTT5_PROXY_PORT)); 419 proxyOptions.setConnectionType(HttpProxyConnectionType.Tunneling); 420 421 try (TlsContextOptions tlsOptions = TlsContextOptions.createDefaultClient()) { 422 tlsOptions.withVerifyPeer(false); 423 try (TlsContext tlsContext = new TlsContext(tlsOptions)) { 424 builder.withTlsContext(tlsContext); 425 builder.withHttpProxyOptions(proxyOptions); 426 427 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 428 client.start(); 429 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 430 client.stop(); 431 } 432 } 433 } 434 } 435 436 } catch (Exception ex) { 437 fail(ex.getMessage()); 438 } 439 } 440 441 /* Maximum options set connection test */ 442 @Test ConnDC_UC6()443 public void ConnDC_UC6() { 444 skipIfNetworkUnavailable(); 445 Assume.assumeNotNull( 446 AWS_TEST_MQTT5_DIRECT_MQTT_BASIC_AUTH_HOST, AWS_TEST_MQTT5_DIRECT_MQTT_BASIC_AUTH_PORT, 447 AWS_TEST_MQTT5_BASIC_AUTH_USERNAME, AWS_TEST_MQTT5_BASIC_AUTH_PASSWORD); 448 try { 449 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 450 451 try ( 452 EventLoopGroup elg = new EventLoopGroup(1); 453 HostResolver hr = new HostResolver(elg); 454 ClientBootstrap bootstrap = new ClientBootstrap(elg, hr); 455 SocketOptions socketOptions = new SocketOptions(); 456 ) { 457 PublishPacketBuilder willPacketBuilder = new PublishPacketBuilder(); 458 willPacketBuilder.withQOS(QOS.AT_LEAST_ONCE).withPayload("Hello World".getBytes()).withTopic("test/topic"); 459 460 ConnectPacketBuilder connectBuilder = new ConnectPacketBuilder(); 461 connectBuilder.withClientId("MQTT5 CRT" + UUID.randomUUID().toString()); 462 connectBuilder.withKeepAliveIntervalSeconds(1000L); 463 connectBuilder.withMaximumPacketSizeBytes(1000L); 464 connectBuilder.withPassword(AWS_TEST_MQTT5_BASIC_AUTH_PASSWORD.getBytes()); 465 connectBuilder.withReceiveMaximum(1000L); 466 connectBuilder.withRequestProblemInformation(true); 467 connectBuilder.withRequestResponseInformation(true); 468 connectBuilder.withSessionExpiryIntervalSeconds(1000L); 469 connectBuilder.withUsername(AWS_TEST_MQTT5_BASIC_AUTH_USERNAME); 470 connectBuilder.withWill(willPacketBuilder.build()); 471 connectBuilder.withWillDelayIntervalSeconds(1000L); 472 473 ArrayList<UserProperty> userProperties = new ArrayList<UserProperty>(); 474 userProperties.add(new UserProperty("Hello", "World")); 475 connectBuilder.withUserProperties(userProperties); 476 477 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder( 478 AWS_TEST_MQTT5_DIRECT_MQTT_BASIC_AUTH_HOST, 479 Long.parseLong(AWS_TEST_MQTT5_DIRECT_MQTT_BASIC_AUTH_PORT)); 480 builder.withBootstrap(bootstrap) 481 .withConnackTimeoutMs(1000L) 482 .withConnectOptions(connectBuilder.build()) 483 .withExtendedValidationAndFlowControlOptions(ExtendedValidationAndFlowControlOptions.NONE) 484 .withLifecycleEvents(events) 485 .withMaxReconnectDelayMs(1000L) 486 .withMinConnectedTimeToResetReconnectDelayMs(1000L) 487 .withMinReconnectDelayMs(1000L) 488 .withOfflineQueueBehavior(ClientOfflineQueueBehavior.FAIL_ALL_ON_DISCONNECT) 489 .withAckTimeoutSeconds(1000L) 490 .withPingTimeoutMs(1000L) 491 .withPublishEvents(new PublishEvents() { 492 @Override 493 public void onMessageReceived(Mqtt5Client client, PublishReturn publishReturn) {} 494 }) 495 .withRetryJitterMode(JitterMode.Default) 496 .withSessionBehavior(ClientSessionBehavior.CLEAN) 497 .withSocketOptions(socketOptions); 498 // Skip websocket, proxy options, and TLS options - those are all different tests 499 500 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 501 client.start(); 502 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 503 DisconnectPacketBuilder disconnect = new DisconnectPacketBuilder(); 504 client.stop(disconnect.build()); 505 } 506 } 507 508 } catch (Exception ex) { 509 fail(ex.getMessage()); 510 } 511 512 CrtResource.waitForNoResources(); 513 } 514 515 /** 516 * ============================================================ 517 * WEBSOCKET CONNECT TEST CASES 518 * ============================================================ 519 */ 520 521 /* Happy path. Websocket connection with minimal configuration */ 522 @Test ConnWS_UC1()523 public void ConnWS_UC1() { 524 skipIfNetworkUnavailable(); 525 Assume.assumeNotNull(AWS_TEST_MQTT5_WS_MQTT_HOST, AWS_TEST_MQTT5_WS_MQTT_PORT); 526 try { 527 528 try ( 529 EventLoopGroup elg = new EventLoopGroup(1); 530 HostResolver hr = new HostResolver(elg); 531 ClientBootstrap bootstrap = new ClientBootstrap(elg, hr); 532 ) { 533 534 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 535 536 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder( 537 AWS_TEST_MQTT5_WS_MQTT_HOST, Long.parseLong(AWS_TEST_MQTT5_WS_MQTT_PORT)); 538 builder.withLifecycleEvents(events); 539 builder.withBootstrap(bootstrap); 540 541 Consumer<Mqtt5WebsocketHandshakeTransformArgs> websocketTransform = new Consumer<Mqtt5WebsocketHandshakeTransformArgs>() { 542 @Override 543 public void accept(Mqtt5WebsocketHandshakeTransformArgs t) { 544 t.complete(t.getHttpRequest()); 545 } 546 }; 547 builder.withWebsocketHandshakeTransform(websocketTransform); 548 549 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 550 client.start(); 551 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 552 client.stop(); 553 } 554 } 555 556 } catch (Exception ex) { 557 fail(ex.getMessage()); 558 } 559 } 560 561 /* Websocket connection with basic authentication */ 562 @Test ConnWS_UC2()563 public void ConnWS_UC2() { 564 skipIfNetworkUnavailable(); 565 Assume.assumeNotNull( 566 AWS_TEST_MQTT5_WS_MQTT_BASIC_AUTH_HOST, AWS_TEST_MQTT5_WS_MQTT_BASIC_AUTH_PORT, 567 AWS_TEST_MQTT5_BASIC_AUTH_USERNAME, AWS_TEST_MQTT5_BASIC_AUTH_PASSWORD); 568 try { 569 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 570 571 try ( 572 EventLoopGroup elg = new EventLoopGroup(1); 573 HostResolver hr = new HostResolver(elg); 574 ClientBootstrap bootstrap = new ClientBootstrap(elg, hr); 575 ) { 576 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder( 577 AWS_TEST_MQTT5_WS_MQTT_BASIC_AUTH_HOST, Long.parseLong(AWS_TEST_MQTT5_WS_MQTT_BASIC_AUTH_PORT)); 578 builder.withLifecycleEvents(events); 579 builder.withBootstrap(bootstrap); 580 581 Consumer<Mqtt5WebsocketHandshakeTransformArgs> websocketTransform = new Consumer<Mqtt5WebsocketHandshakeTransformArgs>() { 582 @Override 583 public void accept(Mqtt5WebsocketHandshakeTransformArgs t) { 584 t.complete(t.getHttpRequest()); 585 } 586 }; 587 builder.withWebsocketHandshakeTransform(websocketTransform); 588 589 ConnectPacketBuilder connectOptions = new ConnectPacketBuilder(); 590 connectOptions.withUsername(AWS_TEST_MQTT5_BASIC_AUTH_USERNAME).withPassword(AWS_TEST_MQTT5_BASIC_AUTH_PASSWORD.getBytes()); 591 builder.withConnectOptions(connectOptions.build()); 592 593 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 594 client.start(); 595 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 596 client.stop(); 597 } 598 } 599 } catch (Exception ex) { 600 fail(ex.getMessage()); 601 } 602 } 603 604 /* Websocket connection with TLS */ 605 @Test ConnWS_UC3()606 public void ConnWS_UC3() { 607 skipIfNetworkUnavailable(); 608 Assume.assumeNotNull(AWS_TEST_MQTT5_WS_MQTT_TLS_HOST, AWS_TEST_MQTT5_WS_MQTT_TLS_PORT); 609 try { 610 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 611 612 try ( 613 EventLoopGroup elg = new EventLoopGroup(1); 614 HostResolver hr = new HostResolver(elg); 615 ClientBootstrap bootstrap = new ClientBootstrap(elg, hr); 616 ) { 617 618 try (TlsContextOptions tlsOptions = TlsContextOptions.createDefaultClient()) { 619 tlsOptions.withVerifyPeer(false); 620 try (TlsContext tlsContext = new TlsContext(tlsOptions)) { 621 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder( 622 AWS_TEST_MQTT5_WS_MQTT_TLS_HOST, Long.parseLong(AWS_TEST_MQTT5_WS_MQTT_TLS_PORT)); 623 builder.withLifecycleEvents(events); 624 builder.withBootstrap(bootstrap); 625 626 Consumer<Mqtt5WebsocketHandshakeTransformArgs> websocketTransform = new Consumer<Mqtt5WebsocketHandshakeTransformArgs>() { 627 @Override 628 public void accept(Mqtt5WebsocketHandshakeTransformArgs t) { 629 t.complete(t.getHttpRequest()); 630 } 631 }; 632 builder.withWebsocketHandshakeTransform(websocketTransform); 633 builder.withTlsContext(tlsContext); 634 635 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 636 client.start(); 637 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 638 client.stop(); 639 } 640 } 641 } 642 } 643 644 } catch (Exception ex) { 645 fail(ex.getMessage()); 646 } 647 } 648 649 /* Websocket connection with HttpProxyOptions */ 650 @Test ConnWS_UC5()651 public void ConnWS_UC5() { 652 skipIfNetworkUnavailable(); 653 Assume.assumeNotNull( 654 AWS_TEST_MQTT5_WS_MQTT_TLS_HOST, AWS_TEST_MQTT5_WS_MQTT_TLS_PORT, 655 AWS_TEST_MQTT5_PROXY_HOST, AWS_TEST_MQTT5_PROXY_PORT); 656 try { 657 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 658 659 EventLoopGroup elg = new EventLoopGroup(1); 660 HostResolver hr = new HostResolver(elg); 661 ClientBootstrap bootstrap = new ClientBootstrap(elg, hr); 662 663 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder( 664 AWS_TEST_MQTT5_WS_MQTT_TLS_HOST, Long.parseLong(AWS_TEST_MQTT5_WS_MQTT_TLS_PORT)); 665 builder.withLifecycleEvents(events); 666 builder.withBootstrap(bootstrap); 667 668 TlsContextOptions tlsOptions = TlsContextOptions.createDefaultClient(); 669 tlsOptions.withVerifyPeer(false); 670 TlsContext tlsContext = new TlsContext(tlsOptions); 671 builder.withTlsContext(tlsContext); 672 673 Consumer<Mqtt5WebsocketHandshakeTransformArgs> websocketTransform = new Consumer<Mqtt5WebsocketHandshakeTransformArgs>() { 674 @Override 675 public void accept(Mqtt5WebsocketHandshakeTransformArgs t) { 676 t.complete(t.getHttpRequest()); 677 } 678 }; 679 builder.withWebsocketHandshakeTransform(websocketTransform); 680 681 HttpProxyOptions proxyOptions = new HttpProxyOptions(); 682 proxyOptions.setHost(AWS_TEST_MQTT5_PROXY_HOST); 683 proxyOptions.setPort(Integer.parseInt(AWS_TEST_MQTT5_PROXY_PORT)); 684 proxyOptions.setConnectionType(HttpProxyConnectionType.Tunneling); 685 builder.withHttpProxyOptions(proxyOptions); 686 687 Mqtt5Client client = new Mqtt5Client(builder.build()); 688 689 client.start(); 690 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 691 client.stop(); 692 693 client.close(); 694 tlsContext.close(); 695 tlsOptions.close(); 696 elg.close(); 697 hr.close(); 698 bootstrap.close(); 699 700 } catch (Exception ex) { 701 fail(ex.getMessage()); 702 } 703 } 704 705 /* Websocket connection with all options set */ 706 @Test ConnWS_UC6()707 public void ConnWS_UC6() { 708 skipIfNetworkUnavailable(); 709 Assume.assumeNotNull( 710 AWS_TEST_MQTT5_WS_MQTT_BASIC_AUTH_HOST, AWS_TEST_MQTT5_WS_MQTT_BASIC_AUTH_PORT, 711 AWS_TEST_MQTT5_BASIC_AUTH_USERNAME, AWS_TEST_MQTT5_BASIC_AUTH_PASSWORD); 712 try { 713 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 714 715 try ( 716 EventLoopGroup elg = new EventLoopGroup(1); 717 HostResolver hr = new HostResolver(elg); 718 ClientBootstrap bootstrap = new ClientBootstrap(elg, hr); 719 SocketOptions socketOptions = new SocketOptions(); 720 ) { 721 PublishPacketBuilder willPacketBuilder = new PublishPacketBuilder(); 722 willPacketBuilder.withQOS(QOS.AT_LEAST_ONCE).withPayload("Hello World".getBytes()).withTopic("test/topic"); 723 724 ConnectPacketBuilder connectBuilder = new ConnectPacketBuilder(); 725 connectBuilder.withClientId("MQTT5 CRT"+UUID.randomUUID().toString()); 726 connectBuilder.withKeepAliveIntervalSeconds(1000L); 727 connectBuilder.withMaximumPacketSizeBytes(1000L); 728 connectBuilder.withPassword(AWS_TEST_MQTT5_BASIC_AUTH_PASSWORD.getBytes()); 729 connectBuilder.withReceiveMaximum(1000L); 730 connectBuilder.withRequestProblemInformation(true); 731 connectBuilder.withRequestResponseInformation(true); 732 connectBuilder.withSessionExpiryIntervalSeconds(1000L); 733 connectBuilder.withUsername(AWS_TEST_MQTT5_BASIC_AUTH_USERNAME); 734 connectBuilder.withWill(willPacketBuilder.build()); 735 connectBuilder.withWillDelayIntervalSeconds(1000L); 736 737 ArrayList<UserProperty> userProperties = new ArrayList<UserProperty>(); 738 userProperties.add(new UserProperty("Hello", "World")); 739 connectBuilder.withUserProperties(userProperties); 740 741 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder( 742 AWS_TEST_MQTT5_WS_MQTT_BASIC_AUTH_HOST, Long.parseLong(AWS_TEST_MQTT5_WS_MQTT_BASIC_AUTH_PORT)); 743 builder.withBootstrap(bootstrap) 744 .withConnackTimeoutMs(1000L) 745 .withConnectOptions(connectBuilder.build()) 746 .withExtendedValidationAndFlowControlOptions(ExtendedValidationAndFlowControlOptions.NONE) 747 .withLifecycleEvents(events) 748 .withMaxReconnectDelayMs(1000L) 749 .withMinConnectedTimeToResetReconnectDelayMs(1000L) 750 .withMinReconnectDelayMs(1000L) 751 .withOfflineQueueBehavior(ClientOfflineQueueBehavior.FAIL_ALL_ON_DISCONNECT) 752 .withAckTimeoutSeconds(1000L) 753 .withPingTimeoutMs(1000L) 754 .withPublishEvents(new PublishEvents() { 755 @Override 756 public void onMessageReceived(Mqtt5Client client, PublishReturn publishReturn) {} 757 }) 758 .withRetryJitterMode(JitterMode.Default) 759 .withSessionBehavior(ClientSessionBehavior.CLEAN) 760 .withSocketOptions(socketOptions); 761 762 Consumer<Mqtt5WebsocketHandshakeTransformArgs> websocketTransform = new Consumer<Mqtt5WebsocketHandshakeTransformArgs>() { 763 @Override 764 public void accept(Mqtt5WebsocketHandshakeTransformArgs t) { 765 t.complete(t.getHttpRequest()); 766 } 767 }; 768 builder.withWebsocketHandshakeTransform(websocketTransform); 769 770 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 771 client.start(); 772 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 773 DisconnectPacketBuilder disconnect = new DisconnectPacketBuilder(); 774 client.stop(disconnect.build()); 775 } 776 } 777 778 } catch (Exception ex) { 779 fail(ex.getMessage()); 780 } 781 CrtResource.waitForNoResources(); 782 } 783 784 /** 785 * ============================================================ 786 * Negative Connect Tests with Incorrect Data 787 * ============================================================ 788 */ 789 790 /* Client connect with invalid host name */ 791 @Test ConnNegativeID_UC1()792 public void ConnNegativeID_UC1() { 793 skipIfNetworkUnavailable(); 794 Assume.assumeNotNull(AWS_TEST_MQTT5_DIRECT_MQTT_PORT); 795 boolean foundExpectedError = false; 796 boolean exceptionOccurred = false; 797 798 try { 799 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 800 801 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder( 802 "_test", Long.parseLong(AWS_TEST_MQTT5_DIRECT_MQTT_PORT)); 803 builder.withLifecycleEvents(events); 804 builder.withMinReconnectDelayMs(1000L); 805 806 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 807 client.start(); 808 809 try { 810 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 811 } catch (Exception ex) { 812 exceptionOccurred = true; 813 if (events.connectFailureCode == 1059) { 814 foundExpectedError = true; 815 } else { 816 System.out.println("EXCEPTION: " + ex); 817 System.out.println(ex.getMessage() + " \n"); 818 } 819 } 820 821 if (foundExpectedError == false) { 822 System.out.println("Error code was not AWS_IO_DNS_INVALID_NAME like expected! There was an exception though"); 823 } 824 if (exceptionOccurred == false) { 825 fail("No exception occurred!"); 826 } 827 } 828 } catch (Exception ex) { 829 fail(ex.getMessage()); 830 } 831 } 832 833 /* Client connect with invalid, nonexistent port for direct connection */ 834 @Test ConnNegativeID_UC2()835 public void ConnNegativeID_UC2() { 836 skipIfNetworkUnavailable(); 837 Assume.assumeNotNull(AWS_TEST_MQTT5_DIRECT_MQTT_HOST); 838 boolean foundExpectedError = false; 839 boolean exceptionOccurred = false; 840 841 try { 842 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 843 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_DIRECT_MQTT_HOST, 65535L); 844 builder.withLifecycleEvents(events); 845 builder.withMinReconnectDelayMs(1000L); 846 847 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 848 client.start(); 849 850 try { 851 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 852 } catch (Exception ex) { 853 exceptionOccurred = true; 854 if (events.connectFailureCode == 1047) { 855 foundExpectedError = true; 856 } 857 } 858 859 if (foundExpectedError == false) { 860 System.out.println("Error code was not AWS_IO_SOCKET_CONNECTION_REFUSED like expected! There was an exception though"); 861 } 862 if (exceptionOccurred == false) { 863 fail("No exception occurred!"); 864 } 865 } 866 867 } catch (Exception ex) { 868 fail(ex.getMessage()); 869 } 870 } 871 872 /* Client connect with invalid protocol port for direct connection */ 873 @Test ConnNegativeID_UC2_ALT()874 public void ConnNegativeID_UC2_ALT() { 875 skipIfNetworkUnavailable(); 876 Assume.assumeNotNull(AWS_TEST_MQTT5_DIRECT_MQTT_HOST, AWS_TEST_MQTT5_WS_MQTT_PORT); 877 boolean foundExpectedError = false; 878 boolean exceptionOccurred = false; 879 880 try { 881 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 882 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder( 883 AWS_TEST_MQTT5_DIRECT_MQTT_HOST, Long.parseLong(AWS_TEST_MQTT5_WS_MQTT_PORT)); 884 builder.withLifecycleEvents(events); 885 886 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 887 client.start(); 888 889 try { 890 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 891 } catch (Exception ex) { 892 exceptionOccurred = true; 893 if (events.connectFailureCode == 5149) { 894 foundExpectedError = true; 895 } 896 } 897 898 if (foundExpectedError == false) { 899 System.out.println("Error code was not AWS_ERROR_MQTT5_DECODE_PROTOCOL_ERROR like expected! There was an exception though"); 900 } 901 if (exceptionOccurred == false) { 902 fail("No exception occurred!"); 903 } 904 } 905 906 } catch (Exception ex) { 907 fail(ex.getMessage()); 908 } 909 } 910 911 /* Client connect with invalid, nonexistent port for websocket connection */ 912 @Test ConnNegativeID_UC3()913 public void ConnNegativeID_UC3() { 914 skipIfNetworkUnavailable(); 915 Assume.assumeNotNull(AWS_TEST_MQTT5_WS_MQTT_HOST); 916 boolean foundExpectedError = false; 917 boolean exceptionOccurred = false; 918 919 try { 920 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 921 922 try ( 923 EventLoopGroup elg = new EventLoopGroup(1); 924 HostResolver hr = new HostResolver(elg); 925 ClientBootstrap bootstrap = new ClientBootstrap(elg, hr); 926 ) { 927 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_WS_MQTT_HOST, 444L); 928 builder.withLifecycleEvents(events); 929 builder.withBootstrap(bootstrap); 930 931 Consumer<Mqtt5WebsocketHandshakeTransformArgs> websocketTransform = new Consumer<Mqtt5WebsocketHandshakeTransformArgs>() { 932 @Override 933 public void accept(Mqtt5WebsocketHandshakeTransformArgs t) { 934 t.complete(t.getHttpRequest()); 935 } 936 }; 937 builder.withWebsocketHandshakeTransform(websocketTransform); 938 939 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 940 client.start(); 941 942 try { 943 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 944 } catch (Exception ex) { 945 exceptionOccurred = true; 946 if (events.connectFailureCode == 1047) { 947 foundExpectedError = true; 948 } 949 } 950 951 if (foundExpectedError == false) { 952 System.out.println("Error code was not AWS_ERROR_MQTT5_DECODE_PROTOCOL_ERROR like expected! There was an exception though"); 953 } 954 if (exceptionOccurred == false) { 955 fail("No exception occurred!"); 956 } 957 } 958 } 959 } catch (Exception ex) { 960 fail(ex.getMessage()); 961 } 962 } 963 964 /* Client connect with invalid protocol port for websocket connection */ 965 @Test ConnNegativeID_UC3_ALT()966 public void ConnNegativeID_UC3_ALT() { 967 skipIfNetworkUnavailable(); 968 Assume.assumeNotNull(AWS_TEST_MQTT5_WS_MQTT_HOST, AWS_TEST_MQTT5_DIRECT_MQTT_PORT); 969 boolean foundExpectedError = false; 970 boolean exceptionOccurred = false; 971 972 try { 973 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 974 975 try ( 976 EventLoopGroup elg = new EventLoopGroup(1); 977 HostResolver hr = new HostResolver(elg); 978 ClientBootstrap bootstrap = new ClientBootstrap(elg, hr); 979 ) { 980 981 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder( 982 AWS_TEST_MQTT5_WS_MQTT_HOST, Long.parseLong(AWS_TEST_MQTT5_DIRECT_MQTT_PORT)); 983 builder.withLifecycleEvents(events); 984 builder.withBootstrap(bootstrap); 985 986 Consumer<Mqtt5WebsocketHandshakeTransformArgs> websocketTransform = new Consumer<Mqtt5WebsocketHandshakeTransformArgs>() { 987 @Override 988 public void accept(Mqtt5WebsocketHandshakeTransformArgs t) { 989 t.complete(t.getHttpRequest()); 990 } 991 }; 992 builder.withWebsocketHandshakeTransform(websocketTransform); 993 994 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 995 client.start(); 996 try { 997 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 998 } catch (Exception ex) { 999 exceptionOccurred = true; 1000 if (events.connectFailureCode == 46) { 1001 foundExpectedError = true; 1002 } 1003 } 1004 1005 if (foundExpectedError == false) { 1006 System.out.println("Error code was not AWS_ERROR_SYS_CALL_FAILURE (occurs right after AWS_ERROR_MQTT5_DECODE_PROTOCOL_ERROR for Websockets) like expected! There was an exception though"); 1007 } 1008 if (exceptionOccurred == false) { 1009 fail("No exception occurred!"); 1010 } 1011 } 1012 } 1013 } catch (Exception ex) { 1014 fail(ex.getMessage()); 1015 } 1016 } 1017 1018 /* Client connect with socket timeout */ 1019 @Test ConnNegativeID_UC4()1020 public void ConnNegativeID_UC4() { 1021 skipIfNetworkUnavailable(); 1022 boolean foundExpectedError = false; 1023 boolean exceptionOccurred = false; 1024 1025 try { 1026 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 1027 1028 try ( 1029 EventLoopGroup elg = new EventLoopGroup(1); 1030 HostResolver hr = new HostResolver(elg); 1031 ClientBootstrap bootstrap = new ClientBootstrap(elg, hr); 1032 SocketOptions options = new SocketOptions(); 1033 ) { 1034 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder("www.example.com", 81L); 1035 builder.withLifecycleEvents(events); 1036 builder.withBootstrap(bootstrap); 1037 1038 options.connectTimeoutMs = 100; 1039 builder.withSocketOptions(options); 1040 1041 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 1042 client.start(); 1043 1044 try { 1045 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1046 } catch (Exception ex) { 1047 exceptionOccurred = true; 1048 if (events.connectFailureCode == 1048) { 1049 foundExpectedError = true; 1050 } 1051 } 1052 if (foundExpectedError == false) { 1053 System.out.println("Error code was not AWS_IO_SOCKET_TIMEOUT like expected! There was an exception though"); 1054 } 1055 if (exceptionOccurred == false) { 1056 fail("No exception occurred!"); 1057 } 1058 } 1059 } 1060 1061 } catch (Exception ex) { 1062 fail(ex.getMessage()); 1063 } 1064 } 1065 1066 /* Websocket handshake failure test */ 1067 @Test ConnNegativeID_UC6()1068 public void ConnNegativeID_UC6() { 1069 skipIfNetworkUnavailable(); 1070 Assume.assumeNotNull(AWS_TEST_MQTT5_WS_MQTT_HOST, AWS_TEST_MQTT5_WS_MQTT_PORT); 1071 boolean foundExpectedError = false; 1072 boolean exceptionOccurred = false; 1073 1074 try { 1075 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 1076 1077 try ( 1078 EventLoopGroup elg = new EventLoopGroup(1); 1079 HostResolver hr = new HostResolver(elg); 1080 ClientBootstrap bootstrap = new ClientBootstrap(elg, hr); 1081 ) { 1082 1083 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder( 1084 AWS_TEST_MQTT5_WS_MQTT_HOST, Long.parseLong(AWS_TEST_MQTT5_WS_MQTT_PORT)); 1085 builder.withLifecycleEvents(events); 1086 builder.withBootstrap(bootstrap); 1087 1088 Consumer<Mqtt5WebsocketHandshakeTransformArgs> websocketTransform = new Consumer<Mqtt5WebsocketHandshakeTransformArgs>() { 1089 @Override 1090 public void accept(Mqtt5WebsocketHandshakeTransformArgs t) { 1091 t.completeExceptionally(new Throwable("Intentional failure!")); 1092 } 1093 }; 1094 builder.withWebsocketHandshakeTransform(websocketTransform); 1095 1096 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 1097 client.start(); 1098 1099 try { 1100 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1101 } catch (Exception ex) { 1102 exceptionOccurred = true; 1103 if (events.connectFailureCode == 3) { 1104 foundExpectedError = true; 1105 } 1106 } 1107 if (foundExpectedError == false) { 1108 System.out.println("Error code was not AWS_ERROR_UNKNOWN like expected! There was an exception though"); 1109 } 1110 if (exceptionOccurred == false) { 1111 fail("No exception occurred!"); 1112 } 1113 1114 client.stop(); 1115 } 1116 } 1117 } catch (Exception ex) { 1118 fail(ex.getMessage()); 1119 } 1120 } 1121 1122 /* For the double client ID test */ 1123 static final class LifecycleEvents_DoubleClientID implements Mqtt5ClientOptions.LifecycleEvents { 1124 CompletableFuture<Void> connectedFuture = new CompletableFuture<>(); 1125 CompletableFuture<Void> disconnectedFuture = new CompletableFuture<>(); 1126 CompletableFuture<Void> stoppedFuture = new CompletableFuture<>(); 1127 String client_name = ""; 1128 1129 @Override onAttemptingConnect(Mqtt5Client client, OnAttemptingConnectReturn onAttemptingConnectReturn)1130 public void onAttemptingConnect(Mqtt5Client client, OnAttemptingConnectReturn onAttemptingConnectReturn) {} 1131 1132 @Override onConnectionSuccess(Mqtt5Client client, OnConnectionSuccessReturn onConnectionSuccessReturn)1133 public void onConnectionSuccess(Mqtt5Client client, OnConnectionSuccessReturn onConnectionSuccessReturn) { 1134 connectedFuture.complete(null); 1135 } 1136 1137 @Override onConnectionFailure(Mqtt5Client client, OnConnectionFailureReturn onConnectionFailureReturn)1138 public void onConnectionFailure(Mqtt5Client client, OnConnectionFailureReturn onConnectionFailureReturn) { 1139 connectedFuture.completeExceptionally(new Exception( 1140 "[" + client_name + "] Could not connect! Error code is: " + onConnectionFailureReturn.getErrorCode() 1141 )); 1142 } 1143 1144 @Override onDisconnection(Mqtt5Client client, OnDisconnectionReturn onDisconnectionReturn)1145 public void onDisconnection(Mqtt5Client client, OnDisconnectionReturn onDisconnectionReturn) { 1146 disconnectedFuture.complete(null); 1147 } 1148 1149 @Override onStopped(Mqtt5Client client, OnStoppedReturn onStoppedReturn)1150 public void onStopped(Mqtt5Client client, OnStoppedReturn onStoppedReturn) { 1151 stoppedFuture.complete(null); 1152 } 1153 } 1154 1155 /* Double Client ID failure test */ 1156 @Test ConnNegativeID_UC7()1157 public void ConnNegativeID_UC7() { 1158 skipIfNetworkUnavailable(); 1159 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1160 String testUUID = UUID.randomUUID().toString(); 1161 1162 try { 1163 LifecycleEvents_DoubleClientID eventsOne = new LifecycleEvents_DoubleClientID(); 1164 LifecycleEvents_DoubleClientID eventsTwo = new LifecycleEvents_DoubleClientID(); 1165 eventsOne.client_name = "client_one"; 1166 eventsTwo.client_name = "client_two"; 1167 1168 ConnectPacketBuilder connectOptions = new ConnectPacketBuilder().withClientId("test/MQTT5_Java_Double_ClientIDFail_" + testUUID); 1169 1170 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 1171 builder.withLifecycleEvents(eventsOne); 1172 builder.withConnectOptions(connectOptions.build()); 1173 builder.withConnackTimeoutMs(30000l); // 30 seconds 1174 1175 Mqtt5ClientOptionsBuilder builderTwo = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 1176 builderTwo.withLifecycleEvents(eventsTwo); 1177 builderTwo.withConnectOptions(connectOptions.build()); 1178 builderTwo.withConnackTimeoutMs(30000l); // 30 seconds 1179 1180 try (TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 1181 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1182 TlsContext tlsContext = new TlsContext(tlsOptions)) 1183 { 1184 builder.withTlsContext(tlsContext); 1185 builderTwo.withTlsContext(tlsContext); 1186 try (Mqtt5Client clientOne = new Mqtt5Client(builder.build()); 1187 Mqtt5Client clientTwo = new Mqtt5Client(builderTwo.build());) { 1188 clientOne.start(); 1189 eventsOne.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1190 1191 Thread.sleep(2000); // Sleep for 2 seconds to not hit IoT Core limits 1192 1193 clientTwo.start(); 1194 eventsTwo.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1195 1196 // Make sure a disconnection for client 1 happened 1197 eventsOne.disconnectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1198 1199 // Stop the clients from disconnecting each other. If we do not do this, then the clients will 1200 // attempt to reconnect endlessly, making a never ending loop. 1201 clientOne.stop(); 1202 clientTwo.stop(); 1203 } 1204 } 1205 } catch (Exception ex) { 1206 fail(ex.getMessage()); 1207 } 1208 } 1209 1210 /** 1211 * ============================================================ 1212 * Negative Data Input Tests 1213 * ============================================================ 1214 */ 1215 1216 /* Negative Connect Packet Properties */ 1217 @Test NewNegative_UC1()1218 public void NewNegative_UC1() { 1219 skipIfNetworkUnavailable(); 1220 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1221 boolean clientCreationFailed = false; 1222 1223 try { 1224 Mqtt5Client client = null; 1225 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 1226 ConnectPacketBuilder connectOptions = new ConnectPacketBuilder(); 1227 1228 connectOptions.withKeepAliveIntervalSeconds(-100L); 1229 builder.withConnectOptions(connectOptions.build()); 1230 1231 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 1232 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1233 TlsContext tlsContext = new TlsContext(tlsOptions); 1234 tlsOptions.close(); 1235 builder.withTlsContext(tlsContext); 1236 1237 clientCreationFailed = false; 1238 try { 1239 client = new Mqtt5Client(builder.build()); 1240 } catch (Exception ex) { 1241 clientCreationFailed = true; 1242 } 1243 if (clientCreationFailed == false) { 1244 fail("Client creation did not fail with negative KeepAliveIntervalSeconds"); 1245 } 1246 connectOptions.withKeepAliveIntervalSeconds(100L); 1247 1248 connectOptions.withSessionExpiryIntervalSeconds(-100L); 1249 builder.withConnectOptions(connectOptions.build()); 1250 clientCreationFailed = false; 1251 try { 1252 client = new Mqtt5Client(builder.build()); 1253 } catch (Exception ex) { 1254 clientCreationFailed = true; 1255 } 1256 if (clientCreationFailed == false) { 1257 fail("Client creation did not fail with negative SessionExpiryIntervalSeconds"); 1258 } 1259 connectOptions.withSessionExpiryIntervalSeconds(100L); 1260 1261 connectOptions.withReceiveMaximum(-100L); 1262 builder.withConnectOptions(connectOptions.build()); 1263 clientCreationFailed = false; 1264 try { 1265 client = new Mqtt5Client(builder.build()); 1266 } catch (Exception ex) { 1267 clientCreationFailed = true; 1268 } 1269 if (clientCreationFailed == false) { 1270 fail("Client creation did not fail negative ReceiveMaximum"); 1271 } 1272 connectOptions.withReceiveMaximum(100L); 1273 1274 connectOptions.withMaximumPacketSizeBytes(-100L); 1275 builder.withConnectOptions(connectOptions.build()); 1276 clientCreationFailed = false; 1277 try { 1278 client = new Mqtt5Client(builder.build()); 1279 } catch (Exception ex) { 1280 clientCreationFailed = true; 1281 } 1282 if (clientCreationFailed == false) { 1283 fail("Client creation did not fail with negative MaximumPacketSizeBytes"); 1284 } 1285 connectOptions.withMaximumPacketSizeBytes(100L); 1286 1287 connectOptions.withWillDelayIntervalSeconds(-100L); 1288 builder.withConnectOptions(connectOptions.build()); 1289 clientCreationFailed = false; 1290 try { 1291 client = new Mqtt5Client(builder.build()); 1292 } catch (Exception ex) { 1293 clientCreationFailed = true; 1294 } 1295 if (clientCreationFailed == false) { 1296 fail("Client creation did not fail with negative willDelayIntervalSeconds"); 1297 } 1298 connectOptions.withWillDelayIntervalSeconds(100L); 1299 1300 // Make sure everything is closed 1301 if (client != null) { 1302 client.close(); 1303 } 1304 if (tlsContext != null) { 1305 tlsContext.close(); 1306 } 1307 1308 } catch (Exception ex) { 1309 fail(ex.getMessage()); 1310 } 1311 } 1312 1313 /* Overflow Connect Packet Properties */ 1314 @Test NewNegative_UC1_ALT()1315 public void NewNegative_UC1_ALT() { 1316 skipIfNetworkUnavailable(); 1317 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1318 boolean clientCreationFailed = false; 1319 1320 try { 1321 Mqtt5Client client = null; 1322 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 1323 ConnectPacketBuilder connectOptions = new ConnectPacketBuilder(); 1324 1325 connectOptions.withKeepAliveIntervalSeconds(2147483647L); 1326 builder.withConnectOptions(connectOptions.build()); 1327 1328 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 1329 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1330 TlsContext tlsContext = new TlsContext(tlsOptions); 1331 tlsOptions.close(); 1332 builder.withTlsContext(tlsContext); 1333 1334 clientCreationFailed = false; 1335 try { 1336 client = new Mqtt5Client(builder.build()); 1337 } catch (Exception ex) { 1338 clientCreationFailed = true; 1339 } 1340 if (clientCreationFailed == false) { 1341 fail("Client creation did not fail with overflow KeepAliveIntervalSeconds"); 1342 } 1343 connectOptions.withKeepAliveIntervalSeconds(100L); 1344 1345 connectOptions.withSessionExpiryIntervalSeconds(9223372036854775807L); 1346 builder.withConnectOptions(connectOptions.build()); 1347 clientCreationFailed = false; 1348 try { 1349 client = new Mqtt5Client(builder.build()); 1350 } catch (Exception ex) { 1351 clientCreationFailed = true; 1352 } 1353 if (clientCreationFailed == false) { 1354 fail("Client creation did not fail with overflow SessionExpiryIntervalSeconds"); 1355 } 1356 connectOptions.withSessionExpiryIntervalSeconds(100L); 1357 1358 connectOptions.withReceiveMaximum(2147483647L); 1359 builder.withConnectOptions(connectOptions.build()); 1360 clientCreationFailed = false; 1361 try { 1362 client = new Mqtt5Client(builder.build()); 1363 } catch (Exception ex) { 1364 clientCreationFailed = true; 1365 } 1366 if (clientCreationFailed == false) { 1367 fail("Client creation did not fail overflow ReceiveMaximum"); 1368 } 1369 connectOptions.withReceiveMaximum(100L); 1370 1371 connectOptions.withMaximumPacketSizeBytes(9223372036854775807L); 1372 builder.withConnectOptions(connectOptions.build()); 1373 clientCreationFailed = false; 1374 try { 1375 client = new Mqtt5Client(builder.build()); 1376 } catch (Exception ex) { 1377 clientCreationFailed = true; 1378 } 1379 if (clientCreationFailed == false) { 1380 fail("Client creation did not fail with overflow MaximumPacketSizeBytes"); 1381 } 1382 connectOptions.withMaximumPacketSizeBytes(100L); 1383 1384 // WillDelayIntervalSeconds is an unsigned 64 bit Long, so it cannot overflow it from Java 1385 1386 // Make sure everything is closed 1387 if (client != null) { 1388 client.close(); 1389 } 1390 if (tlsContext != null) { 1391 tlsContext.close(); 1392 } 1393 1394 } catch (Exception ex) { 1395 fail(ex.getMessage()); 1396 } 1397 } 1398 1399 /* Negative Disconnect Packet Properties */ 1400 @Test NewNegative_UC2()1401 public void NewNegative_UC2() { 1402 skipIfNetworkUnavailable(); 1403 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1404 boolean clientDisconnectFailed = false; 1405 1406 try { 1407 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 1408 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 1409 builder.withLifecycleEvents(events); 1410 1411 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 1412 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1413 TlsContext tlsContext = new TlsContext(tlsOptions); 1414 tlsOptions.close(); 1415 builder.withTlsContext(tlsContext); 1416 1417 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 1418 client.start(); 1419 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1420 1421 DisconnectPacketBuilder disconnectBuilder = new DisconnectPacketBuilder(); 1422 disconnectBuilder.withSessionExpiryIntervalSeconds(-100L); 1423 try { 1424 client.stop(disconnectBuilder.build()); 1425 } catch (Exception ex) { 1426 clientDisconnectFailed = true; 1427 } 1428 1429 if (clientDisconnectFailed == false) { 1430 fail("Client disconnect packet creation did not fail!"); 1431 } 1432 1433 client.stop(new DisconnectPacketBuilder().build()); 1434 } 1435 1436 if (tlsContext != null) { 1437 tlsContext.close(); 1438 } 1439 1440 } catch (Exception ex) { 1441 fail(ex.getMessage()); 1442 } 1443 } 1444 1445 /* Overflow Disconnect Packet Properties */ 1446 @Test NewNegative_UC2_ALT()1447 public void NewNegative_UC2_ALT() { 1448 skipIfNetworkUnavailable(); 1449 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1450 boolean clientDisconnectFailed = false; 1451 1452 try { 1453 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 1454 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 1455 builder.withLifecycleEvents(events); 1456 1457 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 1458 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1459 TlsContext tlsContext = new TlsContext(tlsOptions); 1460 tlsOptions.close(); 1461 builder.withTlsContext(tlsContext); 1462 1463 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 1464 client.start(); 1465 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1466 1467 DisconnectPacketBuilder disconnectBuilder = new DisconnectPacketBuilder(); 1468 disconnectBuilder.withSessionExpiryIntervalSeconds(9223372036854775807L); 1469 try { 1470 client.stop(disconnectBuilder.build()); 1471 } catch (Exception ex) { 1472 clientDisconnectFailed = true; 1473 } 1474 1475 if (clientDisconnectFailed == false) { 1476 fail("Client disconnect did not fail!"); 1477 } 1478 1479 client.stop(new DisconnectPacketBuilder().build()); 1480 } 1481 1482 if (tlsContext != null) { 1483 tlsContext.close(); 1484 } 1485 1486 } catch (Exception ex) { 1487 fail(ex.getMessage()); 1488 } 1489 } 1490 1491 /* Negative Publish Packet Properties */ 1492 @Test NewNegative_UC3()1493 public void NewNegative_UC3() { 1494 skipIfNetworkUnavailable(); 1495 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1496 boolean clientPublishFailed = false; 1497 1498 try { 1499 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 1500 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 1501 builder.withLifecycleEvents(events); 1502 1503 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 1504 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1505 TlsContext tlsContext = new TlsContext(tlsOptions); 1506 tlsOptions.close(); 1507 builder.withTlsContext(tlsContext); 1508 1509 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 1510 client.start(); 1511 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1512 1513 PublishPacketBuilder publishBuilder = new PublishPacketBuilder(); 1514 publishBuilder.withPayload("Hello World".getBytes()).withTopic("test/topic"); 1515 publishBuilder.withMessageExpiryIntervalSeconds(-100L); 1516 try { 1517 CompletableFuture<PublishResult> future = client.publish(publishBuilder.build()); 1518 future.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1519 } catch (Exception ex) { 1520 clientPublishFailed = true; 1521 } 1522 1523 if (clientPublishFailed == false) { 1524 fail("Client publish did not fail!"); 1525 } 1526 1527 client.stop(); 1528 } 1529 1530 if (tlsContext != null) { 1531 tlsContext.close(); 1532 } 1533 1534 } catch (Exception ex) { 1535 fail(ex.getMessage()); 1536 } 1537 } 1538 1539 /* Overflow Publish Packet Properties */ 1540 @Test NewNegative_UC3_ALT()1541 public void NewNegative_UC3_ALT() { 1542 skipIfNetworkUnavailable(); 1543 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1544 boolean clientPublishFailed = false; 1545 1546 try { 1547 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 1548 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 1549 builder.withLifecycleEvents(events); 1550 1551 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 1552 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1553 TlsContext tlsContext = new TlsContext(tlsOptions); 1554 tlsOptions.close(); 1555 builder.withTlsContext(tlsContext); 1556 1557 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 1558 client.start(); 1559 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1560 1561 PublishPacketBuilder publishBuilder = new PublishPacketBuilder(); 1562 publishBuilder.withPayload("Hello World".getBytes()).withTopic("test/topic").withQOS(QOS.AT_LEAST_ONCE); 1563 publishBuilder.withMessageExpiryIntervalSeconds(9223372036854775807L); 1564 try { 1565 CompletableFuture<PublishResult> future = client.publish(publishBuilder.build()); 1566 future.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1567 } catch (Exception ex) { 1568 clientPublishFailed = true; 1569 } 1570 1571 if (clientPublishFailed == false) { 1572 fail("Client publish did not fail!"); 1573 } 1574 1575 client.stop(); 1576 } 1577 1578 if (tlsContext != null) { 1579 tlsContext.close(); 1580 } 1581 1582 } catch (Exception ex) { 1583 fail(ex.getMessage()); 1584 } 1585 } 1586 1587 /* Negative Subscribe Packet Properties */ 1588 @Test NewNegative_UC4()1589 public void NewNegative_UC4() { 1590 skipIfNetworkUnavailable(); 1591 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1592 boolean clientSubscribeFailed = false; 1593 1594 try { 1595 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 1596 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 1597 builder.withLifecycleEvents(events); 1598 1599 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 1600 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1601 TlsContext tlsContext = new TlsContext(tlsOptions); 1602 tlsOptions.close(); 1603 builder.withTlsContext(tlsContext); 1604 1605 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 1606 client.start(); 1607 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1608 1609 SubscribePacketBuilder subscribeBuilder = new SubscribePacketBuilder(); 1610 subscribeBuilder.withSubscription("test/topic", QOS.AT_LEAST_ONCE); 1611 subscribeBuilder.withSubscriptionIdentifier(-100L); 1612 try { 1613 CompletableFuture<SubAckPacket> future = client.subscribe(subscribeBuilder.build()); 1614 future.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1615 } catch (Exception ex) { 1616 clientSubscribeFailed = true; 1617 } 1618 1619 if (clientSubscribeFailed == false) { 1620 fail("Client subscribe did not fail!"); 1621 } 1622 1623 client.stop(); 1624 } 1625 1626 if (tlsContext != null) { 1627 tlsContext.close(); 1628 } 1629 1630 } catch (Exception ex) { 1631 fail(ex.getMessage()); 1632 } 1633 } 1634 1635 /* Overflow Subscribe Packet Properties */ 1636 @Test NewNegative_UC4_ALT()1637 public void NewNegative_UC4_ALT() { 1638 skipIfNetworkUnavailable(); 1639 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1640 boolean clientSubscribeFailed = false; 1641 1642 try { 1643 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 1644 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 1645 builder.withLifecycleEvents(events); 1646 1647 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 1648 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1649 TlsContext tlsContext = new TlsContext(tlsOptions); 1650 tlsOptions.close(); 1651 builder.withTlsContext(tlsContext); 1652 1653 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 1654 client.start(); 1655 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1656 1657 SubscribePacketBuilder subscribeBuilder = new SubscribePacketBuilder(); 1658 subscribeBuilder.withSubscription("test/topic", QOS.AT_LEAST_ONCE); 1659 subscribeBuilder.withSubscriptionIdentifier(9223372036854775807L); 1660 try { 1661 CompletableFuture<SubAckPacket> future = client.subscribe(subscribeBuilder.build()); 1662 future.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1663 } catch (Exception ex) { 1664 clientSubscribeFailed = true; 1665 } 1666 1667 if (clientSubscribeFailed == false) { 1668 fail("Client subscribe did not fail!"); 1669 } 1670 1671 client.stop(); 1672 } 1673 1674 if (tlsContext != null) { 1675 tlsContext.close(); 1676 } 1677 1678 } catch (Exception ex) { 1679 fail(ex.getMessage()); 1680 } 1681 } 1682 1683 /** 1684 * ============================================================ 1685 * Negotiated Settings Tests 1686 * ============================================================ 1687 */ 1688 1689 /* Happy path, minimal success test */ 1690 @Test Negotiated_UC1()1691 public void Negotiated_UC1() { 1692 skipIfNetworkUnavailable(); 1693 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1694 try { 1695 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 1696 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 1697 builder.withLifecycleEvents(events); 1698 1699 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 1700 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1701 TlsContext tlsContext = new TlsContext(tlsOptions); 1702 tlsOptions.close(); 1703 builder.withTlsContext(tlsContext); 1704 1705 ConnectPacketBuilder optionsBuilder = new ConnectPacketBuilder(); 1706 optionsBuilder.withSessionExpiryIntervalSeconds(600000L); 1707 builder.withConnectOptions(optionsBuilder.build()); 1708 1709 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 1710 client.start(); 1711 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1712 1713 // TODO: Add support for this in the future 1714 // assertEquals( 1715 // "Negotiated Settings session expiry interval does not match sent session expiry interval", 1716 // events.connectSuccessSettings.getSessionExpiryIntervalSeconds(), 1717 // 600000L); 1718 1719 client.stop(); 1720 } 1721 1722 if (tlsContext != null) { 1723 tlsContext.close(); 1724 } 1725 1726 } catch (Exception ex) { 1727 fail(ex.getMessage()); 1728 } 1729 } 1730 1731 /* Maximum success test */ 1732 @Test Negotiated_UC2()1733 public void Negotiated_UC2() { 1734 skipIfNetworkUnavailable(); 1735 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1736 String testUUID = UUID.randomUUID().toString(); 1737 try { 1738 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 1739 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 1740 builder.withLifecycleEvents(events); 1741 1742 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 1743 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1744 TlsContext tlsContext = new TlsContext(tlsOptions); 1745 tlsOptions.close(); 1746 builder.withTlsContext(tlsContext); 1747 1748 ConnectPacketBuilder optionsBuilder = new ConnectPacketBuilder(); 1749 optionsBuilder.withClientId("test/MQTT5_Binding_Java_" + testUUID); 1750 optionsBuilder.withSessionExpiryIntervalSeconds(0L); 1751 optionsBuilder.withKeepAliveIntervalSeconds(360L); 1752 builder.withConnectOptions(optionsBuilder.build()); 1753 1754 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 1755 client.start(); 1756 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1757 1758 assertEquals( 1759 "Negotiated Settings client ID does not match sent client ID", 1760 events.connectSuccessSettings.getAssignedClientID(), 1761 "test/MQTT5_Binding_Java_" + testUUID); 1762 assertEquals( 1763 "Negotiated Settings session expiry interval does not match sent session expiry interval", 1764 events.connectSuccessSettings.getSessionExpiryIntervalSeconds(), 1765 0L); 1766 assertEquals( 1767 "Negotiated Settings keep alive result does not match sent keep alive", 1768 events.connectSuccessSettings.getServerKeepAliveSeconds(), 1769 360); 1770 assertEquals( 1771 "Negotiated Settings rejoined session does not match expected value", 1772 false, 1773 events.connectSuccessSettings.getRejoinedSession()); 1774 1775 client.stop(); 1776 } 1777 1778 if (tlsContext != null) { 1779 tlsContext.close(); 1780 } 1781 1782 } catch (Exception ex) { 1783 fail(ex.getMessage()); 1784 } 1785 } 1786 1787 /* Rejoin always session resumption test */ 1788 @Test Negotiated_Rejoin_Always()1789 public void Negotiated_Rejoin_Always() { 1790 skipIfNetworkUnavailable(); 1791 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1792 String testUUID = UUID.randomUUID().toString(); 1793 try { 1794 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 1795 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 1796 builder.withLifecycleEvents(events); 1797 1798 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 1799 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1800 TlsContext tlsContext = new TlsContext(tlsOptions); 1801 tlsOptions.close(); 1802 builder.withTlsContext(tlsContext); 1803 1804 ConnectPacketBuilder optionsBuilder = new ConnectPacketBuilder(); 1805 optionsBuilder.withClientId("test/MQTT5_Binding_Java_" + testUUID); 1806 optionsBuilder.withSessionExpiryIntervalSeconds(3600L); 1807 optionsBuilder.withKeepAliveIntervalSeconds(360L); 1808 builder.withConnectOptions(optionsBuilder.build()); 1809 1810 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 1811 client.start(); 1812 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1813 1814 assertEquals( 1815 "Negotiated Settings client ID does not match sent client ID", 1816 events.connectSuccessSettings.getAssignedClientID(), 1817 "test/MQTT5_Binding_Java_" + testUUID); 1818 assertEquals( 1819 "Negotiated Settings session expiry interval does not match sent session expiry interval", 1820 events.connectSuccessSettings.getSessionExpiryIntervalSeconds(), 1821 3600L); 1822 assertEquals( 1823 "Negotiated Settings keep alive result does not match sent keep alive", 1824 events.connectSuccessSettings.getServerKeepAliveSeconds(), 1825 360); 1826 assertEquals( 1827 "Negotiated Settings rejoined session does not match expected value", 1828 false, 1829 events.connectSuccessSettings.getRejoinedSession()); 1830 1831 client.stop(); 1832 events.stopFuture.get(); 1833 } 1834 1835 builder.withSessionBehavior(ClientSessionBehavior.REJOIN_ALWAYS); 1836 LifecycleEvents_Futured rejoinEvents = new LifecycleEvents_Futured(); 1837 builder.withLifecycleEvents(rejoinEvents); 1838 1839 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 1840 client.start(); 1841 rejoinEvents.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1842 1843 assertEquals( 1844 "Negotiated Settings rejoined session does not match expected value", 1845 true, 1846 rejoinEvents.connectSuccessSettings.getRejoinedSession()); 1847 1848 client.stop(); 1849 } 1850 1851 if (tlsContext != null) { 1852 tlsContext.close(); 1853 } 1854 1855 } catch (Exception ex) { 1856 fail(ex.getMessage()); 1857 } 1858 } 1859 1860 /** 1861 * ============================================================ 1862 * Operation Tests 1863 * ============================================================ 1864 */ 1865 1866 /* Sub-UnSub happy path */ 1867 @Test Op_UC1()1868 public void Op_UC1() { 1869 skipIfNetworkUnavailable(); 1870 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1871 String testUUID = UUID.randomUUID().toString(); 1872 String testTopic = "test/MQTT5_Binding_Java_" + testUUID; 1873 try { 1874 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 1875 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 1876 builder.withLifecycleEvents(events); 1877 1878 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 1879 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1880 TlsContext tlsContext = new TlsContext(tlsOptions); 1881 tlsOptions.close(); 1882 builder.withTlsContext(tlsContext); 1883 1884 PublishEvents_Futured publishEvents = new PublishEvents_Futured(); 1885 builder.withPublishEvents(publishEvents); 1886 1887 PublishPacketBuilder publishPacketBuilder = new PublishPacketBuilder(); 1888 publishPacketBuilder.withTopic(testTopic); 1889 publishPacketBuilder.withPayload("Hello World".getBytes()); 1890 publishPacketBuilder.withQOS(QOS.AT_LEAST_ONCE); 1891 1892 SubscribePacketBuilder subscribePacketBuilder = new SubscribePacketBuilder(); 1893 subscribePacketBuilder.withSubscription(testTopic, QOS.AT_LEAST_ONCE); 1894 1895 UnsubscribePacketBuilder unsubscribePacketBuilder = new UnsubscribePacketBuilder(); 1896 unsubscribePacketBuilder.withSubscription(testTopic); 1897 1898 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 1899 client.start(); 1900 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1901 1902 client.subscribe(subscribePacketBuilder.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1903 1904 client.publish(publishPacketBuilder.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1905 publishEvents.publishReceivedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1906 1907 publishEvents.publishReceivedFuture = new CompletableFuture<>(); 1908 publishEvents.publishPacket = null; 1909 client.unsubscribe(unsubscribePacketBuilder.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1910 client.publish(publishPacketBuilder.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1911 1912 assertEquals( 1913 "Publish after unsubscribe still arrived!", 1914 publishEvents.publishPacket, 1915 null); 1916 1917 client.stop(); 1918 } 1919 1920 if (tlsContext != null) { 1921 tlsContext.close(); 1922 } 1923 1924 } catch (Exception ex) { 1925 fail(ex.getMessage()); 1926 } 1927 } 1928 1929 /* Sub-UnSub happy path */ 1930 @Test Op_UC2()1931 public void Op_UC2() { 1932 skipIfNetworkUnavailable(); 1933 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1934 String testUUID = UUID.randomUUID().toString(); 1935 String testTopic = "test/MQTT5_Binding_Java_" + testUUID; 1936 try { 1937 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 1938 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 1939 builder.withLifecycleEvents(events); 1940 1941 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 1942 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1943 TlsContext tlsContext = new TlsContext(tlsOptions); 1944 tlsOptions.close(); 1945 builder.withTlsContext(tlsContext); 1946 1947 ConnectPacketBuilder connectOptions = new ConnectPacketBuilder(); 1948 PublishPacketBuilder willPacket = new PublishPacketBuilder(); 1949 willPacket.withTopic(testTopic); 1950 willPacket.withQOS(QOS.AT_LEAST_ONCE); 1951 willPacket.withPayload("Hello World".getBytes()); 1952 connectOptions.withWill(willPacket.build()); 1953 connectOptions.withWillDelayIntervalSeconds(0L); 1954 builder.withConnectOptions(connectOptions.build()); 1955 1956 Mqtt5ClientOptionsBuilder builderTwo = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 1957 LifecycleEvents_Futured eventsTwo = new LifecycleEvents_Futured(); 1958 builderTwo.withLifecycleEvents(eventsTwo); 1959 PublishEvents_Futured publishEvents = new PublishEvents_Futured(); 1960 builderTwo.withPublishEvents(publishEvents); 1961 1962 TlsContextOptions tlsOptionsTwo = TlsContextOptions.createWithMtlsFromPath( 1963 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 1964 TlsContext tlsContextTwo = new TlsContext(tlsOptionsTwo); 1965 tlsOptionsTwo.close(); 1966 builderTwo.withTlsContext(tlsContextTwo); 1967 1968 SubscribePacketBuilder subscribeOptions = new SubscribePacketBuilder(); 1969 subscribeOptions.withSubscription(testTopic, QOS.AT_LEAST_ONCE); 1970 1971 try ( 1972 Mqtt5Client clientOne = new Mqtt5Client(builder.build()); 1973 Mqtt5Client clientTwo = new Mqtt5Client(builderTwo.build()); 1974 ) { 1975 clientOne.start(); 1976 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1977 clientTwo.start(); 1978 eventsTwo.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1979 1980 clientTwo.subscribe(subscribeOptions.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1981 clientOne.stop(); 1982 1983 // Did we get a publish message? 1984 publishEvents.publishReceivedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 1985 assertTrue(publishEvents.publishPacket != null); 1986 1987 clientTwo.stop(new DisconnectPacketBuilder().build()); 1988 } 1989 1990 if (tlsContext != null) { 1991 tlsContext.close(); 1992 tlsContextTwo.close(); 1993 } 1994 1995 } catch (Exception ex) { 1996 fail(ex.getMessage()); 1997 } 1998 } 1999 2000 /* Binary Publish Test */ 2001 @Test Op_UC3()2002 public void Op_UC3() { 2003 skipIfNetworkUnavailable(); 2004 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2005 String testUUID = UUID.randomUUID().toString(); 2006 String testTopic = "test/MQTT5_Binding_Java_" + testUUID; 2007 try { 2008 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2009 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 2010 builder.withLifecycleEvents(events); 2011 2012 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 2013 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2014 TlsContext tlsContext = new TlsContext(tlsOptions); 2015 tlsOptions.close(); 2016 builder.withTlsContext(tlsContext); 2017 2018 PublishEvents_Futured publishEvents = new PublishEvents_Futured(); 2019 builder.withPublishEvents(publishEvents); 2020 2021 // Make random binary 2022 byte[] randomBytes = new byte[256]; 2023 Random random = new Random(); 2024 random.nextBytes(randomBytes); 2025 2026 PublishPacketBuilder publishPacketBuilder = new PublishPacketBuilder(); 2027 publishPacketBuilder.withTopic(testTopic).withPayload(randomBytes).withQOS(QOS.AT_LEAST_ONCE); 2028 2029 SubscribePacketBuilder subscribePacketBuilder = new SubscribePacketBuilder(); 2030 subscribePacketBuilder.withSubscription(testTopic, QOS.AT_LEAST_ONCE); 2031 2032 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 2033 client.start(); 2034 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2035 2036 client.subscribe(subscribePacketBuilder.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2037 2038 client.publish(publishPacketBuilder.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2039 publishEvents.publishReceivedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2040 2041 assertTrue(java.util.Arrays.equals(publishEvents.publishPacket.getPayload(), randomBytes)); 2042 2043 client.stop(); 2044 events.stopFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2045 } 2046 2047 if (tlsContext != null) { 2048 tlsContext.close(); 2049 } 2050 2051 } catch (Exception ex) { 2052 fail(ex.getMessage()); 2053 } 2054 } 2055 2056 /* Will test */ 2057 @Test Op_UC4()2058 public void Op_UC4() { 2059 skipIfNetworkUnavailable(); 2060 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2061 String testUUID = UUID.randomUUID().toString(); 2062 String testTopic = "test/MQTT5_Binding_Java_" + testUUID; 2063 try { 2064 // Publisher 2065 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2066 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 2067 builder.withLifecycleEvents(events); 2068 2069 // Subscriber 2070 Mqtt5ClientOptionsBuilder builderTwo = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2071 LifecycleEvents_Futured eventsTwo = new LifecycleEvents_Futured(); 2072 builderTwo.withLifecycleEvents(eventsTwo); 2073 2074 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 2075 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2076 TlsContext tlsContext = new TlsContext(tlsOptions); 2077 tlsOptions.close(); 2078 builder.withTlsContext(tlsContext); 2079 builderTwo.withTlsContext(tlsContext); 2080 2081 PublishEvents_Futured publishEvents = new PublishEvents_Futured(); 2082 builderTwo.withPublishEvents(publishEvents); 2083 SubscribePacketBuilder subscribePacketBuilder = new SubscribePacketBuilder(); 2084 subscribePacketBuilder.withSubscription(testTopic, QOS.AT_LEAST_ONCE); 2085 2086 ConnectPacketBuilder connectPacketBuilder = new ConnectPacketBuilder(); 2087 PublishPacketBuilder publishPacketBuilder = new PublishPacketBuilder(); 2088 publishPacketBuilder.withTopic(testTopic); 2089 publishPacketBuilder.withPayload("Hello World".getBytes()); 2090 publishPacketBuilder.withQOS(QOS.AT_LEAST_ONCE); 2091 connectPacketBuilder.withWill(publishPacketBuilder.build()); 2092 connectPacketBuilder.withKeepAliveIntervalSeconds(4l); 2093 builder.withConnectOptions(connectPacketBuilder.build()); 2094 builder.withPingTimeoutMs(8l); 2095 2096 DisconnectPacketBuilder disconnectPacketBuilder = new DisconnectPacketBuilder(); 2097 disconnectPacketBuilder.withReasonCode(DisconnectReasonCode.DISCONNECT_WITH_WILL_MESSAGE); 2098 2099 try (Mqtt5Client publisher = new Mqtt5Client(builder.build()); 2100 Mqtt5Client subscriber = new Mqtt5Client(builderTwo.build())) { 2101 2102 publisher.start(); 2103 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2104 2105 subscriber.start(); 2106 eventsTwo.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2107 subscriber.subscribe(subscribePacketBuilder.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2108 2109 publisher.stop(disconnectPacketBuilder.build()); 2110 2111 publishEvents.publishReceivedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2112 subscriber.stop(new DisconnectPacketBuilder().build()); 2113 } 2114 2115 if (tlsContext != null) { 2116 tlsContext.close(); 2117 } 2118 2119 } catch (Exception ex) { 2120 fail(ex.getMessage()); 2121 } 2122 } 2123 2124 /* Shared subscriptions test */ 2125 @Test Op_SharedSubscription()2126 public void Op_SharedSubscription() { 2127 skipIfNetworkUnavailable(); 2128 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2129 int messageCount = 10; 2130 String testUUID = UUID.randomUUID().toString(); 2131 String testTopic = "test/MQTT5_Binding_Java_" + testUUID; 2132 String sharedTopicfilter = "$share/crttest/test/MQTT5_Binding_Java_" + testUUID; 2133 2134 try { 2135 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 2136 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2137 TlsContext tlsContext = new TlsContext(tlsOptions); 2138 tlsOptions.close(); 2139 2140 // Publisher builder 2141 Mqtt5ClientOptionsBuilder publisherBuilder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2142 LifecycleEvents_Futured publisherLCEvents = new LifecycleEvents_Futured(); 2143 publisherBuilder.withLifecycleEvents(publisherLCEvents); 2144 publisherBuilder.withTlsContext(tlsContext); 2145 2146 PublishEvents_Futured_Counted publishEvents = new PublishEvents_Futured_Counted(); 2147 publishEvents.desiredPublishCount = messageCount; 2148 2149 // SubscriberOne builder 2150 Mqtt5ClientOptionsBuilder subscriberOneBuilder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2151 LifecycleEvents_Futured subscriberOneLCEvents = new LifecycleEvents_Futured(); 2152 subscriberOneBuilder.withLifecycleEvents(subscriberOneLCEvents); 2153 subscriberOneBuilder.withTlsContext(tlsContext); 2154 subscriberOneBuilder.withPublishEvents(publishEvents); 2155 2156 // SubscriberTwo builder 2157 Mqtt5ClientOptionsBuilder subscriberTwoBuilder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2158 LifecycleEvents_Futured subscriberTwoLCEvents = new LifecycleEvents_Futured(); 2159 subscriberTwoBuilder.withLifecycleEvents(subscriberTwoLCEvents); 2160 subscriberTwoBuilder.withTlsContext(tlsContext); 2161 subscriberTwoBuilder.withPublishEvents(publishEvents); 2162 2163 // PublishPacketBuilder 2164 PublishPacketBuilder publishPacketBuilder = new PublishPacketBuilder(); 2165 publishPacketBuilder.withTopic(testTopic); 2166 publishPacketBuilder.withQOS(QOS.AT_LEAST_ONCE); 2167 2168 // SubscribePacketBuilder 2169 SubscribePacketBuilder subscribePacketBuilder = new SubscribePacketBuilder(); 2170 subscribePacketBuilder.withSubscription(sharedTopicfilter, QOS.AT_LEAST_ONCE); 2171 2172 try ( 2173 Mqtt5Client publisherClient = new Mqtt5Client(publisherBuilder.build()); 2174 Mqtt5Client subscriberOneClient = new Mqtt5Client(subscriberOneBuilder.build()); 2175 Mqtt5Client subscriberTwoClient = new Mqtt5Client(subscriberTwoBuilder.build()) 2176 ) { 2177 publisherClient.start(); 2178 subscriberOneClient.start(); 2179 subscriberTwoClient.start(); 2180 2181 publisherLCEvents.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2182 subscriberOneLCEvents.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2183 subscriberTwoLCEvents.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2184 2185 subscriberOneClient.subscribe(subscribePacketBuilder.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2186 subscriberTwoClient.subscribe(subscribePacketBuilder.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2187 2188 for (int i = 0; i < messageCount; ++i) { 2189 publishPacketBuilder.withPayload(String.valueOf(i).getBytes()); 2190 publisherClient.publish(publishPacketBuilder.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2191 } 2192 2193 publishEvents.publishReceivedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2194 2195 // Wait a little longer just to ensure that no packets beyond expectations are arrived. 2196 publishEvents.afterCompletionFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2197 2198 // Check that both clients received packets. 2199 // PublishEvents_Futured_Counted also checks for duplicated packets, so this one assert is enough 2200 // to ensure that AWS IoT Core sent different packets to different subscribers. 2201 assertTrue(publishEvents.clientsReceived.size() == 2); 2202 2203 subscriberOneClient.stop(); 2204 subscriberTwoClient.stop(); 2205 publisherClient.stop(); 2206 } 2207 2208 if (tlsContext != null) { 2209 tlsContext.close(); 2210 } 2211 } catch (Exception ex) { 2212 fail(ex.getMessage()); 2213 } 2214 } 2215 2216 /** 2217 * ============================================================ 2218 * Error Operation Tests 2219 * ============================================================ 2220 */ 2221 2222 /* Null Publish Test */ 2223 @Test ErrorOp_UC1()2224 public void ErrorOp_UC1() { 2225 skipIfNetworkUnavailable(); 2226 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2227 boolean didExceptionOccur = false; 2228 try { 2229 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2230 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 2231 builder.withLifecycleEvents(events); 2232 2233 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 2234 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2235 TlsContext tlsContext = new TlsContext(tlsOptions); 2236 tlsOptions.close(); 2237 builder.withTlsContext(tlsContext); 2238 2239 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 2240 client.start(); 2241 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2242 2243 try { 2244 client.publish(null).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2245 } catch (Exception ex) { 2246 didExceptionOccur = true; 2247 } 2248 2249 if (didExceptionOccur == false) { 2250 fail("Null publish packet did not cause exception with error!"); 2251 } 2252 client.stop(new DisconnectPacketBuilder().build()); 2253 } 2254 2255 if (tlsContext != null) { 2256 tlsContext.close(); 2257 } 2258 2259 } catch (Exception ex) { 2260 fail(ex.getMessage()); 2261 } 2262 } 2263 2264 /* Publish with empty builder test */ 2265 @Test ErrorOp_UC1_ALT()2266 public void ErrorOp_UC1_ALT() { 2267 skipIfNetworkUnavailable(); 2268 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2269 boolean didExceptionOccur = false; 2270 try { 2271 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2272 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 2273 builder.withLifecycleEvents(events); 2274 2275 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 2276 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2277 TlsContext tlsContext = new TlsContext(tlsOptions); 2278 tlsOptions.close(); 2279 builder.withTlsContext(tlsContext); 2280 2281 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 2282 client.start(); 2283 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2284 2285 try { 2286 client.publish(new PublishPacketBuilder().build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2287 } catch (Exception ex) { 2288 didExceptionOccur = true; 2289 } 2290 2291 if (didExceptionOccur == false) { 2292 fail("Empty publish packet did not cause exception with error!"); 2293 } 2294 client.stop(new DisconnectPacketBuilder().build()); 2295 } 2296 2297 if (tlsContext != null) { 2298 tlsContext.close(); 2299 } 2300 2301 } catch (Exception ex) { 2302 fail(ex.getMessage()); 2303 } 2304 } 2305 2306 /* Null Subscribe Test */ 2307 @Test ErrorOp_UC2()2308 public void ErrorOp_UC2() { 2309 skipIfNetworkUnavailable(); 2310 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2311 boolean didExceptionOccur = false; 2312 try { 2313 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2314 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 2315 builder.withLifecycleEvents(events); 2316 2317 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 2318 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2319 TlsContext tlsContext = new TlsContext(tlsOptions); 2320 tlsOptions.close(); 2321 builder.withTlsContext(tlsContext); 2322 2323 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 2324 client.start(); 2325 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2326 2327 try { 2328 client.subscribe(null).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2329 } catch (Exception ex) { 2330 didExceptionOccur = true; 2331 } 2332 2333 if (didExceptionOccur == false) { 2334 fail("Null subscribe packet did not cause exception with error!"); 2335 } 2336 client.stop(); 2337 } 2338 2339 if (tlsContext != null) { 2340 tlsContext.close(); 2341 } 2342 2343 } catch (Exception ex) { 2344 fail(ex.getMessage()); 2345 } 2346 } 2347 2348 /* Empty Subscribe Test */ 2349 @Test ErrorOp_UC2_ALT()2350 public void ErrorOp_UC2_ALT() { 2351 skipIfNetworkUnavailable(); 2352 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2353 boolean didExceptionOccur = false; 2354 try { 2355 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2356 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 2357 builder.withLifecycleEvents(events); 2358 2359 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 2360 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2361 TlsContext tlsContext = new TlsContext(tlsOptions); 2362 tlsOptions.close(); 2363 builder.withTlsContext(tlsContext); 2364 2365 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 2366 client.start(); 2367 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2368 2369 try { 2370 client.subscribe(new SubscribePacketBuilder().build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2371 } catch (Exception ex) { 2372 didExceptionOccur = true; 2373 } 2374 2375 if (didExceptionOccur == false) { 2376 fail("Empty subscribe packet did not cause exception with error!"); 2377 } 2378 client.stop(); 2379 } 2380 2381 if (tlsContext != null) { 2382 tlsContext.close(); 2383 } 2384 2385 } catch (Exception ex) { 2386 fail(ex.getMessage()); 2387 } 2388 } 2389 2390 /* Null Unsubscribe Test */ 2391 @Test ErrorOp_UC3()2392 public void ErrorOp_UC3() { 2393 skipIfNetworkUnavailable(); 2394 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2395 boolean didExceptionOccur = false; 2396 try { 2397 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2398 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 2399 builder.withLifecycleEvents(events); 2400 2401 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 2402 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2403 TlsContext tlsContext = new TlsContext(tlsOptions); 2404 tlsOptions.close(); 2405 builder.withTlsContext(tlsContext); 2406 2407 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 2408 client.start(); 2409 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2410 2411 try { 2412 client.unsubscribe(null).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2413 } catch (Exception ex) { 2414 didExceptionOccur = true; 2415 } 2416 2417 if (didExceptionOccur == false) { 2418 fail("Null unsubscribe packet did not cause exception with error!"); 2419 } 2420 client.stop(); 2421 } 2422 2423 if (tlsContext != null) { 2424 tlsContext.close(); 2425 } 2426 2427 } catch (Exception ex) { 2428 fail(ex.getMessage()); 2429 } 2430 } 2431 2432 /* Empty Unsubscribe Test */ 2433 @Test ErrorOp_UC3_ALT()2434 public void ErrorOp_UC3_ALT() { 2435 skipIfNetworkUnavailable(); 2436 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2437 boolean didExceptionOccur = false; 2438 try { 2439 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2440 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 2441 builder.withLifecycleEvents(events); 2442 2443 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 2444 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2445 TlsContext tlsContext = new TlsContext(tlsOptions); 2446 tlsOptions.close(); 2447 builder.withTlsContext(tlsContext); 2448 2449 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 2450 client.start(); 2451 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2452 2453 try { 2454 client.unsubscribe(new UnsubscribePacketBuilder().build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2455 } catch (Exception ex) { 2456 didExceptionOccur = true; 2457 } 2458 2459 if (didExceptionOccur == false) { 2460 fail("Empty unsubscribe packet did not cause exception with error!"); 2461 } 2462 client.stop(); 2463 } 2464 2465 if (tlsContext != null) { 2466 tlsContext.close(); 2467 } 2468 2469 } catch (Exception ex) { 2470 fail(ex.getMessage()); 2471 } 2472 } 2473 2474 /* Unsupported Connect packet data sent (IoT Core only) */ 2475 @Test ErrorOp_UC4()2476 public void ErrorOp_UC4() { 2477 skipIfNetworkUnavailable(); 2478 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2479 boolean didExceptionOccur = false; 2480 try { 2481 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2482 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 2483 builder.withLifecycleEvents(events); 2484 2485 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 2486 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2487 TlsContext tlsContext = new TlsContext(tlsOptions); 2488 tlsOptions.close(); 2489 builder.withTlsContext(tlsContext); 2490 2491 ConnectPacketBuilder connectOptions = new ConnectPacketBuilder(); 2492 String clientIDString = ""; 2493 for (int i = 0; i < 256; i++) { 2494 clientIDString += "a"; 2495 } 2496 connectOptions.withClientId(clientIDString); 2497 builder.withConnectOptions(connectOptions.build()); 2498 2499 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 2500 try { 2501 client.start(); 2502 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2503 } catch (Exception ex) { 2504 didExceptionOccur = true; 2505 } 2506 2507 if (didExceptionOccur == false) { 2508 fail("Was able to connect with Client ID longer than 128 characters (AWS_IOT_CORE_MAXIMUM_CLIENT_ID_LENGTH)"); 2509 } 2510 client.stop(); 2511 } 2512 2513 if (tlsContext != null) { 2514 tlsContext.close(); 2515 } 2516 2517 } catch (Exception ex) { 2518 fail(ex.getMessage()); 2519 } 2520 } 2521 2522 /** 2523 * ============================================================ 2524 * QoS1 Tests 2525 * ============================================================ 2526 */ 2527 2528 /* Happy path. No drop in connection, no retry, no reconnect */ 2529 @Test QoS1_UC1()2530 public void QoS1_UC1() { 2531 skipIfNetworkUnavailable(); 2532 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2533 int messageCount = 10; 2534 String testUUID = UUID.randomUUID().toString(); 2535 String testTopic = "test/MQTT5_Binding_Java_" + testUUID; 2536 try { 2537 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2538 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 2539 builder.withLifecycleEvents(events); 2540 2541 Mqtt5ClientOptionsBuilder builderTwo = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2542 LifecycleEvents_Futured eventsTwo = new LifecycleEvents_Futured(); 2543 builderTwo.withLifecycleEvents(eventsTwo); 2544 PublishEvents_Futured_Counted publishEvents = new PublishEvents_Futured_Counted(); 2545 publishEvents.desiredPublishCount = messageCount; 2546 builderTwo.withPublishEvents(publishEvents); 2547 2548 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 2549 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2550 TlsContext tlsContext = new TlsContext(tlsOptions); 2551 tlsOptions.close(); 2552 builder.withTlsContext(tlsContext); 2553 builderTwo.withTlsContext(tlsContext); 2554 2555 try ( 2556 Mqtt5Client publisher = new Mqtt5Client(builder.build()); 2557 Mqtt5Client subscriber = new Mqtt5Client(builderTwo.build()); 2558 ) { 2559 publisher.start(); 2560 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2561 subscriber.start(); 2562 eventsTwo.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2563 2564 SubscribePacketBuilder subscribePacketBuilder = new SubscribePacketBuilder(); 2565 subscribePacketBuilder.withSubscription(testTopic, QOS.AT_LEAST_ONCE); 2566 subscriber.subscribe(subscribePacketBuilder.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2567 2568 PublishPacketBuilder publishPacketBuilder = new PublishPacketBuilder(); 2569 publishPacketBuilder.withTopic(testTopic); 2570 publishPacketBuilder.withPayload("Hello World".getBytes()); 2571 publishPacketBuilder.withQOS(QOS.AT_LEAST_ONCE); 2572 2573 for (int i = 0; i < messageCount; i++) { 2574 publisher.publish(publishPacketBuilder.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2575 } 2576 2577 // Did we get all the messages? 2578 publishEvents.publishReceivedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2579 2580 subscriber.stop(); 2581 publisher.stop(); 2582 } 2583 2584 if (tlsContext != null) { 2585 tlsContext.close(); 2586 } 2587 2588 } catch (Exception ex) { 2589 fail(ex.getMessage()); 2590 } 2591 } 2592 2593 /** 2594 * ============================================================ 2595 * Retain Tests 2596 * ============================================================ 2597 */ 2598 2599 /* Happy path. No drop in connection, no retry, no reconnect */ 2600 @Test Retain_UC1()2601 public void Retain_UC1() { 2602 skipIfNetworkUnavailable(); 2603 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2604 String testUUID = UUID.randomUUID().toString(); 2605 String testTopic = "test/retained_topic/MQTT5_Binding_Java_" + testUUID; 2606 try { 2607 Mqtt5ClientOptionsBuilder publisherEventsBuilder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2608 LifecycleEvents_Futured publisherEvents = new LifecycleEvents_Futured(); 2609 publisherEventsBuilder.withLifecycleEvents(publisherEvents); 2610 2611 Mqtt5ClientOptionsBuilder successSubscriberBuilder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2612 LifecycleEvents_Futured successSubscriberEvents = new LifecycleEvents_Futured(); 2613 PublishEvents_Futured successSubscriberPublishEvents = new PublishEvents_Futured(); 2614 successSubscriberBuilder.withLifecycleEvents(successSubscriberEvents); 2615 successSubscriberBuilder.withPublishEvents(successSubscriberPublishEvents); 2616 2617 Mqtt5ClientOptionsBuilder unsuccessSubscriberBuilder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2618 LifecycleEvents_Futured unsuccessfulSubscriberEvents = new LifecycleEvents_Futured(); 2619 PublishEvents_Futured unsuccessfulSubscriberPublishEvents = new PublishEvents_Futured(); 2620 unsuccessSubscriberBuilder.withLifecycleEvents(unsuccessfulSubscriberEvents); 2621 unsuccessSubscriberBuilder.withPublishEvents(unsuccessfulSubscriberPublishEvents); 2622 2623 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 2624 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2625 TlsContext tlsContext = new TlsContext(tlsOptions); 2626 tlsOptions.close(); 2627 publisherEventsBuilder.withTlsContext(tlsContext); 2628 successSubscriberBuilder.withTlsContext(tlsContext); 2629 unsuccessSubscriberBuilder.withTlsContext(tlsContext); 2630 2631 try ( 2632 Mqtt5Client publisher = new Mqtt5Client(publisherEventsBuilder.build()); 2633 Mqtt5Client successSubscriber = new Mqtt5Client(successSubscriberBuilder.build()); 2634 Mqtt5Client unsuccessfulSubscriber = new Mqtt5Client(unsuccessSubscriberBuilder.build()); 2635 ) { 2636 // Connect and publish a retained message 2637 publisher.start(); 2638 publisherEvents.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2639 PublishPacketBuilder publishPacketBuilder = new PublishPacketBuilder(); 2640 publishPacketBuilder.withTopic(testTopic) 2641 .withPayload("Hello World".getBytes()) 2642 .withQOS(QOS.AT_LEAST_ONCE) 2643 .withRetain(true); 2644 publisher.publish(publishPacketBuilder.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2645 2646 // Setup for clearing the retained message 2647 publishPacketBuilder.withPayload(null); 2648 2649 // Connect the successful subscriber 2650 successSubscriber.start(); 2651 try { 2652 successSubscriberEvents.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2653 } catch (Exception ex) { 2654 // Clear the retained message 2655 publisher.publish(publishPacketBuilder.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2656 fail("Success subscriber could not connect!"); 2657 } 2658 2659 // Subscribe and verify the retained message 2660 SubscribePacketBuilder subscribePacketBuilder = new SubscribePacketBuilder(); 2661 subscribePacketBuilder.withSubscription(testTopic, QOS.AT_LEAST_ONCE, false, true, RetainHandlingType.SEND_ON_SUBSCRIBE); 2662 try { 2663 successSubscriber.subscribe(subscribePacketBuilder.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2664 } catch (Exception ex) { 2665 // Clear the retained message 2666 publisher.publish(publishPacketBuilder.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2667 fail("Success subscriber could not subscribe!"); 2668 } 2669 try { 2670 successSubscriberPublishEvents.publishReceivedFuture.get(360, TimeUnit.SECONDS); 2671 } catch (Exception ex) { 2672 // Clear the retained message 2673 publisher.publish(publishPacketBuilder.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2674 fail("Success subscriber did not get retained message!"); 2675 } 2676 2677 // Clear the retained message 2678 publisher.publish(publishPacketBuilder.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2679 2680 // Wait 15 seconds to give the server time to clear everything out 2681 Thread.sleep(15000); 2682 2683 // Connect the unsuccessful subscriber 2684 unsuccessfulSubscriber.start(); 2685 unsuccessfulSubscriberEvents.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2686 unsuccessfulSubscriber.subscribe(subscribePacketBuilder.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2687 // Make sure we do NOT get a publish 2688 boolean didExceptionOccur = false; 2689 try { 2690 unsuccessfulSubscriberPublishEvents.publishReceivedFuture.get(30, TimeUnit.SECONDS); 2691 } catch (Exception ex) { 2692 didExceptionOccur = true; 2693 } 2694 2695 if (didExceptionOccur == false) { 2696 fail("Unsuccessful subscriber got retained message even though it should be cleared!"); 2697 } 2698 2699 // Disconnect all clients 2700 publisher.stop(); 2701 publisherEvents.stopFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2702 successSubscriber.stop(); 2703 successSubscriberEvents.stopFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2704 unsuccessfulSubscriber.stop(); 2705 unsuccessfulSubscriberEvents.stopFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2706 } 2707 2708 if (tlsContext != null) { 2709 tlsContext.close(); 2710 } 2711 2712 } catch (Exception ex) { 2713 fail(ex.getMessage()); 2714 } 2715 } 2716 2717 /** 2718 * ============================================================ 2719 * Operation Interrupt Tests 2720 * ============================================================ 2721 */ 2722 2723 // Subscribe interrupt test 2724 @Test Interrupt_Sub_UC1()2725 public void Interrupt_Sub_UC1() { 2726 skipIfNetworkUnavailable(); 2727 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2728 String testUUID = UUID.randomUUID().toString(); 2729 String testTopic = "test/MQTT5_Binding_Java_" + testUUID; 2730 try { 2731 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2732 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 2733 builder.withLifecycleEvents(events); 2734 2735 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 2736 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2737 TlsContext tlsContext = new TlsContext(tlsOptions); 2738 tlsOptions.close(); 2739 builder.withTlsContext(tlsContext); 2740 2741 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 2742 client.start(); 2743 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2744 2745 SubscribePacketBuilder subscribePacketBuilder = new SubscribePacketBuilder(); 2746 subscribePacketBuilder.withSubscription(testTopic, QOS.AT_LEAST_ONCE); 2747 2748 try { 2749 CompletableFuture<SubAckPacket> subscribeResult = client.subscribe(subscribePacketBuilder.build()); 2750 client.stop(); 2751 SubAckPacket packet = subscribeResult.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2752 } catch (Exception ex) { 2753 if (ex.getCause().getClass() == CrtRuntimeException.class) { 2754 CrtRuntimeException exCrt = (CrtRuntimeException)ex.getCause(); 2755 if (exCrt.errorCode != 5153) { 2756 System.out.println("Exception ocurred when stopping subscribe" + 2757 "but it was not AWS_ERROR_MQTT5_USER_REQUESTED_STOP like expected"); 2758 } 2759 } 2760 } 2761 } 2762 2763 if (tlsContext != null) { 2764 tlsContext.close(); 2765 } 2766 2767 } catch (Exception ex) { 2768 fail(ex.getMessage()); 2769 } 2770 } 2771 2772 // Unsubscribe interrupt test 2773 @Test Interrupt_Unsub_UC1()2774 public void Interrupt_Unsub_UC1() { 2775 skipIfNetworkUnavailable(); 2776 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2777 String testUUID = UUID.randomUUID().toString(); 2778 String testTopic = "test/MQTT5_Binding_Java_" + testUUID; 2779 try { 2780 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2781 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 2782 builder.withLifecycleEvents(events); 2783 2784 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 2785 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2786 TlsContext tlsContext = new TlsContext(tlsOptions); 2787 tlsOptions.close(); 2788 builder.withTlsContext(tlsContext); 2789 2790 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 2791 client.start(); 2792 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2793 2794 UnsubscribePacketBuilder unsubscribePacketBuilder = new UnsubscribePacketBuilder(); 2795 unsubscribePacketBuilder.withSubscription(testTopic); 2796 2797 try { 2798 CompletableFuture<UnsubAckPacket> unsubscribeResult = client.unsubscribe(unsubscribePacketBuilder.build()); 2799 client.stop(); 2800 UnsubAckPacket packet = unsubscribeResult.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2801 } catch (Exception ex) { 2802 if (ex.getCause().getClass() == CrtRuntimeException.class) { 2803 CrtRuntimeException exCrt = (CrtRuntimeException)ex.getCause(); 2804 if (exCrt.errorCode != 5153) { 2805 System.out.println("Exception ocurred when stopping unsubscribe" + 2806 "but it was not AWS_ERROR_MQTT5_USER_REQUESTED_STOP like expected"); 2807 } 2808 } 2809 } 2810 } 2811 2812 if (tlsContext != null) { 2813 tlsContext.close(); 2814 } 2815 2816 } catch (Exception ex) { 2817 fail(ex.getMessage()); 2818 } 2819 } 2820 2821 // Publish interrupt test 2822 @Test Interrupt_Publish_UC1()2823 public void Interrupt_Publish_UC1() { 2824 skipIfNetworkUnavailable(); 2825 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2826 String testUUID = UUID.randomUUID().toString(); 2827 String testTopic = "test/MQTT5_Binding_Java_" + testUUID; 2828 try { 2829 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2830 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 2831 builder.withLifecycleEvents(events); 2832 2833 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 2834 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2835 TlsContext tlsContext = new TlsContext(tlsOptions); 2836 tlsOptions.close(); 2837 builder.withTlsContext(tlsContext); 2838 2839 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 2840 client.start(); 2841 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2842 2843 PublishPacketBuilder publishPacketBuilder = new PublishPacketBuilder(); 2844 publishPacketBuilder.withTopic(testTopic).withQOS(QOS.AT_LEAST_ONCE).withPayload("null".getBytes()); 2845 2846 try { 2847 CompletableFuture<PublishResult> publishResult = client.publish(publishPacketBuilder.build()); 2848 client.stop(); 2849 PublishResult publishData = publishResult.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2850 } catch (Exception ex) { 2851 if (ex.getCause().getClass() == CrtRuntimeException.class) { 2852 CrtRuntimeException exCrt = (CrtRuntimeException)ex.getCause(); 2853 if (exCrt.errorCode != 5153) { 2854 System.out.println("Exception ocurred when stopping publish" + 2855 "but it was not AWS_ERROR_MQTT5_USER_REQUESTED_STOP like expected"); 2856 } 2857 } 2858 } 2859 } 2860 2861 if (tlsContext != null) { 2862 tlsContext.close(); 2863 } 2864 2865 } catch (Exception ex) { 2866 fail(ex.getMessage()); 2867 } 2868 } 2869 2870 /** 2871 * ============================================================ 2872 * Misc Tests 2873 * ============================================================ 2874 */ 2875 2876 /* Happy path. Check statistics before, make some publishes, check it after */ 2877 @Test OperationStatistics_UC1()2878 public void OperationStatistics_UC1() { 2879 skipIfNetworkUnavailable(); 2880 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2881 int messageCount = 10; 2882 String testUUID = UUID.randomUUID().toString(); 2883 String testTopic = "test/MQTT5_Binding_Java_" + testUUID; 2884 try { 2885 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2886 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 2887 builder.withLifecycleEvents(events); 2888 2889 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsFromPath( 2890 AWS_TEST_MQTT5_IOT_CORE_RSA_CERT, AWS_TEST_MQTT5_IOT_CORE_RSA_KEY); 2891 TlsContext tlsContext = new TlsContext(tlsOptions); 2892 tlsOptions.close(); 2893 builder.withTlsContext(tlsContext); 2894 2895 try ( 2896 Mqtt5Client publisher = new Mqtt5Client(builder.build()); 2897 ) { 2898 publisher.start(); 2899 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2900 2901 Mqtt5ClientOperationStatistics statistics = publisher.getOperationStatistics(); 2902 // Make sure it is empty 2903 if (statistics.getIncompleteOperationCount() != 0) { 2904 fail("Incomplete operation count was not zero!"); 2905 } 2906 if (statistics.getIncompleteOperationSize() != 0) { 2907 fail("Incomplete operation size was not zero!"); 2908 } 2909 if (statistics.getUnackedOperationCount() != 0) { 2910 fail("Unacked operation count was not zero!"); 2911 } 2912 if (statistics.getUnackedOperationSize() != 0) { 2913 fail("Unacked operation size was not zero!"); 2914 } 2915 2916 PublishPacketBuilder publishPacketBuilder = new PublishPacketBuilder(); 2917 publishPacketBuilder.withTopic(testTopic); 2918 publishPacketBuilder.withPayload("Hello World".getBytes()); 2919 publishPacketBuilder.withQOS(QOS.AT_LEAST_ONCE); 2920 2921 for (int i = 0; i < messageCount; i++) { 2922 publisher.publish(publishPacketBuilder.build()).get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2923 } 2924 2925 // Make sure it is empty 2926 if (statistics.getIncompleteOperationCount() != 0) { 2927 fail("Incomplete operation count was not zero!"); 2928 } 2929 if (statistics.getIncompleteOperationSize() != 0) { 2930 fail("Incomplete operation size was not zero!"); 2931 } 2932 if (statistics.getUnackedOperationCount() != 0) { 2933 fail("Unacked operation count was not zero!"); 2934 } 2935 if (statistics.getUnackedOperationSize() != 0) { 2936 fail("Unacked operation size was not zero!"); 2937 } 2938 2939 publisher.stop(); 2940 events.stopFuture.get(60, TimeUnit.SECONDS); 2941 } 2942 2943 if (tlsContext != null) { 2944 tlsContext.close(); 2945 } 2946 2947 } catch (Exception ex) { 2948 fail(ex.getMessage()); 2949 } 2950 } 2951 2952 /** 2953 * ============================================================ 2954 * MQTT5 DIRECT IoT Core CONNECTION TEST CASES 2955 * ============================================================ 2956 */ 2957 2958 /* MQTT5 ConnDC_Cred_UC1 - MQTT5 connect with Java Keystore */ 2959 @Test ConnDC_Cred_UC1()2960 public void ConnDC_Cred_UC1() { 2961 skipIfNetworkUnavailable(); 2962 Assume.assumeNotNull( 2963 AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_KEYSTORE_FORMAT, 2964 AWS_TEST_MQTT5_IOT_CORE_KEYSTORE_FILE, AWS_TEST_MQTT5_IOT_CORE_KEYSTORE_PASSWORD, 2965 AWS_TEST_MQTT5_IOT_CORE_KEYSTORE_CERT_ALIAS, AWS_TEST_MQTT5_IOT_CORE_KEYSTORE_CERT_PASSWORD); 2966 try { 2967 java.security.KeyStore keyStore = java.security.KeyStore.getInstance(AWS_TEST_MQTT5_IOT_CORE_KEYSTORE_FORMAT); 2968 java.io.FileInputStream keyStoreStream = new java.io.FileInputStream(AWS_TEST_MQTT5_IOT_CORE_KEYSTORE_FILE); 2969 keyStore.load(keyStoreStream, AWS_TEST_MQTT5_IOT_CORE_KEYSTORE_PASSWORD.toCharArray()); 2970 keyStoreStream.close(); 2971 2972 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 2973 2974 try ( 2975 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsJavaKeystore( 2976 keyStore, 2977 AWS_TEST_MQTT5_IOT_CORE_KEYSTORE_CERT_ALIAS, 2978 AWS_TEST_MQTT5_IOT_CORE_KEYSTORE_CERT_PASSWORD); 2979 TlsContext tlsContext = new TlsContext(tlsOptions); 2980 ) { 2981 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 2982 builder.withLifecycleEvents(events); 2983 builder.withTlsContext(tlsContext); 2984 2985 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 2986 client.start(); 2987 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 2988 client.stop(); 2989 } 2990 } 2991 } catch (Exception ex) { 2992 fail(ex.getMessage()); 2993 } 2994 } 2995 2996 /* MQTT5 ConnDC_Cred_UC2 - MQTT5 connect with PKCS12 Key */ 2997 @Test ConnDC_Cred_UC2()2998 public void ConnDC_Cred_UC2() { 2999 skipIfNetworkUnavailable(); 3000 Assume.assumeNotNull( 3001 AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_PKCS12_KEY, 3002 AWS_TEST_MQTT5_IOT_CORE_PKCS12_KEY_PASSWORD); 3003 try { 3004 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 3005 try ( 3006 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsPkcs12( 3007 AWS_TEST_MQTT5_IOT_CORE_PKCS12_KEY, 3008 AWS_TEST_MQTT5_IOT_CORE_PKCS12_KEY_PASSWORD); 3009 TlsContext tlsContext = new TlsContext(tlsOptions); 3010 ) { 3011 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 3012 builder.withLifecycleEvents(events); 3013 builder.withTlsContext(tlsContext); 3014 3015 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 3016 client.start(); 3017 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 3018 client.stop(); 3019 } 3020 } 3021 } catch (Exception ex) { 3022 fail(ex.getMessage()); 3023 } 3024 } 3025 3026 /* MQTT5 ConnDC_Cred_UC3 - MQTT5 connect with Windows Cert Store */ 3027 @Test ConnDC_Cred_UC3()3028 public void ConnDC_Cred_UC3() { 3029 skipIfNetworkUnavailable(); 3030 Assume.assumeNotNull( 3031 AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_WINDOWS_PFX_CERT_NO_PASS, 3032 AWS_TEST_MQTT5_IOT_CORE_WINDOWS_CERT_STORE); 3033 try { 3034 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 3035 try ( 3036 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsWindowsCertStorePath( 3037 AWS_TEST_MQTT5_IOT_CORE_WINDOWS_CERT_STORE); 3038 TlsContext tlsContext = new TlsContext(tlsOptions); 3039 ) { 3040 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 3041 builder.withLifecycleEvents(events); 3042 builder.withTlsContext(tlsContext); 3043 3044 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 3045 client.start(); 3046 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 3047 client.stop(); 3048 } 3049 } 3050 } catch (Exception ex) { 3051 fail(ex.getMessage()); 3052 } 3053 } 3054 3055 /* MQTT5 ConnDC_Cred_UC4 - MQTT5 connect with PKCS11 */ 3056 @Test ConnDC_Cred_UC4()3057 public void ConnDC_Cred_UC4() { 3058 skipIfNetworkUnavailable(); 3059 Assume.assumeNotNull( 3060 AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_PKCS11_LIB, 3061 AWS_TEST_MQTT5_IOT_CORE_PKCS11_TOKEN_LABEL, AWS_TEST_MQTT5_IOT_CORE_PKCS11_PIN, 3062 AWS_TEST_MQTT5_IOT_CORE_PKCS11_PKEY_LABEL, AWS_TEST_MQTT5_IOT_CORE_PKCS11_CERT_FILE); 3063 // The published Softhsm package on muslc (Alpine) crashes if we don't call C_Finalize at the end. 3064 try ( 3065 Pkcs11Lib pkcs11Lib = new Pkcs11Lib(AWS_TEST_MQTT5_IOT_CORE_PKCS11_LIB, Pkcs11Lib.InitializeFinalizeBehavior.STRICT); 3066 TlsContextPkcs11Options pkcs11Options = new TlsContextPkcs11Options(pkcs11Lib);) { 3067 pkcs11Options.withTokenLabel(AWS_TEST_MQTT5_IOT_CORE_PKCS11_TOKEN_LABEL); 3068 pkcs11Options.withUserPin(AWS_TEST_MQTT5_IOT_CORE_PKCS11_PIN); 3069 pkcs11Options.withPrivateKeyObjectLabel(AWS_TEST_MQTT5_IOT_CORE_PKCS11_PKEY_LABEL); 3070 pkcs11Options.withCertificateFilePath(AWS_TEST_MQTT5_IOT_CORE_PKCS11_CERT_FILE); 3071 3072 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 3073 try ( 3074 TlsContextOptions tlsOptions = TlsContextOptions.createWithMtlsPkcs11(pkcs11Options); 3075 TlsContext tlsContext = new TlsContext(tlsOptions); 3076 ) { 3077 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 8883l); 3078 builder.withLifecycleEvents(events); 3079 builder.withTlsContext(tlsContext); 3080 3081 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 3082 client.start(); 3083 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 3084 client.stop(); 3085 } 3086 } 3087 } catch (Exception ex) { 3088 fail(ex.getMessage()); 3089 } 3090 } 3091 3092 /** 3093 * ============================================================ 3094 * MQTT5 WEBSOCKET IoT Core CONNECTION TEST CASES 3095 * ============================================================ 3096 */ 3097 3098 /* MQTT5 ConnWS_Cred_UC1 - static credentials connect */ 3099 @Test ConnWS_Cred_UC1()3100 public void ConnWS_Cred_UC1() { 3101 skipIfNetworkUnavailable(); 3102 Assume.assumeNotNull( 3103 AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_REGION, 3104 AWS_TEST_MQTT5_ROLE_CREDENTIAL_ACCESS_KEY, AWS_TEST_MQTT5_ROLE_CREDENTIAL_SECRET_ACCESS_KEY, 3105 AWS_TEST_MQTT5_ROLE_CREDENTIAL_SESSION_TOKEN); 3106 CredentialsProvider provider = null; 3107 AwsSigningConfig signingConfig = new AwsSigningConfig(); 3108 Mqtt5ClientTestSigv4HandshakeTransformer transformer = null; 3109 3110 try { 3111 try ( 3112 EventLoopGroup elg = new EventLoopGroup(1); 3113 HostResolver hr = new HostResolver(elg); 3114 ClientBootstrap bootstrap = new ClientBootstrap(elg, hr); 3115 TlsContextOptions tlsOptions = TlsContextOptions.createDefaultClient(); 3116 TlsContext tlsContext = new TlsContext(tlsOptions); 3117 ) { 3118 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 3119 3120 StaticCredentialsProviderBuilder credentialsBuilder = new StaticCredentialsProviderBuilder(); 3121 credentialsBuilder.withAccessKeyId(AWS_TEST_MQTT5_ROLE_CREDENTIAL_ACCESS_KEY.getBytes()); 3122 credentialsBuilder.withSecretAccessKey(AWS_TEST_MQTT5_ROLE_CREDENTIAL_SECRET_ACCESS_KEY.getBytes()); 3123 credentialsBuilder.withSessionToken(AWS_TEST_MQTT5_ROLE_CREDENTIAL_SESSION_TOKEN.getBytes()); 3124 3125 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 443L); 3126 builder.withLifecycleEvents(events); 3127 builder.withBootstrap(bootstrap); 3128 builder.withTlsContext(tlsContext); 3129 3130 provider = credentialsBuilder.build(); 3131 signingConfig.setCredentialsProvider(provider); 3132 signingConfig.setAlgorithm(AwsSigningAlgorithm.SIGV4); 3133 signingConfig.setSignatureType(AwsSigningConfig.AwsSignatureType.HTTP_REQUEST_VIA_QUERY_PARAMS); 3134 signingConfig.setRegion(AWS_TEST_MQTT5_IOT_CORE_REGION); 3135 signingConfig.setService("iotdevicegateway"); 3136 signingConfig.setOmitSessionToken(true); 3137 transformer = new Mqtt5ClientTestSigv4HandshakeTransformer(signingConfig); 3138 3139 builder.withWebsocketHandshakeTransform(transformer); 3140 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 3141 client.start(); 3142 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 3143 client.stop(); 3144 } 3145 } 3146 } catch (Exception ex) { 3147 ex.printStackTrace(); 3148 fail(ex.getMessage()); 3149 } finally { 3150 if (provider != null) { 3151 provider.close(); 3152 } 3153 if (signingConfig != null) { 3154 signingConfig.close(); 3155 } 3156 if (transformer != null) { 3157 transformer.close(); 3158 } 3159 } 3160 } 3161 3162 /* MQTT5 ConnWS_Cred_UC2 - default credentials connect */ 3163 @Test ConnWS_Cred_UC2()3164 public void ConnWS_Cred_UC2() { 3165 skipIfAndroid(); // Credential Provider support not yet added for Android 3166 skipIfNetworkUnavailable(); 3167 Assume.assumeNotNull(AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_REGION); 3168 CredentialsProvider provider = null; 3169 AwsSigningConfig signingConfig = new AwsSigningConfig(); 3170 Mqtt5ClientTestSigv4HandshakeTransformer transformer = null; 3171 3172 try { 3173 try ( 3174 EventLoopGroup elg = new EventLoopGroup(1); 3175 HostResolver hr = new HostResolver(elg); 3176 ClientBootstrap bootstrap = new ClientBootstrap(elg, hr); 3177 TlsContextOptions tlsOptions = TlsContextOptions.createDefaultClient(); 3178 TlsContext tlsContext = new TlsContext(tlsOptions); 3179 ) { 3180 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 3181 3182 DefaultChainCredentialsProviderBuilder credentialsBuilder = new DefaultChainCredentialsProviderBuilder(); 3183 credentialsBuilder.withClientBootstrap(bootstrap); 3184 3185 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 443l); 3186 builder.withLifecycleEvents(events); 3187 builder.withBootstrap(bootstrap); 3188 builder.withTlsContext(tlsContext); 3189 3190 provider = credentialsBuilder.build(); 3191 signingConfig.setCredentialsProvider(provider); 3192 signingConfig.setAlgorithm(AwsSigningAlgorithm.SIGV4); 3193 signingConfig.setSignatureType(AwsSigningConfig.AwsSignatureType.HTTP_REQUEST_VIA_QUERY_PARAMS); 3194 signingConfig.setRegion(AWS_TEST_MQTT5_IOT_CORE_REGION); 3195 signingConfig.setService("iotdevicegateway"); 3196 signingConfig.setOmitSessionToken(true); 3197 transformer = new Mqtt5ClientTestSigv4HandshakeTransformer(signingConfig); 3198 3199 builder.withWebsocketHandshakeTransform(transformer); 3200 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 3201 client.start(); 3202 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 3203 client.stop(); 3204 } 3205 } 3206 } catch (Exception ex) { 3207 fail(ex.getMessage()); 3208 } finally { 3209 if (provider != null) { 3210 provider.close(); 3211 } 3212 if (signingConfig != null) { 3213 signingConfig.close(); 3214 } 3215 if (transformer != null) { 3216 transformer.close(); 3217 } 3218 } 3219 } 3220 3221 /** 3222 * MQTT5 ConnWS_Cred_UC3 - Cognito Identity credentials connect 3223 */ 3224 @Test ConnWS_Cred_UC3()3225 public void ConnWS_Cred_UC3() { 3226 skipIfNetworkUnavailable(); 3227 Assume.assumeNotNull( 3228 AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_REGION, 3229 AWS_TEST_MQTT5_COGNITO_ENDPOINT, AWS_TEST_MQTT5_COGNITO_IDENTITY); 3230 CredentialsProvider provider = null; 3231 AwsSigningConfig signingConfig = new AwsSigningConfig(); 3232 Mqtt5ClientTestSigv4HandshakeTransformer transformer = null; 3233 3234 try { 3235 try ( 3236 EventLoopGroup elg = new EventLoopGroup(1); 3237 HostResolver hr = new HostResolver(elg); 3238 ClientBootstrap bootstrap = new ClientBootstrap(elg, hr); 3239 TlsContextOptions cognitoContextOptions = TlsContextOptions.createDefaultClient(); 3240 TlsContext cognitoContext = new TlsContext(cognitoContextOptions); 3241 TlsContextOptions tlsOptions = TlsContextOptions.createDefaultClient(); 3242 TlsContext tlsContext = new TlsContext(tlsOptions); 3243 ) { 3244 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 3245 3246 CognitoCredentialsProviderBuilder credentialsBuilder = new CognitoCredentialsProviderBuilder(); 3247 credentialsBuilder.withClientBootstrap(bootstrap); 3248 credentialsBuilder.withTlsContext(cognitoContext); 3249 credentialsBuilder.withEndpoint(AWS_TEST_MQTT5_COGNITO_ENDPOINT); 3250 credentialsBuilder.withIdentity(AWS_TEST_MQTT5_COGNITO_IDENTITY); 3251 3252 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 443l); 3253 builder.withLifecycleEvents(events); 3254 builder.withBootstrap(bootstrap); 3255 builder.withTlsContext(tlsContext); 3256 3257 provider = credentialsBuilder.build(); 3258 signingConfig.setCredentialsProvider(provider); 3259 signingConfig.setAlgorithm(AwsSigningAlgorithm.SIGV4); 3260 signingConfig.setSignatureType(AwsSigningConfig.AwsSignatureType.HTTP_REQUEST_VIA_QUERY_PARAMS); 3261 signingConfig.setRegion(AWS_TEST_MQTT5_IOT_CORE_REGION); 3262 signingConfig.setService("iotdevicegateway"); 3263 signingConfig.setOmitSessionToken(true); 3264 transformer = new Mqtt5ClientTestSigv4HandshakeTransformer(signingConfig); 3265 3266 builder.withWebsocketHandshakeTransform(transformer); 3267 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 3268 client.start(); 3269 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 3270 client.stop(); 3271 } 3272 } 3273 } catch (Exception ex) { 3274 fail(ex.getMessage()); 3275 } finally { 3276 if (provider != null) { 3277 provider.close(); 3278 } 3279 if (signingConfig != null) { 3280 signingConfig.close(); 3281 } 3282 if (transformer != null) { 3283 transformer.close(); 3284 } 3285 } 3286 } 3287 3288 /* MQTT5 ConnWS_Cred_UC4 - X509 credentials connect */ 3289 @Test ConnWS_Cred_UC4()3290 public void ConnWS_Cred_UC4() { 3291 skipIfNetworkUnavailable(); 3292 Assume.assumeNotNull( 3293 AWS_TEST_MQTT5_IOT_CORE_HOST, AWS_TEST_MQTT5_IOT_CORE_REGION, 3294 AWS_TEST_MQTT5_IOT_CORE_X509_CERT, AWS_TEST_MQTT5_IOT_CORE_X509_KEY, 3295 AWS_TEST_MQTT5_IOT_CORE_X509_ENDPOINT, AWS_TEST_MQTT5_IOT_CORE_X509_ROLE_ALIAS, 3296 AWS_TEST_MQTT5_IOT_CORE_X509_THING_NAME); 3297 CredentialsProvider provider = null; 3298 AwsSigningConfig signingConfig = new AwsSigningConfig(); 3299 Mqtt5ClientTestSigv4HandshakeTransformer transformer = null; 3300 try { 3301 try ( 3302 EventLoopGroup elg = new EventLoopGroup(1); 3303 HostResolver hr = new HostResolver(elg); 3304 ClientBootstrap bootstrap = new ClientBootstrap(elg, hr); 3305 TlsContextOptions x509ContextOptions = TlsContextOptions.createWithMtlsFromPath( 3306 AWS_TEST_MQTT5_IOT_CORE_X509_CERT, AWS_TEST_MQTT5_IOT_CORE_X509_KEY); 3307 TlsContext x509Context = new TlsContext(x509ContextOptions); 3308 TlsContextOptions tlsOptions = TlsContextOptions.createDefaultClient(); 3309 TlsContext tlsContext = new TlsContext(tlsOptions); 3310 ) { 3311 LifecycleEvents_Futured events = new LifecycleEvents_Futured(); 3312 3313 X509CredentialsProviderBuilder credentialsBuilder = new X509CredentialsProviderBuilder(); 3314 credentialsBuilder.withClientBootstrap(bootstrap); 3315 credentialsBuilder.withTlsContext(x509Context); 3316 credentialsBuilder.withEndpoint(AWS_TEST_MQTT5_IOT_CORE_X509_ENDPOINT); 3317 credentialsBuilder.withRoleAlias(AWS_TEST_MQTT5_IOT_CORE_X509_ROLE_ALIAS); 3318 credentialsBuilder.withThingName(AWS_TEST_MQTT5_IOT_CORE_X509_THING_NAME); 3319 3320 Mqtt5ClientOptionsBuilder builder = new Mqtt5ClientOptionsBuilder(AWS_TEST_MQTT5_IOT_CORE_HOST, 443l); 3321 builder.withLifecycleEvents(events); 3322 builder.withBootstrap(bootstrap); 3323 builder.withTlsContext(tlsContext); 3324 3325 provider = credentialsBuilder.build(); 3326 signingConfig.setCredentialsProvider(provider); 3327 signingConfig.setAlgorithm(AwsSigningAlgorithm.SIGV4); 3328 signingConfig.setSignatureType(AwsSigningConfig.AwsSignatureType.HTTP_REQUEST_VIA_QUERY_PARAMS); 3329 signingConfig.setRegion(AWS_TEST_MQTT5_IOT_CORE_REGION); 3330 signingConfig.setService("iotdevicegateway"); 3331 signingConfig.setOmitSessionToken(true); 3332 transformer = new Mqtt5ClientTestSigv4HandshakeTransformer(signingConfig); 3333 3334 builder.withWebsocketHandshakeTransform(transformer); 3335 try (Mqtt5Client client = new Mqtt5Client(builder.build())) { 3336 client.start(); 3337 events.connectedFuture.get(OPERATION_TIMEOUT_TIME, TimeUnit.SECONDS); 3338 client.stop(); 3339 } 3340 } 3341 } catch (Exception ex) { 3342 fail(ex.getMessage()); 3343 } finally { 3344 if (provider != null) { 3345 provider.close(); 3346 } 3347 if (signingConfig != null) { 3348 signingConfig.close(); 3349 } 3350 if (transformer != null) { 3351 transformer.close(); 3352 } 3353 } 3354 } 3355 } 3356