This repository has been archived on 2024-12-22. You can view files and clone it, but cannot push or open issues or pull requests.
PyBitmessage-2024-12-22/mockenv/lib/python3.6/site-packages/tempora/tests/test_schedule.py
2022-07-22 16:13:59 +05:30

150 lines
4.7 KiB
Python

import time
import random
import datetime
from unittest import mock
import pytest
import pytz
import freezegun
from tempora import schedule
do_nothing = type(None)
def test_delayed_command_order():
"""
delayed commands should be sorted by delay time
"""
delays = [random.randint(0, 99) for x in range(5)]
cmds = sorted(
[schedule.DelayedCommand.after(delay, do_nothing) for delay in delays]
)
assert [c.delay.seconds for c in cmds] == sorted(delays)
def test_periodic_command_delay():
"A PeriodicCommand must have a positive, non-zero delay."
with pytest.raises(ValueError) as exc_info:
schedule.PeriodicCommand.after(0, None)
assert str(exc_info.value) == test_periodic_command_delay.__doc__
def test_periodic_command_fixed_delay():
"""
Test that we can construct a periodic command with a fixed initial
delay.
"""
fd = schedule.PeriodicCommandFixedDelay.at_time(
at=schedule.now(), delay=datetime.timedelta(seconds=2), target=lambda: None
)
assert fd.due() is True
assert fd.next().due() is False
class TestCommands:
def test_delayed_command_from_timestamp(self):
"""
Ensure a delayed command can be constructed from a timestamp.
"""
t = time.time()
schedule.DelayedCommand.at_time(t, do_nothing)
def test_command_at_noon(self):
"""
Create a periodic command that's run at noon every day.
"""
when = datetime.time(12, 0, tzinfo=pytz.utc)
cmd = schedule.PeriodicCommandFixedDelay.daily_at(when, target=None)
assert cmd.due() is False
next_cmd = cmd.next()
daily = datetime.timedelta(days=1)
day_from_now = schedule.now() + daily
two_days_from_now = day_from_now + daily
assert day_from_now < next_cmd < two_days_from_now
@pytest.mark.parametrize("hour", range(10, 14))
@pytest.mark.parametrize("tz_offset", (14, -14))
def test_command_at_noon_distant_local(self, hour, tz_offset):
"""
Run test_command_at_noon, but with the local timezone
more than 12 hours away from UTC.
"""
with freezegun.freeze_time(f"2020-01-10 {hour:02}:01", tz_offset=tz_offset):
self.test_command_at_noon()
class TestTimezones:
def test_alternate_timezone_west(self):
target_tz = pytz.timezone('US/Pacific')
target = schedule.now().astimezone(target_tz)
cmd = schedule.DelayedCommand.at_time(target, target=None)
assert cmd.due()
def test_alternate_timezone_east(self):
target_tz = pytz.timezone('Europe/Amsterdam')
target = schedule.now().astimezone(target_tz)
cmd = schedule.DelayedCommand.at_time(target, target=None)
assert cmd.due()
def test_daylight_savings(self):
"""
A command at 9am should always be 9am regardless of
a DST boundary.
"""
with freezegun.freeze_time('2018-03-10 08:00:00'):
target_tz = pytz.timezone('US/Eastern')
target_time = datetime.time(9, tzinfo=target_tz)
cmd = schedule.PeriodicCommandFixedDelay.daily_at(
target_time, target=lambda: None
)
def naive(dt):
return dt.replace(tzinfo=None)
assert naive(cmd) == datetime.datetime(2018, 3, 10, 9, 0, 0)
next_ = cmd.next()
assert naive(next_) == datetime.datetime(2018, 3, 11, 9, 0, 0)
assert next_ - cmd == datetime.timedelta(hours=23)
class TestScheduler:
def test_invoke_scheduler(self):
sched = schedule.InvokeScheduler()
target = mock.MagicMock()
cmd = schedule.DelayedCommand.after(0, target)
sched.add(cmd)
sched.run_pending()
target.assert_called_once()
assert not sched.queue
def test_callback_scheduler(self):
callback = mock.MagicMock()
sched = schedule.CallbackScheduler(callback)
target = mock.MagicMock()
cmd = schedule.DelayedCommand.after(0, target)
sched.add(cmd)
sched.run_pending()
callback.assert_called_once_with(target)
def test_periodic_command(self):
sched = schedule.InvokeScheduler()
target = mock.MagicMock()
before = datetime.datetime.utcnow()
cmd = schedule.PeriodicCommand.after(10, target)
sched.add(cmd)
sched.run_pending()
target.assert_not_called()
with freezegun.freeze_time(before + datetime.timedelta(seconds=15)):
sched.run_pending()
assert sched.queue
target.assert_called_once()
with freezegun.freeze_time(before + datetime.timedelta(seconds=25)):
sched.run_pending()
assert target.call_count == 2