comparison tests/unit/test_plugin_xep_0082.py @ 3877:00212260f659

plugin XEP-0420: Implementation of Stanza Content Encryption: Includes implementation of XEP-0082 (XMPP date and time profiles) and tests for both new plugins. Everything is type checked, linted, format checked and unit tested. Adds new dependency xmlschema. fix 377
author Syndace <me@syndace.dev>
date Tue, 23 Aug 2022 12:04:11 +0200
parents
children 8289ac1b34f4
comparison
equal deleted inserted replaced
3876:e3c1f4736ab2 3877:00212260f659
1 #!/usr/bin/env python3
2
3 # Tests for Libervia's XMPP Date and Time Profile formatting and parsing plugin
4 # Copyright (C) 2022-2022 Tim Henkes (me@syndace.dev)
5
6 # This program is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU Affero General Public License as published by
8 # the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU Affero General Public License for more details.
15
16 # You should have received a copy of the GNU Affero General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
19 # Type-check with `mypy --strict`
20 # Lint with `pylint`
21
22 from datetime import date, datetime, time, timezone
23
24 import pytest
25
26 from sat.plugins.plugin_xep_0082 import XEP_0082
27
28
29 __all__ = [ # pylint: disable=unused-variable
30 "test_date_formatting",
31 "test_date_parsing",
32 "test_datetime_formatting",
33 "test_datetime_parsing",
34 "test_time_formatting",
35 "test_time_parsing"
36 ]
37
38
39 def test_date_formatting() -> None: # pylint: disable=missing-function-docstring
40 # The following tests don't check the output of format_date directly; instead, they
41 # assume that parse_date rejects incorrect formatting.
42
43 # The date version 0.1 of XEP-0082 was published
44 value = date(2003, 4, 21)
45
46 # Check that the parsed date equals the formatted date
47 assert XEP_0082.parse_date(XEP_0082.format_date(value)) == value
48
49 # Check that a date instance is returned when format_date is called without an
50 # explicit input date
51 assert isinstance(XEP_0082.parse_date(XEP_0082.format_date()), date)
52
53
54 def test_date_parsing() -> None: # pylint: disable=missing-function-docstring
55 # There isn't really a point in testing much more than this
56 assert XEP_0082.parse_date("2003-04-21") == date(2003, 4, 21)
57
58
59 def test_datetime_formatting() -> None: # pylint: disable=missing-function-docstring
60 # The following tests don't check the output of format_datetime directly; instead,
61 # they assume that parse_datetime rejects incorrect formatting.
62
63 # A datetime in UTC
64 value = datetime(1234, 5, 6, 7, 8, 9, 123456, timezone.utc)
65
66 # Check that the parsed datetime equals the formatted datetime except for the
67 # microseconds
68 parsed = XEP_0082.parse_datetime(XEP_0082.format_datetime(value))
69 assert parsed != value
70 assert parsed.replace(microsecond=123456) == value
71
72 # Check that the parsed datetime equals the formatted datetime including microseconds
73 assert XEP_0082.parse_datetime(XEP_0082.format_datetime(value, True)) == value
74
75 # A datetime in some other timezone, from the Python docs of the datetime module
76 value = datetime.fromisoformat("2011-11-04T00:05:23+04:00")
77
78 # Check that the parsed datetime equals the formatted datetime with or without
79 # microseconds
80 assert XEP_0082.parse_datetime(XEP_0082.format_datetime(value)) == value
81 assert XEP_0082.parse_datetime(XEP_0082.format_datetime(value, True)) == value
82
83 # Check that the datetime was converted to UTC while formatting
84 assert XEP_0082.parse_datetime(XEP_0082.format_datetime(value)).tzinfo == timezone.utc
85
86 # Check that a datetime instance is returned when format_datetime is called without an
87 # explicit input
88 # datetime
89 assert isinstance(XEP_0082.parse_datetime(XEP_0082.format_datetime()), datetime)
90 assert isinstance(XEP_0082.parse_datetime(XEP_0082.format_datetime(
91 include_microsecond=True
92 )), datetime)
93 assert XEP_0082.parse_datetime(XEP_0082.format_datetime()).tzinfo == timezone.utc
94
95
96 def test_datetime_parsing() -> None: # pylint: disable=missing-function-docstring
97 # Datetime of the first human steps on the Moon (UTC)
98 value = datetime(1969, 7, 21, 2, 56, 15, tzinfo=timezone.utc)
99
100 # With timezone 'Z', without a fraction of a second
101 assert XEP_0082.parse_datetime("1969-07-21T02:56:15Z") == value
102
103 # With timezone '+04:00', without a fraction of a second
104 assert XEP_0082.parse_datetime("1969-07-21T06:56:15+04:00") == value
105
106 # With timezone '-05:00', without a fraction of a second
107 assert XEP_0082.parse_datetime("1969-07-20T21:56:15-05:00") == value
108
109 # Without timezone, without a fraction of a second
110 with pytest.raises(ValueError):
111 XEP_0082.parse_datetime("1969-07-21T02:56:15")
112
113 # With timezone 'Z', with a fraction of a second consisting of two digits
114 assert XEP_0082.parse_datetime("1969-07-21T02:56:15.12Z") == \
115 value.replace(microsecond=120000)
116
117 # With timezone 'Z', with a fraction of a second consisting of nine digits
118 assert XEP_0082.parse_datetime("1969-07-21T02:56:15.123456789Z") == \
119 value.replace(microsecond=123456)
120
121 # With timezone '+04:00', with a fraction of a second consisting of six digits
122 assert XEP_0082.parse_datetime("1969-07-21T06:56:15.123456+04:00") == \
123 value.replace(microsecond=123456)
124
125 # With timezone '-05:00', with a fraction of a second consisting of zero digits
126 assert XEP_0082.parse_datetime("1969-07-20T21:56:15.-05:00") == value
127
128 # Without timezone, with a fraction of a second consisting of six digits
129 with pytest.raises(ValueError):
130 XEP_0082.parse_datetime("1969-07-21T02:56:15.123456")
131
132
133 def test_time_formatting() -> None: # pylint: disable=missing-function-docstring
134 # The following tests don't check the output of format_time directly; instead, they
135 # assume that parse_time rejects incorrect formatting.
136
137 # A time in UTC
138 value = time(12, 34, 56, 789012, timezone.utc)
139
140 # Check that the parsed time equals the formatted time except for the microseconds
141 parsed = XEP_0082.parse_time(XEP_0082.format_time(value))
142 assert parsed != value
143 assert parsed.replace(microsecond=789012) == value
144
145 # Check that the parsed time equals the formatted time including microseconds
146 assert XEP_0082.parse_time(XEP_0082.format_time(value, True)) == value
147
148 # A time in some other timezone, from the Python docs of the datetime module
149 value = time.fromisoformat("04:23:01+04:00")
150
151 # Check that the parsed time equals the formatted time with or without microseconds
152 assert XEP_0082.parse_time(XEP_0082.format_time(value)) == value
153 assert XEP_0082.parse_time(XEP_0082.format_time(value, True)) == value
154
155 # Check that the time has retained its timezone
156 assert XEP_0082.parse_time(XEP_0082.format_time(value)).tzinfo == value.tzinfo
157
158 # A time without timezone information, from the Python docs of the datetime module
159 value = time.fromisoformat("04:23:01")
160
161 # Check that the parsed time doesn't have timezone information either
162 assert XEP_0082.parse_time(XEP_0082.format_time(value)).tzinfo is None
163
164 # Check that a time instance is returned when format_time is called without an
165 # explicit input date
166 assert isinstance(XEP_0082.parse_time(XEP_0082.format_time()), time)
167 assert isinstance(XEP_0082.parse_time(XEP_0082.format_time(
168 include_microsecond=True
169 )), time)
170 assert XEP_0082.parse_time(XEP_0082.format_time()).tzinfo == timezone.utc
171
172
173 def test_time_parsing() -> None: # pylint: disable=missing-function-docstring
174 # Time for tea
175 value = time(16, 0, 0, tzinfo=timezone.utc)
176
177 # With timezone 'Z', without a fraction of a second
178 assert XEP_0082.parse_time("16:00:00Z") == value
179
180 # With timezone '+04:00', without a fraction of a second
181 assert XEP_0082.parse_time("20:00:00+04:00") == value
182
183 # With timezone '-05:00', without a fraction of a second
184 assert XEP_0082.parse_time("11:00:00-05:00") == value
185
186 # Without a timezone, without a fraction of a second
187 assert XEP_0082.parse_time("16:00:00") == value.replace(tzinfo=None)
188
189 # With timezone 'Z', with a fraction of a second consisting of two digits
190 assert XEP_0082.parse_time("16:00:00.12Z") == value.replace(microsecond=120000)
191
192 # With timezone 'Z', with a fraction of a second consisting of nine digits
193 assert XEP_0082.parse_time("16:00:00.123456789Z") == value.replace(microsecond=123456)
194
195 # With timezone '+04:00', with a fraction of a second consisting of six digits
196 assert XEP_0082.parse_time("20:00:00.123456+04:00") == \
197 value.replace(microsecond=123456)
198
199 # With timezone '-05:00', with a fraction of a second consisting of zero digits
200 assert XEP_0082.parse_time("11:00:00.-05:00") == value
201
202 # Without a timezone, with a fraction of a second consisting of six digits
203 assert XEP_0082.parse_time("16:00:00.123456") == \
204 value.replace(microsecond=123456, tzinfo=None)