1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/storage/test/unit/head_storage.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,266 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +const Ci = Components.interfaces; 1.9 +const Cc = Components.classes; 1.10 +const Cr = Components.results; 1.11 +const Cu = Components.utils; 1.12 + 1.13 +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 1.14 +XPCOMUtils.defineLazyModuleGetter(this, "Promise", 1.15 + "resource://gre/modules/Promise.jsm"); 1.16 + 1.17 + 1.18 +do_get_profile(); 1.19 +var dirSvc = Cc["@mozilla.org/file/directory_service;1"]. 1.20 + getService(Ci.nsIProperties); 1.21 + 1.22 +function getTestDB() 1.23 +{ 1.24 + var db = dirSvc.get("ProfD", Ci.nsIFile); 1.25 + db.append("test_storage.sqlite"); 1.26 + return db; 1.27 +} 1.28 + 1.29 +/** 1.30 + * Obtains a corrupt database to test against. 1.31 + */ 1.32 +function getCorruptDB() 1.33 +{ 1.34 + return do_get_file("corruptDB.sqlite"); 1.35 +} 1.36 + 1.37 +/** 1.38 + * Obtains a fake (non-SQLite format) database to test against. 1.39 + */ 1.40 +function getFakeDB() 1.41 +{ 1.42 + return do_get_file("fakeDB.sqlite"); 1.43 +} 1.44 + 1.45 +function cleanup() 1.46 +{ 1.47 + // close the connection 1.48 + print("*** Storage Tests: Trying to close!"); 1.49 + getOpenedDatabase().close(); 1.50 + 1.51 + // we need to null out the database variable to get a new connection the next 1.52 + // time getOpenedDatabase is called 1.53 + gDBConn = null; 1.54 + 1.55 + // removing test db 1.56 + print("*** Storage Tests: Trying to remove file!"); 1.57 + var dbFile = getTestDB(); 1.58 + if (dbFile.exists()) 1.59 + try { dbFile.remove(false); } catch(e) { /* stupid windows box */ } 1.60 +} 1.61 + 1.62 +/** 1.63 + * Use asyncClose to cleanup a connection. Synchronous by means of internally 1.64 + * spinning an event loop. 1.65 + */ 1.66 +function asyncCleanup() 1.67 +{ 1.68 + let closed = false; 1.69 + 1.70 + // close the connection 1.71 + print("*** Storage Tests: Trying to asyncClose!"); 1.72 + getOpenedDatabase().asyncClose(function() { closed = true; }); 1.73 + 1.74 + let curThread = Components.classes["@mozilla.org/thread-manager;1"] 1.75 + .getService().currentThread; 1.76 + while (!closed) 1.77 + curThread.processNextEvent(true); 1.78 + 1.79 + // we need to null out the database variable to get a new connection the next 1.80 + // time getOpenedDatabase is called 1.81 + gDBConn = null; 1.82 + 1.83 + // removing test db 1.84 + print("*** Storage Tests: Trying to remove file!"); 1.85 + var dbFile = getTestDB(); 1.86 + if (dbFile.exists()) 1.87 + try { dbFile.remove(false); } catch(e) { /* stupid windows box */ } 1.88 +} 1.89 + 1.90 +function getService() 1.91 +{ 1.92 + return Cc["@mozilla.org/storage/service;1"].getService(Ci.mozIStorageService); 1.93 +} 1.94 + 1.95 +var gDBConn = null; 1.96 + 1.97 +/** 1.98 + * Get a connection to the test database. Creates and caches the connection 1.99 + * if necessary, otherwise reuses the existing cached connection. This 1.100 + * connection shares its cache. 1.101 + * 1.102 + * @returns the mozIStorageConnection for the file. 1.103 + */ 1.104 +function getOpenedDatabase() 1.105 +{ 1.106 + if (!gDBConn) { 1.107 + gDBConn = getService().openDatabase(getTestDB()); 1.108 + } 1.109 + return gDBConn; 1.110 +} 1.111 + 1.112 +/** 1.113 + * Get a connection to the test database. Creates and caches the connection 1.114 + * if necessary, otherwise reuses the existing cached connection. This 1.115 + * connection doesn't share its cache. 1.116 + * 1.117 + * @returns the mozIStorageConnection for the file. 1.118 + */ 1.119 +function getOpenedUnsharedDatabase() 1.120 +{ 1.121 + if (!gDBConn) { 1.122 + gDBConn = getService().openUnsharedDatabase(getTestDB()); 1.123 + } 1.124 + return gDBConn; 1.125 +} 1.126 + 1.127 +/** 1.128 + * Obtains a specific database to use. 1.129 + * 1.130 + * @param aFile 1.131 + * The nsIFile representing the db file to open. 1.132 + * @returns the mozIStorageConnection for the file. 1.133 + */ 1.134 +function getDatabase(aFile) 1.135 +{ 1.136 + return getService().openDatabase(aFile); 1.137 +} 1.138 + 1.139 +function createStatement(aSQL) 1.140 +{ 1.141 + return getOpenedDatabase().createStatement(aSQL); 1.142 +} 1.143 + 1.144 +/** 1.145 + * Creates an asynchronous SQL statement. 1.146 + * 1.147 + * @param aSQL 1.148 + * The SQL to parse into a statement. 1.149 + * @returns a mozIStorageAsyncStatement from aSQL. 1.150 + */ 1.151 +function createAsyncStatement(aSQL) 1.152 +{ 1.153 + return getOpenedDatabase().createAsyncStatement(aSQL); 1.154 +} 1.155 + 1.156 +/** 1.157 + * Invoke the given function and assert that it throws an exception expressing 1.158 + * the provided error code in its 'result' attribute. JS function expressions 1.159 + * can be used to do this concisely. 1.160 + * 1.161 + * Example: 1.162 + * expectError(Cr.NS_ERROR_INVALID_ARG, function() explodingFunction()); 1.163 + * 1.164 + * @param aErrorCode 1.165 + * The error code to expect from invocation of aFunction. 1.166 + * @param aFunction 1.167 + * The function to invoke and expect an XPCOM-style error from. 1.168 + */ 1.169 +function expectError(aErrorCode, aFunction) 1.170 +{ 1.171 + let exceptionCaught = false; 1.172 + try { 1.173 + aFunction(); 1.174 + } 1.175 + catch(e) { 1.176 + if (e.result != aErrorCode) { 1.177 + do_throw("Got an exception, but the result code was not the expected " + 1.178 + "one. Expected " + aErrorCode + ", got " + e.result); 1.179 + } 1.180 + exceptionCaught = true; 1.181 + } 1.182 + if (!exceptionCaught) 1.183 + do_throw(aFunction + " should have thrown an exception but did not!"); 1.184 +} 1.185 + 1.186 +/** 1.187 + * Run a query synchronously and verify that we get back the expected results. 1.188 + * 1.189 + * @param aSQLString 1.190 + * The SQL string for the query. 1.191 + * @param aBind 1.192 + * The value to bind at index 0. 1.193 + * @param aResults 1.194 + * A list of the expected values returned in the sole result row. 1.195 + * Express blobs as lists. 1.196 + */ 1.197 +function verifyQuery(aSQLString, aBind, aResults) 1.198 +{ 1.199 + let stmt = getOpenedDatabase().createStatement(aSQLString); 1.200 + stmt.bindByIndex(0, aBind); 1.201 + try { 1.202 + do_check_true(stmt.executeStep()); 1.203 + let nCols = stmt.numEntries; 1.204 + if (aResults.length != nCols) 1.205 + do_throw("Expected " + aResults.length + " columns in result but " + 1.206 + "there are only " + aResults.length + "!"); 1.207 + for (let iCol = 0; iCol < nCols; iCol++) { 1.208 + let expectedVal = aResults[iCol]; 1.209 + let valType = stmt.getTypeOfIndex(iCol); 1.210 + if (expectedVal === null) { 1.211 + do_check_eq(stmt.VALUE_TYPE_NULL, valType); 1.212 + do_check_true(stmt.getIsNull(iCol)); 1.213 + } 1.214 + else if (typeof(expectedVal) == "number") { 1.215 + if (Math.floor(expectedVal) == expectedVal) { 1.216 + do_check_eq(stmt.VALUE_TYPE_INTEGER, valType); 1.217 + do_check_eq(expectedVal, stmt.getInt32(iCol)); 1.218 + } 1.219 + else { 1.220 + do_check_eq(stmt.VALUE_TYPE_FLOAT, valType); 1.221 + do_check_eq(expectedVal, stmt.getDouble(iCol)); 1.222 + } 1.223 + } 1.224 + else if (typeof(expectedVal) == "string") { 1.225 + do_check_eq(stmt.VALUE_TYPE_TEXT, valType); 1.226 + do_check_eq(expectedVal, stmt.getUTF8String(iCol)); 1.227 + } 1.228 + else { // blob 1.229 + do_check_eq(stmt.VALUE_TYPE_BLOB, valType); 1.230 + let count = { value: 0 }, blob = { value: null }; 1.231 + stmt.getBlob(iCol, count, blob); 1.232 + do_check_eq(count.value, expectedVal.length); 1.233 + for (let i = 0; i < count.value; i++) { 1.234 + do_check_eq(expectedVal[i], blob.value[i]); 1.235 + } 1.236 + } 1.237 + } 1.238 + } 1.239 + finally { 1.240 + stmt.finalize(); 1.241 + } 1.242 +} 1.243 + 1.244 +/** 1.245 + * Return the number of rows in the able with the given name using a synchronous 1.246 + * query. 1.247 + * 1.248 + * @param aTableName 1.249 + * The name of the table. 1.250 + * @return The number of rows. 1.251 + */ 1.252 +function getTableRowCount(aTableName) 1.253 +{ 1.254 + var currentRows = 0; 1.255 + var countStmt = getOpenedDatabase().createStatement( 1.256 + "SELECT COUNT(1) AS count FROM " + aTableName 1.257 + ); 1.258 + try { 1.259 + do_check_true(countStmt.executeStep()); 1.260 + currentRows = countStmt.row.count; 1.261 + } 1.262 + finally { 1.263 + countStmt.finalize(); 1.264 + } 1.265 + return currentRows; 1.266 +} 1.267 + 1.268 +cleanup(); 1.269 +