Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: test/filterStorage_readwrite.js

Issue 29356024: Issue 4223 - Adapt filter storage read/write tests to work in adblockpluscore repository (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore
Patch Set: Created Oct. 5, 2016, 8:02 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
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 })();
OLDNEW
« README.md ('K') | « README.md ('k') | test/stub-modules/io.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld