]> kaliko git repositories - mpd-sima.git/blobdiff - tests/test_simadb.py
Add drop_all, fetch_artists*, get_bl_* methods
[mpd-sima.git] / tests / test_simadb.py
diff --git a/tests/test_simadb.py b/tests/test_simadb.py
new file mode 100644 (file)
index 0000000..b71fa1b
--- /dev/null
@@ -0,0 +1,258 @@
+# coding: utf-8
+
+import datetime
+import unittest
+import os
+
+from sima.lib.db import SimaDB
+from sima.lib.track import Track
+from sima.lib.meta import Album
+
+
+DEVOLT = {
+    'album': 'Grey',
+    'albumartist': 'Devolt',
+    'albumartistsort': 'Devolt',
+    'artist': 'Devolt',
+    'date': '2011-12-01',
+    'disc': '1/1',
+    'file': 'music/Devolt/2011-Grey/03-Devolt - Crazy.mp3',
+    'last-modified': '2012-04-02T20:48:59Z',
+    'musicbrainz_albumartistid': 'd8e7e3e2-49ab-4f7c-b148-fc946d521f99',
+    'musicbrainz_albumid': 'ea2ef2cf-59e1-443a-817e-9066e3e0be4b',
+    'musicbrainz_artistid': 'd8e7e3e2-49ab-4f7c-b148-fc946d521f99',
+    'musicbrainz_trackid': 'fabf8fc9-2ae5-49c9-8214-a839c958d872',
+    'time': '220',
+    'duration': '220.000',
+    'title': 'Crazy',
+    'track': '3/6'}
+
+DB_FILE = 'file::memory:?cache=shared'
+KEEP_FILE = False  # File db in file to ease debug
+if KEEP_FILE:
+    DB_FILE = '/dev/shm/unittest.sqlite'
+CURRENT = datetime.datetime.utcnow()
+IN_THE_PAST = CURRENT - datetime.timedelta(hours=1)
+
+
+class Main(unittest.TestCase):
+    """Deal with database creation and purge between tests"""
+
+    @classmethod
+    def setUpClass(self):
+        self.db = SimaDB(db_path=DB_FILE)
+
+    def setUp(self):
+        # Maintain a connection to keep the database (when stored in memory)
+        self.conn = self.db.get_database_connection()
+        self.db.drop_all()
+        self.db.create_db()
+
+    def tearDown(self):
+        if not KEEP_FILE:
+            self.db.drop_all()
+        self.conn.close()
+
+    @classmethod
+    def tearDownClass(self):
+        if KEEP_FILE:
+            return
+        if os.path.isfile(DB_FILE):
+            os.unlink(DB_FILE)
+
+
+class Test_00DB(Main):
+
+    def test_00_recreation(self):
+        self.db.create_db()
+
+    def test_01_add_track(self):
+        trk = Track(**DEVOLT)
+        trk_id = self.db.get_track(trk)
+        self.assertEqual(trk_id, self.db.get_track(trk),
+                         'Same track, same record')
+
+    def test_02_history(self):
+        # set records in the past to ease purging then
+        last = CURRENT - datetime.timedelta(hours=1)
+        trk = Track(**DEVOLT)
+        self.db.add_history(trk, date=last)
+        self.db.add_history(trk, date=last)
+        hist = self.db.fetch_history()
+        self.assertEqual(len(hist), 1, 'same track results in a single record')
+
+        trk_foo = Track(file="/foo/bar/baz.flac")
+        self.db.add_history(trk_foo, date=last)
+        hist = self.db.fetch_history()
+        self.assertEqual(len(hist), 2)
+
+        self.db.add_history(trk, date=last)
+        hist = self.db.fetch_history()
+        self.assertEqual(len(hist), 2)
+        self.db.purge_history(duration=0)
+        hist = self.db.fetch_history()
+        self.assertEqual(len(hist), 0)
+
+        # Controls we got history in the right order
+        # recent first, oldest last
+        hist = list()
+        for i in range(1, 5):  # starts at 1 to ensure records are in the past
+            trk = Track(file=f'/foo/bar.{i}', name='{i}-baz', album='foolbum')
+            hist.append(trk)
+            last = CURRENT - datetime.timedelta(minutes=i)
+            self.db.add_history(trk, date=last)
+        hist_records = self.db.fetch_history()
+        self.assertEqual(hist, hist_records)
+        self.db.purge_history(duration=0)
+
+    def test_history_to_tracks(self):
+        tr = dict(**DEVOLT)
+        tr.pop('file')
+        trk01 = Track(file='01', **tr)
+        self.db.add_history(trk01, CURRENT-datetime.timedelta(minutes=1))
+        #
+        tr.pop('musicbrainz_artistid')
+        trk02 = Track(file='02', **tr)
+        self.db.add_history(trk02, CURRENT-datetime.timedelta(minutes=2))
+        #
+        tr.pop('musicbrainz_albumid')
+        trk03 = Track(file='03', **tr)
+        self.db.add_history(trk03, CURRENT-datetime.timedelta(minutes=3))
+        #
+        tr.pop('musicbrainz_albumartistid')
+        trk04 = Track(file='04', **tr)
+        self.db.add_history(trk04, CURRENT-datetime.timedelta(minutes=4))
+        #
+        tr.pop('musicbrainz_trackid')
+        trk05 = Track(file='05', **tr)
+        self.db.add_history(trk05, CURRENT-datetime.timedelta(minutes=5))
+        history = self.db.fetch_history()
+        self.assertEqual(len(history), 5)
+        # Controls history ordering, recent first
+        self.assertEqual(history, [trk01, trk02, trk03, trk04, trk05])
+
+    def test_history_to_artists(self):
+        tr = dict(**DEVOLT)
+        tr.pop('file')
+        tr.pop('musicbrainz_artistid')
+        #
+        trk01 = Track(file='01', **tr)
+        self.db.add_history(trk01, CURRENT-datetime.timedelta(hours=1))
+        #
+        trk02 = Track(file='02', **tr)
+        self.db.add_history(trk02, CURRENT-datetime.timedelta(hours=1))
+        self.db.add_history(trk02, CURRENT-datetime.timedelta(hours=1))
+        #
+        trk03 = Track(file='03', **tr)
+        self.db.add_history(trk03, CURRENT-datetime.timedelta(hours=1))
+        # got multiple tracks, same artist, got artist history len == 1
+        art_history = self.db.fetch_artists_history()
+        self.assertEqual(len(art_history), 1)
+        self.assertEqual(art_history, [trk01.Artist])
+
+        # Now add new artist to history
+        trk04 = Track(file='04', artist='New Art')
+        trk05 = Track(file='05', artist='New² Art')
+        self.db.add_history(trk04, CURRENT-datetime.timedelta(minutes=3))
+        self.db.add_history(trk03, CURRENT-datetime.timedelta(minutes=2))
+        self.db.add_history(trk05, CURRENT-datetime.timedelta(minutes=1))
+        art_history = self.db.fetch_artists_history()
+        # Now we should have 4 artists in history
+        self.assertEqual(len(art_history), 4)
+        # Controling order, recent first
+        self.assertEqual([trk05.artist, trk03.artist,
+                         trk04.artist, trk03.artist],
+                         art_history)
+
+    def test_04_triggers(self):
+        self.db.purge_history(duration=0)
+        tracks_ids = list()
+        #  Add a first track
+        track = Track(file='/baz/bar.baz', name='baz', artist='fooart',
+                      albumartist='not-same', album='not-same',)
+        self.db.get_track(track)
+        # Set 6 more records from same artist but not same album
+        for i in range(1, 6):  # starts at 1 to ensure records are in the past
+            trk = Track(file=f'/foo/{i}', name=f'{i}', artist='fooart',
+                        albumartist='fooalbart', album='foolbum',)
+            # Add track, save its DB id
+            tracks_ids.append(self.db.get_track(trk))
+            # set records in the past to ease purging then
+            last = CURRENT - datetime.timedelta(minutes=i)
+            self.db.add_history(trk, date=last)  # Add to history
+        conn = self.db.get_database_connection()
+        # for tid in tracks_ids:
+        for tid in tracks_ids[:-1]:
+            # Delete lastest record
+            conn.execute('DELETE FROM history WHERE history.track = ?',
+                         (tid,))
+            c = conn.execute('SELECT albums.name FROM albums;')
+            # There are still albums records (still a history using it)
+            self.assertIn((trk.album,), c.fetchall())
+        # purging last entry in history for album == trk.album
+        conn.execute('DELETE FROM history WHERE history.track = ?',
+                     (tracks_ids[-1],))
+        # triggers purge other tables if possible
+        conn.execute('SELECT albums.name FROM albums;')
+        albums = c.fetchall()
+        # No more "foolbum" in the table albums
+        self.assertNotIn(('foolbum',), albums)
+        # There is still "fooart" though
+        c = conn.execute('SELECT artists.name FROM artists;')
+        artists = c.fetchall()
+        # No more "foolbum" in the table albums
+        self.assertIn(('fooart',), artists)
+        conn.close()
+
+
+class Test_01BlockList(Main):
+
+    def test_blocklist_addition(self):
+        tracks_ids = list()
+        # Set 6 records, same album
+        for i in range(1, 6):  # starts at 1 to ensure records are in the past
+            trk = Track(file=f'/foo/{i}', name=f'{i}', artist='fooart',
+                        albumartist='fooalbart', album='foolbum',)
+            # Add track, save its DB id
+            tracks_ids.append(self.db.get_track(trk))
+            # set records in the past to ease purging then
+            last = CURRENT - datetime.timedelta(minutes=i)
+            self.db.add_history(trk, date=last)  # Add to history
+            if i == 1:
+                self.db.get_bl_track(trk)
+            if i == 2:
+                self.db.get_bl_track(trk)
+                self.db.get_bl_album(Album(name=trk.album))
+            if i == 3:
+                self.db.get_bl_artist(trk.Artist)
+
+    def test_blocklist_triggers(self):
+        trk01 = Track(file='01', name='01', artist='artist A', album='album A')
+        trk02 = Track(file='02', name='01', artist='artist A', album='album B')
+        trk01_id = self.db.get_bl_track(trk01)
+        trk02_id = self.db.get_bl_track(trk02)
+        self.db.add_history(trk01, IN_THE_PAST)
+        self.db._remove_blocklist_id(trk01_id)
+        # bl trk01 removed:
+        # albums/artists table not affected since trk01_id still in history
+        conn = self.db.get_database_connection()
+        albums = conn.execute('SELECT albums.name FROM albums;').fetchall()
+        artists = conn.execute('SELECT artists.name FROM artists;').fetchall()
+        self.assertIn(('album A',), albums)
+        self.assertIn(('artist A',), artists)
+        self.db.purge_history(0)
+        # remove last reference to trk01
+        albums = conn.execute('SELECT albums.name FROM albums;').fetchall()
+        self.assertNotIn(('album A',), albums)
+        self.assertIn(('artist A',), artists)
+        # remove trk02
+        self.db._remove_blocklist_id(trk02_id)
+        albums = conn.execute('SELECT albums.name FROM albums;').fetchall()
+        artists = conn.execute('SELECT artists.name FROM artists;').fetchall()
+        self.assertNotIn(('album B',), albums)
+        self.assertNotIn(('artist A'), artists)
+        conn.close()
+
+
+# VIM MODLINE
+# vim: ai ts=4 sw=4 sts=4 expandtab fileencoding=utf8