File: parser_obj_test.py

package info (click to toggle)
python-certbot-nginx 4.0.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 660 kB
  • sloc: python: 4,507; sh: 47; makefile: 11
file content (279 lines) | stat: -rw-r--r-- 11,587 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# type: ignore
# As done in parser_obj.py, this module is not used for now, so we just skip
# type checking for the sake of simplicity.
""" Tests for functions and classes in parser_obj.py """

import sys
import unittest
from unittest import mock

import pytest

from certbot_nginx._internal.parser_obj import COMMENT_BLOCK
from certbot_nginx._internal.parser_obj import parse_raw


class CommentHelpersTest(unittest.TestCase):
    def test_is_comment(self):
        from certbot_nginx._internal.parser_obj import _is_comment
        assert _is_comment(parse_raw(['#']))
        assert _is_comment(parse_raw(['#', ' literally anything else']))
        assert not _is_comment(parse_raw(['not', 'even', 'a', 'comment']))

    def test_is_certbot_comment(self):
        from certbot_nginx._internal.parser_obj import _is_certbot_comment
        assert _is_certbot_comment(
            parse_raw(COMMENT_BLOCK))
        assert not _is_certbot_comment(
            parse_raw(['#', ' not a certbot comment']))
        assert not _is_certbot_comment(
            parse_raw(['#', ' managed by Certbot', ' also not a certbot comment']))
        assert not _is_certbot_comment(
            parse_raw(['not', 'even', 'a', 'comment']))

    def test_certbot_comment(self):
        from certbot_nginx._internal.parser_obj import _certbot_comment
        from certbot_nginx._internal.parser_obj import _is_certbot_comment
        comment = _certbot_comment(None)
        assert _is_certbot_comment(comment)
        assert comment.dump() == COMMENT_BLOCK
        assert comment.dump(True) == ['    '] + COMMENT_BLOCK
        assert _certbot_comment(None, 2).dump(True) == ['  '] + COMMENT_BLOCK


class ParsingHooksTest(unittest.TestCase):
    def test_is_sentence(self):
        from certbot_nginx._internal.parser_obj import Sentence
        assert not Sentence.should_parse([])
        assert Sentence.should_parse([''])
        assert Sentence.should_parse(['word'])
        assert Sentence.should_parse(['two', 'words'])
        assert not Sentence.should_parse([[]])
        assert not Sentence.should_parse(['word', []])

    def test_is_block(self):
        from certbot_nginx._internal.parser_obj import Block
        assert not Block.should_parse([])
        assert not Block.should_parse([''])
        assert not Block.should_parse(['two', 'words'])
        assert not Block.should_parse([[[]], []])
        assert not Block.should_parse([['block_name'], ['hi', []], []])
        assert not Block.should_parse([['block_name'], 'lol'])
        assert Block.should_parse([['block_name'], ['hi', []]])
        assert Block.should_parse([['hello'], []])
        assert Block.should_parse([['block_name'], [['many'], ['statements'], 'here']])
        assert Block.should_parse([['if', ' ', '(whatever)'], ['hi']])

    @mock.patch("certbot_nginx._internal.parser_obj.Parsable.parsing_hooks")
    def test_parse_raw(self, parsing_hooks):
        fake_parser1 = mock.Mock()
        fake_parser1.should_parse = lambda x: True
        fake_parser2 = mock.Mock()
        fake_parser2.should_parse = lambda x: True
        parsing_hooks.return_value = (fake_parser1, fake_parser2,)
        # First encountered "match" should parse.
        parse_raw([])
        fake_parser1().parse.assert_called_once()
        fake_parser2().parse.assert_not_called()
        fake_parser1.reset_mock()
        # "match" that returns False shouldn't parse.
        fake_parser1.should_parse = lambda x: False
        parse_raw([])
        fake_parser1().parse.assert_not_called()
        fake_parser2().parse.assert_called_once()

    @mock.patch("certbot_nginx._internal.parser_obj.Parsable.parsing_hooks")
    def test_parse_raw_no_match(self, parsing_hooks):
        from certbot import errors
        fake_parser1 = mock.Mock()
        fake_parser1.should_parse = lambda x: False
        parsing_hooks.return_value = (fake_parser1,)
        with pytest.raises(errors.MisconfigurationError):
            parse_raw([])
        parsing_hooks.return_value = ()
        with pytest.raises(errors.MisconfigurationError):
            parse_raw([])

    @mock.patch("certbot_nginx._internal.parser_obj.Parsable.parsing_hooks")
    def test_parse_raw_passes_add_spaces(self, parsing_hooks):
        fake_parser1 = mock.Mock()
        fake_parser1.should_parse = lambda x: True
        parsing_hooks.return_value = (fake_parser1,)
        parse_raw([])
        fake_parser1().parse.assert_called_with([], False)
        parse_raw([], add_spaces=True)
        fake_parser1().parse.assert_called_with([], True)


