| /* |
| |
| Derby - Class org.apache.derbyTesting.functionTests.tests.upgradeTests.UpgradeRun |
| |
| 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.upgradeTests; |
| |
| import java.lang.reflect.Method; |
| import java.util.Properties; |
| import junit.extensions.TestSetup; |
| import junit.framework.Test; |
| import org.apache.derbyTesting.functionTests.tests.jdbcapi.DatabaseMetaDataTest; |
| import org.apache.derbyTesting.junit.BaseTestCase; |
| import org.apache.derbyTesting.junit.BaseTestSuite; |
| import org.apache.derbyTesting.junit.SecurityManagerSetup; |
| import org.apache.derbyTesting.junit.SystemPropertyTestSetup; |
| import org.apache.derbyTesting.junit.TestConfiguration; |
| |
| /** |
| * Utility class for creating a set of tests that |
| * comprise a complete upgrade run through all |
| * five phases. This includes handling the |
| * class loading for the old jar files |
| * and setting up the configuration to |
| * use a single use database and DataSource for |
| * connections. |
| * |
| */ |
| class UpgradeRun extends UpgradeClassLoader |
| { |
| |
| /** |
| * Set of additional databases for tests that |
| * require a one-off database. The additional |
| * database decorator wraps all the tests and phases. |
| * They are only created if a test opens a |
| * connection against them. In hard upgrade the test |
| * must explictly upgrade the database. |
| * The databases are shutdown at the end of each phase, unless |
| * "NoShutDown" is specified. The latter is used by databases |
| * which need sqlAuthorization (specified by test). This thwarts |
| * normal shutdown since credentials are required so shutdown is |
| * done in test, not by the tearDown methods. See |
| * Changes10_5#testSQLRoles for example. |
| */ |
| |
| static final AdditionalDb[] ADDITIONAL_DBS = { |
| new AdditionalDb("COLLATED_DB_10_3", true), // db with territory |
| // based collation |
| new AdditionalDb("NO_ENCRYPT_10_2", true), |
| new AdditionalDb("ENCRYPT_10_2", true), |
| new AdditionalDb("ROLES_10_5", false), |
| new AdditionalDb("BUILTIN_10_9", false), |
| new AdditionalDb("DERBY-4753", true), |
| }; |
| |
| public static Test suite(final int[] version, boolean useCreateOnUpgrade) { |
| |
| ClassLoader oldLoader = makeClassLoader( version ); |
| |
| // If no jars then just skip. |
| if (oldLoader == null) |
| { |
| BaseTestSuite suite = new BaseTestSuite( |
| "Empty: Skipped upgrade Tests (no jars) for " + getTextVersion(version)); |
| return suite; |
| } |
| |
| |
| BaseTestSuite suite = new BaseTestSuite( |
| "Upgrade Tests from " + getTextVersion(version)); |
| BaseTestCase.traceit("Prepare to run upgrade tests from " + getTextVersion(version)); |
| |
| |
| for (int phase = 0; |
| phase < UpgradeChange.PHASES.length; phase++) |
| { |
| ClassLoader loader = null; |
| switch (phase) |
| { |
| case UpgradeChange.PH_CREATE: |
| case UpgradeChange.PH_POST_SOFT_UPGRADE: |
| case UpgradeChange.PH_POST_HARD_UPGRADE: |
| loader = oldLoader; |
| break; |
| case UpgradeChange.PH_SOFT_UPGRADE: |
| case UpgradeChange.PH_HARD_UPGRADE: |
| break; |
| |
| } |
| Test phaseTests = baseSuite(getTextVersion(version) |
| + " Upgrade Phase: " + UpgradeChange.PHASES[phase] + " ", |
| phase, version); |
| |
| Test phaseSet = new PhaseChanger(phaseTests, phase, loader, version, useCreateOnUpgrade); |
| phaseSet = handleJavaSE6(phase, version, phaseSet); |
| suite.addTest(phaseSet); |
| } |
| |
| TestSetup setup = TestConfiguration.singleUseDatabaseDecorator(suite); |
| |
| for (int i = 0; i < ADDITIONAL_DBS.length; i++) |
| { |
| if (ADDITIONAL_DBS[i].shutDown) { |
| setup = TestConfiguration.additionalDatabaseDecorator( |
| setup, ADDITIONAL_DBS[i].logicalName); |
| } else { |
| setup = TestConfiguration.additionalDatabaseDecoratorNoShutdown( |
| setup, ADDITIONAL_DBS[i].logicalName); |
| } |
| } |
| |
| Properties preReleaseUpgrade = new Properties(); |
| preReleaseUpgrade.setProperty( |
| "derby.database.allowPreReleaseUpgrade", "true"); |
| |
| setup = new SystemPropertyTestSetup(setup, preReleaseUpgrade); |
| |
| return SecurityManagerSetup.noSecurityManager(setup); |
| } |
| |
| /** |
| * Add the tests from the various Changes classes (sub-classes |
| * of UpgradeChange) to the base suite which corresponds to |
| * a single phase of a run against an old database version. |
| * <BR> |
| * Changes are only added if the old version is older than |
| * then version the changes represent. Thus Changes10_2 |
| * is not added if the old database (upgrade from) is already |
| * at 10.2, since Changes10_2 is intended to test upgrade |
| * from an older version to 10.2. |
| * <BR> |
| * This is for two reasons: |
| * <OL> |
| * <LI> Prevents an endless increase in number of test |
| * cases that do no real testing. |
| * <LI> Simplifies test fixtures by allowing them to |
| * focus on cases where testing is required, and not |
| * handling all future situations. |
| * </OL> |
| * |
| */ |
| private static Test baseSuite(String name, int phase, int[] version) { |
| BaseTestSuite suite = new BaseTestSuite(name); |
| |
| int oldMajor = version[0]; |
| int oldMinor = version[1]; |
| |
| // No connection is expected in the post hard upgrade |
| // phase, so don't bother adding test fixtures. |
| if (phase != UpgradeChange.PH_POST_HARD_UPGRADE) |
| { |
| suite.addTest(BasicSetup.suite()); |
| |
| if (oldMajor == 10) { |
| if (oldMinor < 1) |
| suite.addTest(Changes10_1.suite()); |
| if (oldMinor < 2) |
| suite.addTest(Changes10_2.suite()); |
| if (oldMinor < 3) { |
| //Pass the phase as a parameter to the |
| //suite method that will enable the test to add existing |
| //junit tests after checking for the phase of the current |
| //run. |
| suite.addTest(Changes10_3.suite(phase)); |
| } |
| if (oldMinor < 4) |
| suite.addTest(Changes10_4.suite(phase)); |
| if (oldMinor < 5) |
| suite.addTest(Changes10_5.suite(phase)); |
| if (oldMinor < 6) |
| suite.addTest(Changes10_6.suite(phase)); |
| if (oldMinor < 7) |
| suite.addTest(Changes10_7.suite(phase)); |
| if (oldMinor < 9) |
| suite.addTest(Changes10_9.suite(phase)); |
| if (oldMinor < 10) |
| suite.addTest(Changes10_10.suite(phase)); |
| if (oldMinor < 11) |
| suite.addTest(Changes10_11.suite(phase)); |
| if (oldMinor < 12) |
| suite.addTest(Changes10_12.suite(phase)); |
| if (oldMinor < 13) |
| suite.addTest(Changes10_13.suite(phase)); |
| } |
| |
| // Add DatabaseMetaData tests. Since metadata |
| // queries may be changed by an upgrade it is |
| // an area that is subject to bugs. Here we run |
| // all or a subset of DatabaseMetaData tests |
| // as required. |
| switch (phase) { |
| case UpgradeChange.PH_CREATE: |
| // No need to test, should have been covered |
| // by the original tests of the old release |
| break; |
| |
| case UpgradeChange.PH_POST_SOFT_UPGRADE: |
| // reverted to old engine and metadata queries |
| // must continue to work. Cannot run the full |
| // set of tests here as the full DatabaseMetaDataTest |
| // functionality may not match the old engine. |
| // However we run individual fixtures that exercise |
| // the code path for the metadata queries. |
| // |
| // Any specific change to the metadata queries |
| // due to upgrade (e.g. fixing a system catalog) |
| // must be tested in a ChangesM_n fixture. |
| break; |
| |
| // Running at the new level so the full functionality |
| // of DatabaseMetaData should be available. |
| case UpgradeChange.PH_SOFT_UPGRADE: |
| case UpgradeChange.PH_HARD_UPGRADE: |
| runDataBaseMetaDataTest(suite, oldMinor); |
| break; |
| } |
| } |
| else |
| { |
| suite.addTest(new BasicSetup("noConnectionAfterHardUpgrade")); |
| } |
| |
| if (phase == UpgradeChange.PH_SOFT_UPGRADE && |
| suffersFromDerby4835or5289(version)) { |
| // If the old version suffers from DERBY-4835 or DERBY-5289, |
| // it may not be able to read the trigger plans after soft upgrade. |
| // Drop all trigger plans at the end of soft upgrade to prevent |
| // problems in the post soft upgrade phase. |
| suite.addTest(new BasicSetup("dropAllTriggerPlans")); |
| } |
| |
| return TestConfiguration.connectionDSDecorator(suite); |
| } |
| |
| /** |
| * Check if a version suffers from DERBY-4835 or DERBY-5289. |
| */ |
| private static boolean suffersFromDerby4835or5289(int[] version) { |
| // DERBY-4835 affects the 10.5 and 10.6 branches, and was fixed in |
| // 10.5.3.2 and 10.6.2.3. |
| // DERBY-5289 affects the 10.5, 10.6, 10.7 and 10.8 branches, and was |
| // fixed in 10.5.3.1, 10.6.2.2, 10.7.1.4 and 10.8.2.2. |
| return |
| (lessThan(new int[] { 10, 5, 0, 0 }, version) && |
| lessThan(version, new int[] { 10, 5, 3, 2 })) |
| || |
| (lessThan(new int[] { 10, 6, 0, 0 }, version) && |
| lessThan(version, new int[] { 10, 6, 2, 3 })) |
| || |
| (lessThan(new int[] { 10, 7, 0, 0 }, version) && |
| lessThan(version, new int[] { 10, 7, 1, 4 })) |
| || |
| (lessThan(new int[] { 10, 8, 0, 0 }, version) && |
| lessThan(version, new int[] { 10, 8, 2, 2 })); |
| } |
| |
| /** |
| * Return true if and only if the left version is less than the |
| * right version. |
| */ |
| static boolean lessThan( int[] left, int[] right ) |
| { |
| for (int i = 0; i < left.length; i++) |
| { |
| if ( left[ i ] < right[ i ] ) return true; |
| if ( left[ i ] > right[ i ] ) return false; |
| } |
| |
| // Versions match exactly. That is, not less than. |
| return false; |
| } |
| |
| /** |
| * When running against certains old releases in Java SE 6 |
| * we need to setup the connections to the old |
| * database to not use the specific JDBC 4 |
| * datasources (e.g. EmbeddedDataSource40). |
| * (Since they don't exist in the old release). |
| * |
| */ |
| private static Test handleJavaSE6(int phase, int[] version, Test test) |
| { |
| // |
| // we need to tell the JUnit infratructure not to |
| // look for the 40 datasources (e.g. EmbeddedDataSource40) |
| boolean oldReleaseNeedsJDBC3 = false; |
| switch (phase) |
| { |
| case UpgradeChange.PH_CREATE: |
| case UpgradeChange.PH_POST_SOFT_UPGRADE: |
| |
| // Pre 10.2.2.0 need jdbc 3 drivers. |
| if (version[0] == 10 && version[1] < 3) |
| { |
| if (version[1] < 2 || version[2] < 2) |
| oldReleaseNeedsJDBC3 = true; |
| } |
| break; |
| default: |
| break; |
| } |
| |
| if (oldReleaseNeedsJDBC3) { |
| return TestConfiguration.forceJDBC3Embedded(test); |
| } |
| return test; |
| } |
| |
| /** |
| * Adds a subset of the tests from DatabaseMetaDataTest to the test suite. |
| * <p> |
| * We want to run DatabaseMetaDataTest, but it includes some |
| * features not supported in older versions, so we cannot just |
| * add the DatabaseMetaDataTest.class as is. |
| * Note also, that this does not execute fixture initialCompilationTest. |
| */ |
| private static void runDataBaseMetaDataTest ( |
| BaseTestSuite suite, int oldMinor) |
| { |
| BaseTestSuite dmdSuite = |
| new BaseTestSuite("DatabaseMetaData subsuite"); |
| |
| Method[] methods = DatabaseMetaDataTest.class.getMethods(); |
| for (int i = 0; i < methods.length; i++) { |
| Method m = methods[i]; |
| if (m.getParameterTypes().length > 0 || |
| !m.getReturnType().equals(Void.TYPE)) { |
| continue; |
| } |
| String name = m.getName(); |
| if (name.startsWith("test")) |
| { |
| if ((!(name.equals("testGetTablesModify") && oldMinor < 1)) && |
| // these two tests will fail with versions before 10.2.1.6 |
| // because of missing support for grant/revoke/privileges |
| (!(name.equals("testGetTablePrivileges") && oldMinor <2)) && |
| (!(name.equals("testGetColumnPrivileges") && oldMinor <2))) |
| dmdSuite.addTest(new DatabaseMetaDataTest(name)); |
| } |
| } |
| // Run the test in its own schema to avoid interference from other |
| // tests. A typical example is additional matching rows when querying |
| // system tables like SYS.SYSFOREIGNKEYS. |
| suite.addTest(TestConfiguration.changeUserDecorator( |
| dmdSuite, "DMDT", "DMDT")); |
| } |
| |
| } |
| |
| class AdditionalDb |
| { |
| final String logicalName; |
| final boolean shutDown; |
| public AdditionalDb(String logicalName, boolean shutDown) |
| { |
| this.logicalName = logicalName; |
| this.shutDown = shutDown; |
| } |
| } |