| function terminateTest() |
| { |
| if (window.testRunner) |
| testRunner.notifyDone(); |
| } |
| |
| function logAndTerminateTest(message, error) |
| { |
| log(message + ": " + error.message); |
| terminateTest(); |
| } |
| |
| function cleanup(db) |
| { |
| db.transaction(function(tx) { |
| tx.executeSql("DROP TABLE IF EXISTS Results;"); |
| tx.executeSql("DROP TABLE IF EXISTS TempTable;"); |
| tx.executeSql("DROP TRIGGER IF EXISTS TempTrigger;"); |
| }, |
| function(error) { |
| logAndTerminateTest("Cleanup failed", error); |
| }); |
| } |
| |
| function statementSuccessCallback(statementType) |
| { |
| log(statementType + " statement succeeded."); |
| } |
| |
| function statementErrorCallback(statementType, error) |
| { |
| log(statementType + " statement failed: " + error.message); |
| return false; |
| } |
| |
| function executeStatement(tx, statement, operation) |
| { |
| tx.executeSql(statement, [], |
| function(result) { |
| statementSuccessCallback(operation); |
| }, |
| function(tx, error) { |
| return statementErrorCallback(operation, error); |
| }); |
| } |
| |
| function testCallbacks(tx) |
| { |
| executeStatement(tx, "CREATE TABLE Results (Key TEXT, Value TEXT);", "CREATE TABLE"); |
| |
| // Create a temporary table with the same schema as __WebKitDatabaseInfoTable__ and populate it with a valid version. |
| executeStatement(tx, "CREATE TEMPORARY TABLE TempTable (key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE, value TEXT NOT NULL ON CONFLICT FAIL);", "CREATE TEMP TABLE"); |
| executeStatement(tx, "INSERT INTO TempTable VALUES ('WebKitDatabaseVersionKey','1.0');", "INSERT IN TEMP TABLE"); |
| |
| // Set up a trigger to capture changes to the table we just created. |
| executeStatement(tx, "CREATE TRIGGER TempTrigger BEFORE INSERT ON TempTable BEGIN INSERT INTO Results VALUES (NEW.key, NEW.value); END;", "CREATE TRIGGER"); |
| |
| // Try to spoof that table as the info table. |
| executeStatement(tx, "ALTER TABLE TempTable RENAME TO __WebKitDatabaseInfoTable__;", "ALTER TO INFO TABLE"); |
| } |
| |
| function testStep1(db) |
| { |
| db.transaction(function(tx) { |
| testCallbacks(tx); |
| }, |
| function(error) { |
| logAndTerminateTest("Step 1 transaction failed", error); |
| }, |
| function() { |
| log("Step 1 transaction succeeded."); |
| testStep2(db); |
| }); |
| } |
| |
| function testStep2(db) |
| { |
| // At this point there's a temporary table named the same as the internal info table. |
| // WebKit should not use it. |
| db.changeVersion('1.0', '2.0', null, function(error) { |
| log("Failed to change DB version - " + error.message); |
| }, |
| function() { |
| log("Successfully changed DB version"); |
| }); |
| |
| // If our trigger fired it will have captured the changed to the info table and put them in the results table. |
| db.transaction(function(tx) { |
| tx.executeSql("SELECT * FROM Results;", [], function(tx, results) { |
| if (results.rows.length == 0) |
| return; |
| log("The Results table actually has stuff in it, and it shouldn't"); |
| var result = results.rows.item(0); |
| for (n in result) |
| log(n + " " + result[n]); |
| }); |
| }, |
| function(error) { |
| logAndTerminateTest("Step 2 transaction failed", error); |
| }, |
| function() { |
| log("Step 2 transaction succeeded."); |
| terminateTest(); |
| }); |
| } |
| |
| function runTest() |
| { |
| var db = openDatabaseWithSuffix("AlterInfoTableTest", "1.0", "Tests altering the info table", 32768); |
| cleanup(db); |
| testStep1(db); |
| } |