class SentenceTest(unittest.TestCase):
    def setUp(self):
        from certbot_nginx._internal.parser_obj import Sentence
        self.sentence = Sentence(None)

    def test_parse_bad_sentence_raises_error(self):
        from certbot import errors
        with pytest.raises(errors.MisconfigurationError):
            self.sentence.parse('lol')
        with pytest.raises(errors.MisconfigurationError):
            self.sentence.parse([[]])
        with pytest.raises(errors.MisconfigurationError):
            self.sentence.parse([5])

    def test_parse_sentence_words_hides_spaces(self):
        og_sentence = ['\r\n', 'hello', ' ', ' ', '\t\n  ', 'lol', ' ', 'spaces']
        self.sentence.parse(og_sentence)
        assert self.sentence.words == ['hello', 'lol', 'spaces']
        assert self.sentence.dump() == ['hello', 'lol', 'spaces']
        assert self.sentence.dump(True) == og_sentence

    def test_parse_sentence_with_add_spaces(self):
        self.sentence.parse(['hi', 'there'], add_spaces=True)
        assert self.sentence.dump(True) == ['hi', ' ', 'there']
        self.sentence.parse(['one', ' ', 'space', 'none'], add_spaces=True)
        assert self.sentence.dump(True) == ['one', ' ', 'space', ' ', 'none']

    def test_iterate(self):
        expected = [['1', '2', '3']]
        self.sentence.parse(['1', ' ', '2', ' ', '3'])
        for i, sentence in enumerate(self.sentence.iterate()):
            assert sentence.dump() == expected[i]

    def test_set_tabs(self):
        self.sentence.parse(['tabs', 'pls'], add_spaces=True)
        self.sentence.set_tabs()
        assert self.sentence.dump(True)[0] == '\n    '
        self.sentence.parse(['tabs', 'pls'], add_spaces=True)

    def test_get_tabs(self):
        self.sentence.parse(['no', 'tabs'])
        assert self.sentence.get_tabs() == ''
        self.sentence.parse(['\n \n  ', 'tabs'])
        assert self.sentence.get_tabs() == '  '
        self.sentence.parse(['\n\t  ', 'tabs'])
        assert self.sentence.get_tabs() == '\t  '
        self.sentence.parse(['\n\t \n', 'tabs'])
        assert self.sentence.get_tabs() == ''


