For now this doesn't add any corresponding APIs to backends, or for that matter tracklist.add(uris). This is just to get the API in for clients in 0.20.
351 lines
14 KiB
Python
351 lines
14 KiB
Python
from __future__ import absolute_import, unicode_literals
|
|
|
|
import unittest
|
|
|
|
import mock
|
|
|
|
from mopidy import backend, core
|
|
from mopidy.models import Image, Ref, SearchResult, Track
|
|
|
|
|
|
class CoreLibraryTest(unittest.TestCase):
|
|
def setUp(self): # noqa: N802
|
|
dummy1_root = Ref.directory(uri='dummy1:directory', name='dummy1')
|
|
self.backend1 = mock.Mock()
|
|
self.backend1.uri_schemes.get.return_value = ['dummy1']
|
|
self.library1 = mock.Mock(spec=backend.LibraryProvider)
|
|
self.library1.get_images().get.return_value = {}
|
|
self.library1.get_images.reset_mock()
|
|
self.library1.root_directory.get.return_value = dummy1_root
|
|
self.backend1.library = self.library1
|
|
|
|
dummy2_root = Ref.directory(uri='dummy2:directory', name='dummy2')
|
|
self.backend2 = mock.Mock()
|
|
self.backend2.uri_schemes.get.return_value = ['dummy2', 'du2']
|
|
self.library2 = mock.Mock(spec=backend.LibraryProvider)
|
|
self.library2.get_images().get.return_value = {}
|
|
self.library2.get_images.reset_mock()
|
|
self.library2.root_directory.get.return_value = dummy2_root
|
|
self.backend2.library = self.library2
|
|
|
|
# A backend without the optional library provider
|
|
self.backend3 = mock.Mock()
|
|
self.backend3.uri_schemes.get.return_value = ['dummy3']
|
|
self.backend3.has_library().get.return_value = False
|
|
self.backend3.has_library_browse().get.return_value = False
|
|
|
|
self.core = core.Core(mixer=None, backends=[
|
|
self.backend1, self.backend2, self.backend3])
|
|
|
|
def test_get_images_returns_empty_dict_for_no_uris(self):
|
|
self.assertEqual({}, self.core.library.get_images([]))
|
|
|
|
def test_get_images_returns_empty_result_for_unknown_uri(self):
|
|
result = self.core.library.get_images(['dummy4:track'])
|
|
self.assertEqual({'dummy4:track': tuple()}, result)
|
|
|
|
def test_get_images_returns_empty_result_for_library_less_uri(self):
|
|
result = self.core.library.get_images(['dummy3:track'])
|
|
self.assertEqual({'dummy3:track': tuple()}, result)
|
|
|
|
def test_get_images_maps_uri_to_backend(self):
|
|
self.core.library.get_images(['dummy1:track'])
|
|
self.library1.get_images.assert_called_once_with(['dummy1:track'])
|
|
self.library2.get_images.assert_not_called()
|
|
|
|
def test_get_images_maps_uri_to_backends(self):
|
|
self.core.library.get_images(['dummy1:track', 'dummy2:track'])
|
|
self.library1.get_images.assert_called_once_with(['dummy1:track'])
|
|
self.library2.get_images.assert_called_once_with(['dummy2:track'])
|
|
|
|
def test_get_images_returns_images(self):
|
|
self.library1.get_images().get.return_value = {
|
|
'dummy1:track': [Image(uri='uri')]}
|
|
self.library1.get_images.reset_mock()
|
|
|
|
result = self.core.library.get_images(['dummy1:track'])
|
|
self.assertEqual({'dummy1:track': (Image(uri='uri'),)}, result)
|
|
|
|
def test_get_images_merges_results(self):
|
|
self.library1.get_images().get.return_value = {
|
|
'dummy1:track': [Image(uri='uri1')]}
|
|
self.library1.get_images.reset_mock()
|
|
self.library2.get_images().get.return_value = {
|
|
'dummy2:track': [Image(uri='uri2')]}
|
|
self.library2.get_images.reset_mock()
|
|
|
|
result = self.core.library.get_images(
|
|
['dummy1:track', 'dummy2:track', 'dummy3:track', 'dummy4:track'])
|
|
expected = {'dummy1:track': (Image(uri='uri1'),),
|
|
'dummy2:track': (Image(uri='uri2'),),
|
|
'dummy3:track': tuple(), 'dummy4:track': tuple()}
|
|
self.assertEqual(expected, result)
|
|
|
|
def test_browse_root_returns_dir_ref_for_each_lib_with_root_dir_name(self):
|
|
result = self.core.library.browse(None)
|
|
|
|
self.assertEqual(result, [
|
|
Ref.directory(uri='dummy1:directory', name='dummy1'),
|
|
Ref.directory(uri='dummy2:directory', name='dummy2'),
|
|
])
|
|
self.assertFalse(self.library1.browse.called)
|
|
self.assertFalse(self.library2.browse.called)
|
|
self.assertFalse(self.backend3.library.browse.called)
|
|
|
|
def test_browse_empty_string_returns_nothing(self):
|
|
result = self.core.library.browse('')
|
|
|
|
self.assertEqual(result, [])
|
|
self.assertFalse(self.library1.browse.called)
|
|
self.assertFalse(self.library2.browse.called)
|
|
|
|
def test_browse_dummy1_selects_dummy1_backend(self):
|
|
self.library1.browse().get.return_value = [
|
|
Ref.directory(uri='dummy1:directory:/foo/bar', name='bar'),
|
|
Ref.track(uri='dummy1:track:/foo/baz.mp3', name='Baz'),
|
|
]
|
|
self.library1.browse.reset_mock()
|
|
|
|
self.core.library.browse('dummy1:directory:/foo')
|
|
|
|
self.assertEqual(self.library1.browse.call_count, 1)
|
|
self.assertEqual(self.library2.browse.call_count, 0)
|
|
self.library1.browse.assert_called_with('dummy1:directory:/foo')
|
|
|
|
def test_browse_dummy2_selects_dummy2_backend(self):
|
|
self.library2.browse().get.return_value = [
|
|
Ref.directory(uri='dummy2:directory:/bar/baz', name='quux'),
|
|
Ref.track(uri='dummy2:track:/bar/foo.mp3', name='Baz'),
|
|
]
|
|
self.library2.browse.reset_mock()
|
|
|
|
self.core.library.browse('dummy2:directory:/bar')
|
|
|
|
self.assertEqual(self.library1.browse.call_count, 0)
|
|
self.assertEqual(self.library2.browse.call_count, 1)
|
|
self.library2.browse.assert_called_with('dummy2:directory:/bar')
|
|
|
|
def test_browse_dummy3_returns_nothing(self):
|
|
result = self.core.library.browse('dummy3:test')
|
|
|
|
self.assertEqual(result, [])
|
|
self.assertEqual(self.library1.browse.call_count, 0)
|
|
self.assertEqual(self.library2.browse.call_count, 0)
|
|
|
|
def test_browse_dir_returns_subdirs_and_tracks(self):
|
|
self.library1.browse().get.return_value = [
|
|
Ref.directory(uri='dummy1:directory:/foo/bar', name='Bar'),
|
|
Ref.track(uri='dummy1:track:/foo/baz.mp3', name='Baz'),
|
|
]
|
|
self.library1.browse.reset_mock()
|
|
|
|
result = self.core.library.browse('dummy1:directory:/foo')
|
|
self.assertEqual(result, [
|
|
Ref.directory(uri='dummy1:directory:/foo/bar', name='Bar'),
|
|
Ref.track(uri='dummy1:track:/foo/baz.mp3', name='Baz'),
|
|
])
|
|
|
|
def test_lookup_selects_dummy1_backend(self):
|
|
self.core.library.lookup('dummy1:a')
|
|
|
|
self.library1.lookup.assert_called_once_with('dummy1:a')
|
|
self.assertFalse(self.library2.lookup.called)
|
|
|
|
def test_lookup_selects_dummy2_backend(self):
|
|
self.core.library.lookup('dummy2:a')
|
|
|
|
self.assertFalse(self.library1.lookup.called)
|
|
self.library2.lookup.assert_called_once_with('dummy2:a')
|
|
|
|
def test_lookup_fails_with_uri_and_uris_set(self):
|
|
with self.assertRaises(ValueError):
|
|
self.core.library.lookup('dummy1:a', ['dummy2:a'])
|
|
|
|
def test_lookup_can_handle_uris(self):
|
|
self.library1.lookup().get.return_value = [1234]
|
|
self.library2.lookup().get.return_value = [5678]
|
|
|
|
result = self.core.library.lookup(uris=['dummy1:a', 'dummy2:a'])
|
|
self.assertEqual(result, {'dummy2:a': [5678], 'dummy1:a': [1234]})
|
|
|
|
def test_lookup_returns_nothing_for_dummy3_track(self):
|
|
result = self.core.library.lookup('dummy3:a')
|
|
|
|
self.assertEqual(result, [])
|
|
self.assertFalse(self.library1.lookup.called)
|
|
self.assertFalse(self.library2.lookup.called)
|
|
|
|
def test_refresh_with_uri_selects_dummy1_backend(self):
|
|
self.core.library.refresh('dummy1:a')
|
|
|
|
self.library1.refresh.assert_called_once_with('dummy1:a')
|
|
self.assertFalse(self.library2.refresh.called)
|
|
|
|
def test_refresh_with_uri_selects_dummy2_backend(self):
|
|
self.core.library.refresh('dummy2:a')
|
|
|
|
self.assertFalse(self.library1.refresh.called)
|
|
self.library2.refresh.assert_called_once_with('dummy2:a')
|
|
|
|
def test_refresh_with_uri_fails_silently_for_dummy3_uri(self):
|
|
self.core.library.refresh('dummy3:a')
|
|
|
|
self.assertFalse(self.library1.refresh.called)
|
|
self.assertFalse(self.library2.refresh.called)
|
|
|
|
def test_refresh_without_uri_calls_all_backends(self):
|
|
self.core.library.refresh()
|
|
|
|
self.library1.refresh.assert_called_once_with(None)
|
|
self.library2.refresh.assert_called_twice_with(None)
|
|
|
|
def test_find_exact_combines_results_from_all_backends(self):
|
|
track1 = Track(uri='dummy1:a')
|
|
track2 = Track(uri='dummy2:a')
|
|
result1 = SearchResult(tracks=[track1])
|
|
result2 = SearchResult(tracks=[track2])
|
|
|
|
self.library1.find_exact().get.return_value = result1
|
|
self.library1.find_exact.reset_mock()
|
|
self.library2.find_exact().get.return_value = result2
|
|
self.library2.find_exact.reset_mock()
|
|
|
|
result = self.core.library.find_exact(any=['a'])
|
|
|
|
self.assertIn(result1, result)
|
|
self.assertIn(result2, result)
|
|
self.library1.find_exact.assert_called_once_with(
|
|
query=dict(any=['a']), uris=None)
|
|
self.library2.find_exact.assert_called_once_with(
|
|
query=dict(any=['a']), uris=None)
|
|
|
|
def test_find_exact_with_uris_selects_dummy1_backend(self):
|
|
self.core.library.find_exact(
|
|
any=['a'], uris=['dummy1:', 'dummy1:foo', 'dummy3:'])
|
|
|
|
self.library1.find_exact.assert_called_once_with(
|
|
query=dict(any=['a']), uris=['dummy1:', 'dummy1:foo'])
|
|
self.assertFalse(self.library2.find_exact.called)
|
|
|
|
def test_find_exact_with_uris_selects_both_backends(self):
|
|
self.core.library.find_exact(
|
|
any=['a'], uris=['dummy1:', 'dummy1:foo', 'dummy2:'])
|
|
|
|
self.library1.find_exact.assert_called_once_with(
|
|
query=dict(any=['a']), uris=['dummy1:', 'dummy1:foo'])
|
|
self.library2.find_exact.assert_called_once_with(
|
|
query=dict(any=['a']), uris=['dummy2:'])
|
|
|
|
def test_find_exact_filters_out_none(self):
|
|
track1 = Track(uri='dummy1:a')
|
|
result1 = SearchResult(tracks=[track1])
|
|
|
|
self.library1.find_exact().get.return_value = result1
|
|
self.library1.find_exact.reset_mock()
|
|
self.library2.find_exact().get.return_value = None
|
|
self.library2.find_exact.reset_mock()
|
|
|
|
result = self.core.library.find_exact(any=['a'])
|
|
|
|
self.assertIn(result1, result)
|
|
self.assertNotIn(None, result)
|
|
self.library1.find_exact.assert_called_once_with(
|
|
query=dict(any=['a']), uris=None)
|
|
self.library2.find_exact.assert_called_once_with(
|
|
query=dict(any=['a']), uris=None)
|
|
|
|
def test_find_accepts_query_dict_instead_of_kwargs(self):
|
|
track1 = Track(uri='dummy1:a')
|
|
track2 = Track(uri='dummy2:a')
|
|
result1 = SearchResult(tracks=[track1])
|
|
result2 = SearchResult(tracks=[track2])
|
|
|
|
self.library1.find_exact().get.return_value = result1
|
|
self.library1.find_exact.reset_mock()
|
|
self.library2.find_exact().get.return_value = result2
|
|
self.library2.find_exact.reset_mock()
|
|
|
|
result = self.core.library.find_exact(dict(any=['a']))
|
|
|
|
self.assertIn(result1, result)
|
|
self.assertIn(result2, result)
|
|
self.library1.find_exact.assert_called_once_with(
|
|
query=dict(any=['a']), uris=None)
|
|
self.library2.find_exact.assert_called_once_with(
|
|
query=dict(any=['a']), uris=None)
|
|
|
|
def test_search_combines_results_from_all_backends(self):
|
|
track1 = Track(uri='dummy1:a')
|
|
track2 = Track(uri='dummy2:a')
|
|
result1 = SearchResult(tracks=[track1])
|
|
result2 = SearchResult(tracks=[track2])
|
|
|
|
self.library1.search().get.return_value = result1
|
|
self.library1.search.reset_mock()
|
|
self.library2.search().get.return_value = result2
|
|
self.library2.search.reset_mock()
|
|
|
|
result = self.core.library.search(any=['a'])
|
|
|
|
self.assertIn(result1, result)
|
|
self.assertIn(result2, result)
|
|
self.library1.search.assert_called_once_with(
|
|
query=dict(any=['a']), uris=None)
|
|
self.library2.search.assert_called_once_with(
|
|
query=dict(any=['a']), uris=None)
|
|
|
|
def test_search_with_uris_selects_dummy1_backend(self):
|
|
self.core.library.search(
|
|
query=dict(any=['a']), uris=['dummy1:', 'dummy1:foo', 'dummy3:'])
|
|
|
|
self.library1.search.assert_called_once_with(
|
|
query=dict(any=['a']), uris=['dummy1:', 'dummy1:foo'])
|
|
self.assertFalse(self.library2.search.called)
|
|
|
|
def test_search_with_uris_selects_both_backends(self):
|
|
self.core.library.search(
|
|
query=dict(any=['a']), uris=['dummy1:', 'dummy1:foo', 'dummy2:'])
|
|
|
|
self.library1.search.assert_called_once_with(
|
|
query=dict(any=['a']), uris=['dummy1:', 'dummy1:foo'])
|
|
self.library2.search.assert_called_once_with(
|
|
query=dict(any=['a']), uris=['dummy2:'])
|
|
|
|
def test_search_filters_out_none(self):
|
|
track1 = Track(uri='dummy1:a')
|
|
result1 = SearchResult(tracks=[track1])
|
|
|
|
self.library1.search().get.return_value = result1
|
|
self.library1.search.reset_mock()
|
|
self.library2.search().get.return_value = None
|
|
self.library2.search.reset_mock()
|
|
|
|
result = self.core.library.search(any=['a'])
|
|
|
|
self.assertIn(result1, result)
|
|
self.assertNotIn(None, result)
|
|
self.library1.search.assert_called_once_with(
|
|
query=dict(any=['a']), uris=None)
|
|
self.library2.search.assert_called_once_with(
|
|
query=dict(any=['a']), uris=None)
|
|
|
|
def test_search_accepts_query_dict_instead_of_kwargs(self):
|
|
track1 = Track(uri='dummy1:a')
|
|
track2 = Track(uri='dummy2:a')
|
|
result1 = SearchResult(tracks=[track1])
|
|
result2 = SearchResult(tracks=[track2])
|
|
|
|
self.library1.search().get.return_value = result1
|
|
self.library1.search.reset_mock()
|
|
self.library2.search().get.return_value = result2
|
|
self.library2.search.reset_mock()
|
|
|
|
result = self.core.library.search(dict(any=['a']))
|
|
|
|
self.assertIn(result1, result)
|
|
self.assertIn(result2, result)
|
|
self.library1.search.assert_called_once_with(
|
|
query=dict(any=['a']), uris=None)
|
|
self.library2.search.assert_called_once_with(
|
|
query=dict(any=['a']), uris=None)
|