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