You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by su...@apache.org on 2006/08/05 19:11:48 UTC
svn commit: r429014 [2/2] - in /db/derby/code/trunk/java:
engine/org/apache/derby/iapi/services/io/
engine/org/apache/derby/iapi/store/raw/
engine/org/apache/derby/iapi/store/raw/data/
engine/org/apache/derby/iapi/store/raw/log/ engine/org/apache/derby...
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/ReEncryptCrashRecovery.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/ReEncryptCrashRecovery.java?rev=429014&r1=429013&r2=429014&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/ReEncryptCrashRecovery.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/ReEncryptCrashRecovery.java Sat Aug 5 10:11:47 2006
@@ -29,9 +29,10 @@
import org.apache.derby.iapi.services.sanity.SanityManager;
/*
- * This class tests crash/recovery scenarions during re-encryption of
- * databas. Debug flags are used to simulate crashes during the
- * re-encrytpion.
+ * This class tests crash/recovery scenarions during (re) encryption of
+ * database. Debug flags are used to simulate crashes during the
+ * encrytpion of an un-encrypted database and re-encryption of an encrypted
+ * database with new password/key.
*
* Unlike the other recovery tests which do a setup and recovery as different
* tests, Incase of re-encryption crash/recovery can be simulated in one
@@ -49,10 +50,49 @@
public class ReEncryptCrashRecovery
{
- private static final String TEST_DATABASE_NAME = "wombat_pwd" ;
+ // database name used to test re-encryption of an encrypted database
+ // using a new boot password.
+ private static final String TEST_REENCRYPT_PWD_DATABASE = "wombat_pwd_ren" ;
+ // database name used to test encryption and un-encrypted database.
+ // using a boot password.
+ private static final String TEST_ENCRYPT_PWD_DATABASE = "wombat_pwd_en";
+
+
+ // database name used to test re-encryption of an encrypted database
+ // using the external encryption key.
+ private static final String TEST_REENCRYPT_KEY_DATABASE = "wombat_key_ren" ;
+ // database name used to test encryption of un-encrypted database.
+ // using external encryption key.
+ private static final String TEST_ENCRYPT_KEY_DATABASE = "wombat_key_en";
+
+ // flags to indicate type of mechanism used to test the (re)encryption
+ private static final int USING_KEY = 1;
+ private static final int USING_PASSWORD = 2;
+
+ // flags to indicate the password/key to be used during recovery
+ // on reboot after a crash.
+ private static final int NONE = 1;
+ private static final int OLD = 2;
+ private static final int NEW = 3;
+
+ // test table name.
private static final String TEST_TABLE_NAME = "emp";
+
private static final String OLD_PASSWORD = "xyz1234abc";
private static final String NEW_PASSWORD = "new1234xyz";
+
+ private static final String OLD_KEY = "6162636465666768";
+ private static final String NEW_KEY = "5666768616263646";
+
+ // the current database being tested.
+ private String currentTestDatabase ;
+ // the current encryption type being tested.
+ private int encryptionType;
+
+ // set the following to true, for this test
+ // spit out more status messages.
+ private boolean verbose = false;
+
ReEncryptCrashRecovery() {
@@ -60,78 +100,215 @@
/*
- * Test Re-encrytpion crash/recovery scenarios.
+ * Test (re)encrytpion crash/recovery scenarios.
*/
private void runTest() throws Exception {
logMessage("Begin ReEncryptCrashRecovery Test");
- createEncryptedDatabase();
- Connection conn = TestUtil.getConnection(TEST_DATABASE_NAME,
- null);
+
+ if (SanityManager.DEBUG) {
+ if (verbose)
+ logMessage("Start testing re-encryption with Password");
+ // test crash recovery during re-encryption
+ // using the password mechanism.
+ currentTestDatabase = TEST_REENCRYPT_PWD_DATABASE;
+ encryptionType = USING_PASSWORD;
+ runCrashRecoveryTestCases(true);
+
+
+ if (verbose)
+ logMessage("Start Testing encryption with Password");
+
+ // test crash recovery during databse encryption
+ // using the password mechanism.
+ currentTestDatabase = TEST_ENCRYPT_PWD_DATABASE;
+ encryptionType = USING_PASSWORD;
+ // run crash recovery test cases.
+ runCrashRecoveryTestCases(false);
+
+
+ if (verbose) {
+ logMessage("Start Testing Encryption with external Key");
+ }
+ // test crash recovery during database encryption
+ // using the encryption key.
+
+ currentTestDatabase = TEST_ENCRYPT_KEY_DATABASE;
+ encryptionType = USING_KEY;
+ runCrashRecoveryTestCases(false);
+
+ if (verbose)
+ logMessage("Start Testing re-encryption with external Key");
+
+ // test crash recovery dureing re-encryption
+ // using the encryption key.
+
+ currentTestDatabase = TEST_REENCRYPT_KEY_DATABASE;
+ encryptionType = USING_KEY;
+ runCrashRecoveryTestCases(true);
+ }
+ logMessage("End ReEncryptCrashRecovery Test");
+ }
+
+
+ /**
+ * run crash recovery test scenarios using the debug flags.
+ * @param reEncrypt <code> true </code> if testing re-encryption
+ * <colde> false </code> otherwise.
+ */
+ private void runCrashRecoveryTestCases(boolean reEncrypt)
+ throws SQLException
+ {
+ Connection conn;
+ if (reEncrypt)
+ conn = createEncryptedDatabase();
+ else
+ conn = createDatabase();
+
createTable(conn, TEST_TABLE_NAME);
//load some rows
insert(conn, TEST_TABLE_NAME, 100);
conn.commit();
- //shutdown the test db
- shutdown(TEST_DATABASE_NAME);
-
- // re-enryption crash/recovery test cases.
- crashBeforeCommit();
- recover_crashBeforeCommit();
- //shutdown the test db
- shutdown(TEST_DATABASE_NAME);
+ conn.close();
+ shutdown();
- logMessage("End ReEncryptCrashRecovery Test");
- }
+ // following cases of (re) encryption should be rolled back.
+ int passwordKey = (reEncrypt ? OLD : NONE );
+ crash(reEncrypt, TEST_REENCRYPT_CRASH_BEFORE_COMMT);
+ recover(passwordKey);
+ shutdown();
+
+ crash(reEncrypt, TEST_REENCRYPT_CRASH_AFTER_COMMT);
+ crashInRecovery(passwordKey,
+ TEST_REENCRYPT_CRASH_AFTER_RECOVERY_UNDO_LOGFILE_DELETE);
+ crashInRecovery(passwordKey,
+ TEST_REENCRYPT_CRASH_AFTER_RECOVERY_UNDO_REVERTING_KEY);
+ crashInRecovery(passwordKey,
+ TEST_REENCRYPT_CRASH_BEFORE_RECOVERY_FINAL_CLEANUP);
+ recover(passwordKey);
+ shutdown();
+
+
+ crash(reEncrypt, TEST_REENCRYPT_CRASH_AFTER_SWITCH_TO_NEWKEY);
+ crashInRecovery(passwordKey,
+ TEST_REENCRYPT_CRASH_AFTER_RECOVERY_UNDO_LOGFILE_DELETE);
+ crashInRecovery(passwordKey,
+ TEST_REENCRYPT_CRASH_AFTER_RECOVERY_UNDO_REVERTING_KEY);
+ crashInRecovery(passwordKey,
+ TEST_REENCRYPT_CRASH_BEFORE_RECOVERY_FINAL_CLEANUP);
+
+ recover(passwordKey);
+ shutdown();
+
+ // following cases (re) encryption should be successful, only
+ // cleanup is pending.
+
+ // crash after database is re-encrypted, but before cleanup.
+ // (re)encryption is complete, database should be bootable
+ // with a new password.
+ passwordKey = (reEncrypt ? NEW : OLD);
+ crash(reEncrypt, TEST_REENCRYPT_CRASH_AFTER_CHECKPOINT);
+ crashInRecovery(passwordKey,
+ TEST_REENCRYPT_CRASH_BEFORE_RECOVERY_FINAL_CLEANUP);
+
+ recover(passwordKey);
+ shutdown();
+ }
- /** *************************************************
- * Crash/recovery test scenarios during re-encryption.
- ****************************************************/
/*
- * Attempt to re-encrypt the database and force it to fail
- * using debug flags just before the commit.
+ * Attempt to (re)encrypt the database and force it to crash
+ * at the given debug flag.
*/
- private void crashBeforeCommit() {
- // Re-encrytption crash before commit
- setDebugFlag(TEST_REENCRYPT_CRASH_BEFORE_COMMT);
+ private void crash(boolean reEncrypt, String debugFlag)
+ {
+ if (verbose)
+ logMessage("Testing : " + debugFlag);
+ // set the debug flag to crash.
+ setDebugFlag(debugFlag);
SQLException sqle = null;
+ Connection conn;
try {
- reEncryptDatabase(OLD_PASSWORD, NEW_PASSWORD);
+ if (reEncrypt)
+ conn = reEncryptDatabase();
+ else
+ conn = encryptDatabase();
+
}catch (SQLException se) {
- // re-encryption of the database should have failed,
+ // (re)encryption of the database should have failed,
// at the specified debug flag.
sqle = se;
}
// check that database boot failed at the set debug flag.
- verifyException(sqle, TEST_REENCRYPT_CRASH_BEFORE_COMMT);
+ verifyException(sqle, debugFlag);
// clear the debug flag.
- clearDebugFlag(TEST_REENCRYPT_CRASH_BEFORE_COMMT);
+ clearDebugFlag(debugFlag);
}
+
+ /*
+ * Crash in recovery of the database at the given
+ * debug flag.
+ */
+ private void crashInRecovery(int passwordKey, String debugFlag)
+ throws SQLException
+ {
+ if (verbose)
+ logMessage("Testing : " + debugFlag);
+
+ // set the debug flag to crash.
+ setDebugFlag(debugFlag);
+ SQLException sqle = null;
+ try {
+ Connection conn = bootDatabase(passwordKey);
+ } catch (SQLException se) {
+ // recovery of the database
+ // shold have failed at the specified
+ // debug flag.
+ sqle = se;
+ }
+ // check that database boot failed at the set debug flag.
+ verifyException(sqle, debugFlag);
+ // clear the debug flag.
+ clearDebugFlag(debugFlag);
+ }
+
+
/*
* Recover the database that failied during re-encryption and
* perform some simple sanity check on the database.
*/
- private void recover_crashBeforeCommit() throws SQLException{
+ private void recover(int passwordKey)
+ throws SQLException
+ {
// starting recovery of database with failed Re-encrytpion
// in debug mode;
- Connection conn = bootDatabase(OLD_PASSWORD);
+
+ Connection conn = bootDatabase(passwordKey);
+
// verify the contents of the db are ok.
runConsistencyChecker(conn, TEST_TABLE_NAME);
// insert some rows, this might fail if anyhing is
// wrong in the logging system setup.
insert(conn, TEST_TABLE_NAME, 100);
+ conn.commit();
conn.close();
- }
+ }
+
+ /** *************************************************
+ * Crash/recovery test scenarios during
+ * encryption of an un-encrypted database.
+ ****************************************************/
- // Debug flags that needs to be set to simulate a crash
- // at different points during re-encryption of the database.
+
+
+ // Debug flags that are to be set to simulate a crash
+ // at different points during (re)encryption of the database.
// these flags should match the flags in the engine code;
// these are redifined here to avoid pulling the engine code
// into the tests.
@@ -144,7 +321,25 @@
public static final String TEST_REENCRYPT_CRASH_BEFORE_COMMT =
SanityManager.DEBUG ? "TEST_REENCRYPT_CRASH_BEFORE_COMMT" : null ;
-
+ public static final String TEST_REENCRYPT_CRASH_AFTER_COMMT =
+ SanityManager.DEBUG ? "TEST_REENCRYPT_CRASH_AFTER_COMMT" : null ;
+ public static final String TEST_REENCRYPT_CRASH_AFTER_SWITCH_TO_NEWKEY =
+ SanityManager.DEBUG ? "TEST_REENCRYPT_CRASH_AFTER_SWITCH_TO_NEWKEY" : null ;
+ public static final String TEST_REENCRYPT_CRASH_AFTER_CHECKPOINT =
+ SanityManager.DEBUG ? "TEST_REENCRYPT_CRASH_AFTER_CHECKPOINT" : null ;
+
+ public static final String
+ TEST_REENCRYPT_CRASH_AFTER_RECOVERY_UNDO_LOGFILE_DELETE =
+ SanityManager.DEBUG ?
+ "TEST_REENCRYPT_CRASH_AFTER_RECOVERY_UNDO_LOGFILE_DELETE" : null;
+ public static final String
+ TEST_REENCRYPT_CRASH_AFTER_RECOVERY_UNDO_REVERTING_KEY =
+ SanityManager.DEBUG ?
+ "TEST_REENCRYPT_CRASH_AFTER_RECOVERY_UNDO_REVERTING_KEY" : null;
+ public static final String
+ TEST_REENCRYPT_CRASH_BEFORE_RECOVERY_FINAL_CLEANUP =
+ SanityManager.DEBUG ?
+ "TEST_REENCRYPT_CRASH_BEFORE_RECOVERY_FINAL_CLEANUP" : null;
void setDebugFlag(String debugFlag) {
@@ -164,17 +359,31 @@
*/
private void verifyException(SQLException sqle, String debugFlag)
{
+ boolean expectedExcepion = false ;
if (sqle != null)
{
+
if (sqle.getSQLState() != null &&
sqle.getSQLState().equals("XJ040"))
{
// boot failed as expected with the debug flag
- }else
- {
- dumpSQLException(sqle);
+ // now check if it failed with specifed debug flags.
+ SQLException ne = sqle.getNextException();
+ if (ne != null) {
+ String message = ne.getMessage();
+ // check if debug flag exists in the message
+ if (message.indexOf(debugFlag) != -1)
+ {
+ expectedExcepion = true;
+ }
+ }
}
- } else {
+
+ if (!expectedExcepion)
+ dumpSQLException(sqle);
+ }
+ else
+ {
if (SanityManager.DEBUG)
{
logMessage("Did not crash at " + debugFlag);
@@ -239,8 +448,8 @@
ps.setString(2 , "skywalker" + i);
ps.executeUpdate();
}
- conn.commit();
ps.close();
+ conn.commit();
}
/**
@@ -256,7 +465,10 @@
ResultSet rs = s.executeQuery("SELECT max(ID) from " +
tableName);
rs.next();
- return rs.getInt(1);
+ int max = rs.getInt(1);
+ rs.close();
+ s.close();
+ return max;
}
@@ -300,28 +512,59 @@
/*
* create an encrypted database.
*/
- private void createEncryptedDatabase() throws SQLException
+ private Connection createEncryptedDatabase() throws SQLException
{
- TestUtil.getConnection(TEST_DATABASE_NAME,
- "create=true;dataEncryption=true;bootPassword=" +
- OLD_PASSWORD);
+ String connAttrs = "";
+ if (encryptionType == USING_PASSWORD)
+ {
+ // create encrypted database.
+ connAttrs = "create=true;dataEncryption=true;bootPassword=" +
+ OLD_PASSWORD;
+ }
+
+ if (encryptionType == USING_KEY)
+ {
+ // create an encrypted database.
+ connAttrs = "create=true;dataEncryption=true;encryptionKey=" +
+ OLD_KEY;
+ }
+
+ return TestUtil.getConnection(currentTestDatabase, connAttrs);
}
+
+ /*
+ * create an un-encrypted database.
+ */
+ private Connection createDatabase() throws SQLException
+ {
+ return TestUtil.getConnection(currentTestDatabase,
+ "create=true" );
+ }
+
+
/**
* Re-encrypt the database.
- * @param currentPassword current boot password.
- * @param newPassword new password to boot the database
- * after successful re-encryption.
* @exception SQLException if any database exception occurs.
*/
- private void reEncryptDatabase(String currentPassword,
- String newPassword)
- throws SQLException
+ private Connection reEncryptDatabase() throws SQLException
{
- // re-encrypt the database.
- String connAttrs = "bootPassword=" + currentPassword +
- ";newBootPassword=" + newPassword;
- TestUtil.getConnection(TEST_DATABASE_NAME, connAttrs);
+ String connAttrs = "";
+ if (encryptionType == USING_PASSWORD)
+ {
+ // re-encrypt the database.
+ connAttrs = "bootPassword=" + OLD_PASSWORD +
+ ";newBootPassword=" + NEW_PASSWORD;
+ }
+
+ if (encryptionType == USING_KEY)
+ {
+ // re-encrypt the database.
+ connAttrs = "encryptionKey=" + OLD_KEY +
+ ";newEncryptionKey=" + NEW_KEY;
+ }
+
+ return TestUtil.getConnection(currentTestDatabase, connAttrs);
}
@@ -330,39 +573,73 @@
* @param password boot password of the database.
* @exception SQLException if any database exception occurs.
*/
- private void encryptDatabase(String password)
+ private Connection encryptDatabase()
throws SQLException
{
- //encrypt an existing database.
- String connAttrs = "dataEncryption=true;bootPassword=" +
- password ;
+ String connAttrs = "";
+ if (encryptionType == USING_PASSWORD)
+ {
+ //encrypt an existing database.
+ connAttrs = "dataEncryption=true;bootPassword=" + OLD_PASSWORD;
+ }
+ if (encryptionType == USING_KEY)
+ {
+ //encrypt an existing database.
+ connAttrs = "dataEncryption=true;encryptionKey=" + OLD_KEY;
+ }
- TestUtil.getConnection(TEST_DATABASE_NAME, connAttrs);
+ if (verbose)
+ logMessage("encrypting " + currentTestDatabase +
+ " with " + connAttrs);
+ return TestUtil.getConnection(currentTestDatabase, connAttrs);
}
/**
* Boot the database.
- * @param password boot password of the database.
+ * @param passwordOrKey the password/key to use.
* @exception SQLException if any database exception occurs.
*/
- Connection bootDatabase(String password) throws SQLException {
+ Connection bootDatabase(int passwordKey)
+ throws SQLException
+ {
+
+ String connAttrs = "";
+ if (encryptionType == USING_PASSWORD)
+ {
+ if (passwordKey == NEW)
+ connAttrs = "bootPassword=" + NEW_PASSWORD;
+ else if (passwordKey == OLD)
+ connAttrs = "bootPassword=" + OLD_PASSWORD;
+ }
+
- return TestUtil.getConnection(TEST_DATABASE_NAME,
- "bootPassword=" + password);
+ if (encryptionType == USING_KEY)
+ {
+ if (passwordKey == NEW)
+ connAttrs = "encryptionKey=" + NEW_KEY;
+ else if (passwordKey == OLD)
+ connAttrs = "encryptionKey=" + OLD_KEY;
+ }
+
+ if (verbose)
+ logMessage("booting " + currentTestDatabase +
+ " with " + connAttrs);
+ return TestUtil.getConnection(currentTestDatabase, connAttrs);
}
-
+
/**
* Shutdown the datbase
- * @param dbName Name of the database to shutdown.
*/
- void shutdown(String dbName) {
+ void shutdown() {
+ if (verbose)
+ logMessage("Shutdown " + currentTestDatabase);
try{
//shutdown
- TestUtil.getConnection(dbName, "shutdown=true");
+ TestUtil.getConnection(currentTestDatabase, "shutdown=true");
}catch(SQLException se){
if (se.getSQLState() == null || !(se.getSQLState().equals("08006")))
{
@@ -370,6 +647,8 @@
dumpSQLException(se);
}
}
+
+
}
/**