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

Delta Between Two Patch Sets: tests/test_parser.py

Issue 29465715: Fixes 4969 - Add parsing of filters (Closed)
Left Patch Set: Created June 14, 2017, 5:32 p.m.
Right Patch Set: Rebase to 1f5d7ead9bff Created Oct. 24, 2017, 3:58 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « abp/filters/parser.py ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 # This file is part of Adblock Plus <https://adblockplus.org/>, 1 # This file is part of Adblock Plus <https://adblockplus.org/>,
2 # Copyright (C) 2006-2017 eyeo GmbH 2 # Copyright (C) 2006-present eyeo GmbH
3 # 3 #
4 # Adblock Plus is free software: you can redistribute it and/or modify 4 # Adblock Plus is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License version 3 as 5 # it under the terms of the GNU General Public License version 3 as
6 # published by the Free Software Foundation. 6 # published by the Free Software Foundation.
7 # 7 #
8 # Adblock Plus is distributed in the hope that it will be useful, 8 # Adblock Plus is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of 9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details. 11 # GNU General Public License for more details.
12 # 12 #
13 # You should have received a copy of the GNU General Public License 13 # You should have received a copy of the GNU General Public License
14 # along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 14 # along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
15 15
16 from __future__ import unicode_literals 16 from __future__ import unicode_literals
17 17
18 import pytest 18 import pytest
19 19
20 from abp.filters import parse_line, parse_filterlist 20 from abp.filters import (
21 from abp.filters.parser import InvalidLine, Comment, Metadata, ParseError 21 parse_line, parse_filterlist, ParseError,
22 SELECTOR_TYPE as ST, FILTER_ACTION as FA, FILTER_OPTION as OPT,
23 )
24 from abp.filters.parser import Comment, Metadata
22 25
23 26
24 def test_parse_empty(): 27 def test_parse_empty():
25 line = parse_line(' ') 28 line = parse_line(' ')
26 assert line.type == 'emptyline' 29 assert line.type == 'emptyline'
27 30
28 31
29 @pytest.mark.parametrize('filter_text, expected', { 32 @pytest.mark.parametrize('filter_text, expected', {
30 '||example.com/banner.gif$image,~match-case,domain=abc.com|~def.org': { 33 # Blocking filters with patterns and regexps and blocking exceptions.
34 '*asdf*d**dd*': {
35 'selector': {'type': ST.URL_PATTERN, 'value': '*asdf*d**dd*'},
36 'action': FA.BLOCK,
37 },
38 '@@|*asd|f*d**dd*|': {
39 'selector': {'type': ST.URL_PATTERN, 'value': '|*asd|f*d**dd*|'},
40 'action': FA.ALLOW,
41 },
42 '/ddd|f?a[s]d/': {
43 'selector': {'type': ST.URL_REGEXP, 'value': 'ddd|f?a[s]d'},
44 'action': FA.BLOCK,
45 },
46 '@@/ddd|f?a[s]d/': {
47 'selector': {'type': ST.URL_REGEXP, 'value': 'ddd|f?a[s]d'},
48 'action': FA.ALLOW,
49 },
50 # Blocking filters with some options.
51 'bla$match-case,~script,domain=foo.com|~bar.com,sitekey=foo': {
52 'selector': {'type': ST.URL_PATTERN, 'value': 'bla'},
53 'action': FA.BLOCK,
54 'options': [
55 (OPT.MATCH_CASE, True),
56 (OPT.SCRIPT, False),
57 (OPT.DOMAIN, [('foo.com', True), ('bar.com', False)]),
58 (OPT.SITEKEY, ['foo']),
59 ],
60 },
61 '@@http://bla$~script,~other,sitekey=foo|bar': {
62 'selector': {'type': ST.URL_PATTERN, 'value': 'http://bla'},
63 'action': FA.ALLOW,
64 'options': [
65 (OPT.SCRIPT, False),
66 (OPT.OTHER, False),
67 (OPT.SITEKEY, ['foo', 'bar']),
68 ],
69 },
70 # Element hiding filters and exceptions.
71 '##ddd': {
72 'selector': {'type': ST.CSS, 'value': 'ddd'},
73 'action': FA.HIDE,
74 'options': [],
75 },
76 '#@#body > div:first-child': {
77 'selector': {'type': ST.CSS, 'value': 'body > div:first-child'},
78 'action': FA.SHOW,
79 'options': [],
80 },
81 'foo,~bar##ddd': {
82 'options': [(OPT.DOMAIN, [('foo', True), ('bar', False)])],
83 },
84 # Element hiding emulation filters (extended CSS).
85 'foo,~bar#?#:-abp-properties(abc)': {
86 'selector': {'type': ST.XCSS, 'value': ':-abp-properties(abc)'},
87 'action': FA.HIDE,
88 'options': [(OPT.DOMAIN, [('foo', True), ('bar', False)])],
89 },
90 'foo.com#?#aaa :-abp-properties(abc) bbb': {
31 'selector': { 91 'selector': {
32 'type': 'url-pattern', 92 'type': ST.XCSS,
33 'value': '||example.com/banner.gif', 93 'value': 'aaa :-abp-properties(abc) bbb'
34 },
35 'action': 'block',
36 'options': {
37 'match-case': False,
38 'types-none': True,
39 'types-include': ['image'],
40 'domains-none': True,
41 'domains-include': ['abc.com'],
42 'domains-exclude': ['def.org'],
43 }, 94 },
44 }, 95 },
45 '/ab?c\\.com/$image': { 96 '#?#:-abp-properties(|background-image: url(data:*))': {
46 'selector': {'type': 'url-regexp', 'value': 'ab?c\\.com'}, 97 'selector': {
47 'action': 'block', 98 'type': ST.XCSS,
48 'options': { 99 'value': ':-abp-properties(|background-image: url(data:*))'
49 'types-none': True,
50 'types-include': ['image'],
51 }, 100 },
52 }, 101 'options': [],
53 'abc$~image': {
54 'selector': {'type': 'url-pattern', 'value': 'abc'},
55 'action': 'block',
56 'options': {
57 'types-exclude': ['image'],
58 },
59 },
60 '@@||example.com/good.gif': {
61 'selector': {'type': 'url-pattern', 'value': '||example.com/good.gif'},
62 'action': 'allow',
63 'options': {},
64 },
65 '@@/ab?c\\.com/': {
66 'selector': {'type': 'url-regexp', 'value': 'ab?c\\.com'},
67 'action': 'allow',
68 'options': {},
69 },
70 'abc.com,cdf.com##div#ad1': {
71 'selector': {'type': 'css', 'value': 'div#ad1'},
72 'action': 'hide',
73 'options': {
74 'domains-none': True,
75 'domains-include': ['abc.com', 'cdf.com'],
76 },
77 },
78 '#@#div#ad1': {
79 'selector': {'type': 'css', 'value': 'div#ad1'},
80 'action': 'show',
81 'options': {},
82 },
83 'abc.com,~cdf.abc.com#@##ad1': {
84 'selector': {'type': 'css', 'value': '#ad1'},
85 'action': 'show',
86 'options': {
87 'domains-none': True,
88 'domains-include': ['abc.com'],
89 'domains-exclude': ['cdf.abc.com'],
90 },
91 },
92 # Exception with a site key.
93 '@@||abc.com/ad?$subdocument,sitekey=foo': {
94 'selector': {'type': 'url-pattern', 'value': '||abc.com/ad?'},
95 'action': 'allow',
96 'options': {
97 'types-none': True,
98 'types-include': ['subdocument'],
99 'sitekeys': ['foo']
100 },
101 },
102 # Element hiding filter using old (a.k.a. simple) syntax.
103 'abc.com#div(foo)(name=bar)(value=baz)': {
104 'selector': {
105 'type': 'abp-simple',
106 'value': 'div(foo)(name=bar)(value=baz)',
107 },
108 'action': 'hide',
109 'options': {
110 'domains-none': True,
111 'domains-include': ['abc.com'],
112 },
113 },
114 # Exclude all types with "x|~x" trick.
115 'x$image,~image': {'options': {'types-none': True}},
116 # More tricky combos of type flags.
117 'x$~image,image': {'options': {}},
118 'x$~image,image,~image': {'options': {'types-exclude': ['image']}},
119 'x$image,~image,image': {
120 'options': {'types-none': True, 'types-include': ['image']},
121 }, 102 },
122 }.items()) 103 }.items())
123 def test_parse_filters(filter_text, expected): 104 def test_parse_filters(filter_text, expected):
124 """Parametric test for filter parsing""" 105 """Parametric test for filter parsing"""
125 parsed = parse_line(filter_text) 106 parsed = parse_line(filter_text)
126 assert parsed.type == 'filter' 107 assert parsed.type == 'filter'
127 assert parsed.text == filter_text 108 assert parsed.text == filter_text
128 for attribute, expected_value in expected.items(): 109 for attribute, expected_value in expected.items():
129 assert getattr(parsed, attribute) == expected_value 110 assert getattr(parsed, attribute) == expected_value
130 111
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 def test_parse_bad_header(): 148 def test_parse_bad_header():
168 with pytest.raises(ParseError): 149 with pytest.raises(ParseError):
169 parse_line('[Adblock 1.1]') 150 parse_line('[Adblock 1.1]')
170 151
171 152
172 def test_parse_filterlist(): 153 def test_parse_filterlist():
173 result = parse_filterlist(['! foo', '! Title: bar']) 154 result = parse_filterlist(['! foo', '! Title: bar'])
174 assert list(result) == [Comment('foo'), Metadata('Title', 'bar')] 155 assert list(result) == [Comment('foo'), Metadata('Title', 'bar')]
175 156
176 157
177 def test_invalid_lines(): 158 def test_exception_timing():
178 result = parse_filterlist([ 159 result = parse_filterlist(['! good line', '%bad line%'])
179 '[Bad header]', 160 assert next(result) == Comment('good line')
180 '! Good comment', 161 with pytest.raises(ParseError):
181 '%Bad instruction%', 162 next(result)
182 ])
183 assert list(result) == [
184 InvalidLine('[Bad header]', 'Malformed header'),
185 Comment('Good comment'),
186 InvalidLine('%Bad instruction%', 'Unrecognized instruction'),
187 ]
LEFTRIGHT

Powered by Google App Engine
This is Rietveld