From 8e8ee82580d39626586351055a201e3014034522 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Fri, 15 Nov 2019 12:24:57 +0100 Subject: [PATCH] tests: Add GMemoryMonitor installed-tests Those tests require Python, gobject-introspection and python-dbusmock making them unsuitable to be run within the uninstalled test suite. There are no restrictions of dependencies when it comes to installed tests so use those to exercise GMemoryMonitor. --- gio/tests/memory-monitor-dbus.py.in | 92 +++++++++++++++++++++++ gio/tests/memory-monitor-portal.py.in | 104 ++++++++++++++++++++++++++ gio/tests/meson.build | 25 +++++++ 3 files changed, 221 insertions(+) create mode 100755 gio/tests/memory-monitor-dbus.py.in create mode 100755 gio/tests/memory-monitor-portal.py.in diff --git a/gio/tests/memory-monitor-dbus.py.in b/gio/tests/memory-monitor-dbus.py.in new file mode 100755 index 000000000..b1bae7c40 --- /dev/null +++ b/gio/tests/memory-monitor-dbus.py.in @@ -0,0 +1,92 @@ +#!/usr/bin/python3 + +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 3 of the License, or (at your option) any +# later version. See http://www.gnu.org/copyleft/lgpl.html for the full text +# of the license. + +__author__ = 'Bastien Nocera' +__email__ = 'hadess@hadess.net' +__copyright__ = '(c) 2019 Red Hat Inc.' +__license__ = 'LGPL 3+' + +import unittest +import sys +import subprocess +import dbus +import dbus.mainloop.glib +import dbusmock +import fcntl +import os +import time + +from gi.repository import GLib +from gi.repository import Gio + +dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + +# XDG_DESKTOP_PORTAL_PATH = os.path.expanduser("~/.cache/jhbuild/build/xdg-desktop-portal/xdg-desktop-portal") +XDG_DESKTOP_PORTAL_PATH = "@libexecdir@/xdg-desktop-portal" + +class TestLowMemoryMonitor(dbusmock.DBusTestCase): + '''Test GMemoryMonitorDBus''' + + @classmethod + def setUpClass(klass): + klass.start_system_bus() + klass.dbus_con = klass.get_dbus(True) + + def setUp(self): + (self.p_mock, self.obj_lmm) = self.spawn_server_template( + 'low_memory_monitor', {}, stdout=subprocess.PIPE) + # set log to nonblocking + flags = fcntl.fcntl(self.p_mock.stdout, fcntl.F_GETFL) + fcntl.fcntl(self.p_mock.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK) + self.last_warning = -1 + self.dbusmock = dbus.Interface(self.obj_lmm, dbusmock.MOCK_IFACE) + self.memory_monitor = Gio.MemoryMonitor.dup_default() + self.memory_monitor.connect("low-memory-warning", self.memory_warning_cb) + self.mainloop = GLib.MainLoop() + self.main_context = self.mainloop.get_context() + + def tearDown(self): + self.p_mock.terminate() + self.p_mock.wait() + + def memory_warning_cb(self, monitor, level): + self.last_warning = level + self.main_context.wakeup() + + def test_low_memory_warning_signal(self): + '''LowMemoryWarning signal''' + + # Wait 2 seconds + timeout = 2 + while timeout > 0: + time.sleep(0.5) + timeout -= 0.5 + self.main_context.iteration(False) + + self.dbusmock.EmitWarning(100) + # Wait 2 seconds or until warning + timeout = 2 + while timeout > 0 or self.last_warning != 100: + time.sleep(0.5) + timeout -= 0.5 + self.main_context.iteration(False) + self.assertEqual(self.last_warning, 100) + + self.dbusmock.EmitWarning(255) + # Wait 2 seconds or until warning + timeout = 2 + while timeout > 0 or self.last_warning != 255: + time.sleep(0.5) + timeout -= 0.5 + self.main_context.iteration(False) + self.assertEqual(self.last_warning, 255) + + +if __name__ == '__main__': + # avoid writing to stderr + unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2)) diff --git a/gio/tests/memory-monitor-portal.py.in b/gio/tests/memory-monitor-portal.py.in new file mode 100755 index 000000000..35f546212 --- /dev/null +++ b/gio/tests/memory-monitor-portal.py.in @@ -0,0 +1,104 @@ +#!/usr/bin/python3 + +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 3 of the License, or (at your option) any +# later version. See http://www.gnu.org/copyleft/lgpl.html for the full text +# of the license. + +__author__ = 'Bastien Nocera' +__email__ = 'hadess@hadess.net' +__copyright__ = '(c) 2019 Red Hat Inc.' +__license__ = 'LGPL 3+' + +import unittest +import sys +import subprocess +import dbus +import dbus.mainloop.glib +import dbusmock +import fcntl +import os +import time + +from gi.repository import GLib +from gi.repository import Gio + +dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + +# XDG_DESKTOP_PORTAL_PATH = os.path.expanduser("~/.cache/jhbuild/build/xdg-desktop-portal/xdg-desktop-portal") +XDG_DESKTOP_PORTAL_PATH = "@libexecdir@/xdg-desktop-portal" + +class TestLowMemoryMonitorPortal(dbusmock.DBusTestCase): + '''Test GMemoryMonitorPortal''' + + @classmethod + def setUpClass(klass): + klass.start_system_bus() + klass.dbus_con = klass.get_dbus(True) + # Start session bus so that xdg-desktop-portal can run on it + klass.start_session_bus() + + def setUp(self): + (self.p_mock, self.obj_lmm) = self.spawn_server_template( + 'low_memory_monitor', {}, stdout=subprocess.PIPE) + # set log to nonblocking + flags = fcntl.fcntl(self.p_mock.stdout, fcntl.F_GETFL) + fcntl.fcntl(self.p_mock.stdout, fcntl.F_SETFL, flags | os.O_NONBLOCK) + self.last_warning = -1 + self.dbusmock = dbus.Interface(self.obj_lmm, dbusmock.MOCK_IFACE) + self.xdp = subprocess.Popen([XDG_DESKTOP_PORTAL_PATH]) + try: + self.wait_for_bus_object('org.freedesktop.portal.Desktop', + '/org/freedesktop/portal/desktop') + except: + raise + # subprocess.Popen(['gdbus', 'monitor', '--session', '--dest', 'org.freedesktop.portal.Desktop']) + + os.environ['GTK_USE_PORTAL'] = "1" + self.memory_monitor = Gio.MemoryMonitor.dup_default() + assert("GMemoryMonitorPortal" in str(self.memory_monitor)) + self.memory_monitor.connect("low-memory-warning", self.portal_memory_warning_cb) + self.mainloop = GLib.MainLoop() + self.main_context = self.mainloop.get_context() + + def tearDown(self): + self.p_mock.terminate() + self.p_mock.wait() + + def portal_memory_warning_cb(self, monitor, level): + self.last_warning = level + self.main_context.wakeup() + + def test_low_memory_warning_portal_signal(self): + '''LowMemoryWarning signal''' + + # Wait 2 seconds + timeout = 2 + while timeout > 0: + time.sleep(0.5) + timeout -= 0.5 + self.main_context.iteration(False) + + self.dbusmock.EmitWarning(100) + # Wait 2 seconds or until warning + timeout = 2 + while timeout > 0 or self.last_warning != 100: + time.sleep(0.5) + timeout -= 0.5 + self.main_context.iteration(False) + self.assertEqual(self.last_warning, 100) + + self.dbusmock.EmitWarning(255) + # Wait 2 seconds or until warning + timeout = 2 + while timeout > 0 or self.last_warning != 255: + time.sleep(0.5) + timeout -= 0.5 + self.main_context.iteration(False) + self.assertEqual(self.last_warning, 255) + + +if __name__ == '__main__': + # avoid writing to stderr + unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=2)) diff --git a/gio/tests/meson.build b/gio/tests/meson.build index 6ef2d6110..890f7b74d 100644 --- a/gio/tests/meson.build +++ b/gio/tests/meson.build @@ -478,6 +478,31 @@ if installed_tests_enabled install_data('static-link.py', install_dir : installed_tests_execdir) endif +memory_monitor_tests = [ + 'memory-monitor-dbus', + 'memory-monitor-portal', +] + +foreach memory_monitor_test : memory_monitor_tests + cdata = configuration_data() + cdata.set('installed_tests_dir', installed_tests_execdir) + cdata.set('program', memory_monitor_test + '.py') + configure_file( + input: installed_tests_template, + output: memory_monitor_test + '.test', + install_dir: installed_tests_metadir, + configuration: cdata + ) + cdata = configuration_data() + cdata.set('libexecdir', join_paths(glib_prefix, get_option('libexecdir'))) + configure_file( + input: memory_monitor_test + '.py.in', + output: memory_monitor_test + '.py', + install_dir : installed_tests_execdir, + configuration: cdata, + ) +endforeach + if not meson.is_cross_build() or meson.has_exe_wrapper() plugin_resources_c = custom_target('plugin-resources.c',