diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8513aae6b..bf1cb57c4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,8 +16,16 @@ variables: .mutter.fedora:34@common: variables: FDO_DISTRIBUTION_VERSION: 34 - BASE_TAG: '2021-08-25.0' - FDO_DISTRIBUTION_PACKAGES: 'gdm gnome-shell xorg-x11-server-Xvfb sassc gcovr clang uncrustify' + BASE_TAG: '2021-09-04.0' + FDO_DISTRIBUTION_PACKAGES: + clang + gcovr + gdm + gnome-shell + python3-dbusmock + sassc + uncrustify + xorg-x11-server-Xvfb FDO_DISTRIBUTION_EXEC: | dnf install -y 'dnf-command(builddep)' && diff --git a/meson.build b/meson.build index 6211181be..d0b960b2f 100644 --- a/meson.build +++ b/meson.build @@ -295,11 +295,22 @@ if have_tests have_clutter_tests = get_option('clutter_tests') have_installed_tests = get_option('installed_tests') + meta_dbus_runner = find_program('src/tests/meta-dbus-runner.py') + default_test_wrappers = [ + meta_dbus_runner, + ] + + add_test_setup('default', + is_default: true, + exe_wrapper: default_test_wrappers, + ) + add_test_setup('CI', env: [ 'MUTTER_DEBUG_DUMMY_MODE_SPECS=800x600@10.0', ], exe_wrapper: [ + default_test_wrappers, find_program('catchsegv'), find_program('xvfb-run'), '-a', '-s', '+iglx -noreset', ], diff --git a/src/backends/meta-orientation-manager.h b/src/backends/meta-orientation-manager.h index 9ceefb81e..f41c84331 100644 --- a/src/backends/meta-orientation-manager.h +++ b/src/backends/meta-orientation-manager.h @@ -24,6 +24,8 @@ #include +#include "core/util-private.h" + typedef enum { META_ORIENTATION_UNDEFINED, @@ -35,11 +37,15 @@ typedef enum #define META_N_ORIENTATIONS (META_ORIENTATION_RIGHT_UP + 1) #define META_TYPE_ORIENTATION_MANAGER (meta_orientation_manager_get_type ()) + +META_EXPORT_TEST G_DECLARE_FINAL_TYPE (MetaOrientationManager, meta_orientation_manager, META, ORIENTATION_MANAGER, GObject) +META_EXPORT_TEST MetaOrientation meta_orientation_manager_get_orientation (MetaOrientationManager *self); +META_EXPORT_TEST gboolean meta_orientation_manager_has_accelerometer (MetaOrientationManager *self); #endif /* META_ORIENTATION_MANAGER_H */ diff --git a/src/tests/dbusmock-templates/iio-sensors-proxy.py b/src/tests/dbusmock-templates/iio-sensors-proxy.py new file mode 100644 index 000000000..83ab989bd --- /dev/null +++ b/src/tests/dbusmock-templates/iio-sensors-proxy.py @@ -0,0 +1,204 @@ +'''sensors proxy mock template +''' + +# 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__ = 'Marco Trevisan' +__copyright__ = '(c) 2021 Canonical Ltd.' + +import re + +import dbus +from dbusmock import MOCK_IFACE + +BUS_NAME = 'net.hadess.SensorProxy' +MAIN_OBJ = '/net/hadess/SensorProxy' +MAIN_IFACE = 'net.hadess.SensorProxy' +COMPASS_IFACE = 'net.hadess.SensorProxy.Compass' +SYSTEM_BUS = True + +CAMEL_TO_SNAKE_CASE_RE = re.compile(r'(?. + * + * Author: Marco Trevisan + */ + +#include "config.h" + +#include "meta-sensors-proxy-mock.h" + +#define SENSORS_MOCK_TEMPLATE "iio-sensors-proxy" + +static MetaSensorsProxyMock *sensors_proxy_mock = NULL; + +static const char * +orientation_to_string (MetaOrientation orientation) +{ + const char *orientation_str = "undefined"; + + switch (orientation) + { + case META_ORIENTATION_UNDEFINED: + orientation_str = "undefined"; + break; + case META_ORIENTATION_NORMAL: + orientation_str = "normal"; + break; + case META_ORIENTATION_BOTTOM_UP: + orientation_str = "bottom-up"; + break; + case META_ORIENTATION_LEFT_UP: + orientation_str = "left-up"; + break; + case META_ORIENTATION_RIGHT_UP: + orientation_str = "right-up"; + break; + } + + return orientation_str; +} + +static void +on_proxy_call_cb (GObject *object, + GAsyncResult *res, + gpointer user_data) +{ + g_autoptr(GError) error = NULL; + GVariant **ret = user_data; + + *ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (object), res, &error); + g_assert_no_error (error); + g_assert_nonnull (ret); +} + +static GVariant * +get_internal_property_value (MetaSensorsProxyMock *proxy, + const char *property_name) +{ + g_autoptr (GVariant) ret = NULL; + + g_dbus_proxy_call (proxy, "GetInternalProperty", + g_variant_new ("(s)", property_name), + G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, + on_proxy_call_cb, &ret); + + while (!ret) + g_main_context_iteration (NULL, TRUE); + + return g_variant_get_child_value (ret, 0); +} + +static void +ensure_property (MetaSensorsProxyMock *proxy, + const char *property_name, + GVariant *expected_value) +{ + g_autoptr (GVariant) value = NULL; + g_autoptr (GVariant) expected = NULL; + gboolean equal_properties; + + value = get_internal_property_value (proxy, property_name); + + if (!g_variant_is_of_type (value, G_VARIANT_TYPE_VARIANT)) + { + g_autoptr (GVariant) tmp = g_variant_ref (value); + value = g_variant_new ("v", tmp); + } + + if (g_variant_is_of_type (expected_value, G_VARIANT_TYPE_VARIANT)) + expected = g_variant_ref (expected_value); + else + expected = g_variant_new ("v", expected_value); + + equal_properties = g_variant_equal (expected, value); + + if (!equal_properties) + { + g_autofree char *actual_str = g_variant_print (value, TRUE); + g_autofree char *expected_str = g_variant_print (expected, TRUE); + + g_debug ("Property: %s", property_name); + g_debug ("Expected: %s", expected_str); + g_debug ("Actual: %s", actual_str); + } + + g_assert_true (equal_properties); +} + +static void +stop_sensors_mock (GDBusConnection *connection) +{ + g_autoptr (GVariant) ret = NULL; + g_autoptr (GError) error = NULL; + + ret = g_dbus_connection_call_sync (connection, + "org.gnome.Mutter.TestDBusMocksManager", + "/org/gnome/Mutter/TestDBusMocksManager", + "org.gnome.Mutter.TestDBusMocksManager", + "StopLocalTemplate", + g_variant_new ("(s)", SENSORS_MOCK_TEMPLATE), + NULL, G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, + NULL, &error); + + g_assert_no_error (error); + g_assert_nonnull (ret); +} + +static void +start_sensors_mock (void) +{ + g_autoptr (GDBusConnection) connection = NULL; + g_autoptr (GError) error = NULL; + g_autoptr (GVariant) ret = NULL; + + connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); + g_assert_no_error (error); + + ret = g_dbus_connection_call_sync (connection, + "org.gnome.Mutter.TestDBusMocksManager", + "/org/gnome/Mutter/TestDBusMocksManager", + "org.gnome.Mutter.TestDBusMocksManager", + "StartFromLocalTemplate", + g_variant_new ("(s)", SENSORS_MOCK_TEMPLATE), + NULL, G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, + NULL, &error); + + g_assert_no_error (error); + g_assert_nonnull (ret); +} + +static void +on_proxy_removed (gpointer data) +{ + g_autoptr (GDBusConnection) connection = data; + + stop_sensors_mock (connection); +} + +MetaSensorsProxyMock * +meta_sensors_proxy_mock_get (void) +{ + GDBusProxy *proxy = NULL; + g_autoptr (GError) error = NULL; + + if (sensors_proxy_mock) + return g_object_ref (sensors_proxy_mock); + + start_sensors_mock (); + + proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START | + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + NULL, + "net.hadess.SensorProxy", + "/net/hadess/SensorProxy", + "org.freedesktop.DBus.Mock", + NULL, &error); + g_assert_true (G_IS_DBUS_PROXY (proxy)); + g_assert_no_error (error); + + while (TRUE) + { + g_autoptr (GVariant) ret = NULL; + size_t n_owners = 0; + + ret = get_internal_property_value (proxy, "AccelerometerOwners"); + if (g_variant_get_strv (ret, &n_owners) && n_owners) + { + g_assert_cmpuint (n_owners, ==, 1); + break; + } + } + + sensors_proxy_mock = proxy; + g_object_add_weak_pointer (G_OBJECT (sensors_proxy_mock), + (gpointer *) &sensors_proxy_mock); + + g_object_set_data_full (G_OBJECT (proxy), "proxy-data", + g_object_ref (g_dbus_proxy_get_connection (proxy)), + on_proxy_removed); + + return proxy; +} + +void +meta_sensors_proxy_mock_set_property (MetaSensorsProxyMock *proxy, + const gchar *property_name, + GVariant *value) +{ + g_autoptr (GVariant) ret = NULL; + g_autoptr (GVariant) reffed_value = g_variant_ref (value); + + g_dbus_proxy_call (proxy, "SetInternalProperty", + g_variant_new ("(ssv)", + "net.hadess.SensorProxy", + property_name, + reffed_value), + G_DBUS_CALL_FLAGS_NONE, + -1, NULL, on_proxy_call_cb, &ret); + + while (!ret) + g_main_context_iteration (NULL, TRUE); + + g_assert_nonnull (ret); + + ensure_property (proxy, property_name, value); +} + +void +meta_sensors_proxy_mock_set_orientation (MetaSensorsProxyMock *proxy, + MetaOrientation orientation) +{ + const char *orientation_str; + + meta_sensors_proxy_mock_set_property (proxy, "HasAccelerometer", + g_variant_new_boolean (TRUE)); + + orientation_str = orientation_to_string (orientation); + meta_sensors_proxy_mock_set_property (proxy, "AccelerometerOrientation", + g_variant_new_string (orientation_str)); +} diff --git a/src/tests/meta-sensors-proxy-mock.h b/src/tests/meta-sensors-proxy-mock.h new file mode 100644 index 000000000..b32c5868d --- /dev/null +++ b/src/tests/meta-sensors-proxy-mock.h @@ -0,0 +1,41 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* + * Copyright (C) 2020 Canonical, Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * Author: Marco Trevisan + */ + +#ifndef META_SENSORS_PROXY_MOCK_H +#define META_SENSORS_PROXY_MOCK_H + +#include "backends/meta-orientation-manager.h" + +typedef GDBusProxy MetaSensorsProxyMock; +G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaSensorsProxyMock, g_object_unref) + +META_EXPORT +MetaSensorsProxyMock * meta_sensors_proxy_mock_get (void); + +META_EXPORT +void meta_sensors_proxy_mock_set_property (MetaSensorsProxyMock *proxy, + const gchar *property_name, + GVariant *value); + +META_EXPORT +void meta_sensors_proxy_mock_set_orientation (MetaSensorsProxyMock *proxy, + MetaOrientation orientation); + +#endif /* META_SENSORS_PROXY_MOCK_H */ diff --git a/src/tests/mutter-all.test.in b/src/tests/mutter-all.test.in index 6e103c51d..413d2acd5 100644 --- a/src/tests/mutter-all.test.in +++ b/src/tests/mutter-all.test.in @@ -1,6 +1,6 @@ [Test] Description=All Mutter tests TestEnvironment=GSETTINGS_BACKEND=memory; -Exec=sh -c 'env XDG_RUNTIME_DIR="$(mktemp -d -t mutter-@apiversion@-all-tests-XXXXXX)" dbus-run-session -- xvfb-run -a -s "+iglx -noreset" -- @libexecdir@/installed-tests/mutter-@apiversion@/mutter-test-runner --all' +Exec=sh -c 'env XDG_RUNTIME_DIR="$(mktemp -d -t mutter-@apiversion@-all-tests-XXXXXX)" @libexecdir@/installed-tests/mutter-@apiversion@/meta-dbus-runner.py xvfb-run -a -s "+iglx -noreset" -- @libexecdir@/installed-tests/mutter-@apiversion@/mutter-test-runner --all' Type=session Output=TAP diff --git a/src/tests/orientation-manager-unit-tests.c b/src/tests/orientation-manager-unit-tests.c new file mode 100644 index 000000000..74a861ab0 --- /dev/null +++ b/src/tests/orientation-manager-unit-tests.c @@ -0,0 +1,131 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* + * Copyright (C) 2020 Canonical, Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * Author: Marco Trevisan + */ + +#include "config.h" + +#include "orientation-manager-unit-tests.h" + +#include "tests/meta-sensors-proxy-mock.h" + +static void +meta_test_orientation_manager_no_daemon (void) +{ + g_autoptr (MetaOrientationManager) manager = NULL; + + manager = g_object_new (META_TYPE_ORIENTATION_MANAGER, NULL); + g_assert_false (meta_orientation_manager_has_accelerometer (manager)); + g_assert_cmpuint (meta_orientation_manager_get_orientation (manager), + ==, + META_ORIENTATION_UNDEFINED); +} + +static void +meta_test_orientation_manager_no_device (void) +{ + g_autoptr (MetaOrientationManager) manager = NULL; + MetaSensorsProxyMock* orientation_mock = NULL; + + orientation_mock = meta_sensors_proxy_mock_get (); + manager = g_object_new (META_TYPE_ORIENTATION_MANAGER, NULL); + g_assert_false (meta_orientation_manager_has_accelerometer (manager)); + g_assert_cmpuint (meta_orientation_manager_get_orientation (manager), + ==, + META_ORIENTATION_UNDEFINED); + + g_object_unref (orientation_mock); +} + +static void +meta_test_orientation_manager_has_accelerometer (void) +{ + g_autoptr (MetaOrientationManager) manager = NULL; + g_autoptr (MetaSensorsProxyMock) orientation_mock = NULL; + + manager = g_object_new (META_TYPE_ORIENTATION_MANAGER, NULL); + orientation_mock = meta_sensors_proxy_mock_get (); + + meta_sensors_proxy_mock_set_property (orientation_mock, + "HasAccelerometer", + g_variant_new_boolean (TRUE)); + + g_debug ("Checking whether accelerometer is present"); + g_assert_true (meta_orientation_manager_has_accelerometer (manager)); + g_assert_cmpuint (meta_orientation_manager_get_orientation (manager), + ==, + META_ORIENTATION_UNDEFINED); +} + +static void +orientation_changed_cb (MetaOrientationManager *manager, + gpointer user_data) +{ + gboolean *changed_called = user_data; + + *changed_called = TRUE; +} + +static void +meta_test_orientation_manager_accelerometer_orientations (void) +{ + g_autoptr (MetaOrientationManager) manager = NULL; + g_autoptr (MetaSensorsProxyMock) orientation_mock = NULL; + + manager = g_object_new (META_TYPE_ORIENTATION_MANAGER, NULL); + orientation_mock = meta_sensors_proxy_mock_get (); + + MetaOrientation initial; + gboolean changed_called; + unsigned i; + + g_signal_connect (manager, "orientation-changed", + G_CALLBACK (orientation_changed_cb), + &changed_called); + + initial = meta_orientation_manager_get_orientation (manager); + + for (i = initial + 1; i != initial; i = (i + 1) % META_N_ORIENTATIONS) + { + changed_called = FALSE; + meta_sensors_proxy_mock_set_orientation (orientation_mock, i); + + g_debug ("Checking orientation %d", i); + g_assert_cmpuint (meta_orientation_manager_get_orientation (manager), + ==, + i); + + if (i != META_ORIENTATION_UNDEFINED) + g_assert_true (changed_called); + else + g_assert_false (changed_called); + } +} + +void +init_orientation_manager_tests (void) +{ + g_test_add_func ("/backends/orientation-manager/no-daemon", + meta_test_orientation_manager_no_daemon); + g_test_add_func ("/backends/orientation-manager/no-device", + meta_test_orientation_manager_no_device); + g_test_add_func ("/backends/orientation-manager/has-accelerometer", + meta_test_orientation_manager_has_accelerometer); + g_test_add_func ("/backends/orientation-manager/accelerometer-orientations", + meta_test_orientation_manager_accelerometer_orientations); +} diff --git a/src/tests/orientation-manager-unit-tests.h b/src/tests/orientation-manager-unit-tests.h new file mode 100644 index 000000000..34b175f0c --- /dev/null +++ b/src/tests/orientation-manager-unit-tests.h @@ -0,0 +1,26 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* + * Copyright (C) 2020 Canonical, Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + * Author: Marco Trevisan + */ + +#ifndef ORIENTATION_MANAGER_UNIT_TESTS_H +#define ORIENTATION_MANAGER_UNIT_TESTS_H + +void init_orientation_manager_tests (void); + +#endif /* ORIENTATION_MANAGER_UNIT_TESTS_H */ diff --git a/src/tests/unit-tests.c b/src/tests/unit-tests.c index a31f50536..20f965ce4 100644 --- a/src/tests/unit-tests.c +++ b/src/tests/unit-tests.c @@ -35,6 +35,8 @@ #include "tests/monitor-unit-tests.h" #include "tests/monitor-store-unit-tests.h" #include "tests/monitor-transform-tests.h" +#include "tests/meta-test-utils.h" +#include "tests/orientation-manager-unit-tests.h" #include "tests/wayland-unit-tests.h" MetaContext *test_context; @@ -232,6 +234,7 @@ init_tests (void) init_boxes_tests (); init_wayland_tests (); init_monitor_transform_tests (); + init_orientation_manager_tests (); } int