"""Tests for stream info module.""" from typing import Any from unittest.mock import MagicMock, call, patch import pytest from _pytest.monkeypatch import MonkeyPatch from freezegun import freeze_time from assets.config import SYSTEM_ORCHARD_USER_ID from assets.constants import error as error_constants from assets.exceptions import ( AssetEncodingInProgress, AssetFinalNotFound, AssetUploadNotFound, WrongAssetStatus, ) from assets.logic import stream_info from assets.models import asset_final, asset_status, asset_upload from assets.utils import wowza user_id = "123" ip_address = "0.0.0.0" expected_start_time = 946684702 expected_end_time = 946685802 freeze_timestamp = "2000-01-01 00:00:02" STEREO_UPLOAD_TYPE_ID = 1 @pytest.fixture(autouse=True) def mock_resolve_asset_upload_type_id(monkeypatch: MonkeyPatch) -> None: """Mock resolve_asset_upload_type_id to avoid DB calls in unit tests.""" monkeypatch.setattr( stream_info, "resolve_asset_upload_type_id", MagicMock(return_value=STEREO_UPLOAD_TYPE_ID), ) @pytest.fixture def fixture_track_id() -> int: """Fixture for track unique id.""" return 10 @pytest.fixture def fixture_asset_upload_success(fixture_track_id: int) -> list[dict[str, Any]]: """Fixture for asset_upload records.""" return [ { "id": 11, "product_id": 555, "track_unique_id": fixture_track_id, "is_correction": 0, } ] @pytest.fixture def fixture_asset_encoding_error() -> dict[str, Any]: """Fixture for encoding error asset_status record.""" return {"asset_upload_id": 11, "status": "encoding_error"} @pytest.fixture def fixture_asset_encoding_in_progress() -> dict[str, Any]: """Fixture for encoding in progress asset_status record.""" return {"asset_upload_id": 11, "status": "validation_complete"} @pytest.fixture def fixture_asset_final() -> dict[str, Any]: """Fixture for asset_final record.""" return { "asset_upload_id": 11, "filename": "some_file.mp3", "asset_type": "MP3_192", "bucket": "some_bucket", } @freeze_time(freeze_timestamp) @patch("assets.logic.stream_info.asset_access_log.create_asset_access_log") def test_get_track_wowza_stream_url_with_correction_assets_success( mock_asset_access_log: MagicMock, monkeypatch: MonkeyPatch, fixture_track_id: int, fixture_asset_upload_success: list[dict[str, Any]], fixture_asset_final: dict[str, Any], ) -> None: """Test for get_track_wowza_stream_url_with_correction_assets success.""" monkeypatch.setattr( asset_upload, "get_latest_asset_upload", MagicMock(return_value=fixture_asset_upload_success), ) monkeypatch.setattr( asset_final, "get_asset_final_by_asset_upload_id_and_type", MagicMock(return_value=fixture_asset_final), ) monkeypatch.setattr( wowza, "get_wowza_secure_access_token", MagicMock(return_value="TOKEN123ABC") ) result = stream_info.get_track_wowza_stream_url_with_correction_assets( track_id=fixture_track_id, user_id=user_id, ip_address=ip_address, referrer="workstation.qaoarch.com", is_correction_mode=False, ) assert result == { "url": "https://qa-test-wowza.theorchard.io/vods3/_definst_/amazons3/mp3:some_bucket/some_file.mp3/" "playlist.m3u8?wowzatokenendtime=946685802&wowzatokenstarttime=946684702&wowzatokenhash=TOKEN123ABC" } @freeze_time(freeze_timestamp) def test_get_track_wowza_stream_url_with_correction_assets_not_found( monkeypatch: MonkeyPatch, fixture_track_id: int ) -> None: """Test for get_track_wowza_stream_url fallback on v1 logic.""" monkeypatch.setattr( asset_upload, "get_latest_asset_upload", MagicMock( side_effect=AssetUploadNotFound( error_constants.ERROR_ASSET_UPLOAD_NOT_FOUND ) ), ) monkeypatch.setattr( wowza, "get_wowza_secure_access_token", MagicMock(return_value="TOKEN123ABC") ) with pytest.raises(AssetUploadNotFound) as exc: stream_info.get_track_wowza_stream_url_with_correction_assets( track_id=fixture_track_id, user_id=user_id, ip_address=ip_address, is_correction_mode=False, ) assert exc.value.description == error_constants.ERROR_ASSET_UPLOAD_NOT_FOUND @patch("assets.logic.stream_info.asset_access_log.create_asset_access_log") def test_get_track_wowza_stream_url_with_correction_assets_failure( mock_asset_access_log: MagicMock, monkeypatch: MonkeyPatch, fixture_track_id: int, fixture_asset_upload_success: list[dict[str, Any]], fixture_asset_encoding_error: dict[str, Any], ) -> None: """Test for get_track_wowza_stream_url failure.""" monkeypatch.setattr( asset_upload, "get_latest_asset_upload", MagicMock(return_value=fixture_asset_upload_success), ) monkeypatch.setattr( asset_final, "get_asset_final_by_asset_upload_id_and_type", MagicMock( side_effect=AssetFinalNotFound(error_constants.ERROR_ASSET_FINAL_NOT_FOUND) ), ) monkeypatch.setattr( asset_status, "get_last_asset_status", MagicMock( side_effect=WrongAssetStatus( error_constants.ERROR_ASSET_WRONG_STATUS.format( status=fixture_asset_encoding_error["status"] ) ) ), ) mock_get_wowza_secure_access_token = MagicMock(return_value="TOKEN123ABC") monkeypatch.setattr( wowza, "get_wowza_secure_access_token", mock_get_wowza_secure_access_token ) with pytest.raises(WrongAssetStatus) as exc: stream_info.get_track_wowza_stream_url_with_correction_assets( track_id=fixture_track_id, user_id=user_id, ip_address=ip_address, is_correction_mode=False, ) assert exc.value.description == error_constants.ERROR_ASSET_WRONG_STATUS.format( status=fixture_asset_encoding_error["status"] ) mock_get_wowza_secure_access_token.assert_not_called() @patch("assets.logic.stream_info.asset_access_log.create_asset_access_log") def test_get_track_wowza_stream_url_with_correction_assets_no_content( mock_asset_access_log: MagicMock, monkeypatch: MonkeyPatch, fixture_track_id: int, fixture_asset_upload_success: list[dict[str, Any]], fixture_asset_encoding_in_progress: dict[str, Any], ) -> None: """Test for get_track_wowza_stream_url when asset is not done encoding.""" monkeypatch.setattr( asset_upload, "get_latest_asset_upload", MagicMock(return_value=fixture_asset_upload_success), ) monkeypatch.setattr( asset_final, "get_asset_final_by_asset_upload_id_and_type", MagicMock( side_effect=AssetFinalNotFound(error_constants.ERROR_ASSET_FINAL_NOT_FOUND) ), ) monkeypatch.setattr( asset_status, "get_last_asset_status", MagicMock( side_effect=AssetEncodingInProgress( error_constants.ERROR_ASSET_WRONG_STATUS.format( status=fixture_asset_encoding_in_progress["status"] ) ) ), ) mock_get_wowza_secure_access_token = MagicMock(return_value="TOKEN123ABC") monkeypatch.setattr( wowza, "get_wowza_secure_access_token", mock_get_wowza_secure_access_token ) with pytest.raises(AssetEncodingInProgress) as exc: stream_info.get_track_wowza_stream_url_with_correction_assets( track_id=fixture_track_id, user_id=user_id, ip_address=ip_address, is_correction_mode=False, ) assert exc.value.description == error_constants.ERROR_ASSET_WRONG_STATUS.format( status=fixture_asset_encoding_in_progress["status"] ) mock_get_wowza_secure_access_token.assert_not_called() @freeze_time(freeze_timestamp) @patch("assets.logic.stream_info.asset_access_log.create_asset_access_log") def test_get_track_wowza_stream_url_with_correction_assets_local( mock_asset_access_log: MagicMock, monkeypatch: MonkeyPatch, fixture_track_id: int, fixture_asset_upload_success: list[dict[str, Any]], fixture_asset_final: dict[str, Any], ) -> None: """Test for get_track_wowza_stream_url success.""" monkeypatch.setattr( asset_upload, "get_latest_asset_upload", MagicMock(return_value=fixture_asset_upload_success), ) monkeypatch.setattr( asset_final, "get_asset_final_by_asset_upload_id_and_type", MagicMock(return_value=fixture_asset_final), ) monkeypatch.setattr( wowza, "get_wowza_secure_access_token", MagicMock(return_value="TOKEN123ABC") ) result = stream_info.get_track_wowza_stream_url_with_correction_assets( track_id=fixture_track_id, user_id=user_id, ip_address=ip_address, referrer="localhost:8080", is_correction_mode=False, ) assert result == { "url": "https://qa-test-wowza.theorchard.io/vods3local/_definst_/amazons3/mp3:some_bucket/some_file.mp3/" "playlist.m3u8?wowzatokenendtime=946685802&wowzatokenstarttime=946684702&wowzatokenhash=TOKEN123ABC" } @freeze_time(freeze_timestamp) @patch("assets.logic.stream_info.asset_access_log.create_asset_access_log") def test_get_track_wowza_stream_url_with_correction_assets_oa( mock_asset_access_log: MagicMock, monkeypatch: MonkeyPatch, fixture_track_id: int, fixture_asset_upload_success: list[dict[str, Any]], fixture_asset_final: dict[str, Any], ) -> None: """Test that an OA user gets the appropriate path.""" monkeypatch.setattr( asset_upload, "get_latest_asset_upload", MagicMock(return_value=fixture_asset_upload_success), ) monkeypatch.setattr( asset_final, "get_asset_final_by_asset_upload_id_and_type", MagicMock(return_value=fixture_asset_final), ) monkeypatch.setattr( wowza, "get_wowza_secure_access_token", MagicMock(return_value="TOKEN123ABC") ) result = stream_info.get_track_wowza_stream_url_with_correction_assets( track_id=fixture_track_id, user_id="oa:123", ip_address=ip_address, referrer="oa.qaoarch.com", ) assert result == { "url": "https://qa-test-wowza.theorchard.io/vods3oa/_definst_/amazons3/mp3:some_bucket/some_file.mp3/" "playlist.m3u8?wowzatokenendtime=946685802&wowzatokenstarttime=946684702&wowzatokenhash=TOKEN123ABC" } @freeze_time(freeze_timestamp) @patch("assets.logic.stream_info.asset_access_log.create_asset_access_log") def test_get_track_wowza_stream_url_with_correction_assets_promo( mock_asset_access_log: MagicMock, monkeypatch: MonkeyPatch, fixture_track_id: int, fixture_asset_upload_success: list[dict[str, Any]], fixture_asset_final: dict[str, Any], ) -> None: """Test that a Promo Player user gets the appropriate path.""" monkeypatch.setattr( asset_upload, "get_latest_asset_upload", MagicMock(return_value=fixture_asset_upload_success), ) monkeypatch.setattr( asset_final, "get_asset_final_by_asset_upload_id_and_type", MagicMock(return_value=fixture_asset_final), ) monkeypatch.setattr( wowza, "get_wowza_secure_access_token", MagicMock(return_value="TOKEN123ABC") ) result = stream_info.get_track_wowza_stream_url_with_correction_assets( track_id=fixture_track_id, user_id=SYSTEM_ORCHARD_USER_ID, ip_address=ip_address, referrer="promo.qaorch.com", is_correction_mode=False, ) host = "https://qa-aws-wowza.qaorch.com" assert result == { "url": f"{host}/vods3promo/_definst_/amazons3/mp3:some_bucket/some_file.mp3/" "playlist.m3u8?wowzatokenendtime=946685802&wowzatokenstarttime=946684702&wowzatokenhash=TOKEN123ABC" } awal_result = stream_info.get_track_wowza_stream_url_with_correction_assets( track_id=fixture_track_id, user_id=SYSTEM_ORCHARD_USER_ID, ip_address=ip_address, referrer="promo.qaawal.com", is_correction_mode=False, ) host = "https://qa-aws-wowza.qaawal.com" assert awal_result == { "url": f"{host}/vods3promoawal/_definst_/amazons3/mp3:some_bucket/some_file.mp3/" "playlist.m3u8?wowzatokenendtime=946685802&wowzatokenstarttime=946684702&wowzatokenhash=TOKEN123ABC" } awal_result = stream_info.get_track_wowza_stream_url_with_correction_assets( track_id=fixture_track_id, user_id=SYSTEM_ORCHARD_USER_ID, ip_address=ip_address, referrer="promo.awal.com", is_correction_mode=False, ) host = "https://prod-aws-wowza.awal.com" assert awal_result == { "url": f"{host}/vods3promoawal/_definst_/amazons3/mp3:some_bucket/some_file.mp3/" "playlist.m3u8?wowzatokenendtime=946685802&wowzatokenstarttime=946684702&wowzatokenhash=TOKEN123ABC" } awal_result = stream_info.get_track_wowza_stream_url_with_correction_assets( track_id=fixture_track_id, user_id=SYSTEM_ORCHARD_USER_ID, ip_address=ip_address, referrer="promo.theorchard.com", is_correction_mode=False, ) host = "https://prod-aws-wowza.theorchard.com" assert awal_result == { "url": f"{host}/vods3promo/_definst_/amazons3/mp3:some_bucket/some_file.mp3/" "playlist.m3u8?wowzatokenendtime=946685802&wowzatokenstarttime=946684702&wowzatokenhash=TOKEN123ABC" } no_referrer_result = stream_info.get_track_wowza_stream_url_with_correction_assets( track_id=fixture_track_id, user_id=SYSTEM_ORCHARD_USER_ID, ip_address=ip_address, is_correction_mode=False, ) assert no_referrer_result == { "url": "https://qa-test-wowza.theorchard.io/vods3promo/_definst_/amazons3/mp3:some_bucket/some_file.mp3/" "playlist.m3u8?wowzatokenendtime=946685802&wowzatokenstarttime=946684702&wowzatokenhash=TOKEN123ABC" } @freeze_time(freeze_timestamp) @patch("assets.logic.stream_info.asset_access_log.create_asset_access_log") def test_get_track_wowza_stream_url_with_correction_assets_standalone( mock_asset_access_log: MagicMock, monkeypatch: MonkeyPatch, fixture_track_id: int, fixture_asset_upload_success: list[dict[str, Any]], fixture_asset_final: dict[str, Any], ) -> None: """Test that a Promo Player user gets the appropriate path.""" monkeypatch.setattr( asset_upload, "get_latest_asset_upload", MagicMock(return_value=fixture_asset_upload_success), ) monkeypatch.setattr( asset_final, "get_asset_final_by_asset_upload_id_and_type", MagicMock(return_value=fixture_asset_final), ) monkeypatch.setattr( wowza, "get_wowza_secure_access_token", MagicMock(return_value="TOKEN123ABC") ) result = stream_info.get_track_wowza_stream_url_with_correction_assets( track_id=fixture_track_id, user_id="alw:123", ip_address=ip_address, referrer="qa-frontend-distribution-standalone", is_correction_mode=False, ) assert result == { "url": "https://qa-test-wowza.theorchard.io/vods3standalone/_definst_/amazons3/mp3:some_bucket/some_file.mp3/" "playlist.m3u8?wowzatokenendtime=946685802&wowzatokenstarttime=946684702&wowzatokenhash=TOKEN123ABC" } @patch("assets.logic.stream_info.asset_upload") @patch("assets.logic.stream_info.asset_final") @patch("assets.logic.stream_info.wowza") @patch("assets.logic.stream_info.asset_access_log") def test_get_track_wowza_stream_url_for_content_profile_local( mock_access_log: MagicMock, mock_wowza: MagicMock, mock_asset_final: MagicMock, mock_asset_upload: MagicMock, fixture_asset_upload_success: list[dict[str, Any]], fixture_asset_final: dict[str, Any], fixture_track_id: int, ) -> None: """Test that the correct url is generated for local content profile development.""" mock_asset_upload.get_latest_asset_update.return_value = ( fixture_asset_upload_success ) mock_asset_final.get_asset_final_by_asset_upload_id_and_type.return_value = ( fixture_asset_final ) mock_wowza.get_wowza_secure_access_token.return_value = "abc" result = stream_info.get_track_wowza_stream_url_with_correction_assets( track_id=fixture_track_id, user_id=None, ip_address="0.0.0.0", referrer="http://localhost:5000", is_correction_mode=True, profile_type="ContentProfile", identity_uuid="def", ) url_pieces = result["url"].split("/") assert url_pieces[0] == "https:" assert url_pieces[2] == "qa-test-wowza.theorchard.io" assert url_pieces[3] == "vods3local" assert url_pieces[4] == "_definst_" assert url_pieces[5] == "amazons3" assert url_pieces[6] == "mp3:some_bucket" assert url_pieces[7] == "some_file.mp3" uri, queries = url_pieces[8].split("?") assert uri == "playlist.m3u8" query_pieces = queries.split("&") assert query_pieces[0].startswith("wowzatokenendtime=") assert query_pieces[1].startswith("wowzatokenstarttime=") assert query_pieces[2] == "wowzatokenhash=abc" mock_access_log.create_asset_access_log.assert_called_with( { "activity_type": "streaming", "ip_address": "0.0.0.0", "orchard_user_id": "def", "track_id": 10, } ) result = stream_info.get_track_wowza_stream_url_with_correction_assets( track_id=fixture_track_id, user_id=None, ip_address="0.0.0.0", referrer="https://content.:5000", is_correction_mode=True, profile_type="ContentProfile", identity_uuid="def", ) url_pieces = result["url"].split("/") assert url_pieces[3] == "vods3contentreview" @patch("assets.logic.stream_info.asset_access_log.create_asset_access_log") def test_get_track_wowza_stream_url_passes_stereo_upload_type_id( mock_asset_access_log: MagicMock, monkeypatch: MonkeyPatch, fixture_track_id: int, fixture_asset_upload_success: list[dict[str, Any]], fixture_asset_final: dict[str, Any], ) -> None: """Test that get_latest_asset_upload is called with the stereo upload type id.""" mock_get_latest = MagicMock(return_value=fixture_asset_upload_success) monkeypatch.setattr(asset_upload, "get_latest_asset_upload", mock_get_latest) monkeypatch.setattr( asset_final, "get_asset_final_by_asset_upload_id_and_type", MagicMock(return_value=fixture_asset_final), ) monkeypatch.setattr( wowza, "get_wowza_secure_access_token", MagicMock(return_value="TOKEN123ABC") ) stream_info.get_track_wowza_stream_url_with_correction_assets( track_id=fixture_track_id, user_id=user_id, ip_address=ip_address, is_correction_mode=False, ) assert mock_get_latest.call_args == call( track_id=fixture_track_id, is_correction_mode=False, asset_upload_type_id=1, )