/* * Copyright © 2017 Endless Mobile, Inc. * Copyright (C) 2022 Igalia S.L. * * SPDX-License-Identifier: LGPL-2.0+ * * This library 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 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . * * Authors: * - Philip Withnall */ #include "config.h" #include #include #include #include #include "test-mock-gio.h" /** * SECTION:mock-gio * @title: Mock GIO volume interfaces * @short_description: Mock implementations of GIO volume, mount and drive * interfaces * @stability: Unstable * @include: tests/test-mock-gio.h * * A set of classes implementing GIO interfaces for volumes, mounts, drives * and volume monitoring, which return mock data to the caller when used. These * are designed for use in unit tests, to mock up removable drives when testing * code which monitors such drives being added and removed and then queries * properties of them. * * By returning mock drive locations to the caller, for example, the contents of * a removable drive may be mocked up using temporary files. * * Currently, all the mock data returned by these classes to callers is static, * set at construction time. * * Since: 2017.8 */ /* Mock volume monitor class. This returns a static set of data to the caller, * which it was initialised with. */ struct _OstreeMockVolumeMonitor { GVolumeMonitor parent_instance; GList *mounts; /* (element-type OstreeMockMount) */ GList *volumes; /* (element-type OstreeMockVolume) */ }; G_DEFINE_TYPE (OstreeMockVolumeMonitor, ostree_mock_volume_monitor, G_TYPE_VOLUME_MONITOR) static GList * ostree_mock_volume_monitor_get_mounts (GVolumeMonitor *monitor) { OstreeMockVolumeMonitor *self = OSTREE_MOCK_VOLUME_MONITOR (monitor); return g_list_copy_deep (self->mounts, (GCopyFunc)g_object_ref, NULL); } static GList * ostree_mock_volume_monitor_get_volumes (GVolumeMonitor *monitor) { OstreeMockVolumeMonitor *self = OSTREE_MOCK_VOLUME_MONITOR (monitor); return g_list_copy_deep (self->volumes, (GCopyFunc)g_object_ref, NULL); } static void ostree_mock_volume_monitor_init (OstreeMockVolumeMonitor *self) { /* Nothing to see here. */ } static void ostree_mock_volume_monitor_dispose (GObject *object) { OstreeMockVolumeMonitor *self = OSTREE_MOCK_VOLUME_MONITOR (object); g_list_free_full (self->volumes, g_object_unref); self->volumes = NULL; g_list_free_full (self->mounts, g_object_unref); self->mounts = NULL; G_OBJECT_CLASS (ostree_mock_volume_monitor_parent_class)->dispose (object); } static void ostree_mock_volume_monitor_class_init (OstreeMockVolumeMonitorClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GVolumeMonitorClass *monitor_class = G_VOLUME_MONITOR_CLASS (klass); object_class->dispose = ostree_mock_volume_monitor_dispose; monitor_class->get_mounts = ostree_mock_volume_monitor_get_mounts; monitor_class->get_volumes = ostree_mock_volume_monitor_get_volumes; } /** * ostree_mock_volume_monitor_new: * @mounts: (element-type GMount) (transfer none): list of current #GMounts * @volumes: (element-type GVolume) (transfer none): list of current #GVolumes * * Create a new mock #GVolumeMonitor which will return the given static lists of * #GMounts and #GVolumes to any caller of g_volume_monitor_get_mounts() or * g_volume_monitor_get_volumes(). * * Typically, the elements of @mounts will be #OstreeMockMount objects and the * elements of @volumes will be #OstreeMockVolume objects; but this does not * have to be the case. * * Returns: (transfer full): a new #GVolumeMonitor object * Since: 2017.8 */ GVolumeMonitor * ostree_mock_volume_monitor_new (GList *mounts, GList *volumes) { g_autoptr (OstreeMockVolumeMonitor) monitor = NULL; monitor = g_object_new (OSTREE_TYPE_MOCK_VOLUME_MONITOR, NULL); monitor->mounts = g_list_copy_deep (mounts, (GCopyFunc)g_object_ref, NULL); monitor->volumes = g_list_copy_deep (volumes, (GCopyFunc)g_object_ref, NULL); return (GVolumeMonitor *)g_steal_pointer (&monitor); } /* Mock volume class. This returns a static set of data to the caller, which it * was initialised with. */ struct _OstreeMockVolume { GObject parent_instance; gchar *name; GDrive *drive; /* (owned) (nullable) */ GMount *mount; /* (owned) (nullable) */ }; static void ostree_mock_volume_iface_init (GVolumeIface *iface); G_DEFINE_TYPE_WITH_CODE (OstreeMockVolume, ostree_mock_volume, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_VOLUME, ostree_mock_volume_iface_init)) static gchar * ostree_mock_volume_get_name (GVolume *volume) { OstreeMockVolume *self = OSTREE_MOCK_VOLUME (volume); return g_strdup (self->name); } static GDrive * ostree_mock_volume_get_drive (GVolume *volume) { OstreeMockVolume *self = OSTREE_MOCK_VOLUME (volume); return (self->drive != NULL) ? g_object_ref (self->drive) : NULL; } static GMount * ostree_mock_volume_get_mount (GVolume *volume) { OstreeMockVolume *self = OSTREE_MOCK_VOLUME (volume); return (self->mount != NULL) ? g_object_ref (self->mount) : NULL; } static void ostree_mock_volume_init (OstreeMockVolume *self) { /* Nothing to see here. */ } static void ostree_mock_volume_dispose (GObject *object) { OstreeMockVolume *self = OSTREE_MOCK_VOLUME (object); g_clear_pointer (&self->name, g_free); g_clear_object (&self->drive); g_clear_object (&self->mount); G_OBJECT_CLASS (ostree_mock_volume_parent_class)->dispose (object); } static void ostree_mock_volume_class_init (OstreeMockVolumeClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = ostree_mock_volume_dispose; } static void ostree_mock_volume_iface_init (GVolumeIface *iface) { iface->get_name = ostree_mock_volume_get_name; iface->get_drive = ostree_mock_volume_get_drive; iface->get_mount = ostree_mock_volume_get_mount; } /** * ostree_mock_volume_new: * @name: volume name * @drive: (transfer none) (nullable): drive for the volume, or %NULL if none * should be associated * @mount: (transfer none) (nullable): mount for the volume, or %NULL if it’s * not mounted * * Create a new mock #GVolume which will return the given static @name, @drive * and @mount to any caller of its getter methods. There is currently no * provision for changing these values dynamically. There is also currently no * provision for mocking the other getters of #GVolume. * * Typically, @drive will be an #OstreeMockDrive object and @mount will be an * #OstreeMockMount object; but this does not have to be the case. * * Returns: (transfer full): a new #GVolume object * Since: 2017.8 */ OstreeMockVolume * ostree_mock_volume_new (const gchar *name, GDrive *drive, GMount *mount) { g_autoptr (OstreeMockVolume) volume = NULL; volume = g_object_new (OSTREE_TYPE_MOCK_VOLUME, NULL); volume->name = g_strdup (name); volume->drive = (drive != NULL) ? g_object_ref (drive) : NULL; volume->mount = (mount != NULL) ? g_object_ref (mount) : NULL; return g_steal_pointer (&volume); } /* Mock drive class. This returns a static set of data to the caller, which it * was initialised with. */ struct _OstreeMockDrive { GObject parent_instance; gboolean is_removable; }; static void ostree_mock_drive_iface_init (GDriveIface *iface); G_DEFINE_TYPE_WITH_CODE (OstreeMockDrive, ostree_mock_drive, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_DRIVE, ostree_mock_drive_iface_init)) #if GLIB_CHECK_VERSION(2, 50, 0) static gboolean ostree_mock_drive_is_removable (GDrive *drive) { OstreeMockDrive *self = OSTREE_MOCK_DRIVE (drive); return self->is_removable; } #endif static void ostree_mock_drive_init (OstreeMockDrive *self) { /* Nothing to see here. */ } static void ostree_mock_drive_class_init (OstreeMockDriveClass *klass) { /* Nothing to see here. */ } static void ostree_mock_drive_iface_init (GDriveIface *iface) { #if GLIB_CHECK_VERSION(2, 50, 0) iface->is_removable = ostree_mock_drive_is_removable; #endif } /** * ostree_mock_drive_new: * @is_removable: %TRUE if the drive is removable; %FALSE otherwise * * Create a new mock #GDrive which will return the given static @is_removable to * any caller of its getter methods. There is currently no provision for mocking * the other getters of #GDrive. * * Returns: (transfer full): a new #GDrive object * Since: 2017.8 */ OstreeMockDrive * ostree_mock_drive_new (gboolean is_removable) { g_autoptr (OstreeMockDrive) drive = NULL; drive = g_object_new (OSTREE_TYPE_MOCK_DRIVE, NULL); drive->is_removable = is_removable; return g_steal_pointer (&drive); } /* Mock mount class. This returns a static set of data to the caller, which it * was initialised with. */ struct _OstreeMockMount { GObject parent_instance; gchar *name; /* (owned) */ GFile *root; /* (owned) */ }; static void ostree_mock_mount_iface_init (GMountIface *iface); G_DEFINE_TYPE_WITH_CODE (OstreeMockMount, ostree_mock_mount, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_MOUNT, ostree_mock_mount_iface_init)) static gchar * ostree_mock_mount_get_name (GMount *mount) { OstreeMockMount *self = OSTREE_MOCK_MOUNT (mount); return g_strdup (self->name); } static GFile * ostree_mock_mount_get_root (GMount *mount) { OstreeMockMount *self = OSTREE_MOCK_MOUNT (mount); return g_object_ref (self->root); } static void ostree_mock_mount_init (OstreeMockMount *self) { /* Nothing to see here. */ } static void ostree_mock_mount_dispose (GObject *object) { OstreeMockMount *self = OSTREE_MOCK_MOUNT (object); g_clear_pointer (&self->name, g_free); g_clear_object (&self->root); G_OBJECT_CLASS (ostree_mock_mount_parent_class)->dispose (object); } static void ostree_mock_mount_class_init (OstreeMockMountClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = ostree_mock_mount_dispose; } static void ostree_mock_mount_iface_init (GMountIface *iface) { iface->get_name = ostree_mock_mount_get_name; iface->get_root = ostree_mock_mount_get_root; } /** * ostree_mock_mount_new: * @name: mount name * @root: (transfer none): root path for the mounted file system * * Create a new mock #GMount which will return the given static @name and @root * to any caller of its getter methods. There is currently no provision for * mocking the other getters of #GMount. * * Typically, @root will point to a temporary directory where a mocked file * system is present; but this does not have to be the case. * * Returns: (transfer full): a new #GMount object * Since: 2017.8 */ OstreeMockMount * ostree_mock_mount_new (const gchar *name, GFile *root) { g_autoptr (OstreeMockMount) mount = NULL; mount = g_object_new (OSTREE_TYPE_MOCK_MOUNT, NULL); mount->name = g_strdup (name); mount->root = g_object_ref (root); return g_steal_pointer (&mount); }