mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-26 19:01:39 -04:00
Python 3.11 is now required, old versions were causing unpredictability in tests. (Sanic does not yet support 3.12) Sanic has been upgraded to 23.6.0, which is the latest version that avoids this bug: https://github.com/sanic-org/sanic/issues/2921 New strategy for multiprocessing is to create all multiprocessing tools in one process, then fork to other processes. The previous strategy was to declare multiprocessing tools at the top of every file, or wherever they were needed at import/creation. Now all multiprocessing tools are attached to the app.shared_ctx. This means `api_app` is imported in many, many places. This forced a change in how the DownloadManager works. Previously, it would continually run download workers which would pull downloads from a multiprocessing.Queue. Now, a single worker checks for new downloads and sends a Sanic signal. Flags have been reworked to use the `api_app`. I removed the `which` flag functionality because the `which` are called at import and needed their own multiprocessing.Event.
195 lines
7.7 KiB
Python
195 lines
7.7 KiB
Python
from datetime import datetime, timezone
|
|
|
|
import pytest
|
|
|
|
from modules.videos.lib import save_channels_config
|
|
from modules.videos.models import Video
|
|
from wrolpi.errors import FileGroupIsTagged
|
|
from wrolpi.files import lib as files_lib
|
|
from wrolpi.files.models import FileGroup
|
|
|
|
|
|
def test_delete_video_no_channel(test_session, simple_video):
|
|
"""A Video can be deleted even if it does not have a channel."""
|
|
assert simple_video.channel
|
|
simple_video.channel_id = None
|
|
test_session.commit()
|
|
|
|
paths = list(simple_video.file_group.my_paths())
|
|
|
|
assert not simple_video.channel
|
|
simple_video.delete()
|
|
|
|
# All files were deleted.
|
|
for path in paths:
|
|
assert not path.exists()
|
|
|
|
test_session.commit()
|
|
|
|
assert test_session.query(FileGroup).count() == 0
|
|
assert test_session.query(Video).count() == 0
|
|
|
|
|
|
def test_delete_video(test_session, video_factory):
|
|
"""When a Video record is deleted, all referenced file records should be deleted."""
|
|
video = video_factory(with_video_file=True, with_poster_ext='png')
|
|
test_session.commit()
|
|
|
|
assert video.video_path.is_file(), 'Video file was not created.'
|
|
assert video.poster_path.is_file(), 'Video poster was not created.'
|
|
assert test_session.query(Video).count() == 1, 'Video was not created.'
|
|
assert test_session.query(FileGroup).count() == 1, 'Video file and poster file were not created.'
|
|
|
|
video.delete()
|
|
test_session.commit()
|
|
assert test_session.query(Video).count() == 0, 'Video was not deleted.'
|
|
assert test_session.query(FileGroup).count() == 0, 'Video files were not deleted.'
|
|
|
|
|
|
def test_delete_video_with_tag(test_session, video_factory, tag_factory):
|
|
"""You cannot delete a video with a tag."""
|
|
video = video_factory(with_video_file=True, with_poster_ext='png')
|
|
tag = tag_factory()
|
|
video.add_tag(tag)
|
|
test_session.commit()
|
|
|
|
with pytest.raises(FileGroupIsTagged):
|
|
video.delete()
|
|
|
|
# Video was not deleted.
|
|
test_session.commit()
|
|
assert test_session.query(Video).count() == 1
|
|
assert test_session.query(FileGroup).count() == 1
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_video_channel_refresh(test_session, test_directory, channel_factory, video_factory):
|
|
"""A Video will be associated with a Channel when it's files are in that Channel's directory."""
|
|
# Create a video file in this channel's directory.
|
|
channel = channel_factory()
|
|
video1_path = channel.directory / 'video1.mp4'
|
|
video_factory(channel_id=channel.id, with_video_file=video1_path, with_poster_ext='jpg')
|
|
# Create another video outside the channel's directory. It should not have a channel.
|
|
video2_path = test_directory / 'video2.mp4'
|
|
video_factory(with_video_file=video2_path)
|
|
# Delete all FileGroups so the channel will be associated again.
|
|
test_session.query(FileGroup).delete()
|
|
test_session.commit()
|
|
|
|
await files_lib.refresh_files()
|
|
|
|
assert test_session.query(FileGroup).count() == 2
|
|
assert test_session.query(Video).count() == 2
|
|
|
|
# The video is associated with `simple_channel` because its file is in the Channel's directory.
|
|
video1: Video = Video.get_by_path(video1_path, test_session)
|
|
video2: Video = Video.get_by_path(video2_path, test_session)
|
|
assert video1.channel == channel
|
|
assert not video2.channel
|
|
assert video1.__json__()['video']['channel']
|
|
video_channel = video1.__json__()['video']['channel']
|
|
assert video_channel['id'] == channel.id
|
|
assert video_channel['name'] == channel.name
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_delete_duplicate_video(test_session, channel_factory, video_factory, tag_factory):
|
|
"""If duplicate Video's exist, and everything about the files matches, delete a random one."""
|
|
channel = channel_factory(name='Channel Name')
|
|
video_path = channel.directory / f'{channel.name}_20000101_ABC123456_The video title.mp4'
|
|
|
|
channel.info_json = {'entries': [{'id': 'ABC123456', 'title': 'The video title'}]}
|
|
entry = channel.info_json['entries'][0]
|
|
|
|
tag = tag_factory()
|
|
vid1 = video_factory(
|
|
channel_id=channel.id,
|
|
title=f'{channel.name}_20000101_ABC123456_The video title',
|
|
upload_date=datetime(2000, 1, 1, tzinfo=timezone.utc),
|
|
source_id='ABC123456',
|
|
with_video_file=True,
|
|
with_info_json=True,
|
|
with_caption_file=True,
|
|
tag_names=[tag.name, ]
|
|
)
|
|
vid2 = video_factory(
|
|
channel_id=channel.id,
|
|
title=f'{channel.name}_20000101_ABC123456_The video title ', # Video was renamed, trailing space was removed.
|
|
upload_date=datetime(2000, 1, 1, tzinfo=timezone.utc),
|
|
source_id='ABC123456',
|
|
with_video_file=True,
|
|
with_info_json=True,
|
|
with_caption_file=True,
|
|
)
|
|
vid1.file_group.url = vid2.file_group.url = 'https://example.com/video'
|
|
|
|
assert test_session.query(Video).count() == 2
|
|
|
|
test_session.commit()
|
|
|
|
assert await Video.delete_duplicate_videos(test_session, 'https://example.com/video', entry['id'], video_path)
|
|
test_session.commit()
|
|
|
|
assert test_session.query(Video).count() == 1, 'Duplicate video was not deleted.'
|
|
video = test_session.query(Video).one()
|
|
assert video.video_path == video_path, 'Video path does not match'
|
|
assert video.video_path.is_file()
|
|
assert set(channel.directory.iterdir()) == set(video.file_group.my_paths())
|
|
assert video.file_group.tag_names == [tag.name, ]
|
|
|
|
# Running again has no effect.
|
|
assert not await Video.delete_duplicate_videos(test_session, 'https://example.com/video', entry['id'], video_path)
|
|
test_session.commit()
|
|
|
|
assert test_session.query(Video).count() == 1, 'Duplicate video was not deleted.'
|
|
video = test_session.query(Video).one()
|
|
assert video.video_path.is_file()
|
|
assert video.video_path == video_path, 'Video path does not match'
|
|
assert set(channel.directory.iterdir()) == set(video.file_group.my_paths())
|
|
assert video.file_group.tag_names == [tag.name, ]
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_delete_renamed_video(test_session, channel_factory, video_factory, tag_factory):
|
|
"""If duplicate Video's exist, delete all the videos that do not have the new title."""
|
|
channel = channel_factory(name='Channel Name')
|
|
video_path = channel.directory / f'{channel.name}_20000101_ABC123456_Some new title.mp4'
|
|
|
|
channel.info_json = {'entries': [{'id': 'ABC123456', 'title': 'Some new title'}]}
|
|
entry = channel.info_json['entries'][0]
|
|
|
|
tag = tag_factory()
|
|
vid1 = video_factory(
|
|
channel_id=channel.id,
|
|
title=f'{channel.name}_20000101_ABC123456_The video title',
|
|
upload_date=datetime(2000, 1, 1, tzinfo=timezone.utc),
|
|
source_id='ABC123456',
|
|
with_video_file=True,
|
|
with_info_json=True,
|
|
with_caption_file=True,
|
|
tag_names=[tag.name, ]
|
|
)
|
|
vid2 = video_factory(
|
|
channel_id=channel.id,
|
|
title=f'{channel.name}_20000101_ABC123456_The video title ', # Video was renamed, trailing space was removed.
|
|
upload_date=datetime(2000, 1, 1, tzinfo=timezone.utc),
|
|
source_id='ABC123456',
|
|
with_video_file=True,
|
|
with_info_json=True,
|
|
with_caption_file=True,
|
|
)
|
|
vid1.file_group.url = vid2.file_group.url = 'https://example.com/video'
|
|
|
|
assert test_session.query(Video).count() == 2
|
|
|
|
test_session.commit()
|
|
|
|
await Video.delete_duplicate_videos(test_session, 'https://example.com/video', entry['id'], video_path)
|
|
test_session.commit()
|
|
|
|
assert test_session.query(Video).count() == 1, 'Duplicate video was not deleted.'
|
|
video = test_session.query(Video).one()
|
|
assert video.video_path == video_path, 'Video path does not match'
|
|
assert video.video_path.is_file()
|
|
assert set(channel.directory.iterdir()) == set(video.file_group.my_paths())
|
|
assert video.file_group.tag_names == [tag.name, ]
|