/*
* Copyright (c) 2008, SQL Power Group Inc.
*
* This file is part of SQL Power Library.
*
* SQL Power Library is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* SQL Power Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ca.sqlpower.sql;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.undo.UndoableEdit;
import junit.framework.TestCase;
import ca.sqlpower.sql.JDBCDataSourceType.JDBCClassLoader;
public class SPDataSourceTypeTest extends TestCase {
private static final String PL_INI_CONTENTS =
"[Database Types_0]\n" +
"Name=Type 0\n" +
"JDBC Driver Class=ca.sqlpower.cow.Cow\n" +
"JDBC URL=jdbc:cow://moo\n" +
"Comment=No Comment\n" +
"Property Name We Will Never Use=I hope this is ok\n" +
"JDBC JAR Count=2\n" +
"JDBC JAR_0=my.jar\n" +
"JDBC JAR_1=your.jar\n" +
"[Database Types_1]\n" +
"Parent Type=Type 0\n" +
"Name=Type 0.1\n" +
"";
/**
* A sample instance of the data source type for testing.
*/
private JDBCDataSourceType superType;
/**
* This is a subtype of superType.
*/
private JDBCDataSourceType subType;
protected void setUp() throws Exception {
superType = new JDBCDataSourceType();
subType = new JDBCDataSourceType();
subType.setParentType(superType);
JDBCDataSourceType currentType = null;
for (String line : PL_INI_CONTENTS.split("\\n")) {
if (line.equals("[Database Types_0]")) {
currentType = superType;
} else if (line.equals("[Database Types_1]")) {
currentType = subType;
} else if (line.startsWith("[")) {
throw new RuntimeException("File format problem");
} else {
int splitPoint = line.indexOf('=');
String key = line.substring(0, splitPoint);
String value = line.substring(splitPoint + 1);
currentType.putProperty(key, value);
}
}
assertTrue("Supertype didn't load properly", superType.getProperties().size() > 0);
assertTrue("Subtype didn't load properly", subType.getProperties().size() > 0);
}
protected void tearDown() throws Exception {
super.tearDown();
}
public void testGetName() {
assertEquals("Type 0", superType.getName());
}
public void testInheritedProperty() {
assertEquals("ca.sqlpower.cow.Cow", subType.getJdbcDriver());
}
public void testHasClassLoader() {
assertNotNull(superType.getJdbcClassLoader());
}
public void testGetComment() {
assertEquals("No Comment", superType.getComment());
}
public void testGetJdbcDriver() {
assertEquals("ca.sqlpower.cow.Cow", superType.getJdbcDriver());
}
public void testGetJdbcJarList() {
List<String> l = superType.getJdbcJarList();
assertNotNull(l);
assertEquals(2, l.size());
assertEquals("incorrect jar list entry. properties="+superType.getProperties(), "my.jar", l.get(0));
assertEquals("your.jar", l.get(1));
}
public void testGetJdbcUrl() throws Exception {
assertEquals("jdbc:cow://moo", superType.getJdbcUrl());
}
public void testGetParentType() {
assertSame(superType, subType.getParentType());
assertNull(superType.getParentType());
}
public void testGetPropertiesImmutable() {
try {
superType.getProperties().put("this won't", "work");
fail("I changed a property");
} catch (UnsupportedOperationException ex) {
// this is good
}
}
public void testUnknownPropertiesStillExist() {
assertEquals("I hope this is ok", superType.getProperties().get("Property Name We Will Never Use"));
}
public void testSetJdbcJarList() {
List<String> list = new ArrayList<String>();
list.add("zero");
list.add("one");
list.add("two");
superType.setJdbcJarList(list);
List<String> newList = superType.getJdbcJarList();
assertEquals(list, newList);
}
public void testAddJdbcJar() {
List<String> list = new ArrayList<String>(superType.getJdbcJarList());
list.add("new thing");
superType.addJdbcJar("new thing");
assertEquals(list, superType.getJdbcJarList());
assertEquals(String.valueOf(list.size()), superType.getProperty(JDBCDataSourceType.JDBC_JAR_COUNT));
}
public void testJdbcJarListImmutable() {
List<String> list = superType.getJdbcJarList();
try {
list.add("new thing");
fail("I think I modified the list");
} catch (UnsupportedOperationException ex) {
// good result
}
}
public void testRemoveJdbcJar() {
int jarCount = superType.getJdbcJarList().size();
superType.removeJdbcJar("your.jar");
assertEquals(jarCount - 1, superType.getJdbcJarList().size());
superType.removeJdbcJar("your.jar");
}
public void testRetrieveURLParsing() {
JDBCDataSourceType dsType = new JDBCDataSourceType();
dsType.setJdbcUrl("<Database>:<Port>:<Hostname>");
Map<String, String> map = dsType.retrieveURLParsing("data:1234:");
assertEquals("data", map.get("Database"));
assertEquals("1234", map.get("Port"));
assertEquals("", map.get("Hostname") );
}
public void testRetrieveURLParsingWithUnclosedVariable() {
JDBCDataSourceType dsType = new JDBCDataSourceType();
dsType.setJdbcUrl("<Database");
Map<String, String> map = dsType.retrieveURLParsing("data");
assertTrue(map.isEmpty());
}
public void testRetrieveURLParsingWithDefaults() {
JDBCDataSourceType dsType = new JDBCDataSourceType();
dsType.setJdbcUrl("<Database:db>:<Port:2222>:<Hostname:home>");
Map<String, String> map = dsType.retrieveURLParsing("data:1234:");
assertEquals("data", map.get("Database"));
assertEquals("1234", map.get("Port"));
assertEquals("", map.get("Hostname"));
}
public void testRetrieveURLParsingNullTemplateURL() {
JDBCDataSourceType dsType = new JDBCDataSourceType();
dsType.setJdbcUrl(null);
Map<String, String> map = dsType.retrieveURLParsing("data:1234:");
assertEquals(0, map.size());
}
public void testRetrieveURLParsingURLDoesntmMatchTemplate() {
JDBCDataSourceType dsType = new JDBCDataSourceType();
dsType.setJdbcUrl("hello:<Database:db>:<Port:2222>:<Hostname:home>");
Map<String, String> map = dsType.retrieveURLParsing("hello");
assertEquals(0, map.size());
}
public void testRetrieveURLDefaults(){
JDBCDataSourceType dsType = new JDBCDataSourceType();
dsType.setJdbcUrl("<Database>:<Port:1234>:<Hostname:home>");
Map<String, String> map = dsType.retrieveURLDefaults();
assertEquals("", map.get("Database"));
assertEquals("1234", map.get("Port"));
assertEquals("home", map.get("Hostname"));
}
/**
* Tests for regression: the retrieveURLDefaults method used to
* get into an infinite loop when there's an unterminated variable
* name (< without a matching >).
*/
public void testRetrieveURLDefaultsWithUnclosedVariable(){
JDBCDataSourceType dsType = new JDBCDataSourceType();
dsType.setJdbcUrl("<Database");
Map<String, String> map = dsType.retrieveURLDefaults();
assertTrue(map.isEmpty());
}
public void testRetrieveURLDefaultsNoTemplate(){
JDBCDataSourceType dsType = new JDBCDataSourceType();
dsType.setJdbcUrl(null);
Map<String, String> map = dsType.retrieveURLDefaults();
assertEquals(0, map.size());
}
/**
* Regression test: when there's a classpath entry for a built-in resource
* that doesn't exist, you get NPE when loading a resource (not a class,
* just a resource)
*/
public void testLoadResourceFromMissingJar() throws Exception {
JDBCDataSourceType dsType = new JDBCDataSourceType();
dsType.addJdbcJar("builtin:does/not/exist.jar");
JDBCClassLoader jdbcClassLoader = (JDBCClassLoader) dsType.getJdbcClassLoader();
jdbcClassLoader.findResources("my_resource");
// test passes if previous statement doesn't throw NPE
}
public void testUndoAndRedo() throws Exception {
final JDBCDataSourceType dsType = new JDBCDataSourceType();
class TestUndoableEditListener implements UndoableEditListener {
private int editCount = 0;
public void undoableEditHappened(UndoableEditEvent e) {
editCount++;
UndoableEdit edit = e.getEdit();
assertTrue(edit.canUndo());
assertEquals("hello", dsType.getProperty("Test"));
edit.undo();
assertTrue(edit.canRedo());
assertNull(dsType.getProperty("Test"));
edit.redo();
assertTrue(edit.canUndo());
assertEquals("hello", dsType.getProperty("Test"));
}
public int getEditCount() {
return editCount;
}
}
TestUndoableEditListener undoableEditListener = new TestUndoableEditListener();
dsType.addUndoableEditListener(undoableEditListener);
dsType.putProperty("Test", "hello");
assertEquals(1, undoableEditListener.getEditCount());
}
/**
* The setters on the DSType uses a different method to set properties than the
* one used in testUndoAndRedo. This confirms that the setters do create undo and
* redo edits.
*/
public void testUndoOnSetters() throws Exception {
final JDBCDataSourceType dsType = new JDBCDataSourceType();
class TestUndoableEditListener implements UndoableEditListener {
private int editCount = 0;
public void undoableEditHappened(UndoableEditEvent e) {
editCount++;
}
public int getEditCount() {
return editCount;
}
}
TestUndoableEditListener undoableEditListener = new TestUndoableEditListener();
dsType.addUndoableEditListener(undoableEditListener);
dsType.setComment("comment");
dsType.setDDLGeneratorClass("class");
dsType.setName("name");
assertEquals(3, undoableEditListener.getEditCount());
}
public void testStreamFlagDefaultsFalse() throws Exception {
assertFalse(subType.getSupportsStreamQueries());
}
public void testStreamFlagChange() throws Exception {
subType.putProperty(JDBCDataSourceType.SUPPORTS_STREAM_QUERIES, String.valueOf(true));
assertTrue(subType.getSupportsStreamQueries());
}
}