| Left: | ||
| Right: |
| OLD | NEW |
|---|---|
| 1 (function() | 1 /* |
| 2 { | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
| 3 module("Filter storage read/write", { | 3 * Copyright (C) 2006-2016 Eyeo GmbH |
| 4 setup: function() | 4 * |
| 5 { | 5 * Adblock Plus is free software: you can redistribute it and/or modify |
| 6 prepareFilterComponents.call(this); | 6 * it under the terms of the GNU General Public License version 3 as |
| 7 preparePrefs.call(this); | 7 * published by the Free Software Foundation. |
| 8 | 8 * |
| 9 FilterStorage.addSubscription(Subscription.fromURL("~fl~")); | 9 * Adblock Plus is distributed in the hope that it will be useful, |
| 10 }, | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 teardown: function() | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 { | 12 * GNU General Public License for more details. |
| 13 restoreFilterComponents.call(this); | 13 * |
| 14 restorePrefs.call(this); | 14 * You should have received a copy of the GNU General Public License |
| 15 } | 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
| 16 */ | |
| 17 | |
| 18 "use strict"; | |
| 19 | |
| 20 let {createSandbox, unexpectedError} = require("./_common"); | |
| 21 | |
| 22 let Filter = null; | |
| 23 let FilterNotifier = null; | |
| 24 let FilterStorage = null; | |
| 25 let IO = null; | |
| 26 let Prefs = null; | |
| 27 let Subscription = null; | |
| 28 let ExternalSubscription = null; | |
| 29 | |
| 30 exports.setUp = function(callback) | |
| 31 { | |
| 32 let sandboxedRequire = createSandbox(); | |
| 33 ( | |
| 34 {Filter} = sandboxedRequire("../lib/filterClasses"), | |
| 35 {FilterNotifier} = sandboxedRequire("../lib/filterNotifier"), | |
| 36 {FilterStorage} = sandboxedRequire("../lib/filterStorage"), | |
| 37 {IO} = sandboxedRequire("./stub-modules/io"), | |
| 38 {Prefs} = sandboxedRequire("./stub-modules/prefs"), | |
| 39 {Subscription, ExternalSubscription} = sandboxedRequire("../lib/subscription Classes") | |
| 40 ); | |
| 41 | |
| 42 FilterStorage.addSubscription(Subscription.fromURL("~fl~")); | |
| 43 callback(); | |
| 44 } | |
| 45 | |
| 46 let testData = new Promise((resolve, reject) => | |
| 47 { | |
| 48 let fs = require("fs"); | |
| 49 let path = require("path"); | |
| 50 let datapath = path.resolve(__dirname, "data", "patterns.ini"); | |
|
kzar
2016/10/06 05:13:38
Did you forget to add the data/patterns.ini file?
Wladimir Palant
2016/10/06 07:13:59
No, I copied the files in a separate commit - what
kzar
2016/10/06 08:06:47
Acknowledged.
| |
| 51 | |
| 52 fs.readFile(datapath, "utf-8", (error, data) => | |
| 53 { | |
| 54 if (error) | |
| 55 reject(error); | |
| 56 else | |
| 57 resolve(data); | |
| 16 }); | 58 }); |
| 17 | 59 }); |
| 18 let {FileUtils} = Cu.import("resource://gre/modules/FileUtils.jsm", null); | 60 |
| 19 let {NetUtil} = Cu.import("resource://gre/modules/NetUtil.jsm", null); | 61 function loadFilters(file) |
| 20 | 62 { |
| 21 function loadFilters(file, callback) | 63 return new Promise((resolve, reject) => |
| 22 { | 64 { |
| 23 let listener = function(action) | 65 let listener = function(action) |
|
kzar
2016/10/06 05:13:38
Seems like this logic is nearly identical in saveF
Wladimir Palant
2016/10/06 07:13:59
Reusing isn't quite trivial but with the new Filte
| |
| 24 { | 66 { |
| 25 if (action == "load") | 67 if (action == "load") |
| 26 { | 68 { |
| 27 FilterNotifier.removeListener(listener); | 69 FilterNotifier.removeListener(listener); |
| 28 callback(); | 70 resolve(); |
| 29 } | 71 } |
| 30 }; | 72 }; |
| 31 FilterNotifier.addListener(listener); | 73 FilterNotifier.addListener(listener); |
| 32 | 74 |
| 33 FilterStorage.loadFromDisk(file); | 75 FilterStorage.loadFromDisk(file); |
| 34 } | 76 }); |
| 35 | 77 } |
| 36 function writeToFile(file, data) | 78 |
| 37 { | 79 function saveFilters(file, callback) |
| 38 let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createIns tance(Ci.nsIScriptableUnicodeConverter); | 80 { |
| 39 converter.charset = "utf-8"; | 81 return new Promise((resolve, reject) => |
| 40 data = converter.ConvertFromUnicode(data); | |
| 41 | |
| 42 let stream = FileUtils.openFileOutputStream(file); | |
| 43 stream.write(data, data.length); | |
| 44 stream.close(); | |
| 45 } | |
| 46 | |
| 47 function saveFilters(file, callback) | |
| 48 { | 82 { |
| 49 let listener = function(action) | 83 let listener = function(action) |
| 50 { | 84 { |
| 51 if (action == "save") | 85 if (action == "save") |
| 52 { | 86 { |
| 53 FilterNotifier.removeListener(listener); | 87 FilterNotifier.removeListener(listener); |
| 54 callback(); | 88 resolve(); |
| 55 } | 89 } |
| 56 }; | 90 }; |
| 57 FilterNotifier.addListener(listener); | 91 FilterNotifier.addListener(listener); |
| 58 | 92 |
| 59 FilterStorage.saveToDisk(file); | 93 FilterStorage.saveToDisk(file); |
| 94 }); | |
| 95 } | |
| 96 | |
| 97 function testReadWrite(test, withExternal) | |
| 98 { | |
| 99 let tempFile = IO.resolveFilePath("temp_patterns1.ini"); | |
| 100 let tempFile2 = IO.resolveFilePath("temp_patterns2.ini"); | |
| 101 | |
| 102 function canonize(data) | |
| 103 { | |
| 104 let curSection = null; | |
| 105 let sections = []; | |
| 106 for (let line of (data + "\n[end]").split(/[\r\n]+/)) | |
| 107 { | |
| 108 if (/^\[.*\]$/.test(line)) | |
| 109 { | |
| 110 if (curSection) | |
| 111 sections.push(curSection); | |
| 112 | |
| 113 curSection = {header: line, data: []}; | |
| 114 } | |
| 115 else if (curSection && /\S/.test(line)) | |
| 116 curSection.data.push(line); | |
| 117 } | |
| 118 for (let section of sections) | |
| 119 { | |
| 120 section.key = section.header + " " + section.data[0]; | |
| 121 section.data.sort(); | |
| 122 } | |
| 123 sections.sort(function(a, b) | |
| 124 { | |
| 125 if (a.key < b.key) | |
| 126 return -1; | |
| 127 else if (a.key > b.key) | |
| 128 return 1; | |
| 129 else | |
| 130 return 0; | |
| 131 }); | |
| 132 return sections.map(function(section) { | |
| 133 return [section.header].concat(section.data).join("\n"); | |
| 134 }).join("\n"); | |
| 60 } | 135 } |
| 61 | 136 |
| 62 function testReadWrite(withExternal) | 137 return testData.then(data => |
| 63 { | 138 { |
| 64 let tempFile = FileUtils.getFile("TmpD", ["temp_patterns1.ini"]); | 139 tempFile.contents = data; |
| 65 let tempFile2 = FileUtils.getFile("TmpD", ["temp_patterns2.ini"]); | 140 return loadFilters(tempFile); |
| 66 tempFile.createUnique(tempFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); | 141 }).then(() => |
| 67 createTempFile(); | 142 { |
| 68 | 143 test.equal(FilterStorage.fileProperties.version, FilterStorage.formatVersion , "File format version"); |
| 69 function canonize(data) | 144 |
| 70 { | 145 if (withExternal) |
| 71 let curSection = null; | 146 { |
| 72 let sections = []; | 147 let subscription = new ExternalSubscription("~external~external subscripti on ID", "External subscription"); |
| 73 for (let line of (data + "\n[end]").split(/[\r\n]+/)) | 148 subscription.filters = [Filter.fromText("foo"), Filter.fromText("bar")]; |
| 74 { | 149 FilterStorage.addSubscription(subscription); |
|
Wladimir Palant
2016/10/05 20:10:22
This was calling our public API in the original te
kzar
2016/10/06 05:13:38
Acknowledged.
| |
| 75 if (/^\[.*\]$/.test(line)) | 150 |
| 76 { | 151 let externalSubscriptions = FilterStorage.subscriptions.filter(subscriptio n => subscription instanceof ExternalSubscription); |
| 77 if (curSection) | 152 test.equal(externalSubscriptions.length, 1, "Number of external subscripti ons after updateExternalSubscription"); |
| 78 sections.push(curSection); | 153 |
| 79 | 154 test.equal(externalSubscriptions[0].url, "~external~external subscription ID", "ID of external subscription"); |
| 80 curSection = {header: line, data: []}; | 155 test.equal(externalSubscriptions[0].filters.length, 2, "Number of filters in external subscription"); |
| 81 } | |
| 82 else if (curSection && /\S/.test(line)) | |
| 83 curSection.data.push(line); | |
| 84 } | |
| 85 for (let section of sections) | |
| 86 { | |
| 87 section.key = section.header + " " + section.data[0]; | |
| 88 section.data.sort(); | |
| 89 } | |
| 90 sections.sort(function(a, b) | |
| 91 { | |
| 92 if (a.key < b.key) | |
| 93 return -1; | |
| 94 else if (a.key > b.key) | |
| 95 return 1; | |
| 96 else | |
| 97 return 0; | |
| 98 }); | |
| 99 return sections.map(function(section) { | |
| 100 return [section.header].concat(section.data).join("\n"); | |
| 101 }).join("\n"); | |
| 102 } | 156 } |
| 103 | 157 |
| 104 function createTempFile() | 158 return saveFilters(tempFile2); |
| 105 { | 159 }).then(() => testData).then(expected => |
| 106 let request = new XMLHttpRequest(); | 160 { |
| 107 request.open("GET", "data/patterns.ini"); | 161 test.equal(canonize(tempFile2.contents), canonize(expected), "Read/write res ult"); |
| 108 request.overrideMimeType("text/plain; charset=utf-8"); | 162 }).catch(unexpectedError.bind(test)).then(() => test.done()); |
| 109 request.addEventListener("load", function() | 163 } |
| 110 { | 164 |
| 111 writeToFile(tempFile, request.responseText); | 165 exports.testReadAndSaveToFile = function(test) |
| 112 loadFilters(tempFile, saveFile); | 166 { |
| 113 }, false); | 167 testReadWrite(test, false); |
| 114 request.send(null); | 168 }; |
| 169 | |
| 170 exports.testReadAndSaveToFileWithExternalSubscription = function(test) | |
| 171 { | |
| 172 testReadWrite(test, true); | |
| 173 }; | |
| 174 | |
| 175 exports.testLegacyGroups = {}; | |
| 176 | |
| 177 for (let url of ["~wl~", "~fl~", "~eh~"]) | |
| 178 { | |
| 179 exports.testLegacyGroups["read empty " + url] = function(test) | |
| 180 { | |
| 181 let data = "[Subscription]\nurl=" + url; | |
| 182 let tempFile = IO.resolveFilePath("temp_patterns1.ini"); | |
| 183 tempFile.contents = data; | |
| 184 | |
| 185 loadFilters(tempFile, function() | |
| 186 { | |
| 187 test.equal(FilterStorage.subscriptions.length, 0, "Number of filter subscr iptions"); | |
| 188 }).catch(unexpectedError.bind(test)).then(() => test.done()); | |
| 189 }; | |
| 190 | |
| 191 exports.testLegacyGroups["read non-empty " + url] = function(test) | |
| 192 { | |
| 193 let data = "[Subscription]\nurl=" + url + "\n[Subscription filters]\nfoo"; | |
| 194 let tempFile = IO.resolveFilePath("temp_patterns1.ini"); | |
| 195 tempFile.contents = data; | |
| 196 | |
| 197 loadFilters(tempFile).then(() => | |
| 198 { | |
| 199 test.equal(FilterStorage.subscriptions.length, 1, "Number of filter subscr iptions"); | |
| 200 if (FilterStorage.subscriptions.length == 1) | |
| 201 { | |
| 202 let subscription = FilterStorage.subscriptions[0]; | |
| 203 test.equal(subscription.url, url, "Subscription ID"); | |
|
kzar
2016/10/06 05:13:37
Won't `url` always be "~eh~" by the time the test
Wladimir Palant
2016/10/06 07:13:59
Good question. I checked and this isn't the case -
kzar
2016/10/06 08:06:47
Ah of course.
| |
| 204 test.equal(subscription.title, null, "Subscription title"); | |
| 205 test.deepEqual(subscription.defaults, null, "Default types"); | |
|
Wladimir Palant
2016/10/05 20:10:22
I had to modify this, the fallback for legacy grou
kzar
2016/10/06 05:13:37
Acknowledged.
| |
| 206 test.equal(subscription.filters.length, 1, "Number of subscription filte rs"); | |
| 207 if (subscription.filters.length == 1) | |
| 208 test.equal(subscription.filters[0].text, "foo", "First filter"); | |
| 209 } | |
| 210 }).catch(unexpectedError.bind(test)).then(() => test.done()); | |
| 211 }; | |
| 212 } | |
| 213 | |
| 214 exports.testReadLegacyFilters = function(test) | |
| 215 { | |
| 216 let data = "[Subscription]\nurl=~user~1234\ntitle=Foo\n[Subscription filters]\ n[User patterns]\nfoo\n\\[bar]\nfoo#bar"; | |
| 217 let tempFile = IO.resolveFilePath("temp_patterns1.ini"); | |
| 218 tempFile.contents = data; | |
| 219 | |
| 220 loadFilters(tempFile).then(() => | |
| 221 { | |
| 222 test.equal(FilterStorage.subscriptions.length, 1, "Number of filter subscrip tions"); | |
| 223 if (FilterStorage.subscriptions.length == 1) | |
| 224 { | |
| 225 let subscription = FilterStorage.subscriptions[0]; | |
| 226 test.equal(subscription.filters.length, 3, "Number of subscription filters "); | |
| 227 if (subscription.filters.length == 3) | |
| 228 { | |
| 229 test.equal(subscription.filters[0].text, "foo", "First filter"); | |
| 230 test.equal(subscription.filters[1].text, "[bar]", "Second filter"); | |
| 231 test.equal(subscription.filters[2].text, "foo#bar", "Third filter"); | |
| 232 } | |
| 115 } | 233 } |
| 116 | 234 }).catch(unexpectedError.bind(test)).then(() => test.done()); |
| 117 function saveFile() | 235 }; |
| 118 { | 236 |
| 119 equal(FilterStorage.fileProperties.version, FilterStorage.formatVersion, " File format version"); | 237 exports.testSavingWithoutBackups = function(test) |
| 120 | 238 { |
| 121 if (withExternal) | 239 Prefs.patternsbackups = 0; |
| 122 { | 240 Prefs.patternsbackupinterval = 24; |
| 123 let {AdblockPlus} = Cu.import(Cc["@adblockplus.org/abp/public;1"].getSer vice(Ci.nsIURI).spec, null); | 241 |
| 124 AdblockPlus.updateExternalSubscription("~external~external subscription ID", "External subscription", ["foo", "bar"]); | 242 let tempFile = IO.resolveFilePath("temp_patterns.ini"); |
| 125 | 243 Object.defineProperty(FilterStorage, "sourceFile", {get: () => tempFile.clone( )}); |
| 126 let externalSubscriptions = FilterStorage.subscriptions.filter(function (subscription) subscription instanceof ExternalSubscription); | 244 |
| 127 equal(externalSubscriptions.length, 1, "Number of external subscriptions after updateExternalSubscription"); | 245 saveFilters(null).then(() => |
| 128 | 246 { |
| 129 if (externalSubscriptions.length == 1) | 247 return saveFilters(null); |
| 130 { | 248 }).then(() => |
| 131 equal(externalSubscriptions[0].url, "~external~external subscription I D", "ID of external subscription"); | 249 { |
| 132 equal(externalSubscriptions[0].filters.length, 2, "Number of filters i n external subscription"); | |
| 133 } | |
| 134 } | |
| 135 | |
| 136 saveFilters(tempFile2, compareFile); | |
| 137 } | |
| 138 | |
| 139 function compareFile() | |
| 140 { | |
| 141 let stream = Cc["@mozilla.org/network/file-input-stream;1"].createInstance (Ci.nsIFileInputStream); | |
| 142 stream.init(tempFile2, FileUtils.MODE_RDONLY, FileUtils.PERMS_FILE, Ci.nsI FileInputStream.DEFER_OPEN); | |
| 143 | |
| 144 NetUtil.asyncFetch(stream, function(inputStream, nsresult) | |
| 145 { | |
| 146 let result = NetUtil.readInputStreamToString(inputStream, inputStream.av ailable(), {charset: "utf-8"}); | |
| 147 | |
| 148 let request = new XMLHttpRequest(); | |
| 149 request.open("GET", "data/patterns.ini"); | |
| 150 request.overrideMimeType("text/plain"); | |
| 151 request.addEventListener("load", function() | |
| 152 { | |
| 153 let expected = request.responseText; | |
| 154 equal(canonize(result), canonize(expected), "Read/write result"); | |
| 155 | |
| 156 tempFile.remove(false); | |
| 157 tempFile2.remove(false); | |
| 158 start(); | |
| 159 }, false); | |
| 160 request.send(null); | |
| 161 }); | |
| 162 } | |
| 163 } | |
| 164 | |
| 165 asyncTest("Read and save to file", testReadWrite.bind(false)); | |
| 166 asyncTest("Read, add external subscription and save to file", testReadWrite.bi nd(true)); | |
| 167 | |
| 168 let groupTests = [ | |
| 169 ["~wl~", "whitelist"], | |
| 170 ["~fl~", "blocking"], | |
| 171 ["~eh~", "elemhide"] | |
| 172 ]; | |
| 173 for (let i = 0; i < groupTests.length; i++) | |
| 174 { | |
| 175 let [url, defaults] = groupTests[i]; | |
| 176 asyncTest("Read empty legacy user-defined group (" + url + ")", function() | |
| 177 { | |
| 178 let data = "[Subscription]\nurl=" + url; | |
| 179 let tempFile = FileUtils.getFile("TmpD", ["temp_patterns1.ini"]); | |
| 180 writeToFile(tempFile, data); | |
| 181 | |
| 182 loadFilters(tempFile, function() | |
| 183 { | |
| 184 tempFile.remove(false); | |
| 185 equal(FilterStorage.subscriptions.length, 0, "Number of filter subscript ions"); | |
| 186 start(); | |
| 187 }); | |
| 188 }); | |
| 189 asyncTest("Read non-empty legacy user-defined group (" + url + ")", function () | |
| 190 { | |
| 191 let data = "[Subscription]\nurl=" + url + "\n[Subscription filters]\nfoo"; | |
| 192 let tempFile = FileUtils.getFile("TmpD", ["temp_patterns1.ini"]); | |
| 193 writeToFile(tempFile, data); | |
| 194 | |
| 195 loadFilters(tempFile, function() | |
| 196 { | |
| 197 tempFile.remove(false); | |
| 198 equal(FilterStorage.subscriptions.length, 1, "Number of filter subscript ions"); | |
| 199 if (FilterStorage.subscriptions.length == 1) | |
| 200 { | |
| 201 let subscription = FilterStorage.subscriptions[0]; | |
| 202 equal(subscription.url, url, "Subscription ID"); | |
| 203 equal(subscription.title, Utils.getString(defaults + "Group_title"), " Subscription title"); | |
| 204 deepEqual(subscription.defaults, [defaults], "Default types"); | |
| 205 equal(subscription.filters.length, 1, "Number of subscription filters" ); | |
| 206 if (subscription.filters.length == 1) | |
| 207 equal(subscription.filters[0].text, "foo", "First filter"); | |
| 208 } | |
| 209 start(); | |
| 210 }); | |
| 211 }); | |
| 212 } | |
| 213 | |
| 214 asyncTest("Read legacy user-defined filters", function() | |
| 215 { | |
| 216 let data = "[Subscription]\nurl=~user~1234\ntitle=Foo\n[Subscription filters ]\n[User patterns]\nfoo\n\\[bar]\nfoo#bar"; | |
| 217 let tempFile = FileUtils.getFile("TmpD", ["temp_patterns1.ini"]); | |
| 218 writeToFile(tempFile, data); | |
| 219 | |
| 220 loadFilters(tempFile, function() | |
| 221 { | |
| 222 tempFile.remove(false); | |
| 223 equal(FilterStorage.subscriptions.length, 1, "Number of filter subscriptio ns"); | |
| 224 if (FilterStorage.subscriptions.length == 1) | |
| 225 { | |
| 226 let subscription = FilterStorage.subscriptions[0]; | |
| 227 equal(subscription.filters.length, 3, "Number of subscription filters"); | |
| 228 if (subscription.filters.length == 3) | |
| 229 { | |
| 230 equal(subscription.filters[0].text, "foo", "First filter"); | |
| 231 equal(subscription.filters[1].text, "[bar]", "Second filter"); | |
| 232 equal(subscription.filters[2].text, "foo#bar", "Third filter"); | |
| 233 } | |
| 234 } | |
| 235 start(); | |
| 236 }); | |
| 237 }); | |
| 238 | |
| 239 asyncTest("Saving without backups", function() | |
| 240 { | |
| 241 Prefs.patternsbackups = 0; | |
| 242 Prefs.patternsbackupinterval = 24; | |
| 243 | |
| 244 let tempFile = FileUtils.getFile("TmpD", ["temp_patterns.ini"]); | |
| 245 tempFile.createUnique(tempFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); | |
| 246 FilterStorage.__defineGetter__("sourceFile", () => tempFile.clone()); | |
| 247 | |
| 248 saveFilters(null, function() | |
| 249 { | |
| 250 saveFilters(null, function() | |
| 251 { | |
| 252 let backupFile = tempFile.clone(); | |
| 253 backupFile.leafName = backupFile.leafName.replace(/\.ini$/, "-backup1.in i"); | |
| 254 ok(!backupFile.exists(), "Backup shouldn't be created"); | |
| 255 start(); | |
| 256 }); | |
| 257 }); | |
| 258 }); | |
| 259 | |
| 260 asyncTest("Saving with backups", function() | |
| 261 { | |
| 262 Prefs.patternsbackups = 2; | |
| 263 Prefs.patternsbackupinterval = 24; | |
| 264 | |
| 265 let tempFile = FileUtils.getFile("TmpD", ["temp_patterns.ini"]); | |
| 266 tempFile.createUnique(tempFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE); | |
| 267 FilterStorage.__defineGetter__("sourceFile", () => tempFile.clone()); | |
| 268 | |
| 269 let backupFile = tempFile.clone(); | 250 let backupFile = tempFile.clone(); |
| 270 backupFile.leafName = backupFile.leafName.replace(/\.ini$/, "-backup1.ini"); | 251 backupFile.leafName = backupFile.leafName.replace(/\.ini$/, "-backup1.ini"); |
| 271 | 252 test.ok(!backupFile.exists(), "Backup shouldn't be created"); |
| 272 let backupFile2 = tempFile.clone(); | 253 }).catch(unexpectedError.bind(test)).then(() => test.done()); |
| 273 backupFile2.leafName = backupFile2.leafName.replace(/\.ini$/, "-backup2.ini" ); | 254 }; |
| 274 | 255 |
| 275 let backupFile3 = tempFile.clone(); | 256 exports.testSavingWithBackups = function(test) |
| 276 backupFile3.leafName = backupFile3.leafName.replace(/\.ini$/, "-backup3.ini" ); | 257 { |
| 277 | 258 Prefs.patternsbackups = 2; |
| 278 let oldModifiedTime; | 259 Prefs.patternsbackupinterval = 24; |
| 279 | 260 |
| 280 saveFilters(null, callback1); | 261 let tempFile = IO.resolveFilePath("temp_patterns.ini"); |
| 281 | 262 Object.defineProperty(FilterStorage, "sourceFile", {get: () => tempFile.clone( )}); |
| 282 function callback1() | 263 |
| 283 { | 264 let backupFile = tempFile.clone(); |
| 284 // Save again immediately | 265 backupFile.leafName = backupFile.leafName.replace(/\.ini$/, "-backup1.ini"); |
| 285 saveFilters(null, callback2); | 266 |
| 286 } | 267 let backupFile2 = tempFile.clone(); |
| 287 | 268 backupFile2.leafName = backupFile2.leafName.replace(/\.ini$/, "-backup2.ini"); |
| 288 function callback2() | 269 |
| 289 { | 270 let backupFile3 = tempFile.clone(); |
| 290 backupFile = backupFile.clone(); // File parameters are cached, clone to prevent this | 271 backupFile3.leafName = backupFile3.leafName.replace(/\.ini$/, "-backup3.ini"); |
| 291 ok(backupFile.exists(), "First backup created"); | 272 |
| 292 | 273 let oldModifiedTime; |
| 293 backupFile.lastModifiedTime -= 10000; | 274 |
| 294 oldModifiedTime = backupFile.lastModifiedTime; | 275 saveFilters(null).then(() => |
| 295 saveFilters(null, callback3); | 276 { |
| 296 } | 277 // Save again immediately |
| 297 | 278 return saveFilters(null); |
| 298 function callback3() | 279 }).then(() => |
| 299 { | 280 { |
| 300 backupFile = backupFile.clone(); // File parameters are cached, clone to prevent this | 281 test.ok(backupFile.exists(), "First backup created"); |
| 301 equal(backupFile.lastModifiedTime, oldModifiedTime, "Backup not overwritte n if it is only 10 seconds old"); | 282 |
| 302 | 283 backupFile.lastModifiedTime -= 10000; |
| 303 backupFile.lastModifiedTime -= 40*60*60*1000; | 284 oldModifiedTime = backupFile.lastModifiedTime; |
| 304 oldModifiedTime = backupFile.lastModifiedTime; | 285 return saveFilters(null); |
| 305 saveFilters(null, callback4); | 286 }).then(() => |
| 306 } | 287 { |
| 307 | 288 test.equal(backupFile.lastModifiedTime, oldModifiedTime, "Backup not overwri tten if it is only 10 seconds old"); |
| 308 function callback4() | 289 |
| 309 { | 290 backupFile.lastModifiedTime -= 40*60*60*1000; |
| 310 backupFile = backupFile.clone(); // File parameters are cached, clone to prevent this | 291 oldModifiedTime = backupFile.lastModifiedTime; |
| 311 notEqual(backupFile.lastModifiedTime, oldModifiedTime, "Backup overwritten if it is 40 hours old"); | 292 return saveFilters(null); |
| 312 | 293 }).then(() => |
| 313 backupFile2 = backupFile2.clone(); // File parameters are cached, clone t o prevent this | 294 { |
| 314 ok(backupFile2.exists(), "Second backup created when first backup is overw ritten"); | 295 test.notEqual(backupFile.lastModifiedTime, oldModifiedTime, "Backup overwrit ten if it is 40 hours old"); |
| 315 | 296 |
| 316 backupFile.lastModifiedTime -= 20000; | 297 test.ok(backupFile2.exists(), "Second backup created when first backup is ov erwritten"); |
| 317 oldModifiedTime = backupFile2.lastModifiedTime; | 298 |
| 318 saveFilters(null, callback5); | 299 backupFile.lastModifiedTime -= 20000; |
| 319 } | 300 oldModifiedTime = backupFile2.lastModifiedTime; |
| 320 | 301 return saveFilters(null); |
| 321 function callback5() | 302 }).then(() => |
| 322 { | 303 { |
| 323 backupFile2 = backupFile2.clone(); // File parameters are cached, clone t o prevent this | 304 test.equal(backupFile2.lastModifiedTime, oldModifiedTime, "Second backup not overwritten if first one is only 20 seconds old"); |
| 324 equal(backupFile2.lastModifiedTime, oldModifiedTime, "Second backup not ov erwritten if first one is only 20 seconds old"); | 305 |
| 325 | 306 backupFile.lastModifiedTime -= 25*60*60*1000; |
| 326 backupFile.lastModifiedTime -= 25*60*60*1000; | 307 oldModifiedTime = backupFile2.lastModifiedTime; |
| 327 oldModifiedTime = backupFile2.lastModifiedTime; | 308 return saveFilters(null); |
| 328 saveFilters(null, callback6); | 309 }).then(() => |
| 329 } | 310 { |
| 330 | 311 test.notEqual(backupFile2.lastModifiedTime, oldModifiedTime, "Second backup overwritten if first one is 25 hours old"); |
| 331 function callback6() | 312 |
| 332 { | 313 test.ok(!backupFile3.exists(), "Third backup not created with patternsbackup s = 2"); |
| 333 backupFile2 = backupFile2.clone(); // File parameters are cached, clone t o prevent this | 314 }).catch(unexpectedError.bind(test)).then(() => test.done()); |
| 334 notEqual(backupFile2.lastModifiedTime, oldModifiedTime, "Second backup ove rwritten if first one is 25 hours old"); | 315 }; |
| 335 | |
| 336 ok(!backupFile3.exists(), "Third backup not created with patternsbackups = 2"); | |
| 337 | |
| 338 try | |
| 339 { | |
| 340 tempFile.remove(false); | |
| 341 } catch (e) {} | |
| 342 try | |
| 343 { | |
| 344 backupFile.remove(false); | |
| 345 } catch (e) {} | |
| 346 try | |
| 347 { | |
| 348 backupFile2.remove(false); | |
| 349 } catch (e) {} | |
| 350 try | |
| 351 { | |
| 352 backupFile3.remove(false); | |
| 353 } catch (e) {} | |
| 354 | |
| 355 start(); | |
| 356 } | |
| 357 }); | |
| 358 })(); | |
| OLD | NEW |