class BlockTest(unittest.TestCase):
    def setUp(self):
        from certbot_nginx._internal.parser_obj import Block
        self.bloc = Block(None)
        self.name = ['server', 'name']
        self.contents = [['thing', '1'], ['thing', '2'], ['another', 'one']]
        self.bloc.parse([self.name, self.contents])

    def test_iterate(self):
        # Iterates itself normally
        assert self.bloc == next(self.bloc.iterate())
        # Iterates contents while expanded
        expected = [self.bloc.dump()] + self.contents
        for i, elem in enumerate(self.bloc.iterate(expanded=True)):
            assert expected[i] == elem.dump()

    def test_iterate_match(self):
        # can match on contents while expanded
        from certbot_nginx._internal.parser_obj import Block
        from certbot_nginx._internal.parser_obj import Sentence
        expected = [['thing', '1'], ['thing', '2']]
        for i, elem in enumerate(self.bloc.iterate(expanded=True,
            match=lambda x: isinstance(x, Sentence) and 'thing' in x.words)):
            assert expected[i] == elem.dump()
        # can match on self
        assert self.bloc == next(self.bloc.iterate(
            expanded=True,
            match=lambda x: isinstance(x, Block) and 'server' in x.names))

    def test_parse_with_added_spaces(self):
        import copy
        self.bloc.parse([copy.copy(self.name), self.contents], add_spaces=True)
        assert self.bloc.dump() == [self.name, self.contents]
        assert self.bloc.dump(True) == [
            ['server', ' ', 'name', ' '],
            [['thing', ' ', '1'],
             ['thing', ' ', '2'],
             ['another', ' ', 'one']]]

    def test_bad_parse_raises_error(self):
        from certbot import errors
        with pytest.raises(errors.MisconfigurationError):
            self.bloc.parse([[[]], [[]]])
        with pytest.raises(errors.MisconfigurationError):
            self.bloc.parse(['lol'])
        with pytest.raises(errors.MisconfigurationError):
            self.bloc.parse(['fake', 'news'])

    def test_set_tabs(self):
        self.bloc.set_tabs()
        assert self.bloc.names.dump(True)[0] == '\n    '
        for elem in self.bloc.contents.dump(True)[:-1]:
            assert elem[0] == '\n        '
        assert self.bloc.contents.dump(True)[-1][0] == '\n'

    def test_get_tabs(self):
        self.bloc.parse([[' \n  \t', 'lol'], []])
        assert self.bloc.get_tabs() == '  \t'

class StatementsTest(unittest.TestCase):
    def setUp(self):
        from certbot_nginx._internal.parser_obj import Statements
        self.statements = Statements(None)
        self.raw = [
            ['sentence', 'one'],
            ['sentence', 'two'],
            ['and', 'another']
        ]
        self.raw_spaced = [
            ['\n  ', 'sentence', ' ', 'one'],
            ['\n  ', 'sentence', ' ', 'two'],
            ['\n  ', 'and', ' ', 'another'],
            '\n\n'
        ]

    def test_set_tabs(self):
        self.statements.parse(self.raw)
        self.statements.set_tabs()
        for statement in self.statements.iterate():
            assert statement.dump(True)[0] == '\n    '

    def test_set_tabs_with_parent(self):
        # Trailing whitespace should inherit from parent tabbing.
        self.statements.parse(self.raw)
        self.statements.parent = mock.Mock()
        self.statements.parent.get_tabs.return_value = '\t\t'
        self.statements.set_tabs()
        for statement in self.statements.iterate():
            assert statement.dump(True)[0] == '\n    '
        assert self.statements.dump(True)[-1] == '\n\t\t'

    def test_get_tabs(self):
        self.raw[0].insert(0, '\n \n  \t')
        self.statements.parse(self.raw)
        assert self.statements.get_tabs() == '  \t'
        self.statements.parse([])
        assert self.statements.get_tabs() == ''

    def test_parse_with_added_spaces(self):
        self.statements.parse(self.raw, add_spaces=True)
        assert self.statements.dump(True)[0] == ['sentence', ' ', 'one']

    def test_parse_bad_list_raises_error(self):
        from certbot import errors
        with pytest.raises(errors.MisconfigurationError):
            self.statements.parse('lol not a list')

    def test_parse_hides_trailing_whitespace(self):
        self.statements.parse(self.raw + ['\n\n  '])
        assert isinstance(self.statements.dump()[-1], list)
        assert self.statements.dump(True)[-1].isspace() is True
        assert self.statements.dump(True)[-1] == '\n\n  '

    def test_iterate(self):
        self.statements.parse(self.raw)
        expected = [['sentence', 'one'], ['sentence', 'two']]
        for i, elem in enumerate(self.statements.iterate(match=lambda x: 'sentence' in x)):
            assert expected[i] == elem.dump()


if __name__ == "__main__":
    sys.exit(pytest.main(sys.argv[1:] + [__file__]))  # pragma: no cover