You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by mo...@apache.org on 2018/01/11 17:39:00 UTC
[33/53] [abbrv] knox git commit: Merge branch 'master' into
KNOX-998-Package_Restructuring
http://git-wip-us.apache.org/repos/asf/knox/blob/22a7304a/gateway-server/src/test/java/org/apache/knox/gateway/util/KnoxCLITest.java
----------------------------------------------------------------------
diff --cc gateway-server/src/test/java/org/apache/knox/gateway/util/KnoxCLITest.java
index 4c4d419,0000000..902327c
mode 100644,000000..100644
--- a/gateway-server/src/test/java/org/apache/knox/gateway/util/KnoxCLITest.java
+++ b/gateway-server/src/test/java/org/apache/knox/gateway/util/KnoxCLITest.java
@@@ -1,649 -1,0 +1,1032 @@@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.util;
+
+import com.mycila.xmltool.XMLDoc;
+import com.mycila.xmltool.XMLTag;
+import org.apache.commons.io.FileUtils;
++import org.apache.knox.conf.Configuration;
+import org.apache.knox.gateway.config.impl.GatewayConfigImpl;
+import org.apache.knox.gateway.services.GatewayServices;
++import org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClient;
++import org.apache.knox.gateway.services.config.client.RemoteConfigurationRegistryClientService;
+import org.apache.knox.gateway.services.security.AliasService;
+import org.apache.knox.gateway.services.security.MasterService;
++import org.apache.knox.test.TestUtils;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.net.URL;
+import java.util.UUID;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
++import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author larry
+ *
+ */
+public class KnoxCLITest {
+ private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
+ private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();
+
+ @Before
+ public void setup() throws Exception {
+ System.setOut(new PrintStream(outContent));
+ System.setErr(new PrintStream(errContent));
+ }
+
+ @Test
- public void testSuccessfulAlaisLifecycle() throws Exception {
++ public void testRemoteConfigurationRegistryClientService() throws Exception {
++ outContent.reset();
++
++ KnoxCLI cli = new KnoxCLI();
++ Configuration config = new GatewayConfigImpl();
++ // Configure a client for the test local filesystem registry implementation
++ config.set("gateway.remote.config.registry.test_client", "type=LocalFileSystem;address=/test");
++ cli.setConf(config);
++
++ // This is only to get the gateway services initialized
++ cli.run(new String[]{"version"});
++
++ RemoteConfigurationRegistryClientService service =
++ cli.getGatewayServices().getService(GatewayServices.REMOTE_REGISTRY_CLIENT_SERVICE);
++ assertNotNull(service);
++ RemoteConfigurationRegistryClient client = service.get("test_client");
++ assertNotNull(client);
++
++ assertNull(service.get("bogus"));
++ }
++
++ @Test
++ public void testListRemoteConfigurationRegistryClients() throws Exception {
++ outContent.reset();
++
++ KnoxCLI cli = new KnoxCLI();
++ String[] args = { "list-registry-clients", "--master","master" };
++
++ Configuration config = new GatewayConfigImpl();
++ cli.setConf(config);
++
++ // Test with no registry clients configured
++ int rc = cli.run(args);
++ assertEquals(0, rc);
++ assertTrue(outContent.toString(), outContent.toString().isEmpty());
++
++ // Test with a single client configured
++ // Configure a client for the test local filesystem registry implementation
++ config.set("gateway.remote.config.registry.test_client", "type=LocalFileSystem;address=/test1");
++ cli.setConf(config);
++ outContent.reset();
++ rc = cli.run(args);
++ assertEquals(0, rc);
++ assertTrue(outContent.toString(), outContent.toString().contains("test_client"));
++
++ // Configure another client for the test local filesystem registry implementation
++ config.set("gateway.remote.config.registry.another_client", "type=LocalFileSystem;address=/test2");
++ cli.setConf(config);
++ outContent.reset();
++ rc = cli.run(args);
++ assertEquals(0, rc);
++ assertTrue(outContent.toString(), outContent.toString().contains("test_client"));
++ assertTrue(outContent.toString(), outContent.toString().contains("another_client"));
++ }
++
++ @Test
++ public void testRemoteConfigurationRegistryGetACLs() throws Exception {
++ outContent.reset();
++
++
++ final File testRoot = TestUtils.createTempDir(this.getClass().getName());
++ try {
++ final File testRegistry = new File(testRoot, "registryRoot");
++
++ final String providerConfigName = "my-provider-config.xml";
++ final String providerConfigContent = "<gateway/>\n";
++ final File testProviderConfig = new File(testRoot, providerConfigName);
++ final String[] uploadArgs = {"upload-provider-config", testProviderConfig.getAbsolutePath(),
++ "--registry-client", "test_client",
++ "--master", "master"};
++ FileUtils.writeStringToFile(testProviderConfig, providerConfigContent);
++
++
++ final String[] args = {"get-registry-acl", "/knox/config/shared-providers",
++ "--registry-client", "test_client",
++ "--master", "master"};
++
++ KnoxCLI cli = new KnoxCLI();
++ Configuration config = new GatewayConfigImpl();
++ // Configure a client for the test local filesystem registry implementation
++ config.set("gateway.remote.config.registry.test_client", "type=LocalFileSystem;address=" + testRegistry);
++ cli.setConf(config);
++
++ int rc = cli.run(uploadArgs);
++ assertEquals(0, rc);
++
++ // Run the test command
++ rc = cli.run(args);
++
++ // Validate the result
++ assertEquals(0, rc);
++ String result = outContent.toString();
++ assertEquals(result, 3, result.split("\n").length);
++ } finally {
++ FileUtils.forceDelete(testRoot);
++ }
++ }
++
++
++ @Test
++ public void testRemoteConfigurationRegistryUploadProviderConfig() throws Exception {
++ outContent.reset();
++
++ final String providerConfigName = "my-provider-config.xml";
++ final String providerConfigContent = "<gateway/>\n";
++
++ final File testRoot = TestUtils.createTempDir(this.getClass().getName());
++ try {
++ final File testRegistry = new File(testRoot, "registryRoot");
++ final File testProviderConfig = new File(testRoot, providerConfigName);
++
++ final String[] args = {"upload-provider-config", testProviderConfig.getAbsolutePath(),
++ "--registry-client", "test_client",
++ "--master", "master"};
++
++ FileUtils.writeStringToFile(testProviderConfig, providerConfigContent);
++
++ KnoxCLI cli = new KnoxCLI();
++ Configuration config = new GatewayConfigImpl();
++ // Configure a client for the test local filesystem registry implementation
++ config.set("gateway.remote.config.registry.test_client", "type=LocalFileSystem;address=" + testRegistry);
++ cli.setConf(config);
++
++ // Run the test command
++ int rc = cli.run(args);
++
++ // Validate the result
++ assertEquals(0, rc);
++ File registryFile = new File(testRegistry, "knox/config/shared-providers/" + providerConfigName);
++ assertTrue(registryFile.exists());
++ assertEquals(FileUtils.readFileToString(registryFile), providerConfigContent);
++ } finally {
++ FileUtils.forceDelete(testRoot);
++ }
++ }
++
++
++ @Test
++ public void testRemoteConfigurationRegistryUploadProviderConfigWithDestinationOverride() throws Exception {
++ outContent.reset();
++
++ final String providerConfigName = "my-provider-config.xml";
++ final String entryName = "my-providers.xml";
++ final String providerConfigContent = "<gateway/>\n";
++
++ final File testRoot = TestUtils.createTempDir(this.getClass().getName());
++ try {
++ final File testRegistry = new File(testRoot, "registryRoot");
++ final File testProviderConfig = new File(testRoot, providerConfigName);
++
++ final String[] args = {"upload-provider-config", testProviderConfig.getAbsolutePath(),
++ "--entry-name", entryName,
++ "--registry-client", "test_client",
++ "--master", "master"};
++
++ FileUtils.writeStringToFile(testProviderConfig, providerConfigContent);
++
++ KnoxCLI cli = new KnoxCLI();
++ Configuration config = new GatewayConfigImpl();
++ // Configure a client for the test local filesystem registry implementation
++ config.set("gateway.remote.config.registry.test_client", "type=LocalFileSystem;address=" + testRegistry);
++ cli.setConf(config);
++
++ // Run the test command
++ int rc = cli.run(args);
++
++ // Validate the result
++ assertEquals(0, rc);
++ assertFalse((new File(testRegistry, "knox/config/shared-providers/" + providerConfigName)).exists());
++ File registryFile = new File(testRegistry, "knox/config/shared-providers/" + entryName);
++ assertTrue(registryFile.exists());
++ assertEquals(FileUtils.readFileToString(registryFile), providerConfigContent);
++ } finally {
++ FileUtils.forceDelete(testRoot);
++ }
++ }
++
++
++ @Test
++ public void testRemoteConfigurationRegistryUploadDescriptor() throws Exception {
++ outContent.reset();
++
++ final String descriptorName = "my-topology.json";
++ final String descriptorContent = testDescriptorContentJSON;
++
++ final File testRoot = TestUtils.createTempDir(this.getClass().getName());
++ try {
++ final File testRegistry = new File(testRoot, "registryRoot");
++ final File testDescriptor = new File(testRoot, descriptorName);
++
++ final String[] args = {"upload-descriptor", testDescriptor.getAbsolutePath(),
++ "--registry-client", "test_client",
++ "--master", "master"};
++
++ FileUtils.writeStringToFile(testDescriptor, descriptorContent);
++
++ KnoxCLI cli = new KnoxCLI();
++ Configuration config = new GatewayConfigImpl();
++ // Configure a client for the test local filesystem registry implementation
++ config.set("gateway.remote.config.registry.test_client", "type=LocalFileSystem;address=" + testRegistry);
++ cli.setConf(config);
++
++ // Run the test command
++ int rc = cli.run(args);
++
++ // Validate the result
++ assertEquals(0, rc);
++ File registryFile = new File(testRegistry, "knox/config/descriptors/" + descriptorName);
++ assertTrue(registryFile.exists());
++ assertEquals(FileUtils.readFileToString(registryFile), descriptorContent);
++ } finally {
++ FileUtils.forceDelete(testRoot);
++ }
++ }
++
++ @Test
++ public void testRemoteConfigurationRegistryUploadDescriptorWithDestinationOverride() throws Exception {
++ outContent.reset();
++
++ final String descriptorName = "my-topology.json";
++ final String entryName = "different-topology.json";
++ final String descriptorContent = testDescriptorContentJSON;
++
++ final File testRoot = TestUtils.createTempDir(this.getClass().getName());
++ try {
++ final File testRegistry = new File(testRoot, "registryRoot");
++ final File testDescriptor = new File(testRoot, descriptorName);
++
++ final String[] args = {"upload-descriptor", testDescriptor.getAbsolutePath(),
++ "--entry-name", entryName,
++ "--registry-client", "test_client",
++ "--master", "master"};
++
++ FileUtils.writeStringToFile(testDescriptor, descriptorContent);
++
++ KnoxCLI cli = new KnoxCLI();
++ Configuration config = new GatewayConfigImpl();
++ // Configure a client for the test local filesystem registry implementation
++ config.set("gateway.remote.config.registry.test_client", "type=LocalFileSystem;address=" + testRegistry);
++ cli.setConf(config);
++
++ // Run the test command
++ int rc = cli.run(args);
++
++ // Validate the result
++ assertEquals(0, rc);
++ assertFalse((new File(testRegistry, "knox/config/descriptors/" + descriptorName)).exists());
++ File registryFile = new File(testRegistry, "knox/config/descriptors/" + entryName);
++ assertTrue(registryFile.exists());
++ assertEquals(FileUtils.readFileToString(registryFile), descriptorContent);
++ } finally {
++ FileUtils.forceDelete(testRoot);
++ }
++ }
++
++ @Test
++ public void testRemoteConfigurationRegistryDeleteProviderConfig() throws Exception {
++ outContent.reset();
++
++ // Create a provider config
++ final String providerConfigName = "my-provider-config.xml";
++ final String providerConfigContent = "<gateway/>\n";
++
++ final File testRoot = TestUtils.createTempDir(this.getClass().getName());
++ try {
++ final File testRegistry = new File(testRoot, "registryRoot");
++ final File testProviderConfig = new File(testRoot, providerConfigName);
++
++ final String[] createArgs = {"upload-provider-config", testProviderConfig.getAbsolutePath(),
++ "--registry-client", "test_client",
++ "--master", "master"};
++
++ FileUtils.writeStringToFile(testProviderConfig, providerConfigContent);
++
++ KnoxCLI cli = new KnoxCLI();
++ Configuration config = new GatewayConfigImpl();
++ // Configure a client for the test local filesystem registry implementation
++ config.set("gateway.remote.config.registry.test_client", "type=LocalFileSystem;address=" + testRegistry);
++ cli.setConf(config);
++
++ // Run the test command
++ int rc = cli.run(createArgs);
++
++ // Validate the result
++ assertEquals(0, rc);
++ File registryFile = new File(testRegistry, "knox/config/shared-providers/" + providerConfigName);
++ assertTrue(registryFile.exists());
++
++ outContent.reset();
++
++ // Delete the created provider config
++ final String[] deleteArgs = {"delete-provider-config", providerConfigName,
++ "--registry-client", "test_client",
++ "--master", "master"};
++ rc = cli.run(deleteArgs);
++ assertEquals(0, rc);
++ assertFalse(registryFile.exists());
++
++ // Try to delete a provider config that does not exist
++ rc = cli.run(new String[]{"delete-provider-config", "imaginary-providers.xml",
++ "--registry-client", "test_client",
++ "--master", "master"});
++ assertEquals(0, rc);
++ } finally {
++ FileUtils.forceDelete(testRoot);
++ }
++ }
++
++ @Test
++ public void testRemoteConfigurationRegistryDeleteDescriptor() throws Exception {
++ outContent.reset();
++
++ final String descriptorName = "my-topology.json";
++ final String descriptorContent = testDescriptorContentJSON;
++
++ final File testRoot = TestUtils.createTempDir(this.getClass().getName());
++ try {
++ final File testRegistry = new File(testRoot, "registryRoot");
++ final File testDescriptor = new File(testRoot, descriptorName);
++
++ final String[] createArgs = {"upload-descriptor", testDescriptor.getAbsolutePath(),
++ "--registry-client", "test_client",
++ "--master", "master"};
++
++ FileUtils.writeStringToFile(testDescriptor, descriptorContent);
++
++ KnoxCLI cli = new KnoxCLI();
++ Configuration config = new GatewayConfigImpl();
++ // Configure a client for the test local filesystem registry implementation
++ config.set("gateway.remote.config.registry.test_client", "type=LocalFileSystem;address=" + testRegistry);
++ cli.setConf(config);
++
++ // Run the test command
++ int rc = cli.run(createArgs);
++
++ // Validate the result
++ assertEquals(0, rc);
++ File registryFile = new File(testRegistry, "knox/config/descriptors/" + descriptorName);
++ assertTrue(registryFile.exists());
++
++ outContent.reset();
++
++ // Delete the created provider config
++ final String[] deleteArgs = {"delete-descriptor", descriptorName,
++ "--registry-client", "test_client",
++ "--master", "master"};
++ rc = cli.run(deleteArgs);
++ assertEquals(0, rc);
++ assertFalse(registryFile.exists());
++
++ // Try to delete a descriptor that does not exist
++ rc = cli.run(new String[]{"delete-descriptor", "bogus.json",
++ "--registry-client", "test_client",
++ "--master", "master"});
++ assertEquals(0, rc);
++ } finally {
++ FileUtils.forceDelete(testRoot);
++ }
++ }
++
++ @Test
++ public void testSuccessfulAliasLifecycle() throws Exception {
+ outContent.reset();
+ String[] args1 = {"create-alias", "alias1", "--value", "testvalue1", "--master", "master"};
+ int rc = 0;
+ KnoxCLI cli = new KnoxCLI();
+ cli.setConf(new GatewayConfigImpl());
+ rc = cli.run(args1);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(), outContent.toString().contains("alias1 has been successfully " +
+ "created."));
+
+ outContent.reset();
+ String[] args2 = {"list-alias", "--master",
+ "master"};
+ rc = cli.run(args2);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(), outContent.toString().contains("alias1"));
+
+ outContent.reset();
+ String[] args4 = {"delete-alias", "alias1", "--master",
+ "master"};
+ rc = cli.run(args4);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(), outContent.toString().contains("alias1 has been successfully " +
+ "deleted."));
+
+ outContent.reset();
+ rc = cli.run(args2);
+ assertEquals(0, rc);
+ assertFalse(outContent.toString(), outContent.toString().contains("alias1"));
+ }
+
+ @Test
+ public void testListAndDeleteOfAliasForInvalidClusterName() throws Exception {
+ outContent.reset();
+ String[] args1 =
+ { "create-alias", "alias1", "--cluster", "cluster1", "--value", "testvalue1", "--master",
+ "master" };
+ int rc = 0;
+ KnoxCLI cli = new KnoxCLI();
+ cli.setConf(new GatewayConfigImpl());
+ rc = cli.run(args1);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(), outContent.toString().contains(
+ "alias1 has been successfully " + "created."));
+
+ outContent.reset();
+ String[] args2 = { "list-alias", "--cluster", "Invalidcluster1", "--master", "master" };
+ rc = cli.run(args2);
+ assertEquals(0, rc);
+ System.out.println(outContent.toString());
+ assertTrue(outContent.toString(),
+ outContent.toString().contains("Invalid cluster name provided: Invalidcluster1"));
+
+ outContent.reset();
+ String[] args4 =
+ { "delete-alias", "alias1", "--cluster", "Invalidcluster1", "--master", "master" };
+ rc = cli.run(args4);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(),
+ outContent.toString().contains("Invalid cluster name provided: Invalidcluster1"));
+
+ }
+
+ @Test
+ public void testDeleteOfNonExistAliasFromUserDefinedCluster() throws Exception {
+ KnoxCLI cli = new KnoxCLI();
+ cli.setConf(new GatewayConfigImpl());
+ try {
+ int rc = 0;
+ outContent.reset();
+ String[] args1 =
+ { "create-alias", "alias1", "--cluster", "cluster1", "--value", "testvalue1", "--master",
+ "master" };
+ cli.run(args1);
+
+ // Delete invalid alias from the cluster
+ outContent.reset();
+ String[] args2 = { "delete-alias", "alias2", "--cluster", "cluster1", "--master", "master" };
+ rc = cli.run(args2);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString().contains("No such alias exists in the cluster."));
+ } finally {
+ outContent.reset();
+ String[] args1 = { "delete-alias", "alias1", "--cluster", "cluster1", "--master", "master" };
+ cli.run(args1);
+ }
+ }
+
+ @Test
+ public void testDeleteOfNonExistAliasFromDefaultCluster() throws Exception {
+ KnoxCLI cli = new KnoxCLI();
+ cli.setConf(new GatewayConfigImpl());
+ try {
+ int rc = 0;
+ outContent.reset();
+ String[] args1 = { "create-alias", "alias1", "--value", "testvalue1", "--master", "master" };
+ cli.run(args1);
+
+ // Delete invalid alias from the cluster
+ outContent.reset();
+ String[] args2 = { "delete-alias", "alias2", "--master", "master" };
+ rc = cli.run(args2);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString().contains("No such alias exists in the cluster."));
+ } finally {
+ outContent.reset();
+ String[] args1 = { "delete-alias", "alias1", "--master", "master" };
+ cli.run(args1);
+ }
+ }
+
+ @Test
+ public void testForInvalidArgument() throws Exception {
+ outContent.reset();
+ String[] args1 = { "--value", "testvalue1", "--master", "master" };
+ KnoxCLI cli = new KnoxCLI();
+ cli.setConf(new GatewayConfigImpl());
+ int rc = cli.run(args1);
+ assertEquals(-2, rc);
+ assertTrue(outContent.toString().contains("ERROR: Invalid Command"));
+ }
+
+ @Test
+ public void testListAndDeleteOfAliasForValidClusterName() throws Exception {
+ outContent.reset();
+ String[] args1 =
+ { "create-alias", "alias1", "--cluster", "cluster1", "--value", "testvalue1", "--master",
+ "master" };
+ int rc = 0;
+ KnoxCLI cli = new KnoxCLI();
+ cli.setConf(new GatewayConfigImpl());
+ rc = cli.run(args1);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(), outContent.toString().contains(
+ "alias1 has been successfully " + "created."));
+
+ outContent.reset();
+ String[] args2 = { "list-alias", "--cluster", "cluster1", "--master", "master" };
+ rc = cli.run(args2);
+ assertEquals(0, rc);
+ System.out.println(outContent.toString());
+ assertTrue(outContent.toString(), outContent.toString().contains("alias1"));
+
+ outContent.reset();
+ String[] args4 =
+ { "delete-alias", "alias1", "--cluster", "cluster1", "--master", "master" };
+ rc = cli.run(args4);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(), outContent.toString().contains(
+ "alias1 has been successfully " + "deleted."));
+
+ outContent.reset();
+ rc = cli.run(args2);
+ assertEquals(0, rc);
+ assertFalse(outContent.toString(), outContent.toString().contains("alias1"));
+
+ }
+
+ @Test
+ public void testGatewayAndClusterStores() throws Exception {
+ GatewayConfigImpl config = new GatewayConfigImpl();
+ FileUtils.deleteQuietly( new File( config.getGatewaySecurityDir() ) );
+
+ outContent.reset();
+ String[] gwCreateArgs = {"create-alias", "alias1", "--value", "testvalue1", "--master", "master"};
+ int rc = 0;
+ KnoxCLI cli = new KnoxCLI();
+ cli.setConf( config );
+ rc = cli.run(gwCreateArgs);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(), outContent.toString().contains("alias1 has been successfully " +
+ "created."));
+
+ AliasService as = cli.getGatewayServices().getService(GatewayServices.ALIAS_SERVICE);
+
+ outContent.reset();
+ String[] clusterCreateArgs = {"create-alias", "alias2", "--value", "testvalue1", "--cluster", "test",
+ "--master", "master"};
+ cli = new KnoxCLI();
+ cli.setConf( config );
+ rc = cli.run(clusterCreateArgs);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(), outContent.toString().contains("alias2 has been successfully " +
+ "created."));
+
+ outContent.reset();
+ String[] args2 = {"list-alias", "--master", "master"};
+ cli = new KnoxCLI();
+ rc = cli.run(args2);
+ assertEquals(0, rc);
+ assertFalse(outContent.toString(), outContent.toString().contains("alias2"));
+ assertTrue(outContent.toString(), outContent.toString().contains("alias1"));
+
+ char[] passwordChars = as.getPasswordFromAliasForCluster("test", "alias2");
+ assertNotNull(passwordChars);
+ assertTrue(new String(passwordChars), "testvalue1".equals(new String(passwordChars)));
+
+ outContent.reset();
+ String[] args1 = {"list-alias", "--cluster", "test", "--master", "master"};
+ cli = new KnoxCLI();
+ rc = cli.run(args1);
+ assertEquals(0, rc);
+ assertFalse(outContent.toString(), outContent.toString().contains("alias1"));
+ assertTrue(outContent.toString(), outContent.toString().contains("alias2"));
+
+ outContent.reset();
+ String[] args4 = {"delete-alias", "alias1", "--master", "master"};
+ cli = new KnoxCLI();
+ rc = cli.run(args4);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(), outContent.toString().contains("alias1 has been successfully " +
+ "deleted."));
+
+ outContent.reset();
+ String[] args5 = {"delete-alias", "alias2", "--cluster", "test", "--master", "master"};
+ cli = new KnoxCLI();
+ rc = cli.run(args5);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(), outContent.toString().contains("alias2 has been successfully " +
+ "deleted."));
+ }
+
+ private void createTestMaster() throws Exception {
+ outContent.reset();
+ String[] args = new String[]{ "create-master", "--master", "master", "--force" };
+ KnoxCLI cli = new KnoxCLI();
+ int rc = cli.run(args);
+ assertThat( rc, is( 0 ) );
+ MasterService ms = cli.getGatewayServices().getService("MasterService");
+ String master = String.copyValueOf( ms.getMasterSecret() );
+ assertThat( master, is( "master" ) );
+ assertThat( outContent.toString(), containsString( "Master secret has been persisted to disk." ) );
+ }
+
+ @Test
+ public void testCreateSelfSignedCert() throws Exception {
+ GatewayConfigImpl config = new GatewayConfigImpl();
+ FileUtils.deleteQuietly( new File( config.getGatewaySecurityDir() ) );
+ createTestMaster();
+ outContent.reset();
+ KnoxCLI cli = new KnoxCLI();
+ cli.setConf( config );
+ String[] gwCreateArgs = {"create-cert", "--hostname", "hostname1", "--master", "master"};
+ int rc = 0;
+ rc = cli.run(gwCreateArgs);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(), outContent.toString().contains("gateway-identity has been successfully " +
+ "created."));
+ }
+
+ @Test
+ public void testExportCert() throws Exception {
+ GatewayConfigImpl config = new GatewayConfigImpl();
+ FileUtils.deleteQuietly( new File( config.getGatewaySecurityDir() ) );
+ createTestMaster();
+ outContent.reset();
+ KnoxCLI cli = new KnoxCLI();
+ cli.setConf( config );
+ String[] gwCreateArgs = {"create-cert", "--hostname", "hostname1", "--master", "master"};
+ int rc = 0;
+ rc = cli.run(gwCreateArgs);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(), outContent.toString().contains("gateway-identity has been successfully " +
+ "created."));
+
+ outContent.reset();
+ String[] gwCreateArgs2 = {"export-cert", "--type", "PEM"};
+ rc = 0;
+ rc = cli.run(gwCreateArgs2);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(), outContent.toString().contains("Certificate gateway-identity has been successfully exported to"));
+ assertTrue(outContent.toString(), outContent.toString().contains("gateway-identity.pem"));
+
+ outContent.reset();
+ String[] gwCreateArgs2_5 = {"export-cert"};
+ rc = 0;
+ rc = cli.run(gwCreateArgs2_5);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(), outContent.toString().contains("Certificate gateway-identity has been successfully exported to"));
+ assertTrue(outContent.toString(), outContent.toString().contains("gateway-identity.pem"));
+
+ outContent.reset();
+ String[] gwCreateArgs3 = {"export-cert", "--type", "JKS"};
+ rc = 0;
+ rc = cli.run(gwCreateArgs3);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(), outContent.toString().contains("Certificate gateway-identity has been successfully exported to"));
+ assertTrue(outContent.toString(), outContent.toString().contains("gateway-client-trust.jks"));
+
+ outContent.reset();
+ String[] gwCreateArgs4 = {"export-cert", "--type", "invalid"};
+ rc = 0;
+ rc = cli.run(gwCreateArgs4);
+ assertEquals(0, rc);
+ assertTrue(outContent.toString(), outContent.toString().contains("Invalid type for export file provided."));
+ }
+
+ @Test
+ public void testCreateMaster() throws Exception {
+ GatewayConfigImpl config = new GatewayConfigImpl();
+ FileUtils.deleteQuietly( new File( config.getGatewaySecurityDir() ) );
+ outContent.reset();
+ String[] args = {"create-master", "--master", "master"};
+ int rc = 0;
+ KnoxCLI cli = new KnoxCLI();
+ cli.setConf( config );
+ rc = cli.run(args);
+ assertEquals(0, rc);
+ MasterService ms = cli.getGatewayServices().getService("MasterService");
+ // assertTrue(ms.getClass().getName(), ms.getClass().getName().equals("kjdfhgjkhfdgjkh"));
+ assertTrue( new String( ms.getMasterSecret() ), "master".equals( new String( ms.getMasterSecret() ) ) );
+ assertTrue(outContent.toString(), outContent.toString().contains("Master secret has been persisted to disk."));
+ }
+
+ @Test
+ public void testCreateMasterGenerate() throws Exception {
+ String[] args = {"create-master", "--generate" };
+ int rc = 0;
+ GatewayConfigImpl config = new GatewayConfigImpl();
+ File masterFile = new File( config.getGatewaySecurityDir(), "master" );
+
+ // Need to delete the master file so that the change isn't ignored.
+ if( masterFile.exists() ) {
+ assertThat( "Failed to delete existing master file.", masterFile.delete(), is( true ) );
+ }
+ outContent.reset();
+ KnoxCLI cli = new KnoxCLI();
+ cli.setConf(config);
+ rc = cli.run(args);
+ assertThat( rc, is( 0 ) );
+ MasterService ms = cli.getGatewayServices().getService("MasterService");
+ String master = String.copyValueOf( ms.getMasterSecret() );
+ assertThat( master.length(), is( 36 ) );
+ assertThat( master.indexOf( '-' ), is( 8 ) );
+ assertThat( master.indexOf( '-', 9 ), is( 13 ) );
+ assertThat( master.indexOf( '-', 14 ), is( 18 ) );
+ assertThat( master.indexOf( '-', 19 ), is( 23 ) );
+ assertThat( UUID.fromString( master ), notNullValue() );
+ assertThat( outContent.toString(), containsString( "Master secret has been persisted to disk." ) );
+
+ // Need to delete the master file so that the change isn't ignored.
+ if( masterFile.exists() ) {
+ assertThat( "Failed to delete existing master file.", masterFile.delete(), is( true ) );
+ }
+ outContent.reset();
+ cli = new KnoxCLI();
+ rc = cli.run(args);
+ ms = cli.getGatewayServices().getService("MasterService");
+ String master2 = String.copyValueOf( ms.getMasterSecret() );
+ assertThat( master2.length(), is( 36 ) );
+ assertThat( UUID.fromString( master2 ), notNullValue() );
+ assertThat( master2, not( is( master ) ) );
+ assertThat( rc, is( 0 ) );
+ assertThat(outContent.toString(), containsString("Master secret has been persisted to disk."));
+ }
+
+ @Test
+ public void testCreateMasterForce() throws Exception {
+ GatewayConfigImpl config = new GatewayConfigImpl();
+ File masterFile = new File( config.getGatewaySecurityDir(), "master" );
+
+ // Need to delete the master file so that the change isn't ignored.
+ if( masterFile.exists() ) {
+ assertThat( "Failed to delete existing master file.", masterFile.delete(), is( true ) );
+ }
+
+ KnoxCLI cli = new KnoxCLI();
+ cli.setConf(config);
+ MasterService ms;
+ int rc = 0;
+ outContent.reset();
+
+ String[] args = { "create-master", "--master", "test-master-1" };
+
+ rc = cli.run(args);
+ assertThat( rc, is( 0 ) );
+ ms = cli.getGatewayServices().getService("MasterService");
+ String master = String.copyValueOf( ms.getMasterSecret() );
+ assertThat( master, is( "test-master-1" ) );
+ assertThat( outContent.toString(), containsString( "Master secret has been persisted to disk." ) );
+
+ outContent.reset();
+ rc = cli.run(args);
+ assertThat( rc, is(0 ) );
+ assertThat( outContent.toString(), containsString( "Master secret is already present on disk." ) );
+
+ outContent.reset();
+ args = new String[]{ "create-master", "--master", "test-master-2", "--force" };
+ rc = cli.run(args);
+ assertThat( rc, is( 0 ) );
+ ms = cli.getGatewayServices().getService("MasterService");
+ master = String.copyValueOf( ms.getMasterSecret() );
+ assertThat( master, is( "test-master-2" ) );
+ assertThat( outContent.toString(), containsString( "Master secret has been persisted to disk." ) );
+ }
+
+ @Test
+ public void testListTopology() throws Exception {
+
+ GatewayConfigMock config = new GatewayConfigMock();
+ URL topoURL = ClassLoader.getSystemResource("conf-demo/conf/topologies/admin.xml");
+ config.setConfDir( new File(topoURL.getFile()).getParentFile().getParent() );
+ String args[] = {"list-topologies", "--master", "knox"};
+
+ KnoxCLI cli = new KnoxCLI();
+ cli.setConf( config );
+
+ cli.run( args );
+ assertThat(outContent.toString(), containsString("sandbox"));
+ assertThat(outContent.toString(), containsString("admin"));
+ }
+
+ private class GatewayConfigMock extends GatewayConfigImpl{
+ private String confDir;
+ public void setConfDir(String location) {
+ confDir = location;
+ }
+
+ @Override
+ public String getGatewayConfDir(){
+ return confDir;
+ }
+ }
+
+ private static XMLTag createBadTopology() {
+ XMLTag xml = XMLDoc.newDocument(true)
+ .addRoot( "topology" )
+ .addTag( "gateway" )
+
+ .addTag( "provider" )
+ .addTag( "role" ).addText( "authentication" )
+ .addTag( "name" ).addText( "ShiroProvider" )
+ .addTag( "enabled" ).addText( "123" )
+ .addTag( "param" )
+ .addTag( "name" ).addText( "" )
+ .addTag( "value" ).addText( "org.apache.knox.gateway.shirorealm.KnoxLdapRealm" ).gotoParent()
+ .addTag( "param" )
+ .addTag( "name" ).addText( "main.ldapRealm.userDnTemplate" )
+ .addTag( "value" ).addText( "uid={0},ou=people,dc=hadoop,dc=apache,dc=org" ).gotoParent()
+ .addTag( "param" )
+ .addTag( "name" ).addText( "main.ldapRealm.contextFactory.url" )
+ .addTag( "value" ).addText( "ldap://localhost:8443" ).gotoParent()
+ .addTag( "param" )
+ .addTag( "name" ).addText( "main.ldapRealm.contextFactory.authenticationMechanism" )
+ .addTag( "value" ).addText( "simple" ).gotoParent()
+ .addTag( "param" )
+ .addTag( "name" ).addText( "urls./**" )
+ .addTag( "value" ).addText( "authcBasic" ).gotoParent().gotoParent()
+ .addTag( "provider" )
+ .addTag( "role" ).addText( "identity-assertion" )
+ .addTag( "enabled" ).addText( "vvv" )
+ .addTag( "name" ).addText( "Default" ).gotoParent()
+ .addTag( "provider" )
+ .gotoRoot()
+ .addTag( "service" )
+ .addTag( "role" ).addText( "test-service-role" )
+ .gotoRoot();
+ return xml;
+ }
+
+ private static XMLTag createGoodTopology() {
+ XMLTag xml = XMLDoc.newDocument( true )
+ .addRoot( "topology" )
+ .addTag( "gateway" )
+
+ .addTag( "provider" )
+ .addTag( "role" ).addText( "authentication" )
+ .addTag( "name" ).addText( "ShiroProvider" )
+ .addTag( "enabled" ).addText( "true" )
+ .addTag( "param" )
+ .addTag( "name" ).addText( "main.ldapRealm" )
+ .addTag( "value" ).addText( "org.apache.knox.gateway.shirorealm.KnoxLdapRealm" ).gotoParent()
+ .addTag( "param" )
+ .addTag( "name" ).addText( "main.ldapRealm.userDnTemplate" )
+ .addTag( "value" ).addText( "uid={0},ou=people,dc=hadoop,dc=apache,dc=org" ).gotoParent()
+ .addTag( "param" )
+ .addTag( "name" ).addText( "main.ldapRealm.contextFactory.url" )
+ .addTag( "value" ).addText( "ldap://localhost:8443").gotoParent()
+ .addTag( "param" )
+ .addTag( "name" ).addText( "main.ldapRealm.contextFactory.authenticationMechanism" )
+ .addTag( "value" ).addText( "simple" ).gotoParent()
+ .addTag( "param" )
+ .addTag( "name" ).addText( "urls./**" )
+ .addTag( "value" ).addText( "authcBasic" ).gotoParent().gotoParent()
+ .addTag( "provider" )
+ .addTag( "role" ).addText( "identity-assertion" )
+ .addTag( "enabled" ).addText( "true" )
+ .addTag( "name" ).addText( "Default" ).gotoParent()
+ .addTag( "provider" )
+ .gotoRoot()
+ .addTag( "service" )
+ .addTag( "role" ).addText( "test-service-role" )
+ .gotoRoot();
+ return xml;
+ }
+
+ private File writeTestTopology( String name, XMLTag xml ) throws IOException {
+ // Create the test topology.
+
+ GatewayConfigMock config = new GatewayConfigMock();
+ URL topoURL = ClassLoader.getSystemResource("conf-demo/conf/topologies/admin.xml");
+ config.setConfDir( new File(topoURL.getFile()).getParentFile().getParent() );
+
+ File tempFile = new File( config.getGatewayTopologyDir(), name + ".xml." + UUID.randomUUID() );
+ FileOutputStream stream = new FileOutputStream( tempFile );
+ xml.toStream( stream );
+ stream.close();
+ File descriptor = new File( config.getGatewayTopologyDir(), name + ".xml" );
+ tempFile.renameTo( descriptor );
+ return descriptor;
+ }
+
+ @Test
+ public void testValidateTopology() throws Exception {
+
+ GatewayConfigMock config = new GatewayConfigMock();
+ URL topoURL = ClassLoader.getSystemResource("conf-demo/conf/topologies/admin.xml");
+ config.setConfDir( new File(topoURL.getFile()).getParentFile().getParent() );
+ String args[] = {"validate-topology", "--master", "knox", "--cluster", "sandbox"};
+
+ KnoxCLI cli = new KnoxCLI();
+ cli.setConf( config );
+ cli.run( args );
+
+ assertThat(outContent.toString(), containsString(config.getGatewayTopologyDir()));
+ assertThat(outContent.toString(), containsString("sandbox"));
+ assertThat(outContent.toString(), containsString("success"));
+ outContent.reset();
+
+
+ String args2[] = {"validate-topology", "--master", "knox", "--cluster", "NotATopology"};
+ cli.run(args2);
+
+ assertThat(outContent.toString(), containsString("NotATopology"));
+ assertThat(outContent.toString(), containsString("does not exist"));
+ outContent.reset();
+
+ String args3[] = {"validate-topology", "--master", "knox", "--path", config.getGatewayTopologyDir() + "/admin.xml"};
+ cli.run(args3);
+
+ assertThat(outContent.toString(), containsString("admin"));
+ assertThat(outContent.toString(), containsString("success"));
+ outContent.reset();
+
+ String args4[] = {"validate-topology", "--master", "knox", "--path", "not/a/path"};
+ cli.run(args4);
+ assertThat(outContent.toString(), containsString("does not exist"));
+ assertThat(outContent.toString(), containsString("not/a/path"));
+ }
+
+ @Test
+ public void testValidateTopologyOutput() throws Exception {
+
+ File bad = writeTestTopology( "test-cluster-bad", createBadTopology() );
+ File good = writeTestTopology( "test-cluster-good", createGoodTopology() );
+
+ GatewayConfigMock config = new GatewayConfigMock();
+ URL topoURL = ClassLoader.getSystemResource("conf-demo/conf/topologies/admin.xml");
+ config.setConfDir( new File(topoURL.getFile()).getParentFile().getParent() );
+ String args[] = {"validate-topology", "--master", "knox", "--cluster", "test-cluster-bad"};
+
+ KnoxCLI cli = new KnoxCLI();
+ cli.setConf( config );
+ cli.run( args );
+
+ assertThat(outContent.toString(), containsString(config.getGatewayTopologyDir()));
+ assertThat(outContent.toString(), containsString("test-cluster-bad"));
+ assertThat(outContent.toString(), containsString("unsuccessful"));
+ assertThat(outContent.toString(), containsString("Invalid content"));
+ assertThat(outContent.toString(), containsString("Line"));
+
+
+ outContent.reset();
+
+ String args2[] = {"validate-topology", "--master", "knox", "--cluster", "test-cluster-good"};
+
+ cli.run(args2);
+
+ assertThat(outContent.toString(), containsString(config.getGatewayTopologyDir()));
+ assertThat(outContent.toString(), containsString("success"));
+ assertThat(outContent.toString(), containsString("test-cluster-good"));
+
+
+ }
+
++ private static final String testDescriptorContentJSON = "{\n" +
++ " \"discovery-address\":\"http://localhost:8080\",\n" +
++ " \"discovery-user\":\"maria_dev\",\n" +
++ " \"discovery-pwd-alias\":\"sandbox.discovery.password\",\n" +
++ " \"provider-config-ref\":\"my-provider-config\",\n" +
++ " \"cluster\":\"Sandbox\",\n" +
++ " \"services\":[\n" +
++ " {\"name\":\"NAMENODE\"},\n" +
++ " {\"name\":\"JOBTRACKER\"},\n" +
++ " {\"name\":\"WEBHDFS\"},\n" +
++ " {\"name\":\"WEBHCAT\"},\n" +
++ " {\"name\":\"OOZIE\"},\n" +
++ " {\"name\":\"WEBHBASE\"},\n" +
++ " {\"name\":\"HIVE\"},\n" +
++ " {\"name\":\"RESOURCEMANAGER\"}\n" +
++ " ]\n" +
++ "}";
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/22a7304a/gateway-server/src/test/java/org/apache/knox/gateway/websockets/BadUrlTest.java
----------------------------------------------------------------------
diff --cc gateway-server/src/test/java/org/apache/knox/gateway/websockets/BadUrlTest.java
index 3aceadd,0000000..2ca5ede
mode 100644,000000..100644
--- a/gateway-server/src/test/java/org/apache/knox/gateway/websockets/BadUrlTest.java
+++ b/gateway-server/src/test/java/org/apache/knox/gateway/websockets/BadUrlTest.java
@@@ -1,309 -1,0 +1,320 @@@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.websockets;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
++import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import javax.websocket.CloseReason;
+import javax.websocket.ContainerProvider;
+import javax.websocket.WebSocketContainer;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.knox.gateway.config.GatewayConfig;
+import org.apache.knox.gateway.config.impl.GatewayConfigImpl;
+import org.apache.knox.gateway.deploy.DeploymentFactory;
+import org.apache.knox.gateway.services.DefaultGatewayServices;
+import org.apache.knox.gateway.services.GatewayServices;
+import org.apache.knox.gateway.services.ServiceLifecycleException;
+import org.apache.knox.gateway.services.topology.TopologyService;
+import org.apache.knox.gateway.topology.TopologyEvent;
+import org.apache.knox.gateway.topology.TopologyListener;
+import org.apache.knox.test.TestUtils;
+import org.easymock.EasyMock;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.server.handler.HandlerCollection;
+import org.hamcrest.CoreMatchers;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.mycila.xmltool.XMLDoc;
+import com.mycila.xmltool.XMLTag;
+
+/**
+ * Test for bad URLs.
+ * <p>
+ * This test will set up a bad URL through the topology, so this test case will
+ * attempt to test the bad url case and also the plumbing around it.
+ * @since 0.10
+ */
+public class BadUrlTest {
+
+ /**
+ * Non-existant backend websocket server
+ */
+ private static String BACKEND = "http://localhost:9999";
+
+ /**
+ * Mock Gateway server
+ */
+ private static Server gatewayServer;
+
+ /**
+ * Mock gateway config
+ */
+ private static GatewayConfig gatewayConfig;
+
+ private static GatewayServices services;
+
+ /**
+ * URI for gateway server
+ */
+ private static URI serverUri;
+
+ private static File topoDir;
+
+ public BadUrlTest() {
+ super();
+ }
+
+ @BeforeClass
+ public static void startServers() throws Exception {
+
+ startGatewayServer();
+
+ }
+
+ @AfterClass
+ public static void stopServers() {
+ try {
+ gatewayServer.stop();
+ } catch (final Exception e) {
+ e.printStackTrace(System.err);
+ }
+
+ /* Cleanup the created files */
+ FileUtils.deleteQuietly(topoDir);
+
+ }
+
+ /**
+ * Test websocket proxying through gateway.
+ *
+ * @throws Exception
+ */
+
+ @Test
+ public void testBadUrl() throws Exception {
+ WebSocketContainer container = ContainerProvider.getWebSocketContainer();
+
+ WebsocketClient client = new WebsocketClient();
+
+ container.connectToServer(client,
+ new URI(serverUri.toString() + "gateway/websocket/ws"));
+
+ client.awaitClose(CloseReason.CloseCodes.UNEXPECTED_CONDITION.getCode(),
+ 1000, TimeUnit.MILLISECONDS);
+
+ Assert.assertThat(client.close.getCloseCode().getCode(),
+ CoreMatchers.is(CloseReason.CloseCodes.UNEXPECTED_CONDITION.getCode()));
+
+ }
+
+
+ /**
+ * Start Gateway Server.
+ *
+ * @throws Exception
+ */
+ private static void startGatewayServer() throws Exception {
+ gatewayServer = new Server();
+ final ServerConnector connector = new ServerConnector(gatewayServer);
+ gatewayServer.addConnector(connector);
+
+ /* workaround so we can add our handler later at runtime */
+ HandlerCollection handlers = new HandlerCollection(true);
+
+ /* add some initial handlers */
+ ContextHandler context = new ContextHandler();
+ context.setContextPath("/");
+ handlers.addHandler(context);
+
+ gatewayServer.setHandler(handlers);
+
+ // Start Server
+ gatewayServer.start();
+
+ String host = connector.getHost();
+ if (host == null) {
+ host = "localhost";
+ }
+ int port = connector.getLocalPort();
+ serverUri = new URI(String.format("ws://%s:%d/", host, port));
+
+ /* Setup websocket handler */
+ setupGatewayConfig(BACKEND);
+
+ final GatewayWebsocketHandler gatewayWebsocketHandler = new GatewayWebsocketHandler(
+ gatewayConfig, services);
+ handlers.addHandler(gatewayWebsocketHandler);
+ gatewayWebsocketHandler.start();
+ }
+
+ /**
+ * Initialize the configs and components required for this test.
+ *
+ * @param backend
+ * @throws IOException
+ */
+ private static void setupGatewayConfig(final String backend)
+ throws IOException {
+ services = new DefaultGatewayServices();
+
+ topoDir = createDir();
+ URL serviceUrl = ClassLoader.getSystemResource("websocket-services");
+
+ final File descriptor = new File(topoDir, "websocket.xml");
+ final FileOutputStream stream = new FileOutputStream(descriptor);
+ createKnoxTopology(backend).toStream(stream);
+ stream.close();
+
+ final TestTopologyListener topoListener = new TestTopologyListener();
+
+ final Map<String, String> options = new HashMap<>();
+ options.put("persist-master", "false");
+ options.put("master", "password");
+
+ gatewayConfig = EasyMock.createNiceMock(GatewayConfig.class);
+ EasyMock.expect(gatewayConfig.getGatewayTopologyDir())
+ .andReturn(topoDir.toString()).anyTimes();
+
++ EasyMock.expect(gatewayConfig.getGatewayProvidersConfigDir())
++ .andReturn(topoDir.getAbsolutePath() + "/shared-providers").anyTimes();
++
++ EasyMock.expect(gatewayConfig.getGatewayDescriptorsDir())
++ .andReturn(topoDir.getAbsolutePath() + "/descriptors").anyTimes();
++
+ EasyMock.expect(gatewayConfig.getGatewayServicesDir())
+ .andReturn(serviceUrl.getFile()).anyTimes();
+
+ EasyMock.expect(gatewayConfig.getEphemeralDHKeySize()).andReturn("2048")
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getGatewaySecurityDir())
+ .andReturn(topoDir.toString()).anyTimes();
+
+ /* Websocket configs */
+ EasyMock.expect(gatewayConfig.isWebsocketEnabled()).andReturn(true)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketMaxTextMessageSize())
+ .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_TEXT_MESSAGE_SIZE)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketMaxBinaryMessageSize())
+ .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_BINARY_MESSAGE_SIZE)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketMaxTextMessageBufferSize())
+ .andReturn(
+ GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_TEXT_MESSAGE_BUFFER_SIZE)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketMaxBinaryMessageBufferSize())
+ .andReturn(
+ GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_BINARY_MESSAGE_BUFFER_SIZE)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketInputBufferSize())
+ .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_INPUT_BUFFER_SIZE)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketAsyncWriteTimeout())
+ .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_ASYNC_WRITE_TIMEOUT)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketIdleTimeout())
+ .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_IDLE_TIMEOUT).anyTimes();
+
++ EasyMock.expect(gatewayConfig.getRemoteRegistryConfigurationNames())
++ .andReturn(Collections.emptyList())
++ .anyTimes();
++
+ EasyMock.replay(gatewayConfig);
+
+ try {
+ services.init(gatewayConfig, options);
+ } catch (ServiceLifecycleException e) {
+ e.printStackTrace();
+ }
+
+ DeploymentFactory.setGatewayServices(services);
+ final TopologyService monitor = services
+ .getService(GatewayServices.TOPOLOGY_SERVICE);
+ monitor.addTopologyChangeListener(topoListener);
+ monitor.reloadTopologies();
+
+ }
+
+ private static File createDir() throws IOException {
+ return TestUtils
+ .createTempDir(WebsocketEchoTest.class.getSimpleName() + "-");
+ }
+
+ /**
+ * Intentionally add bad URL
+ *
+ * @param backend
+ * @return
+ */
+ private static XMLTag createKnoxTopology(final String backend) {
+ XMLTag xml = XMLDoc.newDocument(true).addRoot("topology").addTag("service")
+ .addTag("role").addText("WEBSOCKET").addTag("url").addText(backend)
+ .gotoParent().gotoRoot();
+ // System.out.println( "GATEWAY=" + xml.toString() );
+ return xml;
+ }
+
+ private static class TestTopologyListener implements TopologyListener {
+
+ public ArrayList<List<TopologyEvent>> events = new ArrayList<List<TopologyEvent>>();
+
+ @Override
+ public void handleTopologyEvent(List<TopologyEvent> events) {
+ this.events.add(events);
+
+ synchronized (this) {
+ for (TopologyEvent event : events) {
+ if (!event.getType().equals(TopologyEvent.Type.DELETED)) {
+
+ /* for this test we only care about this part */
+ DeploymentFactory.createDeployment(gatewayConfig,
+ event.getTopology());
+
+ }
+ }
+
+ }
+
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/22a7304a/gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketEchoTest.java
----------------------------------------------------------------------
diff --cc gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketEchoTest.java
index 268e14b,0000000..64ad87c
mode 100644,000000..100644
--- a/gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketEchoTest.java
+++ b/gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketEchoTest.java
@@@ -1,388 -1,0 +1,399 @@@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.websockets;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
++import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import javax.websocket.ContainerProvider;
+import javax.websocket.Session;
+import javax.websocket.WebSocketContainer;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.knox.gateway.config.GatewayConfig;
+import org.apache.knox.gateway.config.impl.GatewayConfigImpl;
+import org.apache.knox.gateway.deploy.DeploymentFactory;
+import org.apache.knox.gateway.services.DefaultGatewayServices;
+import org.apache.knox.gateway.services.GatewayServices;
+import org.apache.knox.gateway.services.ServiceLifecycleException;
+import org.apache.knox.gateway.services.topology.TopologyService;
+import org.apache.knox.gateway.topology.TopologyEvent;
+import org.apache.knox.gateway.topology.TopologyListener;
+import org.apache.knox.test.TestUtils;
+import org.easymock.EasyMock;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.server.handler.HandlerCollection;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.mycila.xmltool.XMLDoc;
+import com.mycila.xmltool.XMLTag;
+
+/**
+ * A basic test that attempts to proxy websocket connections through Knox
+ * gateway.
+ * <p>
+ * The way the test is set up is as follows: <br/>
+ * <ul>
+ * <li>A Mock Websocket server is setup which simply echos the responses sent by
+ * client.
+ * <li>Knox Gateway is set up with websocket handler
+ * {@link GatewayWebsocketHandler} that can proxy the requests.
+ * <li>Appropriate Topology and service definition files are set up with the
+ * address of the Websocket server.
+ * <li>A mock client is setup to connect to gateway.
+ * </ul>
+ *
+ * The test is to confirm whether the message is sent all the way to the backend
+ * Websocket server through Knox and back.
+ *
+ *
+ * @since 0.10
+ */
+public class WebsocketEchoTest {
+
+ /**
+ * Simulate backend websocket
+ */
+ private static Server backendServer;
+ /**
+ * URI for backend websocket server
+ */
+ private static URI backendServerUri;
+
+ /**
+ * Mock Gateway server
+ */
+ private static Server gatewayServer;
+
+ /**
+ * Mock gateway config
+ */
+ private static GatewayConfig gatewayConfig;
+
+ private static GatewayServices services;
+
+ /**
+ * URI for gateway server
+ */
+ private static URI serverUri;
+
+ private static File topoDir;
+
+ public WebsocketEchoTest() {
+ super();
+ }
+
+ @BeforeClass
+ public static void startServers() throws Exception {
+
+ startWebsocketServer();
+ startGatewayServer();
+
+ }
+
+ @AfterClass
+ public static void stopServers() {
+ try {
+ gatewayServer.stop();
+ backendServer.stop();
+ } catch (final Exception e) {
+ e.printStackTrace(System.err);
+ }
+
+ /* Cleanup the created files */
+ FileUtils.deleteQuietly(topoDir);
+
+ }
+
+ /**
+ * Test direct connection to websocket server without gateway
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testDirectEcho() throws Exception {
+
+ WebSocketContainer container = ContainerProvider.getWebSocketContainer();
+ WebsocketClient client = new WebsocketClient();
+
+ Session session = container.connectToServer(client, backendServerUri);
+
+ session.getBasicRemote().sendText("Echo");
+ client.messageQueue.awaitMessages(1, 1000, TimeUnit.MILLISECONDS);
+
+ }
+
+ /**
+ * Test websocket proxying through gateway.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testGatewayEcho() throws Exception {
+ WebSocketContainer container = ContainerProvider.getWebSocketContainer();
+
+ WebsocketClient client = new WebsocketClient();
+ Session session = container.connectToServer(client,
+ new URI(serverUri.toString() + "gateway/websocket/ws"));
+
+ session.getBasicRemote().sendText("Echo");
+ client.messageQueue.awaitMessages(1, 1000, TimeUnit.MILLISECONDS);
+
+ assertThat(client.messageQueue.get(0), is("Echo"));
+
+ }
+
+ /**
+ * Test websocket rewrite rules proxying through gateway.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testGatewayRewriteEcho() throws Exception {
+ WebSocketContainer container = ContainerProvider.getWebSocketContainer();
+
+ WebsocketClient client = new WebsocketClient();
+ Session session = container.connectToServer(client,
+ new URI(serverUri.toString() + "gateway/websocket/123foo456bar/channels"));
+
+ session.getBasicRemote().sendText("Echo");
+ client.messageQueue.awaitMessages(1, 1000, TimeUnit.MILLISECONDS);
+
+ assertThat(client.messageQueue.get(0), is("Echo"));
+
+ }
+
+ /**
+ * Start Mock Websocket server that acts as backend.
+ *
+ * @throws Exception
+ */
+ private static void startWebsocketServer() throws Exception {
+
+ backendServer = new Server();
+ ServerConnector connector = new ServerConnector(backendServer);
+ backendServer.addConnector(connector);
+
+ final WebsocketEchoHandler handler = new WebsocketEchoHandler();
+
+ ContextHandler context = new ContextHandler();
+ context.setContextPath("/");
+ context.setHandler(handler);
+ backendServer.setHandler(context);
+
+ // Start Server
+ backendServer.start();
+
+ String host = connector.getHost();
+ if (host == null) {
+ host = "localhost";
+ }
+ int port = connector.getLocalPort();
+ backendServerUri = new URI(String.format("ws://%s:%d/ws", host, port));
+
+ }
+
+ /**
+ * Start Gateway Server.
+ *
+ * @throws Exception
+ */
+ private static void startGatewayServer() throws Exception {
+ gatewayServer = new Server();
+ final ServerConnector connector = new ServerConnector(gatewayServer);
+ gatewayServer.addConnector(connector);
+
+ /* workaround so we can add our handler later at runtime */
+ HandlerCollection handlers = new HandlerCollection(true);
+
+ /* add some initial handlers */
+ ContextHandler context = new ContextHandler();
+ context.setContextPath("/");
+ handlers.addHandler(context);
+
+ gatewayServer.setHandler(handlers);
+
+ // Start Server
+ gatewayServer.start();
+
+ String host = connector.getHost();
+ if (host == null) {
+ host = "localhost";
+ }
+ int port = connector.getLocalPort();
+ serverUri = new URI(String.format("ws://%s:%d/", host, port));
+
+ /* Setup websocket handler */
+ setupGatewayConfig(backendServerUri.toString());
+
+ final GatewayWebsocketHandler gatewayWebsocketHandler = new GatewayWebsocketHandler(
+ gatewayConfig, services);
+ handlers.addHandler(gatewayWebsocketHandler);
+ gatewayWebsocketHandler.start();
+ }
+
+ /**
+ * Initialize the configs and components required for this test.
+ *
+ * @param backend
+ * @throws IOException
+ */
+ private static void setupGatewayConfig(final String backend)
+ throws IOException {
+ services = new DefaultGatewayServices();
+
+ topoDir = createDir();
+ URL serviceUrl = ClassLoader.getSystemResource("websocket-services");
+
+ final File descriptor = new File(topoDir, "websocket.xml");
+ final FileOutputStream stream = new FileOutputStream(descriptor);
+ createKnoxTopology(backend).toStream(stream);
+ stream.close();
+
+ final TestTopologyListener topoListener = new TestTopologyListener();
+
+ final Map<String, String> options = new HashMap<>();
+ options.put("persist-master", "false");
+ options.put("master", "password");
+
+ gatewayConfig = EasyMock.createNiceMock(GatewayConfig.class);
+ EasyMock.expect(gatewayConfig.getGatewayTopologyDir())
+ .andReturn(topoDir.toString()).anyTimes();
+
++ EasyMock.expect(gatewayConfig.getGatewayProvidersConfigDir())
++ .andReturn(topoDir.getAbsolutePath() + "/shared-providers").anyTimes();
++
++ EasyMock.expect(gatewayConfig.getGatewayDescriptorsDir())
++ .andReturn(topoDir.getAbsolutePath() + "/descriptors").anyTimes();
++
+ EasyMock.expect(gatewayConfig.getGatewayServicesDir())
+ .andReturn(serviceUrl.getFile()).anyTimes();
+
+ EasyMock.expect(gatewayConfig.getEphemeralDHKeySize()).andReturn("2048")
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getGatewaySecurityDir())
+ .andReturn(topoDir.toString()).anyTimes();
+
+ /* Websocket configs */
+ EasyMock.expect(gatewayConfig.isWebsocketEnabled()).andReturn(true)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketMaxTextMessageSize())
+ .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_TEXT_MESSAGE_SIZE)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketMaxBinaryMessageSize())
+ .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_BINARY_MESSAGE_SIZE)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketMaxTextMessageBufferSize())
+ .andReturn(
+ GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_TEXT_MESSAGE_BUFFER_SIZE)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketMaxBinaryMessageBufferSize())
+ .andReturn(
+ GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_BINARY_MESSAGE_BUFFER_SIZE)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketInputBufferSize())
+ .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_INPUT_BUFFER_SIZE)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketAsyncWriteTimeout())
+ .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_ASYNC_WRITE_TIMEOUT)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketIdleTimeout())
+ .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_IDLE_TIMEOUT).anyTimes();
+
++ EasyMock.expect(gatewayConfig.getRemoteRegistryConfigurationNames())
++ .andReturn(Collections.emptyList())
++ .anyTimes();
++
+ EasyMock.replay(gatewayConfig);
+
+ try {
+ services.init(gatewayConfig, options);
+ } catch (ServiceLifecycleException e) {
+ e.printStackTrace();
+ }
+
+ DeploymentFactory.setGatewayServices(services);
+ final TopologyService monitor = services
+ .getService(GatewayServices.TOPOLOGY_SERVICE);
+ monitor.addTopologyChangeListener(topoListener);
+ monitor.reloadTopologies();
+
+ }
+
+ private static File createDir() throws IOException {
+ return TestUtils
+ .createTempDir(WebsocketEchoTest.class.getSimpleName() + "-");
+ }
+
+ private static XMLTag createKnoxTopology(final String backend) {
+ XMLTag xml = XMLDoc.newDocument(true).addRoot("topology").addTag("service")
+ .addTag("role").addText("WEBSOCKET").addTag("url").addText(backend)
+ .gotoParent().gotoRoot();
+ // System.out.println( "GATEWAY=" + xml.toString() );
+ return xml;
+ }
+
+ private static class TestTopologyListener implements TopologyListener {
+
+ public ArrayList<List<TopologyEvent>> events = new ArrayList<List<TopologyEvent>>();
+
+ @Override
+ public void handleTopologyEvent(List<TopologyEvent> events) {
+ this.events.add(events);
+
+ synchronized (this) {
+ for (TopologyEvent event : events) {
+ if (!event.getType().equals(TopologyEvent.Type.DELETED)) {
+
+ /* for this test we only care about this part */
+ DeploymentFactory.createDeployment(gatewayConfig,
+ event.getTopology());
+
+ }
+ }
+
+ }
+
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/22a7304a/gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketMultipleConnectionTest.java
----------------------------------------------------------------------
diff --cc gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketMultipleConnectionTest.java
index 42bc9c3,0000000..5e5006c
mode 100644,000000..100644
--- a/gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketMultipleConnectionTest.java
+++ b/gateway-server/src/test/java/org/apache/knox/gateway/websockets/WebsocketMultipleConnectionTest.java
@@@ -1,389 -1,0 +1,400 @@@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.websockets;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
++import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.websocket.ContainerProvider;
+import javax.websocket.Endpoint;
+import javax.websocket.EndpointConfig;
+import javax.websocket.MessageHandler;
+import javax.websocket.Session;
+import javax.websocket.WebSocketContainer;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.knox.gateway.config.GatewayConfig;
+import org.apache.knox.gateway.config.impl.GatewayConfigImpl;
+import org.apache.knox.gateway.deploy.DeploymentFactory;
+import org.apache.knox.gateway.services.DefaultGatewayServices;
+import org.apache.knox.gateway.services.GatewayServices;
+import org.apache.knox.gateway.services.ServiceLifecycleException;
+import org.apache.knox.gateway.services.topology.TopologyService;
+import org.apache.knox.gateway.topology.TopologyEvent;
+import org.apache.knox.gateway.topology.TopologyListener;
+import org.apache.knox.test.TestUtils;
+import org.easymock.EasyMock;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.server.handler.HandlerCollection;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import com.mycila.xmltool.XMLDoc;
+import com.mycila.xmltool.XMLTag;
+
+/**
+ * Test how Knox holds up under multiple concurrent connections.
+ *
+ */
+public class WebsocketMultipleConnectionTest {
+ /**
+ * Simulate backend websocket
+ */
+ private static Server backendServer;
+ /**
+ * URI for backend websocket server
+ */
+ private static URI backendServerUri;
+
+ /**
+ * Mock Gateway server
+ */
+ private static Server gatewayServer;
+
+ /**
+ * Mock gateway config
+ */
+ private static GatewayConfig gatewayConfig;
+
+ private static GatewayServices services;
+
+ /**
+ * URI for gateway server
+ */
+ private static URI serverUri;
+
+ private static File topoDir;
+
+ /**
+ * Maximum number of open connections to test.
+ */
+ private static int MAX_CONNECTIONS = 100;
+
+ public WebsocketMultipleConnectionTest() {
+ super();
+ }
+
+ @BeforeClass
+ public static void startServers() throws Exception {
+
+ startWebsocketServer();
+ startGatewayServer();
+
+ }
+
+ @AfterClass
+ public static void stopServers() {
+ try {
+ gatewayServer.stop();
+ backendServer.stop();
+ } catch (final Exception e) {
+ e.printStackTrace(System.err);
+ }
+
+ /* Cleanup the created files */
+ FileUtils.deleteQuietly(topoDir);
+
+ }
+
+ /**
+ * Test websocket proxying through gateway.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testMultipleConnections() throws Exception {
+ WebSocketContainer container = ContainerProvider.getWebSocketContainer();
+
+ final CountDownLatch latch = new CountDownLatch(MAX_CONNECTIONS);
+
+ Session[] sessions = new Session[MAX_CONNECTIONS];
+
+ MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
+
+ System.gc();
+ final long heapt1 = memoryMXBean.getHeapMemoryUsage().getUsed();
+ final long nonHeapt1 = memoryMXBean.getNonHeapMemoryUsage().getUsed();
+
+ for (int i = 0; i < MAX_CONNECTIONS; i++) {
+
+ sessions[i] = container.connectToServer(new WebsocketClient() {
+
+ @Override
+ public void onMessage(String message) {
+ latch.countDown();
+
+ }
+
+ }, new URI(serverUri.toString() + "gateway/websocket/ws"));
+
+ }
+
+ for (int i = 0; i < MAX_CONNECTIONS; i++) {
+ /* make sure the session is active and valid before trying to connect */
+ if(sessions[i].isOpen() && sessions[i].getBasicRemote() != null) {
+ sessions[i].getBasicRemote().sendText("OK");
+ }
+ }
+
+ latch.await(5 * MAX_CONNECTIONS, TimeUnit.MILLISECONDS);
+
+ System.gc();
+
+ final long heapUsed = memoryMXBean.getHeapMemoryUsage().getUsed() - heapt1;
+ final long nonHeapUsed = memoryMXBean.getNonHeapMemoryUsage().getUsed()
+ - nonHeapt1;
+
+ System.out.println("heapUsed = " + heapUsed);
+ System.out.println("nonHeapUsed = " + nonHeapUsed);
+
+ /* 90 KB per connection */
+ /*
+ long expected = 90 * 1024 * MAX_CONNECTIONS;
+ assertThat("heap used", heapUsed, lessThan(expected));
+ */
+ }
+
+ /**
+ * Start Mock Websocket server that acts as backend.
+ *
+ * @throws Exception
+ */
+ private static void startWebsocketServer() throws Exception {
+
+ backendServer = new Server(new QueuedThreadPool(254));
+ ServerConnector connector = new ServerConnector(backendServer);
+ backendServer.addConnector(connector);
+
+ final WebsocketEchoHandler handler = new WebsocketEchoHandler();
+
+ ContextHandler context = new ContextHandler();
+ context.setContextPath("/");
+ context.setHandler(handler);
+ backendServer.setHandler(context);
+
+ // Start Server
+ backendServer.start();
+
+ String host = connector.getHost();
+ if (host == null) {
+ host = "localhost";
+ }
+ int port = connector.getLocalPort();
+ backendServerUri = new URI(String.format("ws://%s:%d/ws", host, port));
+
+ }
+
+ /**
+ * Start Gateway Server.
+ *
+ * @throws Exception
+ */
+ private static void startGatewayServer() throws Exception {
+ /* use default Max threads */
+ gatewayServer = new Server(new QueuedThreadPool(254));
+ final ServerConnector connector = new ServerConnector(gatewayServer);
+ gatewayServer.addConnector(connector);
+
+ /* workaround so we can add our handler later at runtime */
+ HandlerCollection handlers = new HandlerCollection(true);
+
+ /* add some initial handlers */
+ ContextHandler context = new ContextHandler();
+ context.setContextPath("/");
+ handlers.addHandler(context);
+
+ gatewayServer.setHandler(handlers);
+
+ // Start Server
+ gatewayServer.start();
+
+ String host = connector.getHost();
+ if (host == null) {
+ host = "localhost";
+ }
+ int port = connector.getLocalPort();
+ serverUri = new URI(String.format("ws://%s:%d/", host, port));
+
+ /* Setup websocket handler */
+ setupGatewayConfig(backendServerUri.toString());
+
+ final GatewayWebsocketHandler gatewayWebsocketHandler = new GatewayWebsocketHandler(
+ gatewayConfig, services);
+ handlers.addHandler(gatewayWebsocketHandler);
+ gatewayWebsocketHandler.start();
+ }
+
+ /**
+ * Initialize the configs and components required for this test.
+ *
+ * @param backend
+ * @throws IOException
+ */
+ private static void setupGatewayConfig(final String backend)
+ throws IOException {
+ services = new DefaultGatewayServices();
+
+ topoDir = createDir();
+ URL serviceUrl = ClassLoader.getSystemResource("websocket-services");
+
+ final File descriptor = new File(topoDir, "websocket.xml");
+ final FileOutputStream stream = new FileOutputStream(descriptor);
+ createKnoxTopology(backend).toStream(stream);
+ stream.close();
+
+ final TestTopologyListener topoListener = new TestTopologyListener();
+
+ final Map<String, String> options = new HashMap<>();
+ options.put("persist-master", "false");
+ options.put("master", "password");
+
+ gatewayConfig = EasyMock.createNiceMock(GatewayConfig.class);
+ EasyMock.expect(gatewayConfig.getGatewayTopologyDir())
+ .andReturn(topoDir.toString()).anyTimes();
+
++ EasyMock.expect(gatewayConfig.getGatewayProvidersConfigDir())
++ .andReturn(topoDir.getAbsolutePath() + "/shared-providers").anyTimes();
++
++ EasyMock.expect(gatewayConfig.getGatewayDescriptorsDir())
++ .andReturn(topoDir.getAbsolutePath() + "/descriptors").anyTimes();
++
+ EasyMock.expect(gatewayConfig.getGatewayServicesDir())
+ .andReturn(serviceUrl.getFile()).anyTimes();
+
+ EasyMock.expect(gatewayConfig.getEphemeralDHKeySize()).andReturn("2048")
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getGatewaySecurityDir())
+ .andReturn(topoDir.toString()).anyTimes();
+
+ /* Websocket configs */
+ EasyMock.expect(gatewayConfig.isWebsocketEnabled()).andReturn(true)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketMaxTextMessageSize())
+ .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_TEXT_MESSAGE_SIZE)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketMaxBinaryMessageSize())
+ .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_BINARY_MESSAGE_SIZE)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketMaxTextMessageBufferSize())
+ .andReturn(
+ GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_TEXT_MESSAGE_BUFFER_SIZE)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketMaxBinaryMessageBufferSize())
+ .andReturn(
+ GatewayConfigImpl.DEFAULT_WEBSOCKET_MAX_BINARY_MESSAGE_BUFFER_SIZE)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketInputBufferSize())
+ .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_INPUT_BUFFER_SIZE)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketAsyncWriteTimeout())
+ .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_ASYNC_WRITE_TIMEOUT)
+ .anyTimes();
+
+ EasyMock.expect(gatewayConfig.getWebsocketIdleTimeout())
+ .andReturn(GatewayConfigImpl.DEFAULT_WEBSOCKET_IDLE_TIMEOUT).anyTimes();
+
++ EasyMock.expect(gatewayConfig.getRemoteRegistryConfigurationNames())
++ .andReturn(Collections.emptyList())
++ .anyTimes();
++
+ EasyMock.replay(gatewayConfig);
+
+ try {
+ services.init(gatewayConfig, options);
+ } catch (ServiceLifecycleException e) {
+ e.printStackTrace();
+ }
+
+ DeploymentFactory.setGatewayServices(services);
+ final TopologyService monitor = services
+ .getService(GatewayServices.TOPOLOGY_SERVICE);
+ monitor.addTopologyChangeListener(topoListener);
+ monitor.reloadTopologies();
+
+ }
+
+ private static File createDir() throws IOException {
+ return TestUtils
+ .createTempDir(WebsocketEchoTest.class.getSimpleName() + "-");
+ }
+
+ private static XMLTag createKnoxTopology(final String backend) {
+ XMLTag xml = XMLDoc.newDocument(true).addRoot("topology").addTag("service")
+ .addTag("role").addText("WEBSOCKET").addTag("url").addText(backend)
+ .gotoParent().gotoRoot();
+ // System.out.println( "GATEWAY=" + xml.toString() );
+ return xml;
+ }
+
+ private static class TestTopologyListener implements TopologyListener {
+
+ public ArrayList<List<TopologyEvent>> events = new ArrayList<List<TopologyEvent>>();
+
+ @Override
+ public void handleTopologyEvent(List<TopologyEvent> events) {
+ this.events.add(events);
+
+ synchronized (this) {
+ for (TopologyEvent event : events) {
+ if (!event.getType().equals(TopologyEvent.Type.DELETED)) {
+
+ /* for this test we only care about this part */
+ DeploymentFactory.createDeployment(gatewayConfig,
+ event.getTopology());
+
+ }
+ }
+
+ }
+
+ }
+
+ }
+
+ private static abstract class WebsocketClient extends Endpoint
+ implements MessageHandler.Whole<String> {
+ @Override
+ public void onOpen(Session session, EndpointConfig config) {
+ session.addMessageHandler(this);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/22a7304a/gateway-service-definitions/src/main/resources/services/ambariui/2.2.1/service.xml
----------------------------------------------------------------------
diff --cc gateway-service-definitions/src/main/resources/services/ambariui/2.2.1/service.xml
index c6135ae,0000000..e69de29
mode 100644,000000..100644
--- a/gateway-service-definitions/src/main/resources/services/ambariui/2.2.1/service.xml
+++ b/gateway-service-definitions/src/main/resources/services/ambariui/2.2.1/service.xml