This is an automated email from the ASF dual-hosted git repository.

tabish pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-protonj2.git


The following commit(s) were added to refs/heads/main by this push:
     new febc0aea PROTON-2719 Ensure configured virtual host value is sent to 
the remote
febc0aea is described below

commit febc0aea5306a21bb65f388abb79c0950b5270d7
Author: Timothy Bish <tabish...@gmail.com>
AuthorDate: Mon May 1 15:29:06 2023 -0400

    PROTON-2719 Ensure configured virtual host value is sent to the remote
    
    The connection options virtual host should be used to override the value
    set for the connection host or to omit a value if empty string is
    provided.  The host option should be applied both to the Open
    performative and to the SASLInit performative consistently.
---
 .../qpid/protonj2/client/ConnectionOptions.java    |  7 ++
 .../protonj2/client/impl/ClientConnection.java     |  9 ++-
 .../protonj2/client/ConnectionOptionsTest.java     | 93 +++++++++++++++++++++-
 .../qpid/protonj2/client/impl/ConnectionTest.java  | 82 +++++++++++++++++++
 4 files changed, 187 insertions(+), 4 deletions(-)

diff --git 
a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/ConnectionOptions.java
 
b/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/ConnectionOptions.java
index 3f892028..c37e2990 100644
--- 
a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/ConnectionOptions.java
+++ 
b/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/ConnectionOptions.java
@@ -130,6 +130,7 @@ public class ConnectionOptions implements Cloneable {
         other.reconnectedHandler(reconnectedHandler);
         other.disconnectedHandler(disconnectedHandler);
         other.defaultNextReceiverPolicy(nextReceiverPolicy);
+        other.virtualHost(virtualHost);
 
         if (offeredCapabilities != null) {
             other.offeredCapabilities(Arrays.copyOf(offeredCapabilities, 
offeredCapabilities.length));
@@ -501,6 +502,12 @@ public class ConnectionOptions implements Cloneable {
 
     /**
      * The virtual host value to provide to the remote when creating a new 
{@link Connection}.
+     * <p>
+     * A value of <code>null</code> signifies that the client should send the 
host value used
+     * to connect to the remote in the SASLInit and Open performatives, 
otherwise the value
+     * provided is sent unless empty string is provided in which case no AMQP 
host value is
+     * sent in either the SASLInit or the Open performative allowing the 
remote to select from
+     * a configured default.
      *
      * @param virtualHost
      *                 the virtual host to set
diff --git 
a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/impl/ClientConnection.java
 
b/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/impl/ClientConnection.java
index 876b01ca..97ae1d67 100644
--- 
a/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/impl/ClientConnection.java
+++ 
b/protonj2-client/src/main/java/org/apache/qpid/protonj2/client/impl/ClientConnection.java
@@ -837,7 +837,7 @@ public final class ClientConnection implements Connection {
 
                 @Override
                 public String vhost() {
-                    return options.virtualHost();
+                    return protonConnection.getHostname();
                 }
 
                 @Override
@@ -886,10 +886,15 @@ public final class ClientConnection implements Connection 
{
             protonConnection.setContainerId(connectionId);
         }
 
+        if (options.virtualHost() != null) {
+            protonConnection.setHostname(options.virtualHost().isEmpty() ? 
null : options.virtualHost());
+        } else {
+            protonConnection.setHostname(location.getHost());
+        }
+
         protonConnection.setLinkedResource(this);
         protonConnection.setChannelMax(options.channelMax());
         protonConnection.setMaxFrameSize(options.maxFrameSize());
-        protonConnection.setHostname(location.getHost());
         protonConnection.setIdleTimeout((int) options.idleTimeout());
         
protonConnection.setOfferedCapabilities(ClientConversionSupport.toSymbolArray(options.offeredCapabilities()));
         
protonConnection.setDesiredCapabilities(ClientConversionSupport.toSymbolArray(options.desiredCapabilities()));
diff --git 
a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/ConnectionOptionsTest.java
 
b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/ConnectionOptionsTest.java
index 34eef532..3edda0c5 100644
--- 
a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/ConnectionOptionsTest.java
+++ 
b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/ConnectionOptionsTest.java
@@ -16,33 +16,122 @@
  */
 package org.apache.qpid.protonj2.client;
 
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotSame;
 import static org.junit.jupiter.api.Assertions.assertNull;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import org.junit.jupiter.api.Test;
 
 public class ConnectionOptionsTest {
 
     @Test
-    void testCreate() {
+    public void testCreate() {
         ConnectionOptions options = new ConnectionOptions();
 
         assertNull(options.password());
         assertNull(options.user());
+        assertNull(options.virtualHost());
     }
 
     @Test
-    void testCopy() {
+    public void testCreateDefaultsTimeouts() {
         ConnectionOptions options = new ConnectionOptions();
 
+        assertEquals(ConnectionOptions.DEFAULT_CHANNEL_MAX, 
options.channelMax());
+        assertEquals(ConnectionOptions.DEFAULT_MAX_FRAME_SIZE, 
options.maxFrameSize());
+        assertEquals(ConnectionOptions.DEFAULT_OPEN_TIMEOUT, 
options.openTimeout());
+        assertEquals(ConnectionOptions.DEFAULT_CLOSE_TIMEOUT, 
options.closeTimeout());
+        assertEquals(ConnectionOptions.DEFAULT_SEND_TIMEOUT, 
options.sendTimeout());
+        assertEquals(ConnectionOptions.DEFAULT_REQUEST_TIMEOUT, 
options.requestTimeout());
+        assertEquals(ConnectionOptions.DEFAULT_IDLE_TIMEOUT, 
options.idleTimeout());
+        assertEquals(ConnectionOptions.DEFAULT_DRAIN_TIMEOUT, 
options.drainTimeout());
+    }
+
+    @Test
+    public void testCopy() {
+        final ConnectionOptions options = new ConnectionOptions();
+        final String[] offeredCapabilities = new String[] { "one", "two", 
"three" };
+        final String[] desiredCapabilities = new String[] { "four", "five", 
"six" };
+        final Map<String, Object> properties = new HashMap<String, Object>();
+        properties.put("one", "1");
+        properties.put("two", "2");
+
         options.user("test");
         options.password("test-pass");
+        options.virtualHost("test");
+        options.openTimeout(10);
+        options.closeTimeout(20);
+        options.sendTimeout(30);
+        options.requestTimeout(40);
+        options.idleTimeout(50);
+        options.drainTimeout(60);
+        options.channelMax(1);
+        options.maxFrameSize(1024);
+        options.traceFrames(true);
+        options.defaultNextReceiverPolicy(NextReceiverPolicy.FIRST_AVAILABLE);
+        options.offeredCapabilities(offeredCapabilities);
+        options.desiredCapabilities(desiredCapabilities);
+        options.properties(properties);
+        options.transportOptions().allowNativeIO(false);
+        options.transportOptions().defaultTcpPort(8086);
+        options.sslOptions().allowNativeSSL(false);
+        options.sslOptions().defaultSslPort(8087);
+        options.saslOptions().saslEnabled(false);
 
         ConnectionOptions copy = options.clone();
 
         assertNotSame(copy, options);
+        assertNotSame(copy.saslOptions(), options.saslOptions());
+        assertNotSame(copy.transportOptions(), options.transportOptions());
+        assertNotSame(copy.sslOptions(), options.sslOptions());
+        assertNotSame(copy.offeredCapabilities(), 
options.offeredCapabilities());
+        assertNotSame(copy.desiredCapabilities(), 
options.desiredCapabilities());
+        assertNotSame(copy.properties(), options.properties());
+
+        assertArrayEquals(copy.offeredCapabilities(), offeredCapabilities);
+        assertArrayEquals(copy.desiredCapabilities(), desiredCapabilities);
+
+        assertEquals(options.properties(), properties);
         assertEquals(options.user(), copy.user());
         assertEquals(options.password(), copy.password());
+        assertEquals(options.virtualHost(), copy.virtualHost());
+        assertEquals(options.openTimeout(), copy.openTimeout());
+        assertEquals(options.closeTimeout(), copy.closeTimeout());
+        assertEquals(options.sendTimeout(), copy.sendTimeout());
+        assertEquals(options.requestTimeout(), copy.requestTimeout());
+        assertEquals(options.idleTimeout(), copy.idleTimeout());
+        assertEquals(options.drainTimeout(), copy.drainTimeout());
+        assertEquals(options.channelMax(), copy.channelMax());
+        assertEquals(options.maxFrameSize(), copy.maxFrameSize());
+        assertEquals(options.traceFrames(), copy.traceFrames());
+        assertEquals(options.defaultNextReceiverPolicy(), 
copy.defaultNextReceiverPolicy());
+        assertEquals(options.saslOptions().saslEnabled(), 
copy.saslOptions().saslEnabled());
+        assertEquals(options.saslOptions().saslEnabled(), 
copy.saslOptions().saslEnabled());
+        assertEquals(options.transportOptions().defaultTcpPort(), 
copy.transportOptions().defaultTcpPort());
+        assertEquals(options.transportOptions().allowNativeIO(), 
copy.transportOptions().allowNativeIO());
+        assertEquals(options.sslOptions().defaultSslPort(), 
copy.sslOptions().defaultSslPort());
+        assertEquals(options.sslOptions().allowNativeSSL(), 
copy.sslOptions().allowNativeSSL());
+        assertEquals(options.saslOptions().saslEnabled(), 
copy.saslOptions().saslEnabled());
+    }
+
+    @Test
+    public void testCopySaslOptions() {
+        ConnectionOptions options = new ConnectionOptions();
+
+        options.saslOptions().addAllowedMechanism("PLAIN");
+        options.saslOptions().addAllowedMechanism("ANONYMOUS");
+        options.saslOptions().saslEnabled(false);
+
+        ConnectionOptions copy = options.clone();
+
+        assertNotSame(copy, options);
+        assertNotSame(copy.saslOptions(), options.saslOptions());
+
+        assertEquals(options.saslOptions().allowedMechanisms(), 
copy.saslOptions().allowedMechanisms());
+        assertEquals(options.saslOptions().saslEnabled(), 
copy.saslOptions().saslEnabled());
     }
 }
diff --git 
a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/impl/ConnectionTest.java
 
b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/impl/ConnectionTest.java
index 38973302..f60bee32 100644
--- 
a/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/impl/ConnectionTest.java
+++ 
b/protonj2-client/src/test/java/org/apache/qpid/protonj2/client/impl/ConnectionTest.java
@@ -56,6 +56,7 @@ import org.apache.qpid.protonj2.test.driver.ProtonTestServer;
 import org.apache.qpid.protonj2.test.driver.ProtonTestServerOptions;
 import org.apache.qpid.protonj2.test.driver.codec.messaging.TerminusDurability;
 import 
org.apache.qpid.protonj2.test.driver.codec.messaging.TerminusExpiryPolicy;
+import org.apache.qpid.protonj2.test.driver.codec.security.SaslCode;
 import org.apache.qpid.protonj2.test.driver.matchers.messaging.SourceMatcher;
 import org.apache.qpid.protonj2.types.messaging.AmqpValue;
 import org.apache.qpid.protonj2.types.transport.AMQPHeader;
@@ -1745,6 +1746,87 @@ public class ConnectionTest extends 
ImperativeClientTestCase {
         }
     }
 
+    @Test
+    public void testCreateConnectionWithNoVHostCarriesRemoteHost() throws 
Exception {
+        try (ProtonTestServer peer = new 
ProtonTestServer(testServerOptions())) {
+            peer.start();
+
+            final URI remoteURI = peer.getServerURI();
+
+            LOG.info("Connect test started, peer listening on: {}", remoteURI);
+
+            peer.expectSASLHeader().respondWithSASLHeader();
+            peer.remoteSaslMechanisms().withMechanisms("ANONYMOUS").queue();
+            
peer.expectSaslInit().withMechanism("ANONYMOUS").withHostname(remoteURI.getHost());
+            peer.remoteSaslOutcome().withCode(SaslCode.OK).queue();
+            peer.expectAMQPHeader().respondWithAMQPHeader();
+            peer.expectOpen().withHostname(remoteURI.getHost()).respond();
+            peer.expectClose().respond();
+
+            Client container = Client.create();
+            Connection connection = container.connect(remoteURI.getHost(), 
remoteURI.getPort(), connectionOptions());
+
+            connection.openFuture().get(10, TimeUnit.SECONDS);
+            connection.closeAsync().get(10, TimeUnit.SECONDS);
+
+            peer.waitForScriptToComplete(5, TimeUnit.SECONDS);
+        }
+    }
+
+    @Test
+    public void testCreateConnectionWithSpecifiedVHost() throws Exception {
+        try (ProtonTestServer peer = new 
ProtonTestServer(testServerOptions())) {
+            peer.expectSASLHeader().respondWithSASLHeader();
+            peer.remoteSaslMechanisms().withMechanisms("ANONYMOUS").queue();
+            
peer.expectSaslInit().withMechanism("ANONYMOUS").withHostname("test");
+            peer.remoteSaslOutcome().withCode(SaslCode.OK).queue();
+            peer.expectAMQPHeader().respondWithAMQPHeader();
+            peer.expectOpen().withHostname("test").respond();
+            peer.expectClose().respond();
+            peer.start();
+
+            final URI remoteURI = peer.getServerURI();
+
+            LOG.info("Connect test started, peer listening on: {}", remoteURI);
+
+            Client container = Client.create();
+            ConnectionOptions options = 
connectionOptions().virtualHost("test");
+            Connection connection = container.connect(remoteURI.getHost(), 
remoteURI.getPort(), options);
+
+            connection.openFuture().get(10, TimeUnit.SECONDS);
+            connection.closeAsync().get(10, TimeUnit.SECONDS);
+
+            peer.waitForScriptToComplete(5, TimeUnit.SECONDS);
+        }
+    }
+
+    @Test
+    public void testCreateConnectionWithEmptyVHostSendsNullValueInOpen() 
throws Exception {
+        try (ProtonTestServer peer = new 
ProtonTestServer(testServerOptions())) {
+            peer.expectSASLHeader().respondWithSASLHeader();
+            peer.remoteSaslMechanisms().withMechanisms("ANONYMOUS").queue();
+            
peer.expectSaslInit().withMechanism("ANONYMOUS").withHostname(nullValue());
+            peer.remoteSaslOutcome().withCode(SaslCode.OK).queue();
+            peer.expectAMQPHeader().respondWithAMQPHeader();
+            peer.expectOpen().withHostname(nullValue()).respond();
+            peer.expectClose().respond();
+            peer.start();
+
+            final URI remoteURI = peer.getServerURI();
+
+            LOG.info("Connect test started, peer listening on: {}", remoteURI);
+
+            Client container = Client.create();
+            ConnectionOptions options = connectionOptions().virtualHost("");
+            Connection connection = container.connect(remoteURI.getHost(), 
remoteURI.getPort(), options);
+
+            connection.openFuture().get(10, TimeUnit.SECONDS);
+            connection.closeAsync().get(10, TimeUnit.SECONDS);
+
+            peer.waitForScriptToComplete(5, TimeUnit.SECONDS);
+        }
+    }
+
     @Disabled("Disabled due to requirement of hard coded port")
     @Test
     public void testLocalPortOption() throws Exception {


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org
For additional commands, e-mail: commits-h...@qpid.apache.org

Reply via email to