test_fileListUpgrade.js (5757B)
1 /** 2 * Any copyright is dedicated to the Public Domain. 3 * http://creativecommons.org/publicdomain/zero/1.0/ 4 */ 5 6 /* exported testGenerator */ 7 var testGenerator = testSteps(); 8 9 function* testSteps() { 10 /** 11 * High level description: This is a synthetic test whose main aim is to 12 * ensure that DeserializeUpgradeValueHelper is safe with the FileList type 13 * in its future use cases, and in the unlikely case that someone traverses 14 * this code path with an artificially constructed profile. 15 * 16 * The packaged profile of filelistUpgrade_profile.zip was manufactured in 17 * the following way: 18 * 19 * 1. IDBFactory methods OpenForPrincipal was exposed by removing the 20 * ChromeOnly attribute from the IDBFactory.webidl file and making the 21 * corresponding changes to the header and source files. 22 * 1. mochitest test_file_filelist.html was converted to an xpcshell-test 23 * which from here on is referred to as test_file_filelist.js 24 * 1. test_file_filelist.js test was modified to create a principal for 25 * example.com the same way as dom/push/test/xpcshell/test_service_child.js 26 * 1. test_file_filelist.js test was modified to open the databases using 27 * the openForPrincipal method, with the principal above 28 * 1. test_file_filelist.js test was executed and the related 29 * xpcshell profile was saved 30 * 1. this whole play with the principals is necessary to make sure that the 31 * resulting database is not encrypted, and can be queried with a normal 32 * sqlite3 client 33 * 1. file dom/indexedDB/SchemaUpgrades.cpp was modified to expect the 34 * current database version to be 19 and stop the upgrades at this version 35 * 1. additionally, the function UpgradeKeyFunction of 36 * UpgradeSchemaFrom17_0To18_0Helper was modified to copy the aSource value to 37 * aDestination, set aTagOffset to zero and return with NS_OK when the 38 * aSource value equals 48 39 * 1. test_schema18upgrade.js was modified to stop after the database upgrade 40 * and executed. The related xpcshell profile with version 19 was saved. 41 * 1. the version 19 database was opened with sqlite3 client and the other 42 * profile with a filelist was attached to it as "future" 43 * 1. values (2, 0, "FileLists", "key") and 44 * (3, 0, "Other FileLists", "key") were inserted to table object_store 45 * 1. the .schema command was executed to record the current schema 46 * 1. object_data_insert_trigger was dropped (temporarily) 47 * 1. the following query was used to insert all data from the attached 48 * database to the old version: 49 * INSERT INTO object_data ( 50 * object_store_id, 51 * key, 52 * index_data_values, 53 * file_ids, 54 * data) 55 * SELECT 56 * (CASE WHEN (ROW_NUMBER() OVER () <= 2) THEN 2 ELSE 3 END), 57 * key, 58 * NULL, 59 * file_ids, 60 * data 61 * FROM future.object_data; 62 * 1. everything from future.file is inserted to file 63 * 1. the following query was used to update the database name: 64 * INSERT INTO database 65 * SELECT 66 * 'fileListUpgrade', 67 * origin, 68 * version, 69 * last_vacuum_time, 70 * last_analyze_time, 71 * last_vacuum_size 72 * FROM database WHERE name = 'schema18upgrade'; 73 * 1. the row with name 'schema18upgrade' was deleted from database 74 * 1. the sqlite3 client was closed 75 * 1. the filename that is expected for this test was found out with the 76 * GetFileName method of dbFileUrl in the beginning of CreateStorageConnection 77 * function in dom/indexedDB/ActorsParent.cpp 78 * 1. under the idb-directory under the profile/storage path, the 79 * .sqlite database file and the directory with a matching name having 80 * a .files extension were renamed to have the expected name with the same 81 * extensions 82 * 1. the file '1' and the journal firectory from the other, filelist 83 * containing profile, for the example.com principal, were copied under the 84 * just renamed .files directory 85 * 1. lastly, the storage/ folder and storage.sqlite were recursively zipped 86 * into an archive (note: zip -r on wsl did not produce a readable archive, 87 * the artifact was created with the windows file manager compression tool) 88 */ 89 const testName = "fileListUpgrade"; 90 91 clearAllDatabases(continueToNextStepSync); 92 yield undefined; 93 94 info("Installing profile"); 95 96 installPackagedProfile(testName + "_profile"); 97 98 info("Opening existing database with a filelist"); 99 100 let request = indexedDB.open(testName); 101 request.onerror = errorHandler; 102 request.onupgradeneeded = unexpectedSuccessHandler; 103 request.onsuccess = grabEventAndContinueHandler; 104 let event = yield undefined; 105 info("Database version " + event.target.result.version); 106 107 let db = event.target.result; 108 109 is(db.version, 3, "Correct db version"); 110 111 let transaction = db.transaction(["FileLists"]); 112 transaction.oncomplete = grabEventAndContinueHandler; 113 114 let objectStore = transaction.objectStore("FileLists"); 115 116 request = objectStore.openCursor(); 117 request.onerror = errorHandler; 118 request.onupgradeneeded = unexpectedSuccessHandler; 119 var cursorItems = 0; 120 const expectedValues = new Set([ 121 '{"key":"A","idx":0,"fileList":{"0":{},"1":{},"2":{}},"blob":{}}', 122 '{"key":"C","idx":2,"fileList":{"0":{},"1":{},"2":{}},"blob":{}}', 123 ]); 124 request.onsuccess = event => { 125 let cursor = event.target.result; 126 if (cursor) { 127 cursorItems = cursorItems + 1; 128 const actualValue = JSON.stringify(cursor.value); 129 ok(expectedValues.has(actualValue), "Is value as expected?"); 130 cursor.continue(); 131 } else { 132 testGenerator.next(); 133 } 134 }; 135 yield undefined; 136 is(cursorItems, expectedValues.size, "Did we get expected number of items?"); 137 138 finishTest(); 139 yield undefined; 140 }