SDL2/GStreamer DLNA browser for R36S by Matteo Benedetto
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

148 lines
5.5 KiB

"""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>&lt;DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"&gt;&lt;container id="1" parentID="0" /&gt;&lt;/DIDL-Lite&gt;</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>&lt;DIDL-Lite xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/"&gt;&lt;/DIDL-Lite&gt;</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