| LEFT | RIGHT | 
|---|
|  | 1 /* | 
|  | 2  * This file is part of Adblock Plus <https://adblockplus.org/>, | 
|  | 3  * Copyright (C) 2006-2016 Eyeo GmbH | 
|  | 4  * | 
|  | 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 | 
|  | 7  * published by the Free Software Foundation. | 
|  | 8  * | 
|  | 9  * Adblock Plus is distributed in the hope that it will be useful, | 
|  | 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 12  * GNU General Public License for more details. | 
|  | 13  * | 
|  | 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/>. | 
|  | 16  */ | 
|  | 17 | 
| 1 "use strict"; | 18 "use strict"; | 
| 2 | 19 | 
| 3 let { | 20 let {createSandbox} = require("./_common"); | 
| 4   Filter, InvalidFilter, CommentFilter, RegExpFilter, WhitelistFilter, | 21 | 
| 5   ElemHideFilter, ElemHideException, CSSPropertyFilter | 22 let Filter = null; | 
| 6 } = require("../lib/filterClasses"); | 23 let InvalidFilter = null; | 
|  | 24 let CommentFilter = null; | 
|  | 25 let ActiveFilter = null; | 
|  | 26 let RegExpFilter = null; | 
|  | 27 let BlockingFilter = null; | 
|  | 28 let WhitelistFilter = null; | 
|  | 29 let ElemHideBase = null; | 
|  | 30 let ElemHideFilter = null; | 
|  | 31 let ElemHideException = null; | 
|  | 32 let CSSPropertyFilter = null; | 
|  | 33 | 
|  | 34 exports.setUp = function(callback) | 
|  | 35 { | 
|  | 36   let sandboxedRequire = createSandbox(); | 
|  | 37   ( | 
|  | 38     { | 
|  | 39       Filter, InvalidFilter, CommentFilter, ActiveFilter, RegExpFilter, | 
|  | 40       BlockingFilter, WhitelistFilter, ElemHideBase, ElemHideFilter, | 
|  | 41       ElemHideException, CSSPropertyFilter | 
|  | 42     } = sandboxedRequire("../lib/filterClassesNew") | 
|  | 43   ); | 
|  | 44   callback(); | 
|  | 45 }; | 
| 7 | 46 | 
| 8 exports.testFromText = function(test) | 47 exports.testFromText = function(test) | 
| 9 { | 48 { | 
| 10   let tests = [ | 49   let tests = [ | 
| 11     ["!asdf", CommentFilter, "comment"], | 50     ["!asdf", CommentFilter, "comment"], | 
| 12     ["asdf", RegExpFilter, "blocking"], | 51     ["asdf", BlockingFilter, "blocking"], | 
| 13     ["asdf$image,~collapse", RegExpFilter, "blocking"], | 52     ["asdf$image,~collapse", BlockingFilter, "blocking"], | 
| 14     ["/asdf/", RegExpFilter, "blocking"], | 53     ["/asdf/", BlockingFilter, "blocking"], | 
| 15     ["/asdf??+/", InvalidFilter, "invalid"], | 54     ["/asdf??+/", InvalidFilter, "invalid"], | 
| 16     ["@@asdf", WhitelistFilter, "whitelist"], | 55     ["@@asdf", WhitelistFilter, "whitelist"], | 
| 17     ["@@asdf$image,~collapse", WhitelistFilter, "whitelist"], | 56     ["@@asdf$image,~collapse", WhitelistFilter, "whitelist"], | 
| 18     ["@@/asdf/", WhitelistFilter, "whitelist"], | 57     ["@@/asdf/", WhitelistFilter, "whitelist"], | 
| 19     ["@@/asdf??+/", InvalidFilter, "invalid"], | 58     ["@@/asdf??+/", InvalidFilter, "invalid"], | 
| 20     ["##asdf", ElemHideFilter, "elemhide"], | 59     ["##asdf", ElemHideFilter, "elemhide"], | 
| 21     ["#@#asdf", ElemHideException, "elemhideexception"], | 60     ["#@#asdf", ElemHideException, "elemhideexception"], | 
| 22     ["foobar##asdf", ElemHideFilter, "elemhide"], | 61     ["foobar##asdf", ElemHideFilter, "elemhide"], | 
| 23     ["foobar#@#asdf", ElemHideException, "elemhideexception"], | 62     ["foobar#@#asdf", ElemHideException, "elemhideexception"], | 
| 24     ["foobar##a", ElemHideFilter, "elemhide"], | 63     ["foobar##a", ElemHideFilter, "elemhide"], | 
| 25     ["foobar#@#a", ElemHideException, "elemhideexception"], | 64     ["foobar#@#a", ElemHideException, "elemhideexception"], | 
| 26 | 65 | 
| 27     ["foobar#asdf", RegExpFilter, "blocking"], | 66     ["foobar#asdf", BlockingFilter, "blocking"], | 
| 28     ["foobar|foobas##asdf", RegExpFilter, "blocking"], | 67     ["foobar|foobas##asdf", BlockingFilter, "blocking"], | 
| 29     ["foobar##asdf{asdf}", RegExpFilter, "blocking"], | 68     ["foobar##asdf{asdf}", BlockingFilter, "blocking"], | 
| 30     ["foobar##", RegExpFilter, "blocking"], | 69     ["foobar##", BlockingFilter, "blocking"], | 
| 31     ["foobar#@#", RegExpFilter, "blocking"], | 70     ["foobar#@#", BlockingFilter, "blocking"], | 
| 32     ["asdf$foobar", InvalidFilter, "invalid"], | 71     ["asdf$foobar", InvalidFilter, "invalid"], | 
| 33     ["asdf$image,foobar", InvalidFilter, "invalid"], | 72     ["asdf$image,foobar", InvalidFilter, "invalid"], | 
| 34     ["asdf$image=foobar", RegExpFilter, "blocking"], | 73     ["asdf$image=foobar", BlockingFilter, "blocking"], | 
| 35     ["asdf$image=foobar=xyz,~collapse", RegExpFilter, "blocking"], | 74     ["asdf$image=foobar=xyz,~collapse", BlockingFilter, "blocking"], | 
| 36 | 75 | 
| 37     ["##foo[-abp-properties='something']bar", InvalidFilter, "invalid"], | 76     ["##foo[-abp-properties='something']bar", InvalidFilter, "invalid"], | 
| 38     ["#@#foo[-abp-properties='something']bar", ElemHideException, "elemhideexcep
     tion"], | 77     ["#@#foo[-abp-properties='something']bar", ElemHideException, "elemhideexcep
     tion"], | 
| 39     ["example.com##foo[-abp-properties='something']bar", CSSPropertyFilter, "css
     property"], | 78     ["example.com##foo[-abp-properties='something']bar", CSSPropertyFilter, "css
     property"], | 
| 40     ["example.com#@#foo[-abp-properties='something']bar", ElemHideException, "el
     emhideexception"], | 79     ["example.com#@#foo[-abp-properties='something']bar", ElemHideException, "el
     emhideexception"], | 
| 41     ["~example.com##foo[-abp-properties='something']bar", InvalidFilter, "invali
     d"], | 80     ["~example.com##foo[-abp-properties='something']bar", InvalidFilter, "invali
     d"], | 
| 42     ["~example.com#@#foo[-abp-properties='something']bar", ElemHideException, "e
     lemhideexception"], | 81     ["~example.com#@#foo[-abp-properties='something']bar", ElemHideException, "e
     lemhideexception"], | 
| 43     ["~example.com,~example.info##foo[-abp-properties='something']bar", InvalidF
     ilter, "invalid"], | 82     ["~example.com,~example.info##foo[-abp-properties='something']bar", InvalidF
     ilter, "invalid"], | 
| 44     ["~example.com,~example.info#@#foo[-abp-properties='something']bar", ElemHid
     eException, "elemhideexception"], | 83     ["~example.com,~example.info#@#foo[-abp-properties='something']bar", ElemHid
     eException, "elemhideexception"], | 
| 45     ["~sub.example.com,example.com##foo[-abp-properties='something']bar", CSSPro
     pertyFilter, "cssproperty"], | 84     ["~sub.example.com,example.com##foo[-abp-properties='something']bar", CSSPro
     pertyFilter, "cssproperty"], | 
| 46     ["~sub.example.com,example.com#@#foo[-abp-properties='something']bar", ElemH
     ideException, "elemhideexception"], | 85     ["~sub.example.com,example.com#@#foo[-abp-properties='something']bar", ElemH
     ideException, "elemhideexception"], | 
| 47     ["example.com,~sub.example.com##foo[-abp-properties='something']bar", CSSPro
     pertyFilter, "cssproperty"], | 86     ["example.com,~sub.example.com##foo[-abp-properties='something']bar", CSSPro
     pertyFilter, "cssproperty"], | 
| 48     ["example.com,~sub.example.com#@#foo[-abp-properties='something']bar", ElemH
     ideException, "elemhideexception"], | 87     ["example.com,~sub.example.com#@#foo[-abp-properties='something']bar", ElemH
     ideException, "elemhideexception"], | 
| 49     ["example.com##[-abp-properties='something']", CSSPropertyFilter, "cssproper
     ty"], | 88     ["example.com##[-abp-properties='something']", CSSPropertyFilter, "cssproper
     ty"], | 
| 50     ["example.com#@#[-abp-properties='something']", ElemHideException, "elemhide
     exception"], | 89     ["example.com#@#[-abp-properties='something']", ElemHideException, "elemhide
     exception"], | 
| 51     ["example.com##[-abp-properties=\"something\"]", CSSPropertyFilter, "cssprop
     erty"], | 90     ["example.com##[-abp-properties=\"something\"]", CSSPropertyFilter, "cssprop
     erty"], | 
| 52     ["example.com#@#[-abp-properties=\"something\"]", ElemHideException, "elemhi
     deexception"], | 91     ["example.com#@#[-abp-properties=\"something\"]", ElemHideException, "elemhi
     deexception"], | 
| 53     ["example.com##[-abp-properties=(something)]", ElemHideFilter, "elemhide"], | 92     ["example.com##[-abp-properties=(something)]", ElemHideFilter, "elemhide"], | 
| 54     ["example.com#@#[-abp-properties=(something)]", ElemHideException, "elemhide
     exception"], | 93     ["example.com#@#[-abp-properties=(something)]", ElemHideException, "elemhide
     exception"], | 
| 55   ]; | 94   ]; | 
| 56   for (let [text, type, typeName, location] of tests) | 95   for (let [text, type, typeName, location] of tests) | 
| 57   { | 96   { | 
| 58     let filter = Filter.fromText(text); | 97     let filter = Filter.fromText(text); | 
| 59     try | 98     test.ok(filter instanceof Filter, "Got filter for " + text); | 
| 60     { | 99     test.equal(filter.text, text, "Correct filter text for " + text); | 
| 61       test.ok(filter instanceof Filter, "Got filter for " + text); | 100     test.ok(filter instanceof type, "Correct filter type for " + text); | 
| 62       test.equal(filter.text, text, "Correct filter text for " + text); | 101     test.equal(filter.type, typeName, "Type name for " + text + " is " + typeNam
     e); | 
| 63       test.ok(filter instanceof type, "Correct filter type for " + text); | 102     if (type == InvalidFilter) | 
| 64       test.equal(filter.type, typeName, "Type name for " + text + " is " + typeN
     ame); | 103       test.ok(filter.reason, "Invalid filter " + text + " has a reason set"); | 
| 65       if (type == InvalidFilter) | 104     filter.delete(); | 
| 66         test.ok(filter.reason, "Invalid filter " + text + " has a reason set"); | 105   } | 
|  | 106   test.done(); | 
|  | 107 }; | 
|  | 108 | 
|  | 109 exports.testClassHierarchy = function(test) | 
|  | 110 { | 
|  | 111   let allClasses = ["Filter", "InvalidFilter", "CommentFilter", "ActiveFilter", | 
|  | 112     "RegExpFilter", "BlockingFilter", "WhitelistFilter", "ElemHideBase", | 
|  | 113     "ElemHideFilter", "ElemHideException", "CSSPropertyFilter"]; | 
|  | 114   let tests = [ | 
|  | 115     ["/asdf??+/", "Filter", "InvalidFilter"], | 
|  | 116     ["!asdf", "Filter", "CommentFilter"], | 
|  | 117     ["asdf", "Filter", "ActiveFilter", "RegExpFilter", "BlockingFilter"], | 
|  | 118     ["@@asdf", "Filter", "ActiveFilter", "RegExpFilter", "WhitelistFilter"], | 
|  | 119     ["##asdf", "Filter", "ActiveFilter", "ElemHideBase", "ElemHideFilter"], | 
|  | 120     ["#@#asdf", "Filter", "ActiveFilter", "ElemHideBase", "ElemHideException"], | 
|  | 121     ["example.com##[-abp-properties='something']", "Filter", "ActiveFilter", "El
     emHideBase", "CSSPropertyFilter"], | 
|  | 122   ]; | 
|  | 123 | 
|  | 124   for (let list of tests) | 
|  | 125   { | 
|  | 126     let filter = Filter.fromText(list.shift()); | 
|  | 127     for (let cls of list) | 
|  | 128     { | 
|  | 129       test.ok(filter instanceof eval(cls), | 
|  | 130           "Filter " + filter.text + " is an instance of " + cls); | 
| 67     } | 131     } | 
| 68     finally | 132 | 
| 69     { | 133     for (let cls of allClasses) | 
| 70       filter.delete(); | 134     { | 
|  | 135       if (list.indexOf(cls) < 0) | 
|  | 136       { | 
|  | 137         test.ok(!(filter instanceof eval(cls)), | 
|  | 138             "Filter " + filter.text + " isn't an instance of " + cls); | 
|  | 139       } | 
| 71     } | 140     } | 
| 72   } | 141     filter.delete(); | 
|  | 142   } | 
|  | 143 | 
|  | 144   test.done(); | 
|  | 145 }; | 
|  | 146 | 
|  | 147 exports.testGC = function(test) | 
|  | 148 { | 
|  | 149   let filter1 = Filter.fromText("someknownfilter"); | 
|  | 150   test.equal(filter1.hitCount, 0, "Initial hit count"); | 
|  | 151 | 
|  | 152   filter1.hitCount = 432; | 
|  | 153 | 
|  | 154   let filter2 = Filter.fromText("someknownfilter"); | 
|  | 155   test.equal(filter2.hitCount, 432, "Known filter returned"); | 
|  | 156 | 
|  | 157   filter2.hitCount = 234; | 
|  | 158   test.equal(filter1.hitCount, 234, "Changing second wrapper modifies original a
     s well"); | 
|  | 159 | 
|  | 160   filter1.delete(); | 
|  | 161   filter2.delete(); | 
|  | 162 | 
|  | 163   let filter3 = Filter.fromText("someknownfilter"); | 
|  | 164   test.equal(filter3.hitCount, 0, "Filter data has been reset once previous inst
     ances have been released"); | 
|  | 165   filter3.delete(); | 
|  | 166 | 
| 73   test.done(); | 167   test.done(); | 
| 74 }; | 168 }; | 
| 75 | 169 | 
| 76 exports.testNormalize = function(test) | 170 exports.testNormalize = function(test) | 
| 77 { | 171 { | 
| 78   let tests = [ | 172   let tests = [ | 
| 79     ["  foo bar ", "foobar"], |  | 
| 80     ["foobar", "foobar"], |  | 
| 81     [" !  comment something ", "!  comment something"], | 173     [" !  comment something ", "!  comment something"], | 
| 82     [" ! \n comment something ", "!  comment something"], | 174     [" ! \n comment something ", "!  comment something"], | 
| 83     [" foo , bar ## foo > bar ", "foo,bar##foo > bar"], | 175     ["  foo bar ", "foobar"], | 
| 84     [" foo , bar #@# foo > bar ", "foo,bar#@#foo > bar"], | 176     [" foo , bar #  # foo > bar ", "foo,bar##foo > bar", "foo,bar", "foo > bar"]
     , | 
| 85   ]; | 177     [" foo , bar # @   # foo > bar ", "foo,bar#@#foo > bar", "foo,bar", "foo > b
     ar"], | 
| 86   for (let [text, expected] of tests) | 178     ["foOBar"], | 
| 87     test.equal(Filter.normalize(text), expected); | 179     ["foOBar#xyz"], | 
|  | 180     ["foOBar$iMaGe,object_subrequest,~coLLapse", "foOBar$image,object-subrequest
     ,~collapse"], | 
|  | 181     ["foOBar$doMain=EXample.COM|~exAMPLE.РФ", "foOBar$domain=example.com|~exampl
     e.рф"], | 
|  | 182     ["foOBar$sitekeY=SiteKey", "foOBar$sitekey=SiteKey"], | 
|  | 183     ["exampLE.com##fooBAr", "example.com##fooBAr"], | 
|  | 184     ["exampLE.com#@#fooBAr", "example.com#@#fooBAr"], | 
|  | 185     ["exampLE.РФ#@#fooBAr", "example.рф#@#fooBAr"], | 
|  | 186   ]; | 
|  | 187 | 
|  | 188   for (let [text, expected, selectorDomain, selector] of tests) | 
|  | 189   { | 
|  | 190     if (!expected) | 
|  | 191       expected = text; | 
|  | 192 | 
|  | 193     let filter1 = Filter.fromText(text); | 
|  | 194     let filter2 = Filter.fromText(expected); | 
|  | 195 | 
|  | 196     test.equal(filter1.text, expected, "Filter text " + text + " got normalized"
     ); | 
|  | 197     test.equal(filter2.text, expected, "Already normalized text " + expected + "
      didn't change"); | 
|  | 198 | 
|  | 199     if (filter1 instanceof ActiveFilter) | 
|  | 200     { | 
|  | 201       filter1.hitCount = 567; | 
|  | 202       test.equal(filter1.hitCount, filter2.hitCount, "Property changes on filter
      " + text + " get reflected on filter " + expected); | 
|  | 203     } | 
|  | 204 | 
|  | 205     if (selectorDomain) | 
|  | 206     { | 
|  | 207       let expectedDomains = selectorDomain.split(",").sort().join(","); | 
|  | 208       let actualDomains1 = filter1.selectorDomain.split(",").sort().join(","); | 
|  | 209       let actualDomains2 = filter2.selectorDomain.split(",").sort().join(","); | 
|  | 210       test.equal(actualDomains1, expectedDomains, "Correct selector domain for f
     ilter " + text); | 
|  | 211       test.equal(actualDomains1, expectedDomains, "Correct selector domain for f
     ilter " + expected); | 
|  | 212 | 
|  | 213       test.equal(filter1.selector, selector, "Correct selector for filter " + te
     xt); | 
|  | 214       test.equal(filter2.selector, selector, "Correct selector for filter " + ex
     pected); | 
|  | 215     } | 
|  | 216 | 
|  | 217     filter1.delete(); | 
|  | 218     filter2.delete(); | 
|  | 219   } | 
|  | 220 | 
| 88   test.done(); | 221   test.done(); | 
| 89 }; | 222 }; | 
| 90 | 223 | 
| 91 exports.testSerialize = function(test) | 224 exports.testSerialize = function(test) | 
| 92 { | 225 { | 
| 93   // Comment | 226   // Comment | 
| 94   let filter = Filter.fromText("! serialize"); | 227   let filter = Filter.fromText("! serialize"); | 
| 95   test.equal(filter.serialize(), "[Filter]\ntext=! serialize\n"); | 228   test.equal(filter.serialize(), "[Filter]\ntext=! serialize\n"); | 
| 96   filter.delete(); | 229   filter.delete(); | 
| 97 | 230 | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
| 113 | 246 | 
| 114   // Element hiding filter | 247   // Element hiding filter | 
| 115   filter = Filter.fromText("example.com##serialize"); | 248   filter = Filter.fromText("example.com##serialize"); | 
| 116   test.equal(filter.serialize(), "[Filter]\ntext=example.com##serialize\n"); | 249   test.equal(filter.serialize(), "[Filter]\ntext=example.com##serialize\n"); | 
| 117   filter.disabled = true; | 250   filter.disabled = true; | 
| 118   filter.lastHit = 5; | 251   filter.lastHit = 5; | 
| 119   test.equal(filter.serialize(), "[Filter]\ntext=example.com##serialize\ndisable
     d=true\nlastHit=5\n"); | 252   test.equal(filter.serialize(), "[Filter]\ntext=example.com##serialize\ndisable
     d=true\nlastHit=5\n"); | 
| 120   filter.delete(); | 253   filter.delete(); | 
| 121 | 254 | 
| 122   test.done(); | 255   test.done(); | 
| 123 } | 256 }; | 
|  | 257 | 
|  | 258 exports.testInvalidReasons = function(test) | 
|  | 259 { | 
|  | 260   let tests = [ | 
|  | 261     ["/??/", "filter_invalid_regexp"], | 
|  | 262     ["asd$foobar", "filter_unknown_option"], | 
|  | 263     ["~foo.com##[-abp-properties='abc']", "filter_cssproperty_nodomain"], | 
|  | 264   ]; | 
|  | 265 | 
|  | 266   for (let [text, reason] of tests) | 
|  | 267   { | 
|  | 268     let filter = Filter.fromText(text); | 
|  | 269     test.equals(filter.reason, reason, "Reason why filter " + text + " is invali
     d"); | 
|  | 270     filter.delete(); | 
|  | 271   } | 
|  | 272 | 
|  | 273   test.done(); | 
|  | 274 }; | 
| 124 | 275 | 
| 125 exports.testActiveFilter = function(test) | 276 exports.testActiveFilter = function(test) | 
| 126 { | 277 { | 
| 127   let filter1 = Filter.fromText("asdf"); | 278   let filter1 = Filter.fromText("asdf"); | 
| 128   let filter1copy = Filter.fromText("asdf"); | 279   let filter1copy = Filter.fromText("asdf"); | 
| 129   let filter2 = Filter.fromText("##foobar"); | 280   let filter2 = Filter.fromText("##foobar"); | 
| 130 | 281 | 
| 131   try | 282   test.ok(!filter1.disabled && !filter1copy.disabled && !filter2.disabled, "Filt
     ers are initially enabled"); | 
| 132   { | 283   filter1.disabled = true; | 
| 133     test.ok(!filter1.disabled && !filter1copy.disabled && !filter2.disabled, "Fi
     lters are initially enabled"); | 284   test.ok(filter1.disabled, "Disabling filter works"); | 
| 134     filter1.disabled = true; | 285   test.ok(filter1copy.disabled, "Filter copies are also disabled"); | 
| 135     test.ok(filter1.disabled, "Disabling filter works"); | 286   test.ok(!filter2.disabled, "Disabling one filter doesn't disable others"); | 
| 136     test.ok(filter1copy.disabled, "Filter copies are also disabled"); | 287 | 
| 137     test.ok(!filter2.disabled, "Disabling one filter doesn't disable others"); | 288   test.ok(filter1.hitCount === 0 && filter1copy.hitCount === 0 && filter2.hitCou
     nt === 0, "Filters have no hit initially"); | 
| 138 | 289   filter1.hitCount = 5; | 
| 139     test.ok(filter1.hitCount === 0 && filter1copy.hitCount === 0 && filter2.hitC
     ount === 0, "Filters have no hit initially"); | 290   test.equal(filter1.hitCount, 5, "Changing hit count works"); | 
| 140     filter1.hitCount = 5; | 291   test.equal(filter1copy.hitCount, 5, "Hit count of filter copies is also change
     d"); | 
| 141     test.equal(filter1.hitCount, 5, "Changing hit count works"); | 292   test.equal(filter2.hitCount, 0, "Hit count of other filters isn't affected"); | 
| 142     test.equal(filter1copy.hitCount, 5, "Hit count of filter copies is also chan
     ged"); | 293 | 
| 143     test.equal(filter2.hitCount, 0, "Hit count of other filters isn't affected")
     ; | 294   test.ok(filter1.lastHit === 0 && filter1copy.lastHit === 0 && filter2.lastHit 
     === 0, "Filters have no last hit time initially"); | 
| 144 | 295   filter1.lastHit = 10; | 
| 145     test.ok(filter1.lastHit === 0 && filter1copy.lastHit === 0 && filter2.lastHi
     t === 0, "Filters have no last hit time initially"); | 296   test.equal(filter1.lastHit, 10, "Changing last hit time works"); | 
| 146     filter1.lastHit = 10; | 297   test.equal(filter1copy.lastHit, 10, "Last hit time of filter copies is also ch
     anged"); | 
| 147     test.equal(filter1.lastHit, 10, "Changing last hit time works"); | 298   test.equal(filter2.lastHit, 0, "Last hit time of other filters isn't affected"
     ); | 
| 148     test.equal(filter1copy.lastHit, 10, "Last hit time of filter copies is also 
     changed"); | 299 | 
| 149     test.equal(filter2.lastHit, 0, "Last hit time of other filters isn't affecte
     d"); | 300   filter1.delete(); | 
| 150   } | 301   filter1copy.delete(); | 
| 151   finally | 302   filter2.delete(); | 
| 152   { |  | 
| 153     filter1.delete(); |  | 
| 154     filter1copy.delete(); |  | 
| 155     filter2.delete(); |  | 
| 156   } |  | 
| 157 | 303 | 
| 158   test.done(); | 304   test.done(); | 
| 159 }; | 305 }; | 
| 160 | 306 | 
| 161 exports.testIsGeneric = function(test) | 307 exports.testIsGeneric = function(test) | 
| 162 { | 308 { | 
| 163   let tests = [ | 309   let tests = [ | 
| 164     ["asfd", true], | 310     ["asfd", true], | 
| 165     ["|http://example.com/asdf", true], | 311     ["|http://example.com/asdf", true], | 
| 166     ["||example.com/asdf", true], | 312     ["||example.com/asdf", true], | 
| 167     ["asfd$third-party", true], | 313     ["asfd$third-party", true], | 
| 168     ["asdf$domain=com", false], | 314     ["asdf$domain=com", false], | 
| 169     ["asdf$domain=example.com", false], | 315     ["asdf$domain=example.com", false], | 
| 170     ["asdf$image,domain=example.com", false], | 316     ["asdf$image,domain=example.com", false], | 
| 171     ["asdf$~image,domain=example.com", false], | 317     ["asdf$~image,domain=example.com", false], | 
| 172     ["asdf$third-party,domain=example.com", false], | 318     ["asdf$third-party,domain=example.com", false], | 
| 173     ["||example.com/asdf$~coLLapse,domain=example.com", false], | 319     ["||example.com/asdf$~coLLapse,domain=example.com", false], | 
| 174     ["||example.com/asdf$domain=~example.com", true], | 320     ["||example.com/asdf$domain=~example.com", true], | 
| 175     ["||example.com/asdf$third-party,domain=~example.com", true], | 321     ["||example.com/asdf$third-party,domain=~example.com", true], | 
| 176     ["asdf$domain=foo.example.com|~example.com", false], | 322     ["asdf$domain=foo.example.com|~example.com", false], | 
| 177     ["asdf$domain=foo.com|~example.com", false], | 323     ["asdf$domain=foo.com|~example.com", false], | 
| 178     ["asdf$domain=~foo.com|~example.com", true], | 324     ["asdf$domain=~foo.com|~example.com", true], | 
| 179   ]; | 325   ]; | 
| 180 | 326 | 
| 181   for (let [text, generic] of tests) | 327   for (let [text, generic] of tests) | 
| 182   { | 328   { | 
| 183     let filter = Filter.fromText(text); | 329     let filter = Filter.fromText(text); | 
| 184     try | 330     test.equal(filter.isGeneric(), generic, "Filter " + text + " is generic"); | 
| 185     { | 331     filter.delete(); | 
| 186       test.equal(filter.isGeneric(), generic, "Filter " + text + " is generic"); |  | 
| 187     } |  | 
| 188     finally |  | 
| 189     { |  | 
| 190       filter.delete(); |  | 
| 191     } |  | 
| 192   } | 332   } | 
| 193 | 333 | 
| 194   test.done(); | 334   test.done(); | 
| 195 } | 335 } | 
| 196 | 336 | 
| 197 exports.testElemHideSelector = function(test) | 337 exports.testElemHideSelector = function(test) | 
| 198 { | 338 { | 
| 199   function doTest(text, selector, selectorDomain) | 339   function doTest(text, selector, selectorDomain) | 
| 200   { | 340   { | 
| 201     let filter = Filter.fromText(text); | 341     let filter = Filter.fromText(text); | 
| 202     try | 342     test.equal(filter.selector, selector, "Correct selector for " + text); | 
| 203     { | 343 | 
| 204       test.equal(filter.selector, selector, "Correct selector for " + text); | 344     let actualDomains = filter.selectorDomain.split(",").sort().join(","); | 
| 205 | 345     let expectedDomains = selectorDomain.split(",").sort().join(","); | 
| 206       let actualDomains = filter.selectorDomain.split(",").sort().join(","); | 346     test.equal(actualDomains, expectedDomains, "Correct domains list for " + tex
     t); | 
| 207       let expectedDomains = selectorDomain.split(",").sort().join(","); | 347 | 
| 208       test.equal(actualDomains, expectedDomains, "Correct domains list for " + t
     ext); | 348     filter.delete(); | 
| 209     } |  | 
| 210     finally |  | 
| 211     { |  | 
| 212       filter.delete(); |  | 
| 213     } |  | 
| 214   } | 349   } | 
| 215 | 350 | 
| 216   let tests = [ | 351   let tests = [ | 
| 217     ["##foobar", "foobar", ""], | 352     ["##foobar", "foobar", ""], | 
| 218     ["~example.com##foobar", "foobar", ""], | 353     ["~example.com##foobar", "foobar", ""], | 
| 219     ["example.com##body > div:first-child", "body > div:first-child", "example.c
     om"], | 354     ["example.com##body > div:first-child", "body > div:first-child", "example.c
     om"], | 
| 220     ["xYz,~example.com##foobar:not(whatever)", "foobar:not(whatever)","xyz"], | 355     ["xYz,~example.com##foobar:not(whatever)", "foobar:not(whatever)","xyz"], | 
| 221     ["~xyz,com,~abc.com,example.info##foobar", "foobar", "com,example.info"], | 356     ["~xyz,com,~abc.com,example.info##foobar", "foobar", "com,example.info"], | 
| 222     ["foo,bar,bas,bam##foobar", "foobar", "foo,bar,bas,bam"], | 357     ["foo,bar,bas,bam##foobar", "foobar", "foo,bar,bas,bam"], | 
| 223 | 358 | 
| 224     // Good idea to test this? Maybe consider behavior undefined in this case. | 359     // Good idea to test this? Maybe consider behavior undefined in this case. | 
| 225     ["foo,bar,bas,~bar##foobar", "foobar", "foo,bas"], | 360     ["foo,bar,bas,~bar##foobar", "foobar", "foo,bas"], | 
| 226   ]; | 361   ]; | 
| 227 | 362 | 
| 228   for (let [text, selector, selectorDomain] of tests) | 363   for (let [text, selector, selectorDomain] of tests) | 
| 229   { | 364   { | 
| 230     doTest(text, selector, selectorDomain); | 365     doTest(text, selector, selectorDomain); | 
| 231     doTest(text.replace("##", "#@#"), selector, selectorDomain); | 366     doTest(text.replace("##", "#@#"), selector, selectorDomain); | 
| 232   } | 367   } | 
| 233 | 368 | 
| 234   test.done(); | 369   test.done(); | 
| 235 }; | 370 }; | 
| 236 | 371 | 
| 237 exports.textCSSRules = function(test) | 372 exports.testCSSRules = function(test) | 
| 238 { | 373 { | 
| 239   let tests = [ | 374   let tests = [ | 
| 240     ["foo.com##[-abp-properties='abc']", "abc", "", ""], | 375     ["foo.com##[-abp-properties='abc']", "abc", "", ""], | 
| 241     ["foo.com##[-abp-properties='a\"bc']", "a\\\"bc", "", ""], | 376     ["foo.com##[-abp-properties='a\"bc']", "a\\\"bc", "", ""], | 
| 242     ["foo.com##[-abp-properties=\"abc\"]", "abc", "", ""], | 377     ["foo.com##[-abp-properties=\"abc\"]", "abc", "", ""], | 
| 243     ["foo.com##[-abp-properties=\"a'bc\"]", "a\\'bc", "", ""], | 378     ["foo.com##[-abp-properties=\"a'bc\"]", "a\\'bc", "", ""], | 
| 244     ["foo.com##aaa [-abp-properties='abc'] bbb", "abc", "aaa ", " bbb"], | 379     ["foo.com##aaa [-abp-properties='abc'] bbb", "abc", "aaa ", " bbb"], | 
| 245     ["foo.com##[-abp-properties='|background-image: url(data:*)']", "^background
     \\-image\\:\\ url\\(data\\:.*\\)", "", ""], | 380     ["foo.com##[-abp-properties='|background-image: url(data:*)']", "^background
     \\-image\\:\\ url\\(data\\:.*\\)", "", ""], | 
| 246   ]; | 381   ]; | 
| 247 | 382 | 
| 248   for (let [text, regexp, prefix, suffix] of tests) | 383   for (let [text, regexp, prefix, suffix] of tests) | 
| 249   { | 384   { | 
| 250     let filter = Filter.fromText(text); | 385     let filter = Filter.fromText(text); | 
| 251     try | 386     test.equal(filter.regexpString, regexp, "Regular expression of " + text); | 
| 252     { | 387     test.equal(filter.selectorPrefix, prefix, "Selector prefix of " + text); | 
| 253       test.equal(filter.regexpString, regexp, "Regular expression of " + text); | 388     test.equal(filter.selectorSuffix, suffix, "Selector suffix of " + text); | 
| 254       test.equal(filter.selectorPrefix, prefix, "Selector prefix of " + text); | 389     filter.delete(); | 
| 255       test.equal(filter.selectorSuffix, suffix, "Selector suffix of " + text); | 390   } | 
| 256     } | 391 | 
| 257     finally | 392   test.done(); | 
| 258     { | 393 }; | 
| 259       filter.delete(); |  | 
| 260     } |  | 
| 261   } |  | 
| 262 |  | 
| 263   test.done(); |  | 
| 264 }; |  | 
| LEFT | RIGHT | 
|---|