149 lines
5.5 KiB
Python
149 lines
5.5 KiB
Python
"""Tests for the DLNAClient SOAP and DIDL-Lite parsers."""
|
|
|
|
from r36s_dlna_browser.dlna.client import _extract_browse_result, _parse_didl
|
|
from r36s_dlna_browser.dlna.models import ItemType
|
|
|
|
|
|
_SAMPLE_DIDL = """\
|
|
<DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"
|
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/">
|
|
<container id="1" parentID="0" childCount="3">
|
|
<dc:title>Music</dc:title>
|
|
<upnp:class>object.container.storageFolder</upnp:class>
|
|
</container>
|
|
<item id="100" parentID="1">
|
|
<dc:title>Song.mp3</dc:title>
|
|
<upnp:class>object.item.audioItem.musicTrack</upnp:class>
|
|
<upnp:albumArtURI>http://srv/art.jpg</upnp:albumArtURI>
|
|
<res protocolInfo="http-get:*:audio/mpeg:*" size="4000000" duration="0:03:21">http://srv/song.mp3</res>
|
|
</item>
|
|
<item id="200" parentID="1">
|
|
<dc:title>Video.mkv</dc:title>
|
|
<upnp:class>object.item.videoItem</upnp:class>
|
|
<res protocolInfo="http-get:*:video/x-matroska:*">http://srv/video.mkv</res>
|
|
</item>
|
|
</DIDL-Lite>
|
|
"""
|
|
|
|
|
|
class TestParseDIDL:
|
|
def test_parses_container(self):
|
|
items = _parse_didl(_SAMPLE_DIDL, "http://srv")
|
|
containers = [i for i in items if i.is_container]
|
|
assert len(containers) == 1
|
|
assert containers[0].title == "Music"
|
|
assert containers[0].child_count == 3
|
|
|
|
def test_parses_audio_item(self):
|
|
items = _parse_didl(_SAMPLE_DIDL, "http://srv")
|
|
audio = [i for i in items if i.item_type == ItemType.AUDIO]
|
|
assert len(audio) == 1
|
|
assert audio[0].title == "Song.mp3"
|
|
assert audio[0].resource_url == "http://srv/song.mp3"
|
|
assert audio[0].mime_type == "audio/mpeg"
|
|
assert audio[0].size == 4000000
|
|
assert audio[0].duration == "0:03:21"
|
|
assert audio[0].album_art_url == "http://srv/art.jpg"
|
|
|
|
def test_parses_video_item(self):
|
|
items = _parse_didl(_SAMPLE_DIDL, "http://srv")
|
|
video = [i for i in items if i.item_type == ItemType.VIDEO]
|
|
assert len(video) == 1
|
|
assert video[0].title == "Video.mkv"
|
|
assert "video/x-matroska" in video[0].mime_type
|
|
|
|
def test_total_count(self):
|
|
items = _parse_didl(_SAMPLE_DIDL, "http://srv")
|
|
assert len(items) == 3
|
|
|
|
def test_empty_didl(self):
|
|
empty = '<DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"></DIDL-Lite>'
|
|
assert _parse_didl(empty, "http://srv") == []
|
|
|
|
def test_malformed_xml(self):
|
|
assert _parse_didl("<<<not xml>>>", "http://srv") == []
|
|
|
|
def test_relative_url_resolution(self):
|
|
didl = """\
|
|
<DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"
|
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/">
|
|
<item id="300" parentID="1">
|
|
<dc:title>Relative</dc:title>
|
|
<upnp:class>object.item.audioItem</upnp:class>
|
|
<res protocolInfo="http-get:*:audio/flac:*">media/track.flac</res>
|
|
</item>
|
|
</DIDL-Lite>
|
|
"""
|
|
items = _parse_didl(didl, "http://myserver:8200")
|
|
assert items[0].resource_url == "http://myserver:8200/media/track.flac"
|
|
|
|
def test_prefers_video_resource_over_subtitle_resource(self):
|
|
didl = """\
|
|
<DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"
|
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/">
|
|
<item id="400" parentID="1">
|
|
<dc:title>Movie</dc:title>
|
|
<upnp:class>object.item.videoItem</upnp:class>
|
|
<res protocolInfo="http-get:*:text/vtt:*">http://srv/movie.vtt</res>
|
|
<res protocolInfo="http-get:*:video/x-matroska:*" size="999">http://srv/movie.mkv</res>
|
|
</item>
|
|
</DIDL-Lite>
|
|
"""
|
|
items = _parse_didl(didl, "http://srv")
|
|
assert items[0].resource_url == "http://srv/movie.mkv"
|
|
assert items[0].mime_type == "video/x-matroska"
|
|
|
|
|
|
class TestExtractBrowseResult:
|
|
def test_extracts_unnamespaced_result(self):
|
|
soap = """\
|
|
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
|
|
<s:Body>
|
|
<u:BrowseResponse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">
|
|
<Result><DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"><container id="1" parentID="0" /></DIDL-Lite></Result>
|
|
</u:BrowseResponse>
|
|
</s:Body>
|
|
</s:Envelope>
|
|
"""
|
|
result = _extract_browse_result(soap)
|
|
assert result is not None
|
|
assert "DIDL-Lite" in result
|
|
assert 'container id="1"' in result
|
|
|
|
def test_extracts_namespaced_result(self):
|
|
soap = """\
|
|
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">
|
|
<s:Body>
|
|
<u:BrowseResponse>
|
|
<u:Result><DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"></DIDL-Lite></u:Result>
|
|
</u:BrowseResponse>
|
|
</s:Body>
|
|
</s:Envelope>
|
|
"""
|
|
assert _extract_browse_result(soap) is not None
|
|
|
|
def test_extracts_embedded_xml_result(self):
|
|
soap = """\
|
|
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
|
|
<s:Body>
|
|
<BrowseResponse>
|
|
<Result>
|
|
<DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/">
|
|
<container id="1" parentID="0" />
|
|
</DIDL-Lite>
|
|
</Result>
|
|
</BrowseResponse>
|
|
</s:Body>
|
|
</s:Envelope>
|
|
"""
|
|
result = _extract_browse_result(soap)
|
|
assert result is not None
|
|
assert "DIDL-Lite" in result
|
|
|
|
def test_returns_none_when_missing(self):
|
|
soap = "<Envelope><Body><BrowseResponse /></Body></Envelope>"
|
|
assert _extract_browse_result(soap) is None
|