blob: 9335bd96bdc90f3c47074b81ce6af73794327bfb [file]
/**
* Derby - Class org.apache.derbyTesting.functionTests.tests.lang.AggregateClassLoadingTest
*
* 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.derbyTesting.functionTests.tests.lang;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import junit.framework.Test;
import org.apache.derbyTesting.junit.BaseJDBCTestCase;
import org.apache.derbyTesting.junit.BaseTestSuite;
import org.apache.derbyTesting.junit.CleanDatabaseTestSetup;
import org.apache.derbyTesting.junit.JDBC;
import org.apache.derbyTesting.junit.SecurityManagerSetup;
/**
* Test for ensuring the aggregate implementation classes are loaded correctly,
* even when the context class loader loads Derby engine classes as well. This
* is a typical situation we have seen with J2EE servers where Derby may be in
* the application WAR and provided as a system service by the container. <BR>
* Jira issue DERBY-997 <BR>
* Assumes embedded and only needs to be run in embedded, since all class
* loading happens on the engine side.
*/
public class AggregateClassLoadingTest extends BaseJDBCTestCase {
/**
* Basic constructor.
*/
public AggregateClassLoadingTest(String name) {
super(name);
}
/**
* Sets the auto commit to false.
*/
protected void initializeConnection(Connection conn) throws SQLException {
conn.setAutoCommit(false);
}
/**
* Returns the implemented tests.
*
* @return An instance of <code>Test</code> with the implemented tests to
* run.
*/
public static Test suite() {
/* this test creates a class loader, adding that permission to
* derbyTesting.jar would mean that permission was granted all
* the way up the stack to the derby engine. Thus increasing
* the chance that incorrectly a privileged block could be dropped
* but the tests continue to pass.
*/
return SecurityManagerSetup.noSecurityManager(
new CleanDatabaseTestSetup(
new BaseTestSuite(AggregateClassLoadingTest.class,
"AggregateClassLoadingTest")) {
/**
* Save the class loader upon entry to the
* suite, some JVM's install the main loader
* as the context loader.
*/
private ClassLoader originalLoader;
protected void setUp() throws Exception {
originalLoader = Thread.currentThread().getContextClassLoader();
super.setUp();
}
protected void tearDown() throws Exception {
Thread.currentThread().setContextClassLoader(originalLoader);
super.tearDown();
}
/**
* @see org.apache.derbyTesting.junit.CleanDatabaseTestSetup#decorateSQL(java.sql.Statement)
*/
protected void decorateSQL(Statement s)
throws SQLException {
s.execute("create table t (i int)");
s.execute("insert into t values 1,2,3,4,5,6,null,4,5,456,2,4,6,7,2144,44,2,-2,4");
/*
* Find the location of the code for the Derby
* connection. The rest of the engine will be at
* the same location!
*/
URL derbyURL = s.getConnection().getClass().getProtectionDomain().getCodeSource()
.getLocation();
/*
* Create a new loader that loads from the same
* location as the engine. Create it without a
* parent, otherwise the parent will be the
* class loader of this class which is most
* likely the same as the engine. Since the
* class loader delegates to its parent first
* the bug would not show, as all the derby
* engine classes would be from a single loader.
*/
URLClassLoader cl = new URLClassLoader(new URL[] { derbyURL }, null);
Thread.currentThread().setContextClassLoader(cl);
super.decorateSQL(s);
}
});
}
public void testAggregateMAX() throws SQLException {
testAggregate("select MAX(i) from t");
}
public void testAggregateMIN() throws SQLException {
testAggregate("select MIN(i) from t");
}
public void testAggregateAVG() throws SQLException {
testAggregate("select AVG(i) from t");
}
public void testAggregateCOUNT() throws SQLException {
testAggregate("select COUNT(i) from t");
}
public void testAggregateCOUNT2() throws SQLException {
testAggregate("select COUNT(*) from t");
}
/**
* Just run and display the aggregates result.
*
* Test some aggregates, their generated class will attempt
* to load the internal aggregate through the context loader
* first, and then any remaining loader.
*/
private void testAggregate(String query) throws SQLException {
Statement s = createStatement();
JDBC.assertDrainResults(s.executeQuery(query), 1);
s.close();
}
}