/** * VMware Continuent Tungsten Replicator * Copyright (C) 2015 VMware, Inc. All rights reserved. * * Licensed 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. * * Initial developer(s): Robert Hodges * Contributor(s): */ package com.continuent.tungsten.common.cluster.resource; import java.sql.SQLException; import java.util.Properties; import junit.framework.TestCase; /** * Implements a simple test for t-router URL parsing. * * @author <a href="mailto:robert.hodges@continuent.com">Robert Hodges</a> * @version 1.0 */ public class TestRouterUrl extends TestCase { /** * Test a few obvious bad URLs. */ public void testBadUrls() throws Exception { String[] badUrls = {"", "jdbc:", "jdbc:whatever//", "jdbc:t-router:", "jdbc:t-router://", "jdbc:t-router://service/db?qos", "jdbc:t-router://service/db?qos=RW_STRICT&missingvalue"}; for (String badUrl : badUrls) { try { new RouterURL(badUrl, null); fail("Bad URL was parsed: url=[" + badUrl + "]"); } catch (SQLException e) { // this is expected } } } /** * Test URLs with and without properties. */ public void testStandardUrls() throws Exception { // Test a URL with no arguments and no properties. String url = "jdbc:t-router://service/db"; RouterURL ru = new RouterURL(url, new Properties()); assertEquals("service", ru.getService()); assertEquals("db", ru.getDbname()); assertEquals(QualityOfService.RW_STRICT, ru.getQos()); assertEquals(0, ru.getProps().size()); // Test a URL with arguments but no properties. url = "jdbc:t-router://service/db?user=auser&password=pw&qos=RW_STRICT"; ru = new RouterURL(url, new Properties()); assertEquals("service", ru.getService()); assertEquals("db", ru.getDbname()); assertEquals(QualityOfService.RW_STRICT, ru.getQos()); Properties ruProps = ru.getProps(); assertEquals(2, ruProps.size()); assertEquals("auser", ruProps.getProperty("user")); assertEquals("pw", ruProps.getProperty("password")); // Test a URL with arguments and properties. url = "jdbc:t-router://service/db?user=auser&qos=RO_RELAXED"; Properties props = new Properties(); props.setProperty("password", "pw"); ru = new RouterURL(url, props); assertEquals("service", ru.getService()); assertEquals("db", ru.getDbname()); assertEquals(QualityOfService.RO_RELAXED, ru.getQos()); ruProps = ru.getProps(); assertEquals(2, ruProps.size()); assertEquals("auser", ruProps.getProperty("user")); assertEquals("pw", ruProps.getProperty("password")); // Test a URL with problematic characters in the password tryPassword("semi:colon"); tryPassword("question!mark^n"); tryPassword("arobase@and1one"); tryPassword("var1ou$`1^*l)"); // check that the parser is permissive enough to allow empty props RouterURL perm1 = new RouterURL("jdbc:t-router://service/db?", null); assertEquals("Data service name should have been set correctly", perm1.getDataServiceName(), "service"); assertEquals("Database name should have been set correctly", perm1.getDbname(), "db"); assertTrue("No properties should have been set when only giving a '?' " + "after the database name", perm1.getProps().isEmpty()); RouterURL perm2 = new RouterURL("jdbc:t-router://service/db?user=me&", null); assertEquals("Data service name should have been set correctly", perm2.getDataServiceName(), "service"); assertEquals("Database name should have been set correctly", perm2.getDbname(), "db"); assertEquals("User name should have been set to 'me'", perm2.getProps() .get("user"), "me"); assertEquals( "Only the user should have been set when only giving 'user=me&' " + "after the database name", perm2.getProps().size(), 1); RouterURL perm3 = new RouterURL( "jdbc:t-router://service/db?user=me&qos=RO_RELAXED?qos=RW_STRICT", null); assertEquals("qos should have been set to the latest value declared", QualityOfService.RW_STRICT, perm3.getQos()); } private void tryPassword(String pass) throws SQLException { String url; RouterURL ru; Properties ruProps; url = "jdbc:t-router://service/db?user=auser&password=" + pass; ru = new RouterURL(url, null); assertEquals("service", ru.getService()); assertEquals("db", ru.getDbname()); ruProps = ru.getProps(); assertEquals(2, ruProps.size()); assertEquals("auser", ruProps.getProperty("user")); assertEquals(pass, ruProps.getProperty("password")); } public void testEquals() throws SQLException { RouterURL url1 = new RouterURL( "jdbc:t-router://service/db?user=auser&password=asecret&qos=RW_SESSION&sessionId=DATABASE", new Properties()); RouterURL url2 = new RouterURL( "jdbc:t-router://service/db?user=auser&password=asecret&qos=RW_SESSION&sessionId=DATABASE", new Properties()); assertEquals( "Two URLs created with the same string should be identical", url1, url2); Properties userpass = new Properties(); userpass.put("user", "auser"); userpass.put("password", "asecret"); RouterURL url3 = new RouterURL( "jdbc:t-router://service/db?qos=RW_SESSION&sessionId=DATABASE", userpass); // should be equal assertEquals( "When user/pass are given through properties, the URL should be " + "equal to the one that has the same user/pass in the URL string", url1, url3); RouterURL url4 = new RouterURL( "jdbc:t-router://service/db2?user=auser&password=asecret&qos=RW_SESSION&sessionId=DATABASE", new Properties()); url1.setDbname("db2"); // database name modification // assertEquals( "Database name modifiction should give the same url as one that " + "has an identical db name set directly in the string", url1, url4); } public void testOverlappingProperties() throws SQLException { Properties props = new Properties(); props.put("user", "defInProps"); RouterURL url = new RouterURL( "jdbc:t-router://service/db?user=defInURL", props); assertEquals( "Values given in the URL string should supersede the ones in the Properties", url.getProperty("user"), "defInURL"); RouterURL url2 = new RouterURL( "jdbc:t-router://service/db?user=defInURLbefore&user=defInURLafter", null); assertEquals( "Values defined at the end of the URL should supersede the " + "ones defined at the begining", url2.getProperty("user"), "defInURLafter"); } public void testClone() throws SQLException, CloneNotSupportedException { Properties props = new Properties(); props.put("user", "defInProps"); RouterURL orig = new RouterURL( "jdbc:t-router://service/db?user=defInURL", props); RouterURL copy = (RouterURL) orig.clone(); assertTrue(orig.equals(copy)); copy.setDbname("other"); RouterURL copy2 = (RouterURL) copy.clone(); assertFalse(orig.equals(copy2)); } public void testUrlOptionsParsing() throws SQLException { Properties props = new Properties(); RouterURL.urlOptionsToProperties("qos=RO_RELAXED&affinity=sjc", props); assertEquals("Props should contain qos=RO_RELAXED", "RO_RELAXED", props.get("qos")); assertEquals("Props should contain affinity=sjc", "sjc", props.get("affinity")); RouterURL.urlOptionsToProperties("qos=RW_STRICT", props); assertEquals("Props should contain qos=RW_STRICT", "RW_STRICT", props.get("qos")); try { RouterURL.urlOptionsToProperties("invalid", props); fail("invalid paramater should trigger an error"); } catch (SQLException sqle) { // expected } } }