File: test_config.py

package info (click to toggle)
vdirsyncer 0.14.1-1%2Bdeb9u1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 848 kB
  • sloc: python: 6,664; makefile: 243; sh: 59
file content (247 lines) | stat: -rw-r--r-- 6,146 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
import io
from textwrap import dedent

import pytest

from vdirsyncer import cli, exceptions
from vdirsyncer.cli.config import Config, _parse_config_value

import vdirsyncer.cli.utils  # noqa


invalid = object()


@pytest.fixture
def read_config(tmpdir, monkeypatch):
    def inner(cfg):
        errors = []
        monkeypatch.setattr('vdirsyncer.cli.cli_logger.error', errors.append)
        f = io.StringIO(dedent(cfg.format(base=str(tmpdir))))
        rv = Config.from_fileobject(f)
        monkeypatch.undo()
        return errors, rv
    return inner


@pytest.fixture
def parse_config_value(capsys):
    def inner(s):
        try:
            rv = _parse_config_value(s)
        except ValueError:
            return invalid
        else:
            warnings = capsys.readouterr()[1]
            return rv, len(warnings.splitlines())
    return inner


def test_read_config(read_config):
    errors, c = read_config(u'''
        [general]
        status_path = /tmp/status/

        [pair bob]
        a = "bob_a"
        b = "bob_b"
        collections = null

        [storage bob_a]
        type = "filesystem"
        path = "/tmp/contacts/"
        fileext = ".vcf"
        yesno = false
        number = 42

        [storage bob_b]
        type = "carddav"
        ''')

    assert c.general == {'status_path': '/tmp/status/'}

    assert set(c.pairs) == {'bob'}
    bob = c.pairs['bob']
    assert bob.collections is None

    assert c.storages == {
        'bob_a': {'type': 'filesystem', 'path': '/tmp/contacts/', 'fileext':
                  '.vcf', 'yesno': False, 'number': 42,
                  'instance_name': 'bob_a'},
        'bob_b': {'type': 'carddav', 'instance_name': 'bob_b'}
    }


def test_missing_collections_param(read_config):
    with pytest.raises(exceptions.UserError) as excinfo:
        read_config(u'''
            [general]
            status_path = /tmp/status/

            [pair bob]
            a = "bob_a"
            b = "bob_b"

            [storage bob_a]
            type = "lmao"

            [storage bob_b]
            type = "lmao"
            ''')

    assert 'collections parameter missing' in str(excinfo.value)


def test_invalid_section_type(read_config):
    with pytest.raises(exceptions.UserError) as excinfo:
        read_config(u'''
            [general]
            status_path = /tmp/status/

            [bogus]
        ''')

    assert 'Unknown section' in str(excinfo.value)
    assert 'bogus' in str(excinfo.value)


def test_storage_instance_from_config(monkeypatch):
    def lol(**kw):
        assert kw == {'foo': 'bar', 'baz': 1}
        return 'OK'

    monkeypatch.setitem(cli.utils.storage_names._storages,
                        'lol', lol)
    config = {'type': 'lol', 'foo': 'bar', 'baz': 1}
    assert cli.utils.storage_instance_from_config(config) == 'OK'


def test_missing_general_section(read_config):
    with pytest.raises(exceptions.UserError) as excinfo:
        read_config(u'''
            [pair my_pair]
            a = "my_a"
            b = "my_b"
            collections = null

            [storage my_a]
            type = "filesystem"
            path = "{base}/path_a/"
            fileext = ".txt"

            [storage my_b]
            type = "filesystem"
            path = "{base}/path_b/"
            fileext = ".txt"
            ''')

    assert 'Invalid general section.' in str(excinfo.value)


def test_wrong_general_section(read_config):
    with pytest.raises(exceptions.UserError) as excinfo:
        read_config(u'''
            [general]
            wrong = true
            ''')

    assert 'Invalid general section.' in str(excinfo.value)
    assert excinfo.value.problems == [
        'general section doesn\'t take the parameters: wrong',
        'general section is missing the parameters: status_path'
    ]


def test_invalid_storage_name(read_config):
    with pytest.raises(exceptions.UserError) as excinfo:
        read_config(u'''
        [general]
        status_path = {base}/status/

        [storage foo.bar]
        ''')

    assert 'invalid characters' in str(excinfo.value).lower()


def test_invalid_collections_arg(read_config):
    with pytest.raises(exceptions.UserError) as excinfo:
        read_config(u'''
        [general]
        status_path = /tmp/status/

        [pair foobar]
        a = "foo"
        b = "bar"
        collections = [null]

        [storage foo]
        type = "filesystem"
        path = "/tmp/foo/"
        fileext = ".txt"

        [storage bar]
        type = "filesystem"
        path = "/tmp/bar/"
        fileext = ".txt"
        ''')

    assert 'Expected string' in str(excinfo.value)


def test_duplicate_sections(read_config):
    with pytest.raises(exceptions.UserError) as excinfo:
        read_config(u'''
        [general]
        status_path = /tmp/status/

        [pair foobar]
        a = "foobar"
        b = "bar"
        collections = null

        [storage foobar]
        type = "filesystem"
        path = "/tmp/foo/"
        fileext = ".txt"

        [storage bar]
        type = "filesystem"
        path = "/tmp/bar/"
        fileext = ".txt"
        ''')

    assert 'Name "foobar" already used' in str(excinfo.value)


def test_parse_config_value(parse_config_value):
    x = parse_config_value

    assert x('123  # comment!') is invalid

    assert x('True') is invalid
    assert x('False') is invalid
    assert x('Yes') is invalid
    assert x('None') is invalid
    assert x('"True"') == ('True', 0)
    assert x('"False"') == ('False', 0)

    assert x('"123  # comment!"') == ('123  # comment!', 0)
    assert x('true') == (True, 0)
    assert x('false') == (False, 0)
    assert x('null') == (None, 0)
    assert x('3.14') == (3.14, 0)
    assert x('') == ('', 1)
    assert x('""') == ('', 0)


def test_validate_collections_param():
    x = cli.config._validate_collections_param
    x(None)
    x(["c", "a", "b"])
    pytest.raises(ValueError, x, [None])
    pytest.raises(ValueError, x, ["a", "a", "a"])
    pytest.raises(ValueError, x, [[None, "a", "b"]])
    x([["c", None, "b"]])
    x([["c", "a", None]])
    x([["c", None, None]])