mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-26 19:01:39 -04:00
317 lines
9.8 KiB
Python
317 lines
9.8 KiB
Python
import unittest
|
|
from datetime import date, datetime
|
|
|
|
import pytest
|
|
from sanic_openapi import doc
|
|
|
|
from wrolpi.common import combine_dicts, insert_parameter, date_range, api_param_limiter
|
|
from wrolpi.dates import set_timezone, now
|
|
from wrolpi.errors import NoBodyContents, MissingRequiredField, ExcessJSONFields, InvalidTimezone
|
|
from wrolpi.schema import validate_data
|
|
from wrolpi.test.common import build_test_directories, wrap_media_directory
|
|
|
|
|
|
class Model:
|
|
name = doc.String(required=True)
|
|
count = doc.Integer(required=True)
|
|
fish = doc.Tuple()
|
|
on = doc.Boolean()
|
|
obj = doc.Dictionary()
|
|
many = doc.Float()
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
'data,expected',
|
|
(
|
|
(
|
|
dict(name='foo', count='4'),
|
|
dict(name='foo', count=4),
|
|
),
|
|
(
|
|
dict(name='foo', count=4, fish=['red', 'blue'], on='false'),
|
|
dict(name='foo', count=4, fish=('red', 'blue'), on=False),
|
|
),
|
|
(
|
|
dict(name='foo', count=4, fish=['red', 'blue'], on='true'),
|
|
dict(name='foo', count=4, fish=('red', 'blue'), on=True),
|
|
),
|
|
(
|
|
dict(name='foo', count=4, fish=['red', 'blue'], on='t'),
|
|
dict(name='foo', count=4, fish=('red', 'blue'), on=True),
|
|
),
|
|
(
|
|
dict(name='foo', count=4, fish=['red', 'blue'], on=1),
|
|
dict(name='foo', count=4, fish=('red', 'blue'), on=True),
|
|
),
|
|
(
|
|
dict(name='foo', count=1.5, obj={'foo': 'bar'}),
|
|
dict(name='foo', count=1, obj={'foo': 'bar'}),
|
|
),
|
|
(
|
|
dict(name='foo', count=1.5, many='10.3'),
|
|
dict(name='foo', count=1, many=10.3),
|
|
),
|
|
)
|
|
)
|
|
def test_validate_doc(data, expected):
|
|
model = Model()
|
|
result = validate_data(model, data)
|
|
assert result == expected
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
'data,expected',
|
|
(
|
|
(dict(), NoBodyContents),
|
|
(dict(name='foo'), MissingRequiredField),
|
|
(dict(name='foo', count=10, extra='too many'), ExcessJSONFields),
|
|
)
|
|
)
|
|
def test_validate_doc_errors(data, expected):
|
|
model = Model()
|
|
pytest.raises(expected, validate_data, model, data)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
'data,expected',
|
|
(
|
|
(
|
|
[dict()],
|
|
dict()
|
|
), (
|
|
[dict(a='b')],
|
|
dict(a='b')
|
|
), (
|
|
[dict(a='b'), dict(b='c')],
|
|
dict(a='b', b='c')
|
|
), (
|
|
[dict(b='c'), dict(a='b')],
|
|
dict(a='b', b='c'),
|
|
), (
|
|
[dict(a=dict(b='c'), d='e'), dict(a=(dict(f='g')))],
|
|
dict(a=dict(b='c', f='g'), d='e'),
|
|
), (
|
|
[dict(a=dict(b='c'), d='e'), dict(a=(dict(b='g')))],
|
|
dict(a=dict(b='c'), d='e'),
|
|
), (
|
|
[dict(a=dict(b='c'), d=[1, 2, 3]), dict(a=(dict(b='g')))],
|
|
dict(a=dict(b='c'), d=[1, 2, 3]),
|
|
), (
|
|
[dict(a='b', c=dict(d='e')), dict(a='c', e='f')],
|
|
dict(a='b', c=dict(d='e'), e='f')
|
|
), (
|
|
[dict(a='b'), dict(a='c', d='e'), dict(e='f', a='d')],
|
|
dict(a='b', d='e', e='f')
|
|
), (
|
|
[dict(a='b'), dict(), dict(e='f', a='d')],
|
|
dict(a='b', e='f')
|
|
)
|
|
)
|
|
)
|
|
def test_combine_dicts(data, expected):
|
|
assert combine_dicts(*data) == expected
|
|
|
|
|
|
def test_build_video_directories():
|
|
with wrap_media_directory():
|
|
structure = [
|
|
'channel1/vid1.mp4',
|
|
]
|
|
with build_test_directories(structure) as tempdir:
|
|
assert (tempdir / 'channel1').is_dir()
|
|
assert (tempdir / 'channel1/vid1.mp4').is_file()
|
|
|
|
structure = [
|
|
'channel2/',
|
|
'channel2.1/channel2.2/',
|
|
]
|
|
with build_test_directories(structure) as tempdir:
|
|
assert (tempdir / 'channel2').is_dir()
|
|
assert (tempdir / 'channel2.1/channel2.2').is_dir()
|
|
|
|
structure = [
|
|
'channel3/vid1.mp4',
|
|
'channel3/vid2.mp4',
|
|
'channel4/vid1.mp4',
|
|
'channel4/vid1.en.vtt',
|
|
'channel5/',
|
|
]
|
|
with build_test_directories(structure) as tempdir:
|
|
assert (tempdir / 'channel3/vid1.mp4').is_file()
|
|
assert (tempdir / 'channel3').is_dir()
|
|
assert (tempdir / 'channel3/vid2.mp4').is_file()
|
|
assert (tempdir / 'channel4/vid1.mp4').is_file()
|
|
assert (tempdir / 'channel4/vid1.en.vtt').is_file()
|
|
assert (tempdir / 'channel5').is_dir()
|
|
|
|
structure = [
|
|
'channel6/subdirectory/vid1.mp4',
|
|
]
|
|
with build_test_directories(structure) as tempdir:
|
|
assert (tempdir / 'channel6/subdirectory').is_dir()
|
|
assert (tempdir / 'channel6/subdirectory/vid1.mp4').is_file()
|
|
|
|
|
|
def test_insert_parameter():
|
|
"""
|
|
A convenience function exists that inserts a parameter or keyword argument into the provided args/kwargs,
|
|
wherever that may be according to the function's signature.
|
|
"""
|
|
|
|
def func(foo, bar):
|
|
pass
|
|
|
|
results = insert_parameter(func, 'bar', 'bar', (1,), {})
|
|
assert results == ((1, 'bar'), {})
|
|
|
|
def func(foo, bar, baz):
|
|
pass
|
|
|
|
results = insert_parameter(func, 'bar', 'bar', (1, 2), {})
|
|
assert results == ((1, 'bar', 2), {})
|
|
|
|
def func(foo, baz, bar=None):
|
|
pass
|
|
|
|
results = insert_parameter(func, 'bar', 'bar', (1, 2), {})
|
|
assert results == ((1, 2, 'bar'), {})
|
|
|
|
def func(foo, baz, bar=None):
|
|
pass
|
|
|
|
results = insert_parameter(func, 'baz', 'baz', (1, 2), {})
|
|
assert results == ((1, 'baz', 2), {})
|
|
|
|
def func(foo, baz, qux=None, bar=None):
|
|
pass
|
|
|
|
results = insert_parameter(func, 'bar', 'bar', (1, 2, 3), {})
|
|
assert results == ((1, 2, 3, 'bar'), {})
|
|
|
|
# bar is not defined as a parameter!
|
|
def func(foo):
|
|
pass
|
|
|
|
pytest.raises(TypeError, insert_parameter, func, 'bar', 'bar', (1,), {})
|
|
|
|
|
|
class TestCommon(unittest.TestCase):
|
|
|
|
def test_date_range(self):
|
|
# A single step results in the start.
|
|
result = date_range(date(1970, 1, 1), date(1970, 1, 2), 1)
|
|
assert result == [
|
|
date(1970, 1, 1),
|
|
]
|
|
|
|
# Many steps on a single day results in the same day.
|
|
result = date_range(date(1970, 1, 1), date(1970, 1, 1), 5)
|
|
assert result == [
|
|
date(1970, 1, 1),
|
|
date(1970, 1, 1),
|
|
date(1970, 1, 1),
|
|
date(1970, 1, 1),
|
|
date(1970, 1, 1),
|
|
]
|
|
|
|
# Many steps on a single datetime results in a range of times.
|
|
result = date_range(datetime(1970, 1, 1), datetime(1970, 1, 1, 23, 59, 59), 5)
|
|
assert result == [
|
|
datetime(1970, 1, 1, 0, 0),
|
|
datetime(1970, 1, 1, 4, 47, 59, 800000),
|
|
datetime(1970, 1, 1, 9, 35, 59, 600000),
|
|
datetime(1970, 1, 1, 14, 23, 59, 400000),
|
|
datetime(1970, 1, 1, 19, 11, 59, 200000),
|
|
]
|
|
|
|
# date_range is not inclusive, like range().
|
|
result = date_range(date(1970, 1, 1), date(1970, 1, 5), 4)
|
|
assert result == [
|
|
date(1970, 1, 1),
|
|
date(1970, 1, 2),
|
|
date(1970, 1, 3),
|
|
date(1970, 1, 4),
|
|
]
|
|
|
|
# Reversed dates are supported.
|
|
result = date_range(date(1970, 1, 5), date(1970, 1, 1), 4)
|
|
assert result == [
|
|
date(1970, 1, 5),
|
|
date(1970, 1, 4),
|
|
date(1970, 1, 3),
|
|
date(1970, 1, 2),
|
|
]
|
|
|
|
# Large date spans are supported.
|
|
result = date_range(date(1970, 1, 1), date(2020, 5, 1), 4)
|
|
assert result == [
|
|
date(1970, 1, 1),
|
|
date(1982, 8, 1),
|
|
date(1995, 3, 2),
|
|
date(2007, 10, 1),
|
|
]
|
|
|
|
result = date_range(datetime(1970, 1, 1, 0, 0, 0), datetime(1970, 1, 1, 10, 0), 8)
|
|
assert result == [
|
|
datetime(1970, 1, 1, 0, 0),
|
|
datetime(1970, 1, 1, 1, 15),
|
|
datetime(1970, 1, 1, 2, 30),
|
|
datetime(1970, 1, 1, 3, 45),
|
|
datetime(1970, 1, 1, 5, 0),
|
|
datetime(1970, 1, 1, 6, 15),
|
|
datetime(1970, 1, 1, 7, 30),
|
|
datetime(1970, 1, 1, 8, 45),
|
|
]
|
|
|
|
# More steps than days
|
|
result = date_range(date(1970, 1, 1), date(1970, 1, 7), 10)
|
|
assert result == [
|
|
date(1970, 1, 1),
|
|
date(1970, 1, 1),
|
|
date(1970, 1, 2),
|
|
date(1970, 1, 2),
|
|
date(1970, 1, 3),
|
|
date(1970, 1, 4),
|
|
date(1970, 1, 4),
|
|
date(1970, 1, 5),
|
|
date(1970, 1, 5),
|
|
date(1970, 1, 6),
|
|
]
|
|
|
|
def test_set_timezone(self):
|
|
"""
|
|
The global timezone can be changed. Invalid timezones are rejected.
|
|
"""
|
|
original_timezone = now().tzinfo
|
|
|
|
try:
|
|
self.assertRaises(InvalidTimezone, set_timezone, '')
|
|
self.assertEqual(now().tzinfo, original_timezone)
|
|
|
|
set_timezone('US/Pacific')
|
|
self.assertNotEqual(now().tzinfo, original_timezone)
|
|
finally:
|
|
# Restore the timezone before the test.
|
|
set_timezone(original_timezone)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
'i,expected', [
|
|
(1, 1),
|
|
(100, 100),
|
|
(150, 100),
|
|
(-1, -1),
|
|
(-1.0, -1.0),
|
|
(1.0, 1.0),
|
|
(100.0, 100.0),
|
|
(150.0, 100.0),
|
|
('1', 1),
|
|
(None, 20),
|
|
(0, 20),
|
|
(0.0, 20),
|
|
('', 20),
|
|
]
|
|
)
|
|
def test_api_param_limiter(i, expected):
|
|
limiter = api_param_limiter(100) # should never return an integer greater than 100.
|
|
assert limiter(i) == expected
|