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

Side by Side Diff: test/filterStorage_readwrite.js

Issue 29402576: Issue 5052 - Adjust filter storage unit tests for API changes (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore
Patch Set: Created April 4, 2017, 12:06 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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);
kzar 2017/04/05 04:00:15 Shouldn't dataFile be assigned inside the setUp fu
Wladimir Palant 2017/04/05 07:14:24 Isn't it? We are still inside setUp.
kzar 2017/04/05 10:08:58 Argh sorry, so it is.
45
46 FilterStorage.addFilter(Filter.fromText("foobar"));
Wladimir Palant 2017/04/04 12:11:16 Calling FilterStorage.addFilter() has essentially
kzar 2017/04/05 04:00:15 Acknowledged.
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)
Wladimir Palant 2017/04/04 12:11:16 This function was merely moved so that it can be u
kzar 2017/04/05 04:00:15 Acknowledged.
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");
Wladimir Palant 2017/04/04 12:11:16 Working with temporary files is no longer necessar
kzar 2017/04/05 04:00:15 Acknowledged.
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 let backupFile = dataFile.clone();
311 backupFile.leafName = backupFile.leafName.replace(/\.ini$/, "-backup1.ini");
Wladimir Palant 2017/04/04 12:11:16 This variable is unused - I already removed it loc
kzar 2017/04/05 04:00:15 If the variable's unused I don't mind it if you de
312
313 saveFilters().then(() =>
314 {
315 test.equal(FilterStorage.subscriptions.length, 1, "Initial subscription coun t");
316 FilterStorage.removeSubscription(FilterStorage.subscriptions[0]);
317 return saveFilters();
318 }).then(() =>
319 {
320 return loadFilters();
321 }).then(() =>
322 {
323 test.equal(FilterStorage.subscriptions.length, 0, "Subscription count after removing subscriptions and reloading");
324 return FilterStorage.restoreBackup(1);
325 }).then(() =>
326 {
327 test.equal(FilterStorage.subscriptions.length, 1, "Subscription count after restoring backup");
328 return loadFilters();
329 }).then(() =>
330 {
331 test.equal(FilterStorage.subscriptions.length, 1, "Subscription count after reloading");
332 }).catch(unexpectedError.bind(test)).then(() => test.done());
333 };
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld