Home | History | Annotate | Download | only in storage
      1 function terminateTest()
      2 {
      3     if (window.layoutTestController)
      4         layoutTestController.notifyDone();
      5 }
      6 
      7 function logAndTerminateTest(message, error)
      8 {
      9     log(message + ": " + error.message);
     10     terminateTest();
     11 }
     12 
     13 function cleanup(db)
     14 {
     15     db.transaction(function(tx) {
     16             tx.executeSql("DROP TABLE IF EXISTS Test;");
     17             tx.executeSql("DROP INDEX IF EXISTS TestIndex;");
     18             tx.executeSql("DROP VIEW IF EXISTS TestView;");
     19             tx.executeSql("DROP TRIGGER IF EXISTS TestTrigger;");
     20         }, function(error) { logAndTerminateTest("Cleanup failed", error); });
     21 }
     22 
     23 function statementSuccessCallback(statementType)
     24 {
     25     log(statementType + " statement succeeded.");
     26 }
     27 
     28 function statementErrorCallback(statementType, error)
     29 {
     30     log(statementType + " statement failed: " + error.message);
     31     return false;
     32 }
     33 
     34 function executeStatement(tx, statement, operation)
     35 {
     36     tx.executeSql(statement, [],
     37                   function(result) { statementSuccessCallback(operation); },
     38                   function(tx, error) { return statementErrorCallback(operation, error); });
     39 }
     40 
     41 function createTableCallback(tx)
     42 {
     43     executeStatement(tx, "CREATE TABLE Test (Foo int);", "SQLITE_CREATE_TABLE");
     44 }
     45 
     46 function createStatementsCallback(tx)
     47 {
     48     executeStatement(tx, "CREATE INDEX TestIndex ON Test (Foo);", "SQLITE_CREATE_INDEX");
     49 
     50     // Even though the following query should trigger a SQLITE_CREATE_TEMP_INDEX operation
     51     // (according to http://www.sqlite.org/tempfiles.html), it doesn't, and I'm not aware
     52     // of any other way to trigger this operation. So we'll skip it for now.
     53     //executeStatement(tx, "SELECT * FROM Test WHERE Foo IN (1, 2, 3);", "SQLITE_CREATE_TEMP_INDEX");
     54 
     55     executeStatement(tx, "CREATE TEMP TABLE TestTempTable (Foo int);", "SQLITE_CREATE_TEMP_TABLE");
     56     executeStatement(tx, "CREATE TEMP TRIGGER TestTempTrigger INSERT ON Test BEGIN SELECT COUNT(*) FROM Test; END;", "SQLITE_CREATE_TEMP_TRIGGER");
     57     executeStatement(tx, "CREATE TEMP VIEW TestTempView AS SELECT COUNT(*) FROM Test;", "SQLITE_CREATE_TEMP_VIEW");
     58     executeStatement(tx, "CREATE TRIGGER TestTrigger INSERT ON Test BEGIN SELECT COUNT(*) FROM Test; END;", "SQLITE_CREATE_TRIGGER");
     59     executeStatement(tx, "CREATE VIEW TestView AS SELECT COUNT(*) FROM Test;", "SQLITE_CREATE_VIEW");
     60     executeStatement(tx, "CREATE VIRTUAL TABLE TestVirtualTable USING MissingModule;", "SQLITE_CREATE_VTABLE");
     61 }
     62 
     63 function otherStatementsCallback(tx)
     64 {
     65     executeStatement(tx, "SELECT COUNT(*) FROM Test;", "SQLITE_READ");
     66     executeStatement(tx, "SELECT COUNT(*) FROM Test;", "SQLITE_SELECT");
     67     executeStatement(tx, "DELETE FROM Test;", "SQLITE_DELETE");
     68     executeStatement(tx, "INSERT INTO Test VALUES (1);", "SQLITE_INSERT");
     69     executeStatement(tx, "UPDATE Test SET Foo = 2 WHERE Foo = 1;", "SQLITE_UPDATE");
     70     executeStatement(tx, "PRAGMA cache_size;", "SQLITE_PRAGMA");
     71 
     72     executeStatement(tx, "ALTER TABLE Test RENAME TO TestTable;", "SQLITE_ALTER_TABLE");
     73     // Rename the table back to its original name
     74     executeStatement(tx, "ALTER TABLE TestTable RENAME To Test;", "SQLITE_ALTER_TABLE");
     75 
     76     executeStatement(tx, "BEGIN TRANSACTION;", "SQLITE_TRANSACTION");
     77     executeStatement(tx, "ATTACH main AS TestMain;", "SQLITE_ATTACH");
     78     executeStatement(tx, "DETACH TestMain;", "SQLITE_DETACH");
     79     executeStatement(tx, "REINDEX;", "SQLITE_REINDEX");
     80     executeStatement(tx, "ANALYZE;", "SQLITE_ANALYZE");
     81 
     82     // SQLITE_FUNCTION: allowed write mode
     83     // There is no SQL/Javascript API to add user-defined functions to SQLite,
     84     // so we cannot test this operation
     85 }
     86 
     87 function dropStatementsCallback(tx)
     88 {
     89     executeStatement(tx, "DROP INDEX TestIndex;", "SQLITE_DROP_INDEX");
     90 
     91     // SQLITE_DROP_TEMP_INDEX: allowed in write mode
     92     // Not sure how to test this: temp indexes are automatically dropped when
     93     // the database is closed, but HTML5 doesn't specify a closeDatabase() call.
     94 
     95     executeStatement(tx, "DROP TABLE TestTempTable;", "SQLITE_DROP_TEMP_TABLE");
     96     executeStatement(tx, "DROP TRIGGER TestTempTrigger;", "SQLITE_DROP_TEMP_TRIGGER");
     97     executeStatement(tx, "DROP VIEW TestTempView;", "SQLITE_DROP_TEMP_VIEW");
     98     executeStatement(tx, "DROP TRIGGER TestTrigger;", "SQLITE_DROP_TRIGGER");
     99     executeStatement(tx, "DROP VIEW TestView;", "SQLITE_DROP_VIEW");
    100 
    101     // SQLITE_DROP_VTABLE: allowed in write mode
    102     // Not sure how to test this: we cannot create a virtual table because we do not
    103     // have SQL/Javascript APIs to register a module that implements a virtual table.
    104     // Therefore, trying to drop a virtual table will always fail (no such table)
    105     // before even getting to the authorizer.
    106 
    107     executeStatement(tx, "DROP TABLE Test;", "SQLITE_DROP_TABLE");
    108 }
    109 
    110 function testReadWriteMode(db)
    111 {
    112     db.transaction(function(tx) {
    113             createTableCallback(tx);
    114             createStatementsCallback(tx);
    115             otherStatementsCallback(tx);
    116             dropStatementsCallback(tx);
    117         },
    118         function(error) { logAndTerminateTest("Write transaction failed", error); },
    119         function() { log("Write transaction succeeded."); });
    120 }
    121 
    122 function testReadOnlyMode(db)
    123 {
    124     // Test the 'CREATE TABLE' operation; it should be disallowed
    125     db.readTransaction(createTableCallback,
    126         function(error) { logAndTerminateTest("Read 'CREATE TABLE' transaction failed", error); });
    127 
    128     // In order to test all other 'CREATE' operations, we must create the table first
    129     db.transaction(createTableCallback,
    130         function(error) { logAndTerminateTest("Write 'CREATE TABLE' transaction failed", error); });
    131     db.readTransaction(createStatementsCallback,
    132         function(error) { logAndTerminateTest("Read 'CREATE' transaction failed", error); });
    133 
    134     // In order to test the 'DROP' and 'other' operations, we need to first create the respective entities
    135     db.transaction(createStatementsCallback,
    136         function(error) { logAndTerminateTest("Write 'CREATE' transaction failed", error); });
    137     db.readTransaction(otherStatementsCallback,
    138         function(error) { logAndTerminateTest("Read 'other' transaction failed", error); });
    139 
    140     // Hack: insert an empty write transaction to guaratee that these transactions are executed sequentially
    141     db.transaction(function(tx) { });
    142     db.readTransaction(dropStatementsCallback,
    143         function(error) { logAndTerminateTest("Read 'DROP' transaction failed", error); },
    144         function() { log("Read transactions succeeded."); terminateTest(); });
    145 }
    146 
    147 function runTest()
    148 {
    149     var db = openDatabaseWithSuffix("AuthorizerTest", "1.0", "Tests the database authorizer.", 32768);
    150     cleanup(db);
    151     testReadWriteMode(db);
    152     testReadOnlyMode(db);
    153 }
    154