From a71e05973075c9cf42109398b80967236aef9edf Mon Sep 17 00:00:00 2001
From: Xavier Claessens <xavier.claessens@collabora.com>
Date: Tue, 22 Sep 2015 12:59:45 -0400
Subject: [PATCH] grilo: rewrite tests in python

Differential Revision: https://phabricator.apertis.org/D535
Reviewed-by: Philip Withnall <philip.withnall@collabora.co.uk>
---
 grilo/automated/test-grilo.py | 199 ++++++++++++++++++++++++++++++++++
 1 file changed, 199 insertions(+)
 create mode 100755 grilo/automated/test-grilo.py

diff --git a/grilo/automated/test-grilo.py b/grilo/automated/test-grilo.py
new file mode 100755
index 0000000..4279780
--- /dev/null
+++ b/grilo/automated/test-grilo.py
@@ -0,0 +1,199 @@
+#! /usr/bin/python3
+# -*- coding: utf-8 -*-
+
+# Copyright © 2015 Collabora Ltd.
+#
+# SPDX-License-Identifier: MPL-2.0
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import unittest
+import subprocess
+import shutil
+import os
+import sys
+
+from gi.repository import GLib
+from gi.repository import Gio
+from gi.repository import Grl
+from gi.repository import GrlPls
+
+# import from toplevel directory
+sys.path.insert(0, os.path.join(os.path.dirname(__file__),
+                                os.pardir, os.pardir))
+from apertis_tests_lib.grilo import GriloBrowserMixin
+from apertis_tests_lib import ApertisTest
+from apertis_tests_lib import LONG_JPEG_NAME
+
+
+class GriloTest(ApertisTest, GriloBrowserMixin):
+    def setUp(self):
+        self.loop = GLib.MainLoop.new(None, False)
+        self.path = GLib.Dir.make_tmp('test-grilo-XXXXXX')
+        self.registry = Grl.Registry.get_default()
+        gfile = Gio.File.new_for_path(self.path)
+        config = Grl.Config.new('grl-filesystem', 'Filesystem')
+        config.set_string('base-uri', gfile.get_uri())
+        self.registry.add_config(config)
+        self.registry.load_plugin_by_id('grl-filesystem')
+        self.source = self.registry.lookup_source('grl-filesystem')
+        self.assertIsNotNone(self.source)
+
+    def tearDown(self):
+        shutil.rmtree(self.path)
+
+    def content_changed_cb(self, source, changed_medias, change_type,
+                           location_unknown):
+        self.assertEqual(source, self.source)
+        self.assertFalse(location_unknown)
+        for media in changed_medias:
+            print("GriloTest: received 'content-changed' signal:",
+                  media.get_url(), change_type.value_nick)
+
+            self.assertTrue(len(self.expectations) > 0)
+            expected_change_type, expected_uri = self.expectations.pop(0)
+            self.assertEqual(change_type, expected_change_type)
+            self.assertEqual(media.get_url(), expected_uri)
+
+        if len(self.expectations) == 0:
+            self.loop.quit()
+
+    def filesystem_notification_tests(self):
+        print("GriloTest: filesystem notifications")
+
+        ops = self.source.supported_operations()
+        self.assertTrue((ops & Grl.SupportedOps.NOTIFY_CHANGE) != 0)
+
+        self.source.notify_change_start()
+        signal_id = self.source.connect('content-changed',
+                                        self.content_changed_cb)
+
+        self.expectations = []
+        gfiles = []
+
+        # FIXME: Grilo emits change notifications with the parent directory URI
+        # instead of the URI of the actual media being added/removed/changed.
+        # At the time of writing it is unclear if it's a bug or by design.
+        # If upstream changes the behaviour we'll have to remove all those
+        # get_parent() below.
+        # See https://bugzilla.gnome.org/show_bug.cgi?id=755181
+
+        # Create ~/file
+        path = os.path.join(self.path, 'file')
+        gfile = Gio.File.new_for_path(path)
+        gfile.create(Gio.FileCreateFlags.REPLACE_DESTINATION, None)
+        gfiles.append(gfile)
+        self.expectations.append((Grl.SourceChangeType.ADDED,
+                                  gfile.get_parent().get_uri()))
+        self.loop.run()
+
+        # Create ~/subdir
+        path = os.path.join(self.path, 'subdir')
+        gfile = Gio.File.new_for_path(path)
+        gfile.make_directory(None)
+        gfiles.append(gfile)
+        self.expectations.append((Grl.SourceChangeType.ADDED,
+                                  gfile.get_parent().get_uri()))
+        self.loop.run()
+
+        # Create ~/subdir/file
+        path = os.path.join(self.path, 'subdir', 'file')
+        gfile = Gio.File.new_for_path(path)
+        gfile.create(Gio.FileCreateFlags.REPLACE_DESTINATION, None)
+        gfiles.append(gfile)
+        self.expectations.append((Grl.SourceChangeType.ADDED,
+                                  gfile.get_parent().get_uri()))
+        self.loop.run()
+
+        # Create ~/subdir/subdir
+        path = os.path.join(self.path, 'subdir', 'subdir')
+        gfile = Gio.File.new_for_path(path)
+        gfile.make_directory(None)
+        gfiles.append(gfile)
+        self.expectations.append((Grl.SourceChangeType.ADDED,
+                                  gfile.get_parent().get_uri()))
+        self.loop.run()
+
+        # Modify ~/file
+        path = os.path.join(self.path, 'file')
+        gfile = Gio.File.new_for_path(path)
+        iostream = gfile.open_readwrite(None)
+        ostream = iostream.get_output_stream()
+        ostream.write_all(bytes("Hello World\n", encoding='UTF-8'), None)
+        iostream.close(None)
+        self.expectations.append((Grl.SourceChangeType.CHANGED,
+                                  gfile.get_parent().get_uri()))
+        self.loop.run()
+
+        # Delete everything
+        for gfile in reversed(gfiles):
+            gfile.delete(None)
+            self.expectations.append((Grl.SourceChangeType.REMOVED,
+                                      gfile.get_parent().get_uri()))
+            self.loop.run()
+
+        self.source.disconnect(signal_id)
+        self.source.notify_change_stop()
+
+    def assert_browsed(self, medias, filename, title=None):
+        self.assertTrue(filename in medias)
+        media = medias[filename]
+
+        if title is None:
+            # 'file:///foo/generic.mp3' -> 'generic'
+            url = media.get_url()
+            title = url[url.rfind('/') + 1:url.rfind('.')]
+
+        self.assertEqual(media.get_title(), title)
+
+    def filesystem_browse_tests(self):
+        print("GriloTest: filesystem browse")
+        medias = self.browse(self.source, self.path)
+        self.assert_browsed(medias, 'Music/generic.mp3')
+        self.assert_browsed(medias, 'Music/generic.flac')
+        self.assert_browsed(medias, 'Music/generic-no-artwork.mp3')
+        self.assert_browsed(medias, 'Music/generic.oga')
+        self.assert_browsed(medias, 'Music/generic.wav')
+        self.assert_browsed(medias, 'Music/Ghosts.pls')
+        self.assert_browsed(medias, 'Music/Generic_Sounds.pls')
+        self.assert_browsed(medias, 'Music/Ghosts.m3u')
+        self.assert_browsed(medias, 'Pictures/' + LONG_JPEG_NAME)
+        self.assert_browsed(medias, 'Pictures/collabora-logo-big.png')
+        self.assert_browsed(medias, 'Videos/big_buck_bunny_smaller.ogv')
+
+    def playlist_tests(self):
+        print("GriloTest: playlist")
+        ops = self.source.supported_operations()
+        self.assertTrue((ops & Grl.SupportedOps.MEDIA_FROM_URI) != 0)
+
+        caps = self.source.get_caps(Grl.SupportedOps.MEDIA_FROM_URI)
+        options = Grl.OperationOptions.new(caps)
+        keys = [Grl.METADATA_KEY_TITLE,
+                Grl.METADATA_KEY_URL,
+                Grl.METADATA_KEY_MIME]
+
+        uri = 'file://%s/Music/Generic_Sounds.pls' % self.path
+        media = self.source.get_media_from_uri_sync(uri, keys, options)
+        self.assertIsNotNone(media)
+        self.assertTrue(GrlPls.media_is_playlist(media))
+
+        medias = self.browse(self.source, self.path, media)
+        self.assertEqual(len(medias), 3)
+        self.assert_browsed(medias, 'Music/audio/generic.mp3',
+                            "Generic Sound 1")
+        self.assert_browsed(medias, 'Music/audio/generic.flac',
+                            "Generic Sound 2")
+        self.assert_browsed(medias, 'Music/audio/generic.oga',
+                            "Generic Sound 3")
+
+    # This is the only test to avoid multiple initializations of Grilo
+    def test_all(self):
+        self.filesystem_notification_tests()
+        self.copy_medias(self.path)
+        self.filesystem_browse_tests()
+        self.playlist_tests()
+
+if __name__ == "__main__":
+    Grl.init([])
+    unittest.main()
-- 
GitLab