- support for both (modern) OMEMO under the `urn:xmpp:omemo:2` namespace and (legacy) OMEMO under the `eu.siacs.conversations.axolotl` namespace - maintains one identity across both versions of OMEMO - migrates data from the old plugin - includes more features for protocol stability - uses SCE for modern OMEMO - fully type-checked, linted and format-checked - added type hints to various pieces of backend code used by the plugin - added stubs for some Twisted APIs used by the plugin under stubs/ (use `export MYPYPATH=stubs/` before running mypy) - core (xmpp): enabled `send` trigger and made it an asyncPoint fix 375
201 lines
8.5 KiB
Python
201 lines
8.5 KiB
Python
#!/usr/bin/env python3
|
|
|
|
# Tests for Libervia's XMPP Date and Time Profile formatting and parsing plugin
|
|
# Copyright (C) 2022-2022 Tim Henkes (me@syndace.dev)
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU Affero General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Affero General Public License for more details.
|
|
|
|
# You should have received a copy of the GNU Affero General Public License
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
from datetime import date, datetime, time, timezone
|
|
|
|
import pytest
|
|
|
|
from sat.plugins.plugin_xep_0082 import XEP_0082
|
|
|
|
|
|
__all__ = [ # pylint: disable=unused-variable
|
|
"test_date_formatting",
|
|
"test_date_parsing",
|
|
"test_datetime_formatting",
|
|
"test_datetime_parsing",
|
|
"test_time_formatting",
|
|
"test_time_parsing"
|
|
]
|
|
|
|
|
|
def test_date_formatting() -> None: # pylint: disable=missing-function-docstring
|
|
# The following tests don't check the output of format_date directly; instead, they
|
|
# assume that parse_date rejects incorrect formatting.
|
|
|
|
# The date version 0.1 of XEP-0082 was published
|
|
value = date(2003, 4, 21)
|
|
|
|
# Check that the parsed date equals the formatted date
|
|
assert XEP_0082.parse_date(XEP_0082.format_date(value)) == value
|
|
|
|
# Check that a date instance is returned when format_date is called without an
|
|
# explicit input date
|
|
assert isinstance(XEP_0082.parse_date(XEP_0082.format_date()), date)
|
|
|
|
|
|
def test_date_parsing() -> None: # pylint: disable=missing-function-docstring
|
|
# There isn't really a point in testing much more than this
|
|
assert XEP_0082.parse_date("2003-04-21") == date(2003, 4, 21)
|
|
|
|
|
|
def test_datetime_formatting() -> None: # pylint: disable=missing-function-docstring
|
|
# The following tests don't check the output of format_datetime directly; instead,
|
|
# they assume that parse_datetime rejects incorrect formatting.
|
|
|
|
# A datetime in UTC
|
|
value = datetime(1234, 5, 6, 7, 8, 9, 123456, timezone.utc)
|
|
|
|
# Check that the parsed datetime equals the formatted datetime except for the
|
|
# microseconds
|
|
parsed = XEP_0082.parse_datetime(XEP_0082.format_datetime(value))
|
|
assert parsed != value
|
|
assert parsed.replace(microsecond=123456) == value
|
|
|
|
# Check that the parsed datetime equals the formatted datetime including microseconds
|
|
assert XEP_0082.parse_datetime(XEP_0082.format_datetime(value, True)) == value
|
|
|
|
# A datetime in some other timezone, from the Python docs of the datetime module
|
|
value = datetime.fromisoformat("2011-11-04T00:05:23+04:00")
|
|
|
|
# Check that the parsed datetime equals the formatted datetime with or without
|
|
# microseconds
|
|
assert XEP_0082.parse_datetime(XEP_0082.format_datetime(value)) == value
|
|
assert XEP_0082.parse_datetime(XEP_0082.format_datetime(value, True)) == value
|
|
|
|
# Check that the datetime was converted to UTC while formatting
|
|
assert XEP_0082.parse_datetime(XEP_0082.format_datetime(value)).tzinfo == timezone.utc
|
|
|
|
# Check that a datetime instance is returned when format_datetime is called without an
|
|
# explicit input
|
|
# datetime
|
|
assert isinstance(XEP_0082.parse_datetime(XEP_0082.format_datetime()), datetime)
|
|
assert isinstance(XEP_0082.parse_datetime(XEP_0082.format_datetime(
|
|
include_microsecond=True
|
|
)), datetime)
|
|
assert XEP_0082.parse_datetime(XEP_0082.format_datetime()).tzinfo == timezone.utc
|
|
|
|
|
|
def test_datetime_parsing() -> None: # pylint: disable=missing-function-docstring
|
|
# Datetime of the first human steps on the Moon (UTC)
|
|
value = datetime(1969, 7, 21, 2, 56, 15, tzinfo=timezone.utc)
|
|
|
|
# With timezone 'Z', without a fraction of a second
|
|
assert XEP_0082.parse_datetime("1969-07-21T02:56:15Z") == value
|
|
|
|
# With timezone '+04:00', without a fraction of a second
|
|
assert XEP_0082.parse_datetime("1969-07-21T06:56:15+04:00") == value
|
|
|
|
# With timezone '-05:00', without a fraction of a second
|
|
assert XEP_0082.parse_datetime("1969-07-20T21:56:15-05:00") == value
|
|
|
|
# Without timezone, without a fraction of a second
|
|
with pytest.raises(ValueError):
|
|
XEP_0082.parse_datetime("1969-07-21T02:56:15")
|
|
|
|
# With timezone 'Z', with a fraction of a second consisting of two digits
|
|
assert XEP_0082.parse_datetime("1969-07-21T02:56:15.12Z") == \
|
|
value.replace(microsecond=120000)
|
|
|
|
# With timezone 'Z', with a fraction of a second consisting of nine digits
|
|
assert XEP_0082.parse_datetime("1969-07-21T02:56:15.123456789Z") == \
|
|
value.replace(microsecond=123456)
|
|
|
|
# With timezone '+04:00', with a fraction of a second consisting of six digits
|
|
assert XEP_0082.parse_datetime("1969-07-21T06:56:15.123456+04:00") == \
|
|
value.replace(microsecond=123456)
|
|
|
|
# With timezone '-05:00', with a fraction of a second consisting of zero digits
|
|
assert XEP_0082.parse_datetime("1969-07-20T21:56:15.-05:00") == value
|
|
|
|
# Without timezone, with a fraction of a second consisting of six digits
|
|
with pytest.raises(ValueError):
|
|
XEP_0082.parse_datetime("1969-07-21T02:56:15.123456")
|
|
|
|
|
|
def test_time_formatting() -> None: # pylint: disable=missing-function-docstring
|
|
# The following tests don't check the output of format_time directly; instead, they
|
|
# assume that parse_time rejects incorrect formatting.
|
|
|
|
# A time in UTC
|
|
value = time(12, 34, 56, 789012, timezone.utc)
|
|
|
|
# Check that the parsed time equals the formatted time except for the microseconds
|
|
parsed = XEP_0082.parse_time(XEP_0082.format_time(value))
|
|
assert parsed != value
|
|
assert parsed.replace(microsecond=789012) == value
|
|
|
|
# Check that the parsed time equals the formatted time including microseconds
|
|
assert XEP_0082.parse_time(XEP_0082.format_time(value, True)) == value
|
|
|
|
# A time in some other timezone, from the Python docs of the datetime module
|
|
value = time.fromisoformat("04:23:01+04:00")
|
|
|
|
# Check that the parsed time equals the formatted time with or without microseconds
|
|
assert XEP_0082.parse_time(XEP_0082.format_time(value)) == value
|
|
assert XEP_0082.parse_time(XEP_0082.format_time(value, True)) == value
|
|
|
|
# Check that the time has retained its timezone
|
|
assert XEP_0082.parse_time(XEP_0082.format_time(value)).tzinfo == value.tzinfo
|
|
|
|
# A time without timezone information, from the Python docs of the datetime module
|
|
value = time.fromisoformat("04:23:01")
|
|
|
|
# Check that the parsed time doesn't have timezone information either
|
|
assert XEP_0082.parse_time(XEP_0082.format_time(value)).tzinfo is None
|
|
|
|
# Check that a time instance is returned when format_time is called without an
|
|
# explicit input date
|
|
assert isinstance(XEP_0082.parse_time(XEP_0082.format_time()), time)
|
|
assert isinstance(XEP_0082.parse_time(XEP_0082.format_time(
|
|
include_microsecond=True
|
|
)), time)
|
|
assert XEP_0082.parse_time(XEP_0082.format_time()).tzinfo == timezone.utc
|
|
|
|
|
|
def test_time_parsing() -> None: # pylint: disable=missing-function-docstring
|
|
# Time for tea
|
|
value = time(16, 0, 0, tzinfo=timezone.utc)
|
|
|
|
# With timezone 'Z', without a fraction of a second
|
|
assert XEP_0082.parse_time("16:00:00Z") == value
|
|
|
|
# With timezone '+04:00', without a fraction of a second
|
|
assert XEP_0082.parse_time("20:00:00+04:00") == value
|
|
|
|
# With timezone '-05:00', without a fraction of a second
|
|
assert XEP_0082.parse_time("11:00:00-05:00") == value
|
|
|
|
# Without a timezone, without a fraction of a second
|
|
assert XEP_0082.parse_time("16:00:00") == value.replace(tzinfo=None)
|
|
|
|
# With timezone 'Z', with a fraction of a second consisting of two digits
|
|
assert XEP_0082.parse_time("16:00:00.12Z") == value.replace(microsecond=120000)
|
|
|
|
# With timezone 'Z', with a fraction of a second consisting of nine digits
|
|
assert XEP_0082.parse_time("16:00:00.123456789Z") == value.replace(microsecond=123456)
|
|
|
|
# With timezone '+04:00', with a fraction of a second consisting of six digits
|
|
assert XEP_0082.parse_time("20:00:00.123456+04:00") == \
|
|
value.replace(microsecond=123456)
|
|
|
|
# With timezone '-05:00', with a fraction of a second consisting of zero digits
|
|
assert XEP_0082.parse_time("11:00:00.-05:00") == value
|
|
|
|
# Without a timezone, with a fraction of a second consisting of six digits
|
|
assert XEP_0082.parse_time("16:00:00.123456") == \
|
|
value.replace(microsecond=123456, tzinfo=None)
|