| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * This file is part of Adblock Plus <https://adblockplus.org/>, | 2  * This file is part of Adblock Plus <https://adblockplus.org/>, | 
| 3  * Copyright (C) 2006-2017 eyeo GmbH | 3  * Copyright (C) 2006-2017 eyeo GmbH | 
| 4  * | 4  * | 
| 5  * Adblock Plus is free software: you can redistribute it and/or modify | 5  * Adblock Plus is free software: you can redistribute it and/or modify | 
| 6  * it under the terms of the GNU General Public License version 3 as | 6  * it under the terms of the GNU General Public License version 3 as | 
| 7  * published by the Free Software Foundation. | 7  * published by the Free Software Foundation. | 
| 8  * | 8  * | 
| 9  * Adblock Plus is distributed in the hope that it will be useful, | 9  * Adblock Plus is distributed in the hope that it will be useful, | 
| 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| 12  * GNU General Public License for more details. | 12  * GNU General Public License for more details. | 
| 13  * | 13  * | 
| 14  * You should have received a copy of the GNU General Public License | 14  * You should have received a copy of the GNU General Public License | 
| 15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
| 16  */ | 16  */ | 
| 17 | 17 | 
| 18 "use strict"; | 18 "use strict"; | 
| 19 | 19 | 
| 20 const {createSandbox, unexpectedError} = require("./_common"); | 20 const {createSandbox, unexpectedError} = require("./_common"); | 
| 21 | 21 | 
| 22 let Filter = null; | 22 let Filter = null; | 
| 23 let FilterNotifier = null; | 23 let FilterNotifier = null; | 
| 24 let FilterStorage = null; | 24 let FilterStorage = null; | 
| 25 let IO = null; | 25 let IO = null; | 
| 26 let Prefs = null; | 26 let Prefs = null; | 
| 27 let Subscription = null; | 27 let Subscription = null; | 
| 28 let ExternalSubscription = null; | 28 let ExternalSubscription = null; | 
|  | 29 let dataFile = null; | 
| 29 | 30 | 
| 30 exports.setUp = function(callback) | 31 exports.setUp = function(callback) | 
| 31 { | 32 { | 
| 32   let sandboxedRequire = createSandbox(); | 33   let sandboxedRequire = createSandbox(); | 
| 33   ( | 34   ( | 
| 34     {Filter} = sandboxedRequire("../lib/filterClasses"), | 35     {Filter} = sandboxedRequire("../lib/filterClasses"), | 
| 35     {FilterNotifier} = sandboxedRequire("../lib/filterNotifier"), | 36     {FilterNotifier} = sandboxedRequire("../lib/filterNotifier"), | 
| 36     {FilterStorage} = sandboxedRequire("../lib/filterStorage"), | 37     {FilterStorage} = sandboxedRequire("../lib/filterStorage"), | 
| 37     {IO} = sandboxedRequire("./stub-modules/io"), | 38     {IO} = sandboxedRequire("./stub-modules/io"), | 
| 38     {Prefs} = sandboxedRequire("./stub-modules/prefs"), | 39     {Prefs} = sandboxedRequire("./stub-modules/prefs"), | 
| 39     {Subscription, ExternalSubscription} = sandboxedRequire("../lib/subscription
     Classes") | 40     {Subscription, ExternalSubscription} = sandboxedRequire("../lib/subscription
     Classes") | 
| 40   ); | 41   ); | 
| 41 | 42 | 
| 42   FilterStorage.addSubscription(Subscription.fromURL("~fl~")); | 43   Prefs.patternsfile = "patterns.ini"; | 
|  | 44   dataFile = IO.resolveFilePath(Prefs.patternsfile); | 
|  | 45 | 
|  | 46   FilterStorage.addFilter(Filter.fromText("foobar")); | 
| 43   callback(); | 47   callback(); | 
| 44 }; | 48 }; | 
| 45 | 49 | 
| 46 let testData = new Promise((resolve, reject) => | 50 let testData = new Promise((resolve, reject) => | 
| 47 { | 51 { | 
| 48   const fs = require("fs"); | 52   const fs = require("fs"); | 
| 49   const path = require("path"); | 53   const path = require("path"); | 
| 50   let datapath = path.resolve(__dirname, "data", "patterns.ini"); | 54   let datapath = path.resolve(__dirname, "data", "patterns.ini"); | 
| 51 | 55 | 
| 52   fs.readFile(datapath, "utf-8", (error, data) => | 56   fs.readFile(datapath, "utf-8", (error, data) => | 
| 53   { | 57   { | 
| 54     if (error) | 58     if (error) | 
| 55       reject(error); | 59       reject(error); | 
| 56     else | 60     else | 
| 57       resolve(data); | 61       resolve(data); | 
| 58   }); | 62   }); | 
| 59 }); | 63 }); | 
| 60 | 64 | 
| 61 function loadFilters(file) | 65 function loadFilters() | 
| 62 { | 66 { | 
| 63   FilterStorage.loadFromDisk(file); | 67   FilterStorage.loadFromDisk(); | 
| 64   return FilterNotifier.once("load"); | 68   return FilterNotifier.once("load"); | 
| 65 } | 69 } | 
| 66 | 70 | 
| 67 function saveFilters(file) | 71 function saveFilters() | 
| 68 { | 72 { | 
| 69   FilterStorage.saveToDisk(file); | 73   FilterStorage.saveToDisk(); | 
| 70   return FilterNotifier.once("save"); | 74   return FilterNotifier.once("save"); | 
| 71 } | 75 } | 
| 72 | 76 | 
|  | 77 function canonize(data) | 
|  | 78 { | 
|  | 79   let curSection = null; | 
|  | 80   let sections = []; | 
|  | 81   for (let line of (data + "\n[end]").split(/[\r\n]+/)) | 
|  | 82   { | 
|  | 83     if (/^\[.*\]$/.test(line)) | 
|  | 84     { | 
|  | 85       if (curSection) | 
|  | 86         sections.push(curSection); | 
|  | 87 | 
|  | 88       curSection = {header: line, data: []}; | 
|  | 89     } | 
|  | 90     else if (curSection && /\S/.test(line)) | 
|  | 91       curSection.data.push(line); | 
|  | 92   } | 
|  | 93   for (let section of sections) | 
|  | 94   { | 
|  | 95     section.key = section.header + " " + section.data[0]; | 
|  | 96     section.data.sort(); | 
|  | 97   } | 
|  | 98   sections.sort((a, b) => | 
|  | 99   { | 
|  | 100     if (a.key < b.key) | 
|  | 101       return -1; | 
|  | 102     else if (a.key > b.key) | 
|  | 103       return 1; | 
|  | 104     return 0; | 
|  | 105   }); | 
|  | 106   return sections.map( | 
|  | 107     section => [section.header].concat(section.data).join("\n") | 
|  | 108   ).join("\n"); | 
|  | 109 } | 
|  | 110 | 
| 73 function testReadWrite(test, withExternal) | 111 function testReadWrite(test, withExternal) | 
| 74 { | 112 { | 
| 75   let tempFile = IO.resolveFilePath("temp_patterns1.ini"); |  | 
| 76   let tempFile2 = IO.resolveFilePath("temp_patterns2.ini"); |  | 
| 77 |  | 
| 78   function canonize(data) |  | 
| 79   { |  | 
| 80     let curSection = null; |  | 
| 81     let sections = []; |  | 
| 82     for (let line of (data + "\n[end]").split(/[\r\n]+/)) |  | 
| 83     { |  | 
| 84       if (/^\[.*\]$/.test(line)) |  | 
| 85       { |  | 
| 86         if (curSection) |  | 
| 87           sections.push(curSection); |  | 
| 88 |  | 
| 89         curSection = {header: line, data: []}; |  | 
| 90       } |  | 
| 91       else if (curSection && /\S/.test(line)) |  | 
| 92         curSection.data.push(line); |  | 
| 93     } |  | 
| 94     for (let section of sections) |  | 
| 95     { |  | 
| 96       section.key = section.header + " " + section.data[0]; |  | 
| 97       section.data.sort(); |  | 
| 98     } |  | 
| 99     sections.sort((a, b) => |  | 
| 100     { |  | 
| 101       if (a.key < b.key) |  | 
| 102         return -1; |  | 
| 103       else if (a.key > b.key) |  | 
| 104         return 1; |  | 
| 105       return 0; |  | 
| 106     }); |  | 
| 107     return sections.map( |  | 
| 108       section => [section.header].concat(section.data).join("\n") |  | 
| 109     ).join("\n"); |  | 
| 110   } |  | 
| 111 |  | 
| 112   return testData.then(data => | 113   return testData.then(data => | 
| 113   { | 114   { | 
| 114     tempFile.contents = data; | 115     dataFile.contents = data; | 
| 115     return loadFilters(tempFile); | 116     return loadFilters(); | 
| 116   }).then(() => | 117   }).then(() => | 
| 117   { | 118   { | 
| 118     test.equal(FilterStorage.fileProperties.version, FilterStorage.formatVersion
     , "File format version"); | 119     test.equal(FilterStorage.fileProperties.version, FilterStorage.formatVersion
     , "File format version"); | 
| 119 | 120 | 
| 120     if (withExternal) | 121     if (withExternal) | 
| 121     { | 122     { | 
| 122       { | 123       { | 
| 123         let subscription = new ExternalSubscription("~external~external subscrip
     tion ID", "External subscription"); | 124         let subscription = new ExternalSubscription("~external~external subscrip
     tion ID", "External subscription"); | 
| 124         subscription.filters = [Filter.fromText("foo"), Filter.fromText("bar")]; | 125         subscription.filters = [Filter.fromText("foo"), Filter.fromText("bar")]; | 
| 125         FilterStorage.addSubscription(subscription); | 126         FilterStorage.addSubscription(subscription); | 
| 126       } | 127       } | 
| 127 | 128 | 
| 128       let externalSubscriptions = FilterStorage.subscriptions.filter(subscriptio
     n => subscription instanceof ExternalSubscription); | 129       let externalSubscriptions = FilterStorage.subscriptions.filter(subscriptio
     n => subscription instanceof ExternalSubscription); | 
| 129       test.equal(externalSubscriptions.length, 1, "Number of external subscripti
     ons after updateExternalSubscription"); | 130       test.equal(externalSubscriptions.length, 1, "Number of external subscripti
     ons after updateExternalSubscription"); | 
| 130 | 131 | 
| 131       test.equal(externalSubscriptions[0].url, "~external~external subscription 
     ID", "ID of external subscription"); | 132       test.equal(externalSubscriptions[0].url, "~external~external subscription 
     ID", "ID of external subscription"); | 
| 132       test.equal(externalSubscriptions[0].filters.length, 2, "Number of filters 
     in external subscription"); | 133       test.equal(externalSubscriptions[0].filters.length, 2, "Number of filters 
     in external subscription"); | 
| 133     } | 134     } | 
| 134 | 135 | 
| 135     return saveFilters(tempFile2); | 136     return saveFilters(); | 
| 136   }).then(() => testData).then(expected => | 137   }).then(() => testData).then(expected => | 
| 137   { | 138   { | 
| 138     test.equal(canonize(tempFile2.contents), canonize(expected), "Read/write res
     ult"); | 139     test.equal(canonize(dataFile.contents), canonize(expected), "Read/write resu
     lt"); | 
| 139   }).catch(unexpectedError.bind(test)).then(() => test.done()); | 140   }).catch(unexpectedError.bind(test)).then(() => test.done()); | 
| 140 } | 141 } | 
| 141 | 142 | 
| 142 exports.testReadAndSaveToFile = function(test) | 143 exports.testReadAndSaveToFile = function(test) | 
| 143 { | 144 { | 
| 144   testReadWrite(test, false); | 145   testReadWrite(test, false); | 
| 145 }; | 146 }; | 
| 146 | 147 | 
| 147 exports.testReadAndSaveToFileWithExternalSubscription = function(test) | 148 exports.testReadAndSaveToFileWithExternalSubscription = function(test) | 
| 148 { | 149 { | 
| 149   testReadWrite(test, true); | 150   testReadWrite(test, true); | 
| 150 }; | 151 }; | 
| 151 | 152 | 
| 152 exports.testLegacyGroups = {}; | 153 exports.testLegacyGroups = {}; | 
| 153 | 154 | 
| 154 for (let url of ["~wl~", "~fl~", "~eh~"]) | 155 for (let url of ["~wl~", "~fl~", "~eh~"]) | 
| 155 { | 156 { | 
| 156   exports.testLegacyGroups["read empty " + url] = function(test) | 157   exports.testLegacyGroups["read empty " + url] = function(test) | 
| 157   { | 158   { | 
| 158     let data = "[Subscription]\nurl=" + url; | 159     dataFile.contents = "[Subscription]\nurl=" + url; | 
| 159     let tempFile = IO.resolveFilePath("temp_patterns1.ini"); |  | 
| 160     tempFile.contents = data; |  | 
| 161 | 160 | 
| 162     loadFilters(tempFile, () => | 161     loadFilters(() => | 
| 163     { | 162     { | 
| 164       test.equal(FilterStorage.subscriptions.length, 0, "Number of filter subscr
     iptions"); | 163       test.equal(FilterStorage.subscriptions.length, 0, "Number of filter subscr
     iptions"); | 
| 165     }).catch(unexpectedError.bind(test)).then(() => test.done()); | 164     }).catch(unexpectedError.bind(test)).then(() => test.done()); | 
| 166   }; | 165   }; | 
| 167 | 166 | 
| 168   exports.testLegacyGroups["read non-empty " + url] = function(test) | 167   exports.testLegacyGroups["read non-empty " + url] = function(test) | 
| 169   { | 168   { | 
| 170     let data = "[Subscription]\nurl=" + url + "\n[Subscription filters]\nfoo"; | 169     dataFile.contents = "[Subscription]\nurl=" + url + "\n[Subscription filters]
     \nfoo"; | 
| 171     let tempFile = IO.resolveFilePath("temp_patterns1.ini"); |  | 
| 172     tempFile.contents = data; |  | 
| 173 | 170 | 
| 174     loadFilters(tempFile).then(() => | 171     loadFilters().then(() => | 
| 175     { | 172     { | 
| 176       test.equal(FilterStorage.subscriptions.length, 1, "Number of filter subscr
     iptions"); | 173       test.equal(FilterStorage.subscriptions.length, 1, "Number of filter subscr
     iptions"); | 
| 177       if (FilterStorage.subscriptions.length == 1) | 174       if (FilterStorage.subscriptions.length == 1) | 
| 178       { | 175       { | 
| 179         let subscription = FilterStorage.subscriptions[0]; | 176         let subscription = FilterStorage.subscriptions[0]; | 
| 180         test.equal(subscription.url, url, "Subscription ID"); | 177         test.equal(subscription.url, url, "Subscription ID"); | 
| 181         test.equal(subscription.title, null, "Subscription title"); | 178         test.equal(subscription.title, null, "Subscription title"); | 
| 182         test.deepEqual(subscription.defaults, null, "Default types"); | 179         test.deepEqual(subscription.defaults, null, "Default types"); | 
| 183         test.equal(subscription.filters.length, 1, "Number of subscription filte
     rs"); | 180         test.equal(subscription.filters.length, 1, "Number of subscription filte
     rs"); | 
| 184         if (subscription.filters.length == 1) | 181         if (subscription.filters.length == 1) | 
| 185           test.equal(subscription.filters[0].text, "foo", "First filter"); | 182           test.equal(subscription.filters[0].text, "foo", "First filter"); | 
| 186       } | 183       } | 
| 187     }).catch(unexpectedError.bind(test)).then(() => test.done()); | 184     }).catch(unexpectedError.bind(test)).then(() => test.done()); | 
| 188   }; | 185   }; | 
| 189 } | 186 } | 
| 190 | 187 | 
| 191 exports.testReadLegacyFilters = function(test) | 188 exports.testReadLegacyFilters = function(test) | 
| 192 { | 189 { | 
| 193   let data = "[Subscription]\nurl=~user~1234\ntitle=Foo\n[Subscription filters]\
     n[User patterns]\nfoo\n\\[bar]\nfoo#bar"; | 190   dataFile.contents = "[Subscription]\nurl=~user~1234\ntitle=Foo\n[Subscription 
     filters]\n[User patterns]\nfoo\n\\[bar]\nfoo#bar"; | 
| 194   let tempFile = IO.resolveFilePath("temp_patterns1.ini"); |  | 
| 195   tempFile.contents = data; |  | 
| 196 | 191 | 
| 197   loadFilters(tempFile).then(() => | 192   loadFilters().then(() => | 
| 198   { | 193   { | 
| 199     test.equal(FilterStorage.subscriptions.length, 1, "Number of filter subscrip
     tions"); | 194     test.equal(FilterStorage.subscriptions.length, 1, "Number of filter subscrip
     tions"); | 
| 200     if (FilterStorage.subscriptions.length == 1) | 195     if (FilterStorage.subscriptions.length == 1) | 
| 201     { | 196     { | 
| 202       let subscription = FilterStorage.subscriptions[0]; | 197       let subscription = FilterStorage.subscriptions[0]; | 
| 203       test.equal(subscription.filters.length, 3, "Number of subscription filters
     "); | 198       test.equal(subscription.filters.length, 3, "Number of subscription filters
     "); | 
| 204       if (subscription.filters.length == 3) | 199       if (subscription.filters.length == 3) | 
| 205       { | 200       { | 
| 206         test.equal(subscription.filters[0].text, "foo", "First filter"); | 201         test.equal(subscription.filters[0].text, "foo", "First filter"); | 
| 207         test.equal(subscription.filters[1].text, "[bar]", "Second filter"); | 202         test.equal(subscription.filters[1].text, "[bar]", "Second filter"); | 
| 208         test.equal(subscription.filters[2].text, "foo#bar", "Third filter"); | 203         test.equal(subscription.filters[2].text, "foo#bar", "Third filter"); | 
| 209       } | 204       } | 
| 210     } | 205     } | 
| 211   }).catch(unexpectedError.bind(test)).then(() => test.done()); | 206   }).catch(unexpectedError.bind(test)).then(() => test.done()); | 
| 212 }; | 207 }; | 
| 213 | 208 | 
|  | 209 exports.testImportExport = function(test) | 
|  | 210 { | 
|  | 211   testData.then(data => | 
|  | 212   { | 
|  | 213     let lines = data.split("\n"); | 
|  | 214     if (lines.length && lines[lines.length - 1] == "") | 
|  | 215       lines.pop(); | 
|  | 216 | 
|  | 217     let importer = FilterStorage.importData(); | 
|  | 218     for (let line of lines) | 
|  | 219       importer(line); | 
|  | 220     importer(null); | 
|  | 221 | 
|  | 222     test.equal(FilterStorage.fileProperties.version, FilterStorage.formatVersion
     , "File format version"); | 
|  | 223 | 
|  | 224     let exported = ""; | 
|  | 225     for (let line of FilterStorage.exportData()) | 
|  | 226       exported += line + "\n"; | 
|  | 227     test.equal(canonize(exported), canonize(data), "Import/export result"); | 
|  | 228   }).catch(unexpectedError.bind(test)).then(() => test.done()); | 
|  | 229 }; | 
|  | 230 | 
| 214 exports.testSavingWithoutBackups = function(test) | 231 exports.testSavingWithoutBackups = function(test) | 
| 215 { | 232 { | 
| 216   Prefs.patternsbackups = 0; | 233   Prefs.patternsbackups = 0; | 
| 217   Prefs.patternsbackupinterval = 24; | 234   Prefs.patternsbackupinterval = 24; | 
| 218 | 235 | 
| 219   let tempFile = IO.resolveFilePath("temp_patterns.ini"); | 236   saveFilters().then(() => | 
| 220   Object.defineProperty(FilterStorage, "sourceFile", {get: () => tempFile.clone(
     )}); |  | 
| 221 |  | 
| 222   saveFilters(null).then(() => |  | 
| 223   { | 237   { | 
| 224     return saveFilters(null); | 238     return saveFilters(); | 
| 225   }).then(() => | 239   }).then(() => | 
| 226   { | 240   { | 
| 227     let backupFile = tempFile.clone(); | 241     let backupFile = dataFile.clone(); | 
| 228     backupFile.leafName = backupFile.leafName.replace(/\.ini$/, "-backup1.ini"); | 242     backupFile.leafName = backupFile.leafName.replace(/\.ini$/, "-backup1.ini"); | 
| 229     test.ok(!backupFile.exists(), "Backup shouldn't be created"); | 243     test.ok(!backupFile.exists(), "Backup shouldn't be created"); | 
| 230   }).catch(unexpectedError.bind(test)).then(() => test.done()); | 244   }).catch(unexpectedError.bind(test)).then(() => test.done()); | 
| 231 }; | 245 }; | 
| 232 | 246 | 
| 233 exports.testSavingWithBackups = function(test) | 247 exports.testSavingWithBackups = function(test) | 
| 234 { | 248 { | 
| 235   Prefs.patternsbackups = 2; | 249   Prefs.patternsbackups = 2; | 
| 236   Prefs.patternsbackupinterval = 24; | 250   Prefs.patternsbackupinterval = 24; | 
| 237 | 251 | 
| 238   let tempFile = IO.resolveFilePath("temp_patterns.ini"); | 252   let backupFile = dataFile.clone(); | 
| 239   Object.defineProperty(FilterStorage, "sourceFile", {get: () => tempFile.clone(
     )}); |  | 
| 240 |  | 
| 241   let backupFile = tempFile.clone(); |  | 
| 242   backupFile.leafName = backupFile.leafName.replace(/\.ini$/, "-backup1.ini"); | 253   backupFile.leafName = backupFile.leafName.replace(/\.ini$/, "-backup1.ini"); | 
| 243 | 254 | 
| 244   let backupFile2 = tempFile.clone(); | 255   let backupFile2 = dataFile.clone(); | 
| 245   backupFile2.leafName = backupFile2.leafName.replace(/\.ini$/, "-backup2.ini"); | 256   backupFile2.leafName = backupFile2.leafName.replace(/\.ini$/, "-backup2.ini"); | 
| 246 | 257 | 
| 247   let backupFile3 = tempFile.clone(); | 258   let backupFile3 = dataFile.clone(); | 
| 248   backupFile3.leafName = backupFile3.leafName.replace(/\.ini$/, "-backup3.ini"); | 259   backupFile3.leafName = backupFile3.leafName.replace(/\.ini$/, "-backup3.ini"); | 
| 249 | 260 | 
| 250   let oldModifiedTime; | 261   let oldModifiedTime; | 
| 251 | 262 | 
| 252   saveFilters(null).then(() => | 263   saveFilters().then(() => | 
| 253   { | 264   { | 
| 254     // Save again immediately | 265     // Save again immediately | 
| 255     return saveFilters(null); | 266     return saveFilters(); | 
| 256   }).then(() => | 267   }).then(() => | 
| 257   { | 268   { | 
| 258     test.ok(backupFile.exists(), "First backup created"); | 269     test.ok(backupFile.exists(), "First backup created"); | 
| 259 | 270 | 
| 260     backupFile.lastModifiedTime -= 10000; | 271     backupFile.lastModifiedTime -= 10000; | 
| 261     oldModifiedTime = backupFile.lastModifiedTime; | 272     oldModifiedTime = backupFile.lastModifiedTime; | 
| 262     return saveFilters(null); | 273     return saveFilters(); | 
| 263   }).then(() => | 274   }).then(() => | 
| 264   { | 275   { | 
| 265     test.equal(backupFile.lastModifiedTime, oldModifiedTime, "Backup not overwri
     tten if it is only 10 seconds old"); | 276     test.equal(backupFile.lastModifiedTime, oldModifiedTime, "Backup not overwri
     tten if it is only 10 seconds old"); | 
| 266 | 277 | 
| 267     backupFile.lastModifiedTime -= 40 * 60 * 60 * 1000; | 278     backupFile.lastModifiedTime -= 40 * 60 * 60 * 1000; | 
| 268     oldModifiedTime = backupFile.lastModifiedTime; | 279     oldModifiedTime = backupFile.lastModifiedTime; | 
| 269     return saveFilters(null); | 280     return saveFilters(); | 
| 270   }).then(() => | 281   }).then(() => | 
| 271   { | 282   { | 
| 272     test.notEqual(backupFile.lastModifiedTime, oldModifiedTime, "Backup overwrit
     ten if it is 40 hours old"); | 283     test.notEqual(backupFile.lastModifiedTime, oldModifiedTime, "Backup overwrit
     ten if it is 40 hours old"); | 
| 273 | 284 | 
| 274     test.ok(backupFile2.exists(), "Second backup created when first backup is ov
     erwritten"); | 285     test.ok(backupFile2.exists(), "Second backup created when first backup is ov
     erwritten"); | 
| 275 | 286 | 
| 276     backupFile.lastModifiedTime -= 20000; | 287     backupFile.lastModifiedTime -= 20000; | 
| 277     oldModifiedTime = backupFile2.lastModifiedTime; | 288     oldModifiedTime = backupFile2.lastModifiedTime; | 
| 278     return saveFilters(null); | 289     return saveFilters(); | 
| 279   }).then(() => | 290   }).then(() => | 
| 280   { | 291   { | 
| 281     test.equal(backupFile2.lastModifiedTime, oldModifiedTime, "Second backup not
      overwritten if first one is only 20 seconds old"); | 292     test.equal(backupFile2.lastModifiedTime, oldModifiedTime, "Second backup not
      overwritten if first one is only 20 seconds old"); | 
| 282 | 293 | 
| 283     backupFile.lastModifiedTime -= 25 * 60 * 60 * 1000; | 294     backupFile.lastModifiedTime -= 25 * 60 * 60 * 1000; | 
| 284     oldModifiedTime = backupFile2.lastModifiedTime; | 295     oldModifiedTime = backupFile2.lastModifiedTime; | 
| 285     return saveFilters(null); | 296     return saveFilters(); | 
| 286   }).then(() => | 297   }).then(() => | 
| 287   { | 298   { | 
| 288     test.notEqual(backupFile2.lastModifiedTime, oldModifiedTime, "Second backup 
     overwritten if first one is 25 hours old"); | 299     test.notEqual(backupFile2.lastModifiedTime, oldModifiedTime, "Second backup 
     overwritten if first one is 25 hours old"); | 
| 289 | 300 | 
| 290     test.ok(!backupFile3.exists(), "Third backup not created with patternsbackup
     s = 2"); | 301     test.ok(!backupFile3.exists(), "Third backup not created with patternsbackup
     s = 2"); | 
| 291   }).catch(unexpectedError.bind(test)).then(() => test.done()); | 302   }).catch(unexpectedError.bind(test)).then(() => test.done()); | 
| 292 }; | 303 }; | 
|  | 304 | 
|  | 305 exports.testRestoringBackup = function(test) | 
|  | 306 { | 
|  | 307   Prefs.patternsbackups = 2; | 
|  | 308   Prefs.patternsbackupinterval = 24; | 
|  | 309 | 
|  | 310   saveFilters().then(() => | 
|  | 311   { | 
|  | 312     test.equal(FilterStorage.subscriptions.length, 1, "Initial subscription coun
     t"); | 
|  | 313     FilterStorage.removeSubscription(FilterStorage.subscriptions[0]); | 
|  | 314     return saveFilters(); | 
|  | 315   }).then(() => | 
|  | 316   { | 
|  | 317     return loadFilters(); | 
|  | 318   }).then(() => | 
|  | 319   { | 
|  | 320     test.equal(FilterStorage.subscriptions.length, 0, "Subscription count after 
     removing subscriptions and reloading"); | 
|  | 321     return FilterStorage.restoreBackup(1); | 
|  | 322   }).then(() => | 
|  | 323   { | 
|  | 324     test.equal(FilterStorage.subscriptions.length, 1, "Subscription count after 
     restoring backup"); | 
|  | 325     return loadFilters(); | 
|  | 326   }).then(() => | 
|  | 327   { | 
|  | 328     test.equal(FilterStorage.subscriptions.length, 1, "Subscription count after 
     reloading"); | 
|  | 329   }).catch(unexpectedError.bind(test)).then(() => test.done()); | 
|  | 330 }; | 
| OLD | NEW | 
|---|