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 let Filter = require("filterClasses").Filter; | 20 let Filter = require("filterClasses").Filter; |
21 let ContentBlockerList = require("../lib/abp2blocklist.js").ContentBlockerList; | 21 let ContentBlockerList = require("../lib/abp2blocklist.js").ContentBlockerList; |
22 | 22 |
23 function testRules(test, filters, expected, transformFunction) | 23 function runTest(test, assertions) |
24 { | 24 { |
25 let blockerList = new ContentBlockerList(); | 25 // All the assertions are run in parallel but we wait for all of them to |
| 26 // finish before moving on to the next test. |
| 27 test.expect(assertions.length); |
| 28 Promise.all(assertions).then(() => test.done()); |
| 29 } |
| 30 |
| 31 function testRules(test, filters, expected, transformFunction, options) |
| 32 { |
| 33 let blockerList = new ContentBlockerList(options); |
26 for (let filter of filters) | 34 for (let filter of filters) |
27 blockerList.addFilter(Filter.fromText(filter)); | 35 blockerList.addFilter(Filter.fromText(filter)); |
28 | 36 |
29 let rules = blockerList.generateRules(); | 37 return blockerList.generateRules().then(rules => |
30 if (transformFunction) | 38 { |
31 rules = transformFunction(rules); | 39 if (transformFunction) |
32 | 40 rules = transformFunction(rules); |
33 test.deepEqual(rules, expected); | 41 |
| 42 test.deepEqual(rules, expected); |
| 43 }); |
34 } | 44 } |
35 | 45 |
36 exports.generateRules = { | 46 exports.generateRules = { |
37 testElementHiding: function(test) | 47 testElementHiding: function(test) |
38 { | 48 { |
39 testRules(test, ["##.whatever"], [ | 49 runTest(test, [ |
40 {trigger: {"url-filter": "^https?://", | 50 testRules(test, ["##.whatever"], [ |
41 "url-filter-is-case-sensitive": true}, | 51 {trigger: {"url-filter": "^https?://", |
42 action: {type: "css-display-none", selector: ".whatever"}} | 52 "url-filter-is-case-sensitive": true}, |
43 ]); | 53 action: {type: "css-display-none", selector: ".whatever"}} |
44 testRules(test, ["test.com##.whatever"], [ | 54 ]), |
45 {trigger: {"url-filter": "^https?://([^/:]*\\.)?test\\.com[/:]", | 55 testRules(test, ["test.com##.whatever"], [ |
46 "url-filter-is-case-sensitive": true}, | 56 {trigger: {"url-filter": "^https?://([^/:]*\\.)?test\\.com[/:]", |
47 action: {type: "css-display-none", selector: ".whatever"}} | 57 "url-filter-is-case-sensitive": true}, |
48 ]); | 58 action: {type: "css-display-none", selector: ".whatever"}} |
49 | 59 ]) |
50 test.done(); | 60 ]); |
51 }, | 61 }, |
52 | 62 |
53 testElementHidingExceptions: function(test) | 63 testElementHidingExceptions: function(test) |
54 { | 64 { |
55 testRules(test, [ | 65 runTest(test, [ |
56 "##.whatever", | 66 testRules(test, [ |
57 "test.com###something", | 67 "##.whatever", |
58 "@@||special.test.com^$elemhide", | 68 "test.com###something", |
59 "@@||test.com^$generichide", | 69 "@@||special.test.com^$elemhide", |
60 "@@^something^$elemhide", | 70 "@@||test.com^$generichide", |
61 "@@^anything^$generichide" | 71 "@@^something^$elemhide", |
62 ], [ | 72 "@@^anything^$generichide" |
63 ["^https?://", ["*test.com", "*special.test.com"]], | 73 ], [ |
64 ["^https?://([^/:]*\\.)?test\\.com[/:]", ["*special.test.com"]] | 74 ["^https?://", ["*test.com", "*special.test.com"]], |
65 ], rules => rules.map(rule => [rule.trigger["url-filter"], | 75 ["^https?://([^/:]*\\.)?test\\.com[/:]", ["*special.test.com"]] |
66 rule.trigger["unless-domain"]])); | 76 ], rules => rules.map(rule => [rule.trigger["url-filter"], |
67 | 77 rule.trigger["unless-domain"]])), |
68 testRules(test, ["#@#whatever"], []); | 78 |
69 testRules(test, ["test.com#@#whatever"], []); | 79 testRules(test, ["#@#whatever"], []), |
70 testRules(test, ["~test.com#@#whatever"], []); | 80 testRules(test, ["test.com#@#whatever"], []), |
71 | 81 testRules(test, ["~test.com#@#whatever"], []), |
72 // We currently completely ignore any element hiding filters that have the | 82 |
73 // same selector as an element hiding exception. In these examples #whatever | 83 // We currently completely ignore any element hiding filters that have the |
74 // should be hidden for all domains not ending in test.com instead of | 84 // same selector as an element hiding exception. In these examples |
75 // nowhere! | 85 // #whatever should be hidden for all domains not ending in test.com |
76 testRules(test, ["test.com#@#whatever", "##whatever"], []); | 86 // instead of nowhere! |
77 testRules(test, ["~test.com##whatever"], []); | 87 testRules(test, ["test.com#@#whatever", "##whatever"], []), |
78 | 88 testRules(test, ["~test.com##whatever"], []) |
79 test.done(); | 89 ]); |
80 }, | 90 }, |
81 | 91 |
82 testRequestFilters: function(test) | 92 testRequestFilters: function(test) |
83 { | 93 { |
84 testRules(test, [ | 94 runTest(test, [ |
85 "/foo", "||test.com^", "http://example.com/foo", "^foo^" | 95 testRules(test, [ |
86 ], [ | 96 "/foo", "||test.com^", "http://example.com/foo", "^foo^" |
87 { | 97 ], [ |
88 trigger: { | 98 { |
89 "url-filter": "^[^:]+:(//)?.*/foo", | 99 trigger: { |
90 "resource-type": ["image", "style-sheet", "script", "font", | 100 "url-filter": "^[^:]+:(//)?.*/foo", |
91 "media", "raw"] | 101 "resource-type": ["image", "style-sheet", "script", "font", |
| 102 "media", "raw"] |
| 103 }, |
| 104 action: {type: "block"} |
92 }, | 105 }, |
93 action: {type: "block"} | 106 { |
94 }, | 107 trigger: { |
95 { | 108 "url-filter": |
96 trigger: { | 109 "^[^:]+:(//)?([^/]+\\.)?test\\.com([^-_.%a-z0-9].*)?$", |
97 "url-filter": "^[^:]+:(//)?([^/]+\\.)?test\\.com([^-_.%a-z0-9].*)?$", | 110 "url-filter-is-case-sensitive": true, |
98 "url-filter-is-case-sensitive": true, | 111 "resource-type": ["image", "style-sheet", "script", "font", |
99 "resource-type": ["image", "style-sheet", "script", "font", | 112 "media", "raw", "document"], |
100 "media", "raw", "document"], | 113 "unless-top-url": [ |
101 "unless-top-url": [ | 114 "^[^:]+:(//)?([^/]+\\.)?test\\.com([^-_.%a-z0-9].*)?$" |
102 "^[^:]+:(//)?([^/]+\\.)?test\\.com([^-_.%a-z0-9].*)?$" | 115 ], |
103 ], | 116 "top-url-filter-is-case-sensitive": true |
104 "top-url-filter-is-case-sensitive": true | 117 }, |
| 118 action: {type: "block"} |
105 }, | 119 }, |
106 action: {type: "block"} | 120 { |
107 }, | 121 trigger: { |
108 { | 122 "url-filter": "^http://example\\.com/foo", |
109 trigger: { | 123 "resource-type": ["image", "style-sheet", "script", "font", |
110 "url-filter": "^http://example\\.com/foo", | 124 "media", "raw", "document"], |
111 "resource-type": ["image", "style-sheet", "script", "font", | 125 "unless-top-url": ["^http://example\\.com/foo"] |
112 "media", "raw", "document"], | 126 }, |
113 "unless-top-url": ["^http://example\\.com/foo"] | 127 action: {type: "block"} |
114 }, | 128 }, |
115 action: {type: "block"} | 129 { |
116 }, | 130 trigger: { |
117 { | 131 "url-filter": "^[^:]+:(//)?.*http://example\\.com/foo", |
118 trigger: { | 132 "resource-type": ["image", "style-sheet", "script", "font", |
119 "url-filter": "^[^:]+:(//)?.*http://example\\.com/foo", | 133 "media", "raw", "document"], |
120 "resource-type": ["image", "style-sheet", "script", "font", | 134 "unless-top-url": ["^[^:]+:(//)?.*http://example\\.com/foo"] |
121 "media", "raw", "document"], | 135 }, |
122 "unless-top-url": ["^[^:]+:(//)?.*http://example\\.com/foo"] | 136 action: {type: "block"} |
123 }, | 137 }, |
124 action: {type: "block"} | 138 { |
125 }, | 139 trigger: { |
126 { | 140 "url-filter": |
127 trigger: { | 141 "^[^:]+:(//)?(.*[^-_.%A-Za-z0-9])?foo([^-_.%A-Za-z0-9].*)?$", |
128 "url-filter": | 142 "resource-type": ["image", "style-sheet", "script", "font", |
129 "^[^:]+:(//)?(.*[^-_.%A-Za-z0-9])?foo([^-_.%A-Za-z0-9].*)?$", | 143 "media", "raw"] |
130 "resource-type": ["image", "style-sheet", "script", "font", | 144 }, |
131 "media", "raw"] | 145 action: {type: "block"} |
| 146 } |
| 147 ]), |
| 148 |
| 149 testRules(test, ["||example.com"], [ |
| 150 {trigger: {"url-filter": "^[^:]+:(//)?([^/]+\\.)?example\\.com", |
| 151 "url-filter-is-case-sensitive": true, |
| 152 "resource-type": ["image", "style-sheet", "script", "font", |
| 153 "media", "raw", "document"], |
| 154 "unless-top-url": ["^[^:]+:(//)?([^/]+\\.)?example\\.com"], |
| 155 "top-url-filter-is-case-sensitive": true}, |
| 156 |
| 157 action: {type: "block"}} |
| 158 ]), |
| 159 |
| 160 // Rules which would match no resource-types shouldn't be generated. |
| 161 testRules(test, ["foo$document", "||foo.com$document"], []) |
| 162 ]); |
| 163 }, |
| 164 |
| 165 testRequestFilterExceptions: function(test) |
| 166 { |
| 167 runTest(test, [ |
| 168 testRules(test, ["@@example.com"], [ |
| 169 {trigger: {"url-filter": "^[^:]+:(//)?.*example\\.com", |
| 170 "resource-type": ["image", "style-sheet", "script", "font", |
| 171 "media", "raw", "document"]}, |
| 172 action: {type: "ignore-previous-rules"}} |
| 173 ]), |
| 174 |
| 175 testRules(test, ["@@||example.com"], [ |
| 176 {trigger: {"url-filter": "^[^:]+:(//)?([^/]+\\.)?example\\.com", |
| 177 "url-filter-is-case-sensitive": true, |
| 178 "resource-type": ["image", "style-sheet", "script", "font", |
| 179 "media", "raw", "document"]}, |
| 180 action: {type: "ignore-previous-rules"}} |
| 181 ]) |
| 182 ]); |
| 183 }, |
| 184 |
| 185 testElementIDattributeFormat: function(test) |
| 186 { |
| 187 runTest(test, [ |
| 188 testRules(test, |
| 189 ["###example", "test.com###EXAMPLE"], |
| 190 ["[id=example]", "[id=EXAMPLE]"], |
| 191 rules => rules.map(rule => rule.action.selector)) |
| 192 ]); |
| 193 }, |
| 194 |
| 195 testDomainWhitelisting: function(test) |
| 196 { |
| 197 runTest(test, [ |
| 198 testRules(test, ["@@||example.com^$document"], [ |
| 199 { |
| 200 trigger: { |
| 201 "url-filter": ".*", |
| 202 "if-domain": ["*example.com"] |
| 203 }, |
| 204 action: {type: "ignore-previous-rules"} |
| 205 } |
| 206 ]), |
| 207 testRules(test, ["@@||example.com^$document,image"], [ |
| 208 { |
| 209 trigger: { |
| 210 "url-filter": ".*", |
| 211 "if-domain": ["*example.com"] |
| 212 }, |
| 213 action: {type: "ignore-previous-rules"} |
132 }, | 214 }, |
133 action: {type: "block"} | 215 { |
134 } | 216 trigger: { |
135 ]); | 217 "url-filter": |
136 | 218 "^https?://([^/]+\\.)?example\\.com([^-_.%a-z0-9].*)?$", |
137 testRules(test, ["||example.com"], [ | 219 "url-filter-is-case-sensitive": true, |
138 {trigger: {"url-filter": "^[^:]+:(//)?([^/]+\\.)?example\\.com", | 220 "resource-type": ["image"] |
139 "url-filter-is-case-sensitive": true, | 221 }, |
140 "resource-type": ["image", "style-sheet", "script", "font", | 222 action: {type: "ignore-previous-rules"} |
141 "media", "raw", "document"], | 223 } |
142 "unless-top-url": ["^[^:]+:(//)?([^/]+\\.)?example\\.com"], | 224 ]), |
143 "top-url-filter-is-case-sensitive": true}, | 225 testRules(test, ["@@||example.com/path^$font,document"], [ |
144 | 226 { |
145 action: {type: "block"}} | 227 trigger: { |
146 ]); | 228 "url-filter": |
147 | 229 "^https?://([^/]+\\.)?example\\.com/path([^-_.%A-Za-z0-9].*)?$", |
148 // Rules which would match no resource-types shouldn't be generated. | 230 "resource-type": ["font"] |
149 testRules(test, ["foo$document", "||foo.com$document"], []); | 231 }, |
150 | 232 action: {type: "ignore-previous-rules"} |
151 test.done(); | 233 } |
152 }, | 234 ]) |
153 | 235 ]); |
154 testRequestFilterExceptions: function(test) | |
155 { | |
156 testRules(test, ["@@example.com"], [ | |
157 {trigger: {"url-filter": "^[^:]+:(//)?.*example\\.com", | |
158 "resource-type": ["image", "style-sheet", "script", "font", | |
159 "media", "raw", "document"]}, | |
160 action: {type: "ignore-previous-rules"}} | |
161 ]); | |
162 | |
163 testRules(test, ["@@||example.com"], [ | |
164 {trigger: {"url-filter": "^[^:]+:(//)?([^/]+\\.)?example\\.com", | |
165 "url-filter-is-case-sensitive": true, | |
166 "resource-type": ["image", "style-sheet", "script", "font", | |
167 "media", "raw", "document"]}, | |
168 action: {type: "ignore-previous-rules"}} | |
169 ]); | |
170 | |
171 test.done(); | |
172 }, | |
173 | |
174 testElementIDattributeFormat: function(test) | |
175 { | |
176 testRules(test, | |
177 ["###example", "test.com###EXAMPLE"], | |
178 ["[id=example]", "[id=EXAMPLE]"], | |
179 rules => rules.map(rule => rule.action.selector)); | |
180 | |
181 test.done(); | |
182 }, | |
183 | |
184 testDomainWhitelisting: function(test) | |
185 { | |
186 testRules(test, ["@@||example.com^$document"], [ | |
187 { | |
188 trigger: { | |
189 "url-filter": ".*", | |
190 "if-domain": ["*example.com"] | |
191 }, | |
192 action: {type: "ignore-previous-rules"} | |
193 } | |
194 ]); | |
195 testRules(test, ["@@||example.com^$document,image"], [ | |
196 { | |
197 trigger: { | |
198 "url-filter": ".*", | |
199 "if-domain": ["*example.com"] | |
200 }, | |
201 action: {type: "ignore-previous-rules"} | |
202 }, | |
203 { | |
204 trigger: { | |
205 "url-filter": "^https?://([^/]+\\.)?example\\.com([^-_.%a-z0-9].*)?$", | |
206 "url-filter-is-case-sensitive": true, | |
207 "resource-type": ["image"] | |
208 }, | |
209 action: {type: "ignore-previous-rules"} | |
210 } | |
211 ]); | |
212 testRules(test, ["@@||example.com/path^$font,document"], [ | |
213 { | |
214 trigger: { | |
215 "url-filter": | |
216 "^https?://([^/]+\\.)?example\\.com/path([^-_.%A-Za-z0-9].*)?$", | |
217 "resource-type": ["font"] | |
218 }, | |
219 action: {type: "ignore-previous-rules"} | |
220 } | |
221 ]); | |
222 | |
223 test.done(); | |
224 }, | 236 }, |
225 | 237 |
226 testGenericblockExceptions: function(test) | 238 testGenericblockExceptions: function(test) |
227 { | 239 { |
228 testRules(test, ["^ad.jpg|", "@@||example.com^$genericblock"], | 240 runTest(test, [ |
229 [[undefined, ["*example.com"]]], | 241 testRules(test, ["^ad.jpg|", "@@||example.com^$genericblock"], |
230 rules => rules.map(rule => [rule.trigger["if-domain"], | 242 [[undefined, ["*example.com"]]], |
231 rule.trigger["unless-domain"]])); | 243 rules => rules.map(rule => [rule.trigger["if-domain"], |
232 testRules(test, ["^ad.jpg|$domain=test.com", | 244 rule.trigger["unless-domain"]])), |
233 "@@||example.com^$genericblock"], | 245 testRules(test, ["^ad.jpg|$domain=test.com", |
234 [[["*test.com"], undefined]], | 246 "@@||example.com^$genericblock"], |
235 rules => rules.map(rule => [rule.trigger["if-domain"], | 247 [[["*test.com"], undefined]], |
236 rule.trigger["unless-domain"]])); | 248 rules => rules.map(rule => [rule.trigger["if-domain"], |
237 testRules(test, ["^ad.jpg|$domain=~test.com", | 249 rule.trigger["unless-domain"]])), |
238 "@@||example.com^$genericblock"], | 250 testRules(test, ["^ad.jpg|$domain=~test.com", |
239 [[undefined, ["*test.com", "*example.com"]]], | 251 "@@||example.com^$genericblock"], |
240 rules => rules.map(rule => [rule.trigger["if-domain"], | 252 [[undefined, ["*test.com", "*example.com"]]], |
241 rule.trigger["unless-domain"]])); | 253 rules => rules.map(rule => [rule.trigger["if-domain"], |
242 | 254 rule.trigger["unless-domain"]])) |
243 test.done(); | 255 ]); |
244 }, | 256 }, |
245 | 257 |
246 testRuleOrdering: function(test) | 258 testRuleOrdering: function(test) |
247 { | 259 { |
248 testRules( | 260 runTest(test, [ |
249 test, | 261 testRules( |
250 ["/ads.jpg", "@@example.com", "test.com#@#foo", "##bar"], | 262 test, |
251 ["css-display-none", "block", "ignore-previous-rules"], | 263 ["/ads.jpg", "@@example.com", "test.com#@#foo", "##bar"], |
252 rules => rules.map(rule => rule.action.type) | 264 ["css-display-none", "block", "ignore-previous-rules"], |
253 ); | 265 rules => rules.map(rule => rule.action.type) |
254 testRules( | 266 ), |
255 test, | 267 testRules( |
256 ["@@example.com", "##bar", "/ads.jpg", "test.com#@#foo"], | 268 test, |
257 ["css-display-none", "block", "ignore-previous-rules"], | 269 ["@@example.com", "##bar", "/ads.jpg", "test.com#@#foo"], |
258 rules => rules.map(rule => rule.action.type) | 270 ["css-display-none", "block", "ignore-previous-rules"], |
259 ); | 271 rules => rules.map(rule => rule.action.type) |
260 | 272 ) |
261 test.done(); | 273 ]); |
262 }, | 274 }, |
263 | 275 |
264 testRequestTypeMapping: function(test) | 276 testRequestTypeMapping: function(test) |
265 { | 277 { |
266 testRules( | 278 runTest(test, [ |
267 test, | 279 testRules( |
268 ["1", "2$image", "3$stylesheet", "4$script", "5$font", "6$media", | 280 test, |
269 "7$popup", "8$object", "9$object_subrequest", "10$xmlhttprequest", | 281 ["1", "2$image", "3$stylesheet", "4$script", "5$font", "6$media", |
270 "11$websocket", "12$webrtc", | 282 "7$popup", "8$object", "9$object_subrequest", "10$xmlhttprequest", |
271 "13$ping", "14$subdocument", "15$other", "16$IMAGE", | 283 "11$websocket", "12$webrtc", |
272 "17$script,PING,Popup", "18$~image"], | 284 "13$ping", "14$subdocument", "15$other", "16$IMAGE", |
273 [["image", "style-sheet", "script", "font", "media", "raw"], | 285 "17$script,PING,Popup", "18$~image"], |
274 ["image"], | 286 [["image", "style-sheet", "script", "font", "media", "raw"], |
275 ["style-sheet"], | 287 ["image"], |
276 ["script"], | 288 ["style-sheet"], |
277 ["font"], | 289 ["script"], |
278 ["media"], | 290 ["font"], |
279 ["popup"], | 291 ["media"], |
280 ["media"], | 292 ["popup"], |
281 ["raw"], | 293 ["media"], |
282 ["raw"], | 294 ["raw"], |
283 ["raw"], // WebSocket | 295 ["raw"], |
284 ["raw"], // WebRTC: STUN | 296 ["raw"], // WebSocket |
285 ["raw"], // WebRTC: TURN | 297 ["raw"], // WebRTC: STUN |
286 ["raw"], | 298 ["raw"], // WebRTC: TURN |
287 ["raw"], | 299 ["raw"], |
288 ["image"], | 300 ["raw"], |
289 ["script", "popup", "raw" ], | 301 ["image"], |
290 ["style-sheet", "script", "font", "media", "raw"]], | 302 ["script", "popup", "raw" ], |
291 rules => rules.map(rule => rule.trigger["resource-type"]) | 303 ["style-sheet", "script", "font", "media", "raw"]], |
292 ); | 304 rules => rules.map(rule => rule.trigger["resource-type"]) |
293 | 305 ) |
294 test.done(); | 306 ]); |
295 }, | 307 }, |
296 | 308 |
297 testUnsupportedfilters: function(test) | 309 testUnsupportedfilters: function(test) |
298 { | 310 { |
299 // These types of filters are currently completely unsupported. | 311 runTest(test, [ |
300 testRules(test, ["foo$sitekey=bar"], []); | 312 // These types of filters are currently completely unsupported. |
301 | 313 testRules(test, ["foo$sitekey=bar"], []) |
302 test.done(); | 314 ]); |
303 }, | 315 }, |
304 | 316 |
305 testFilterOptions: function(test) | 317 testFilterOptions: function(test) |
306 { | 318 { |
307 testRules(test, ["1$domain=foo.com"], ["*foo.com"], | 319 runTest(test, [ |
308 rules => rules[0]["trigger"]["if-domain"]); | 320 testRules(test, ["1$domain=foo.com"], ["*foo.com"], |
309 testRules(test, ["2$third-party"], ["third-party"], | 321 rules => rules[0]["trigger"]["if-domain"]), |
310 rules => rules[0]["trigger"]["load-type"]); | 322 testRules(test, ["2$third-party"], ["third-party"], |
311 testRules(test, ["foo$match_case"], true, | 323 rules => rules[0]["trigger"]["load-type"]), |
312 rules => rules[0]["trigger"]["url-filter-is-case-sensitive"]); | 324 testRules(test, ["foo$match_case"], true, |
313 | 325 rules => rules[0]["trigger"]["url-filter-is-case-sensitive"]), |
314 // Test subdomain exceptions. | 326 |
315 testRules(test, ["1$domain=foo.com|~bar.foo.com"], | 327 // Test subdomain exceptions. |
316 ["foo.com", "www.foo.com"], | 328 testRules(test, ["1$domain=foo.com|~bar.foo.com"], |
317 rules => rules[0]["trigger"]["if-domain"]); | 329 ["foo.com", "www.foo.com"], |
318 testRules(test, ["1$domain=foo.com|~www.foo.com"], | 330 rules => rules[0]["trigger"]["if-domain"]), |
319 ["foo.com"], | 331 testRules(test, ["1$domain=foo.com|~www.foo.com"], |
320 rules => rules[0]["trigger"]["if-domain"]); | 332 ["foo.com"], |
321 | 333 rules => rules[0]["trigger"]["if-domain"]) |
322 test.done(); | 334 ]); |
323 }, | 335 }, |
324 | 336 |
325 testUnicode: function(test) | 337 testUnicode: function(test) |
326 { | 338 { |
327 testRules(test, ["$domain=🐈.cat"], ["*xn--zn8h.cat"], | 339 runTest(test, [ |
328 rules => rules[0]["trigger"]["if-domain"]); | 340 testRules(test, ["$domain=🐈.cat"], ["*xn--zn8h.cat"], |
329 testRules(test, ["||🐈"], "^[^:]+:(//)?([^/]+\\.)?xn--zn8h", | 341 rules => rules[0]["trigger"]["if-domain"]), |
330 rules => rules[0]["trigger"]["url-filter"]); | 342 testRules(test, ["||🐈"], "^[^:]+:(//)?([^/]+\\.)?xn--zn8h", |
331 testRules(test, ["🐈$domain=🐈.cat"], "^[^:]+:(//)?.*%F0%9F%90%88", | 343 rules => rules[0]["trigger"]["url-filter"]), |
332 rules => rules[0]["trigger"]["url-filter"]); | 344 testRules(test, ["🐈$domain=🐈.cat"], "^[^:]+:(//)?.*%F0%9F%90%88", |
333 testRules(test, ["🐈%F0%9F%90%88$domain=🐈.cat"], | 345 rules => rules[0]["trigger"]["url-filter"]), |
334 "^[^:]+:(//)?.*%F0%9F%90%88%F0%9F%90%88", | 346 testRules(test, ["🐈%F0%9F%90%88$domain=🐈.cat"], |
335 rules => rules[0]["trigger"]["url-filter"]); | 347 "^[^:]+:(//)?.*%F0%9F%90%88%F0%9F%90%88", |
336 testRules(test, ["###🐈"], "[id=🐈]", | 348 rules => rules[0]["trigger"]["url-filter"]), |
337 rules => rules[0]["action"]["selector"]); | 349 testRules(test, ["###🐈"], "[id=🐈]", |
338 | 350 rules => rules[0]["action"]["selector"]) |
339 test.done(); | 351 ]); |
340 }, | 352 }, |
341 | 353 |
342 testWebSocket: function(test) | 354 testWebSocket: function(test) |
343 { | 355 { |
344 testRules(test, ["foo$websocket"], [ | 356 runTest(test, [ |
345 {trigger: {"url-filter": "^wss?://.*foo", "resource-type": ["raw"]}, | 357 testRules(test, ["foo$websocket"], [ |
346 action: {type: "block"}} | 358 {trigger: {"url-filter": "^wss?://.*foo", "resource-type": ["raw"]}, |
347 ]); | 359 action: {type: "block"}} |
348 | 360 ]) |
349 test.done(); | 361 ]); |
350 }, | 362 }, |
351 | 363 |
352 testWebRTC: function(test) | 364 testWebRTC: function(test) |
353 { | 365 { |
354 testRules(test, ["foo$webrtc"], [ | 366 runTest(test, [ |
355 {trigger: {"url-filter": "^stuns?:.*foo", "resource-type": ["raw"]}, | 367 testRules(test, ["foo$webrtc"], [ |
356 action: {type: "block"}}, | 368 {trigger: {"url-filter": "^stuns?:.*foo", "resource-type": ["raw"]}, |
357 {trigger: {"url-filter": "^turns?:.*foo", "resource-type": ["raw"]}, | 369 action: {type: "block"}}, |
358 action: {type: "block"}} | 370 {trigger: {"url-filter": "^turns?:.*foo", "resource-type": ["raw"]}, |
359 ]); | 371 action: {type: "block"}} |
360 | 372 ]) |
361 test.done(); | 373 ]); |
| 374 }, |
| 375 |
| 376 testMerging: function(test) |
| 377 { |
| 378 runTest(test, [ |
| 379 // Single character substitutions, deletions, and insertions. |
| 380 testRules(test, ["/ads", "/adv"], ["^[^:]+:(//)?.*/ad[sv]"], |
| 381 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 382 {merge: "all"}), |
| 383 testRules(test, ["/ads", "/advs"], ["^[^:]+:(//)?.*/adv?s"], |
| 384 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 385 {merge: "all"}), |
| 386 testRules(test, ["/advs", "/ads"], ["^[^:]+:(//)?.*/adv?s"], |
| 387 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 388 {merge: "all"}), |
| 389 testRules(test, ["/adts", "/advs", "/ads"], ["^[^:]+:(//)?.*/ad[tv]?s"], |
| 390 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 391 {merge: "all"}), |
| 392 testRules(test, ["/ads", "/adts", "/advs"], ["^[^:]+:(//)?.*/ad[tv]?s"], |
| 393 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 394 {merge: "all"}), |
| 395 testRules(test, ["/adts", "/ads", "/advs"], ["^[^:]+:(//)?.*/ad[tv]?s"], |
| 396 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 397 {merge: "all"}), |
| 398 testRules(test, ["/ax", "/adx", "/adsx", "/advx"], |
| 399 ["^[^:]+:(//)?.*/ax", "^[^:]+:(//)?.*/ad[sv]?x"], |
| 400 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 401 {merge: "all"}), |
| 402 testRules(test, ["/adx", "/ax", "/adsx", "/advx"], |
| 403 ["^[^:]+:(//)?.*/ax", "^[^:]+:(//)?.*/ad[sv]?x"], |
| 404 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 405 {merge: "all"}), |
| 406 testRules(test, ["/adsx", "/advx", "/adx", "/ax"], |
| 407 ["^[^:]+:(//)?.*/ad[sv]?x", "^[^:]+:(//)?.*/ax"], |
| 408 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 409 {merge: "all"}), |
| 410 testRules(test, ["/adsx", "/advx", "/ax", "/adx"], |
| 411 ["^[^:]+:(//)?.*/ad[sv]?x", "^[^:]+:(//)?.*/ax"], |
| 412 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 413 {merge: "all"}), |
| 414 testRules(test, ["/ad-", "/a-", "/ads-", "/adv-", "/adx-"], |
| 415 ["^[^:]+:(//)?.*/a-", "^[^:]+:(//)?.*/ad[svx]?-"], |
| 416 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 417 {merge: "all"}), |
| 418 testRules(test, ["/ads-", "/a-", "/ad-", "/adv-", "/adx-"], |
| 419 ["^[^:]+:(//)?.*/ad[svx]?-", "^[^:]+:(//)?.*/a-"], |
| 420 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 421 {merge: "all"}), |
| 422 |
| 423 // Multiple character deletions and insertions. |
| 424 testRules(test, ["/ads", "/adxis"], |
| 425 ["^[^:]+:(//)?.*/ad(xi)?s"], |
| 426 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 427 {merge: "all"}), |
| 428 testRules(test, ["/adxsi", "/xsi"], |
| 429 ["^[^:]+:(//)?.*/(ad)?xsi"], |
| 430 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 431 {merge: "all"}), |
| 432 testRules(test, ["/adxsi", "/ai"], |
| 433 ["^[^:]+:(//)?.*/a(dxs)?i"], |
| 434 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 435 {merge: "all"}), |
| 436 |
| 437 // Both single and multiple character edits combined. |
| 438 testRules(test, ["/adq", "/adxsiq", "/xsiq", "/axsiq", "/bxsiq"], |
| 439 ["^[^:]+:(//)?.*/ad(xsi)?q", "^[^:]+:(//)?.*/[ab]?xsiq"], |
| 440 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 441 {merge: "all"}), |
| 442 |
| 443 testRules(test, ["/adsq", "/aq", "/adq", "/advq", "/adxq", "/adxsq"], |
| 444 ["^[^:]+:(//)?.*/ad[svx]?q", "^[^:]+:(//)?.*/a(dxs)?q"], |
| 445 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 446 {merge: "all"}), |
| 447 testRules(test, ["/adxsq", "/aq", "/adq", "/adsq", "/advq", "/adxq"], |
| 448 ["^[^:]+:(//)?.*/a(dxs)?q", "^[^:]+:(//)?.*/ad[svx]?q"], |
| 449 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 450 {merge: "all"}), |
| 451 testRules(test, ["/adxsq", "/aq", "/adsq", "/adq", "/advq", "/adxq"], |
| 452 ["^[^:]+:(//)?.*/a(dxs)?q", "^[^:]+:(//)?.*/ad[svx]?q"], |
| 453 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 454 {merge: "all"}), |
| 455 testRules(test, ["/adxsq", "/aq", "/adsq", "/advq", "/adq", "/adxq"], |
| 456 ["^[^:]+:(//)?.*/a(dxs)?q", "^[^:]+:(//)?.*/ad[svx]?q"], |
| 457 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 458 {merge: "all"}), |
| 459 testRules(test, ["/adsxiq", "/adxsq", "/aq", "/adsq", "/advq", "/adq", |
| 460 "/adxq"], |
| 461 ["^[^:]+:(//)?.*/a(dsxi)?q", "^[^:]+:(//)?.*/adxsq", |
| 462 "^[^:]+:(//)?.*/ad[svx]?q"], |
| 463 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 464 {merge: "all"}), |
| 465 testRules(test, ["/adxsiq", "/adsxiq", "/adxsq", "/aq", "/adsq", "/advq", |
| 466 "/adq", "/adxq"], |
| 467 ["^[^:]+:(//)?.*/adxsi?q", "^[^:]+:(//)?.*/a(dsxi)?q", |
| 468 "^[^:]+:(//)?.*/ad[svx]?q"], |
| 469 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 470 {merge: "all"}), |
| 471 |
| 472 // Given the 6 rules "adsi", "bdsi", "advi", "bdvi", "adxi", and "bdxi", |
| 473 // we want the 2 rules "ad[svx]i" and "bd[svx]i", not the 3 rules |
| 474 // "[ab]dsi", "[ab]dvi", and "[ab]dxi" |
| 475 testRules(test, ["/adsi", "/bdsi", "/advi", "/bdvi", "/adxi", "/bdxi"], |
| 476 ["^[^:]+:(//)?.*/ad[svx]i", "^[^:]+:(//)?.*/bd[svx]i"], |
| 477 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 478 {merge: "all"}), |
| 479 testRules(test, ["/adsi", "/bdsi", "/advi", "/bdvi", "/bdxi"], |
| 480 ["^[^:]+:(//)?.*/ad[sv]i", "^[^:]+:(//)?.*/bd[svx]i"], |
| 481 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 482 {merge: "all"}), |
| 483 |
| 484 // Make sure there's no merge where there are special characters in the |
| 485 // delta. |
| 486 testRules(test, ["/ads?q", "/adsq"], |
| 487 ["^[^:]+:(//)?.*/ads\\?q", "^[^:]+:(//)?.*/adsq"], |
| 488 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 489 {merge: "all"}), |
| 490 testRules(test, ["/ads?", "/ads-"], |
| 491 ["^[^:]+:(//)?.*/ads\\?", "^[^:]+:(//)?.*/ads-"], |
| 492 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 493 {merge: "all"}), |
| 494 testRules(test, ["/ads?-", "/ads-"], |
| 495 ["^[^:]+:(//)?.*/ads\\?-", "^[^:]+:(//)?.*/ads-"], |
| 496 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 497 {merge: "all"}), |
| 498 |
| 499 // Redundant rules should be discarded. |
| 500 testRules(test, ["/ad", "/ads", "/advertisement"], |
| 501 ["^[^:]+:(//)?.*/ad"], |
| 502 rules => rules.map(rule => rule.trigger["url-filter"]), |
| 503 {merge: "all"}) |
| 504 ]); |
362 } | 505 } |
363 }; | 506 }; |
OLD | NEW |