Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package umockdev for openSUSE:Factory 
checked in at 2024-10-14 13:06:22
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/umockdev (Old)
 and      /work/SRC/openSUSE:Factory/.umockdev.new.19354 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "umockdev"

Mon Oct 14 13:06:22 2024 rev:21 rq:1207590 version:0.18.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/umockdev/umockdev.changes        2024-07-22 
17:14:06.195921501 +0200
+++ /work/SRC/openSUSE:Factory/.umockdev.new.19354/umockdev.changes     
2024-10-14 13:06:23.998670921 +0200
@@ -1,0 +2,9 @@
+Mon Oct  7 21:38:00 UTC 2024 - Atri Bhattacharya <badshah...@gmail.com>
+
+- Update to version 0.18.4:
+  * Add ioctls for Chromium OS EC devices.
+  * Generate "remove" uevent in umockdev_testbed_remove_device().
+  * Recursively remove children with uevents.
+  * preload: Fix sigmask block and restore race.
+
+-------------------------------------------------------------------

Old:
----
  umockdev-0.18.3.tar.xz

New:
----
  umockdev-0.18.4.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ umockdev.spec ++++++
--- /var/tmp/diff_new_pack.yoFDOi/_old  2024-10-14 13:06:25.870749506 +0200
+++ /var/tmp/diff_new_pack.yoFDOi/_new  2024-10-14 13:06:25.870749506 +0200
@@ -19,7 +19,7 @@
 %define shlib libumockdev0
 %define shlibpre libumockdev-preload0
 Name:           umockdev
-Version:        0.18.3
+Version:        0.18.4
 Release:        0
 Summary:        Mock hardware devices for creating unit tests and bug reporting
 License:        LGPL-2.1-or-later

++++++ umockdev-0.18.3.tar.xz -> umockdev-0.18.4.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/umockdev-0.18.3/.version new/umockdev-0.18.4/.version
--- old/umockdev-0.18.3/.version        2024-05-23 09:53:17.956983000 +0200
+++ new/umockdev-0.18.4/.version        2024-09-04 07:46:35.302986400 +0200
@@ -1 +1 @@
-0.18.3
+0.18.4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/umockdev-0.18.3/devices/cros_ec/crosfingerprint.ioctl 
new/umockdev-0.18.4/devices/cros_ec/crosfingerprint.ioctl
--- old/umockdev-0.18.3/devices/cros_ec/crosfingerprint.ioctl   1970-01-01 
01:00:00.000000000 +0100
+++ new/umockdev-0.18.4/devices/cros_ec/crosfingerprint.ioctl   2024-08-02 
03:21:59.000000000 +0200
@@ -0,0 +1,4 @@
+@DEV /dev/cros_fp
+CROS_EC_DEV_IOCXCMD_V2 4 000000000204000004000000040000000000000080000000
+CROS_EC_DEV_IOCXCMD_V2 48 
010000000304000000000000300000000000000046504320090000001B020000010000009466000047524559A000A0000800FF0324140000050001000100000004000000
+CROS_EC_DEV_IOCXCMD_V2 22 
000000000704000000000000160000000000000065630100B44A020007B30300DC33505A070000000000
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/umockdev-0.18.3/devices/cros_ec/crosfingerprint.umockdev 
new/umockdev-0.18.4/devices/cros_ec/crosfingerprint.umockdev
--- old/umockdev-0.18.3/devices/cros_ec/crosfingerprint.umockdev        
1970-01-01 01:00:00.000000000 +0100
+++ new/umockdev-0.18.4/devices/cros_ec/crosfingerprint.umockdev        
2024-08-02 03:21:59.000000000 +0200
@@ -0,0 +1,93 @@
+P: 
/devices/platform/AMDI0020:01/AMDI0020:01:0/AMDI0020:01:0.0/serial0/serial0-0/cros-ec-dev.2.auto/misc/cros_fp
+N: cros_fp
+E: DEVNAME=/dev/cros_fp
+E: MAJOR=10
+E: MINOR=122
+E: SUBSYSTEM=misc
+A: dev=10:122\n
+L: device=../../../cros-ec-dev.2.auto
+A: power/control=auto\n
+A: power/runtime_active_time=0\n
+A: power/runtime_status=unsupported\n
+A: power/runtime_suspended_time=0\n
+
+P: 
/devices/platform/AMDI0020:01/AMDI0020:01:0/AMDI0020:01:0.0/serial0/serial0-0/cros-ec-dev.2.auto
+E: DRIVER=cros-ec-dev
+E: ID_PATH=platform-AMDI0020:01-platform-cros-ec-dev.2.auto
+E: ID_PATH_TAG=platform-AMDI0020_01-platform-cros-ec-dev_2_auto
+E: ID_VENDOR_FROM_DATABASE=Amdek Corporation
+E: MODALIAS=platform:cros-ec-dev
+E: SUBSYSTEM=platform
+L: driver=../../../../../../../../bus/platform/drivers/cros-ec-dev
+A: driver_override=(null)\n
+A: modalias=platform:cros-ec-dev\n
+A: power/control=auto\n
+A: power/runtime_active_time=0\n
+A: power/runtime_status=unsupported\n
+A: power/runtime_suspended_time=0\n
+
+P: 
/devices/platform/AMDI0020:01/AMDI0020:01:0/AMDI0020:01:0.0/serial0/serial0-0
+E: DRIVER=cros-ec-uart
+E: MODALIAS=of:NcrfpTCgoogle,cros-ec-uart
+E: SUBSYSTEM=serial
+L: driver=../../../../../../../bus/serial/drivers/cros-ec-uart
+L: 
firmware_node=../../../../../../LNXSYSTM:00/LNXSYBUS:00/AMDI0020:01/PRP0001:00
+A: modalias=of:NcrfpTCgoogle,cros-ec-uart\n
+A: power/control=auto\n
+A: power/runtime_active_time=0\n
+A: power/runtime_status=unsupported\n
+A: power/runtime_suspended_time=0\n
+
+P: /devices/platform/AMDI0020:01/AMDI0020:01:0/AMDI0020:01:0.0/serial0
+E: SUBSYSTEM=serial
+L: firmware_node=../../../../../LNXSYSTM:00/LNXSYBUS:00/AMDI0020:01
+A: power/wakeup=disabled\n
+A: power/wakeup_abort_count=\n
+A: power/wakeup_active=\n
+A: power/wakeup_active_count=\n
+A: power/wakeup_count=\n
+A: power/wakeup_expire_count=\n
+A: power/wakeup_last_time_ms=\n
+A: power/wakeup_max_time_ms=\n
+A: power/wakeup_total_time_ms=\n
+L: software_node=../../../../../../kernel/software_nodes/node1
+A: waiting_for_supplier=0\n
+
+P: /devices/platform/AMDI0020:01/AMDI0020:01:0/AMDI0020:01:0.0
+E: DEVTYPE=port
+E: DRIVER=port
+E: SUBSYSTEM=serial-base
+L: driver=../../../../../bus/serial-base/drivers/port
+A: power/autosuspend_delay_ms=500\n
+A: power/control=auto\n
+A: power/runtime_active_time=31736669\n
+A: power/runtime_status=active\n
+A: power/runtime_suspended_time=5190\n
+
+P: /devices/platform/AMDI0020:01/AMDI0020:01:0
+E: DEVTYPE=ctrl
+E: DRIVER=ctrl
+E: SUBSYSTEM=serial-base
+L: driver=../../../../bus/serial-base/drivers/ctrl
+A: power/control=auto\n
+A: power/runtime_active_time=31736676\n
+A: power/runtime_status=active\n
+A: power/runtime_suspended_time=5190\n
+
+P: /devices/platform/AMDI0020:01
+E: DRIVER=dw-apb-uart
+E: ID_PATH=platform-AMDI0020:01
+E: ID_PATH_TAG=platform-AMDI0020_01
+E: ID_VENDOR_FROM_DATABASE=Amdek Corporation
+E: MODALIAS=acpi:AMDI0020:
+E: SUBSYSTEM=platform
+L: driver=../../../bus/platform/drivers/dw-apb-uart
+A: driver_override=(null)\n
+L: firmware_node=../../LNXSYSTM:00/LNXSYBUS:00/AMDI0020:01
+A: modalias=acpi:AMDI0020:\n
+A: power/control=auto\n
+A: power/runtime_active_time=31736687\n
+A: power/runtime_status=active\n
+A: power/runtime_suspended_time=5189\n
+L: software_node=../../../kernel/software_nodes/node1
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/umockdev-0.18.3/docs/reference/meson.build 
new/umockdev-0.18.4/docs/reference/meson.build
--- old/umockdev-0.18.3/docs/reference/meson.build      2024-05-23 
09:49:45.000000000 +0200
+++ new/umockdev-0.18.4/docs/reference/meson.build      2024-08-02 
03:21:59.000000000 +0200
@@ -10,7 +10,7 @@
   content_files: [version_xml],
   gobject_typesfile: 'umockdev.types',
   scan_args: ['--ignore-decorators', 'VALA_EXTERN'],
-  ignore_headers: ['uevent_sender.h', 'ioctl_tree.h', 'debug.h'],
+  ignore_headers: ['uevent_sender.h', 'cros_ec.h', 'ioctl_tree.h', 'debug.h'],
   dependencies: [glib, gobject, declare_dependency(link_with : 
[umockdev_lib])],
   install: true,
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/umockdev-0.18.3/meson.build 
new/umockdev-0.18.4/meson.build
--- old/umockdev-0.18.3/meson.build     2024-05-23 09:49:45.000000000 +0200
+++ new/umockdev-0.18.4/meson.build     2024-08-02 03:21:59.000000000 +0200
@@ -278,6 +278,7 @@
 
   test('umockdev-vala', executable('test-umockdev-vala',
       'tests/test-umockdev-vala.vala',
+      include_directories: include_directories('src'),
       dependencies: [glib, gobject, gio, gudev, vapi_posix, vapi_assertions, 
vapi_ioctl, vapi_glibc, vapi_selinux, selinux],
       link_with: [umockdev_lib, umockdev_utils_lib],
       vala_args: optional_defines),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/umockdev-0.18.3/packit.yaml 
new/umockdev-0.18.4/packit.yaml
--- old/umockdev-0.18.3/packit.yaml     2024-05-23 09:49:45.000000000 +0200
+++ new/umockdev-0.18.4/packit.yaml     2024-08-02 03:21:59.000000000 +0200
@@ -77,11 +77,13 @@
 
   - job: koji_build
     trigger: commit
+    packages: [umockdev-fedora]
     dist_git_branches:
       - fedora-all
 
   - job: bodhi_update
     trigger: commit
+    packages: [umockdev-fedora]
     dist_git_branches:
       # rawhide updates are created automatically
       - fedora-branched
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/umockdev-0.18.3/src/cros_ec.h 
new/umockdev-0.18.4/src/cros_ec.h
--- old/umockdev-0.18.3/src/cros_ec.h   1970-01-01 01:00:00.000000000 +0100
+++ new/umockdev-0.18.4/src/cros_ec.h   2024-08-02 03:21:59.000000000 +0200
@@ -0,0 +1,20 @@
+#ifndef __CROS_EC_H
+#define __CROS_EC_H
+
+#include <stdint.h>
+
+struct cros_ec_command_v2 {
+    uint32_t version;
+    uint32_t command;
+    uint32_t outsize;
+    uint32_t insize;
+    uint32_t result;
+    uint8_t data[0];
+};
+
+#define CROS_EC_DEV_IOC_V2 0xEC
+#define CROS_EC_DEV_IOCXCMD_V2 \
+    _IOWR(CROS_EC_DEV_IOC_V2, 0, struct cros_ec_command_v2)
+#define CROS_EC_DEV_IOCEVENTMASK_V2 _IO(CROS_EC_DEV_IOC_V2, 2)
+
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/umockdev-0.18.3/src/ioctl.vapi 
new/umockdev-0.18.4/src/ioctl.vapi
--- old/umockdev-0.18.3/src/ioctl.vapi  2024-05-23 09:49:45.000000000 +0200
+++ new/umockdev-0.18.4/src/ioctl.vapi  2024-08-02 03:21:59.000000000 +0200
@@ -131,5 +131,17 @@
                uint32 size;
                uint8 value[HID_MAX_DESCRIPTOR_SIZE];
        }
+
+  [CCode (cheader_filename = "cros_ec.h")]
+  public const int CROS_EC_DEV_IOCXCMD_V2;
+  [CCode (cname = "struct cros_ec_command_v2", cheader_filename = "cros_ec.h")]
+  public struct cros_ec_command_v2 {
+    uint32 version;
+    uint32 command;
+    uint32 outsize;
+    uint32 insize;
+    uint32 result;
+    uint8 data[0];
+  }
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/umockdev-0.18.3/src/ioctl_tree.c 
new/umockdev-0.18.4/src/ioctl_tree.c
--- old/umockdev-0.18.3/src/ioctl_tree.c        2024-05-23 09:49:45.000000000 
+0200
+++ new/umockdev-0.18.4/src/ioctl_tree.c        2024-08-02 03:21:59.000000000 
+0200
@@ -29,6 +29,7 @@
 
 #include "debug.h"
 #include "utils.h"
+#include "cros_ec.h"
 #include "ioctl_tree.h"
 
 #define TRUE 1
@@ -414,6 +415,18 @@
     return NULL;
 }
 
+int
+ioctl_tree_next_ret(ioctl_tree * tree, ioctl_tree * last)
+{
+    const ioctl_tree *i = ioctl_tree_next_wrap(tree, last);
+
+    if (i == NULL) {
+        return 0;
+    }
+
+    return i->ret;
+}
+
 /***********************************
  *
  * Utility functions for ioctl implementations
@@ -555,10 +568,6 @@
  *
  ***********************************/
 
-/* Note, we don't currently have any of those */
-
-#if 0
-
 static void
 ioctl_varlenstruct_init_from_bin(ioctl_tree * node, const void *data)
 {
@@ -622,8 +631,6 @@
     return 0;
 }
 
-#endif
-
 /***********************************
  *
  * USBDEVFS_REAPURB
@@ -872,11 +879,11 @@
     I_NAMED_SIZED_SIMPLE_STRUCT_IN(name, #name, -1, nr_range, 
insertion_parent_fn)
 
 /* input structs with a variable length (but no pointers to substructures) */
-#define I_VARLEN_STRUCT_IN(name, insertion_parent_fn, data_size_fn) \
+#define I_VARLEN_STRUCT_IN(name, equal_fn, insertion_parent_fn, data_size_fn) \
     {name, -1, 0, #name,                                                       
\
      ioctl_varlenstruct_init_from_bin, ioctl_varlenstruct_init_from_text,      
\
      ioctl_simplestruct_free_data,                                             
\
-     ioctl_varlenstruct_write, ioctl_varlenstruct_equal,                       
\
+     ioctl_varlenstruct_write, equal_fn,                       \
      ioctl_varlenstruct_in_execute, insertion_parent_fn, data_size_fn}
 
 /* data with custom handlers; necessary for structs with pointers to nested
@@ -892,6 +899,20 @@
     {name, size, nr_range, #name,                  \
      NULL, NULL, NULL, NULL, NULL, NULL, NULL}     \
 
+static int
+cros_ec_ioctl_equal(UNUSED const ioctl_tree *_n1, UNUSED const ioctl_tree *_n2)
+{
+  return FALSE;
+}
+
+static size_t
+cros_ec_ioctl_get_data_size(IOCTL_REQUEST_TYPE _id, const void *data)
+{
+    const struct cros_ec_command_v2 *s_cmd = (struct cros_ec_command_v2 *)data;
+
+    return sizeof(struct cros_ec_command_v2) + le32toh(s_cmd->insize);
+}
+
 ioctl_type ioctl_db[] = {
     I_SIMPLE_STRUCT_IN(USBDEVFS_CONNECTINFO, 0, 
ioctl_insertion_parent_stateless),
 
@@ -960,6 +981,10 @@
     I_NAMED_SIMPLE_STRUCT_IN(HIDIOCGOUTPUT(32), "HIDIOCGOUTPUT", 0, 
ioctl_insertion_parent_stateless),
 #endif
 
+    /* cros_ec */
+    I_VARLEN_STRUCT_IN(CROS_EC_DEV_IOCXCMD_V2, cros_ec_ioctl_equal, 
ioctl_insertion_parent_stateless, cros_ec_ioctl_get_data_size),
+    I_NOSTATE(CROS_EC_DEV_IOCEVENTMASK_V2, enodata),
+
     /* terminator */
     {0, 0, 0, "", NULL, NULL, NULL, NULL, NULL}
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/umockdev-0.18.3/src/ioctl_tree.h 
new/umockdev-0.18.4/src/ioctl_tree.h
--- old/umockdev-0.18.3/src/ioctl_tree.h        2024-05-23 09:49:45.000000000 
+0200
+++ new/umockdev-0.18.4/src/ioctl_tree.h        2024-08-02 03:21:59.000000000 
+0200
@@ -73,6 +73,7 @@
 ioctl_tree *ioctl_tree_find_equal(ioctl_tree * tree, ioctl_tree * node);
 ioctl_tree *ioctl_tree_next(const ioctl_tree * node);
 ioctl_tree *ioctl_tree_execute(ioctl_tree * tree, ioctl_tree * last, 
IOCTL_REQUEST_TYPE id, void *arg, int *ret);
+int ioctl_tree_next_ret(ioctl_tree * tree, ioctl_tree * last);
 
 /* node lists */
 ioctl_node_list *ioctl_node_list_new(void);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/umockdev-0.18.3/src/ioctl_tree.vapi 
new/umockdev-0.18.4/src/ioctl_tree.vapi
--- old/umockdev-0.18.3/src/ioctl_tree.vapi     2024-05-23 09:49:45.000000000 
+0200
+++ new/umockdev-0.18.4/src/ioctl_tree.vapi     2024-08-02 03:21:59.000000000 
+0200
@@ -13,6 +13,8 @@
       public void* execute(void* last, ulong id, void* addr, ref int ret);
       [CCode (instance_pos = -1)]
       public void write(Posix.FILE f);
+
+      public int next_ret(void* last);
   }
 
   public int data_size_by_id(ulong id);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/umockdev-0.18.3/src/libumockdev-preload.c 
new/umockdev-0.18.4/src/libumockdev-preload.c
--- old/umockdev-0.18.3/src/libumockdev-preload.c       2024-05-23 
09:49:45.000000000 +0200
+++ new/umockdev-0.18.4/src/libumockdev-preload.c       2024-08-02 
03:21:59.000000000 +0200
@@ -175,13 +175,13 @@
     do { \
         sigset_t sig_set; \
         sigfillset(&sig_set); \
-        pthread_sigmask(SIG_SETMASK, &sig_set, &trap_path_sig_restore); \
         pthread_mutex_lock (&trap_path_lock); \
+        pthread_sigmask(SIG_SETMASK, &sig_set, &trap_path_sig_restore); \
     } while (0)
 #define TRAP_PATH_UNLOCK \
     do { \
-        pthread_mutex_unlock (&trap_path_lock); \
         pthread_sigmask(SIG_SETMASK, &trap_path_sig_restore, NULL); \
+        pthread_mutex_unlock (&trap_path_lock); \
     } while (0)
 
 #define IOCTL_LOCK pthread_mutex_lock (&ioctl_lock)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/umockdev-0.18.3/src/umockdev-ioctl.vala 
new/umockdev-0.18.4/src/umockdev-ioctl.vala
--- old/umockdev-0.18.3/src/umockdev-ioctl.vala 2024-05-23 09:49:45.000000000 
+0200
+++ new/umockdev-0.18.4/src/umockdev-ioctl.vala 2024-08-02 03:21:59.000000000 
+0200
@@ -906,7 +906,13 @@
             return true;
         }
 
+        last = client.get_data("last");
+
         try {
+            if (request == Ioctl.CROS_EC_DEV_IOCXCMD_V2) {
+                size += tree.next_ret(last);
+            }
+
             if (size > 0)
                 data = client.arg.resolve(0, size);
 
@@ -927,8 +933,6 @@
             return false;
         }
 
-        last = client.get_data("last");
-
         if ((char) type == 'E') {
             Posix.errno = Posix.ENOENT;
         } else {
@@ -1030,6 +1034,10 @@
                 return true;
             }
 
+            if (request == Ioctl.CROS_EC_DEV_IOCXCMD_V2) {
+              size += ret;
+            }
+
             /* Resolve data */
             if (size > 0)
                 data = client.arg.resolve(0, size);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/umockdev-0.18.3/src/umockdev.vala 
new/umockdev-0.18.4/src/umockdev.vala
--- old/umockdev-0.18.3/src/umockdev.vala       2024-05-23 09:49:45.000000000 
+0200
+++ new/umockdev-0.18.4/src/umockdev.vala       2024-08-02 03:21:59.000000000 
+0200
@@ -637,13 +637,57 @@
     public void remove_device (string syspath)
     {
         string real_path = Path.build_filename(this.root_dir, syspath);
-        string devname = Path.get_basename(syspath);
 
         if (!FileUtils.test(real_path, FileTest.IS_DIR)) {
             critical("umockdev_testbed_remove_device(): device %s does not 
exist", syspath);
             return;
         }
 
+        string path = Path.build_filename(real_path, "uevent");
+        if (!FileUtils.test(path, FileTest.IS_REGULAR)) {
+            critical("umockdev_testbed_remove_device(): device %s does not 
appear to be a device", syspath);
+            return;
+        }
+
+        remove_with_children(syspath);
+    }
+
+    private void remove_with_children (string syspath)
+    {
+        string real_path = Path.build_filename(this.root_dir, syspath);
+
+        try {
+            Dir dir = Dir.open(real_path);
+            string? name = null;
+            while (( name = dir.read_name( )) != null) {
+                string path = Path.build_filename(real_path, name);
+                // Skip over symlinks
+                if (FileUtils.test(path, FileTest.IS_SYMLINK)) {
+                    continue;
+                }
+
+                // Recurse into the directory and remove any children therein.
+                if (FileUtils.test(path, FileTest.IS_DIR)) {
+                    string child_syspath = Path.build_filename(syspath, name);
+                    remove_with_children(child_syspath);
+                }
+            }
+        } catch (FileError e) {
+            critical("umockdev_testbed_remove_device(): cannot determine 
children of %s: %s",
+                     syspath, e.message);
+        }
+
+        // See if this syspath actually corresponds to a device by seeing if
+        // there is a "uevent" file in the directory. If not, then there is
+        // no device to remove so the work is finished.
+        string path = Path.build_filename(real_path, "uevent");
+        if (!FileUtils.test(path, FileTest.IS_REGULAR)) {
+            return;
+        }
+
+        // This syspath corresponds to a device, so remove it.
+
+        string devname = Path.get_basename(syspath);
         string subsystem;
 
         try {
@@ -655,6 +699,10 @@
             return;
         }
 
+        // Generate the removal event (must be called before the directory
+        // structure is removed).
+        uevent(syspath, "remove");
+
         // /dev and pointers to it
         try {
             string dev_maj_min;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/umockdev-0.18.3/tests/test-umockdev-vala.vala 
new/umockdev-0.18.4/tests/test-umockdev-vala.vala
--- old/umockdev-0.18.3/tests/test-umockdev-vala.vala   2024-05-23 
09:49:45.000000000 +0200
+++ new/umockdev-0.18.4/tests/test-umockdev-vala.vala   2024-08-02 
03:21:59.000000000 +0200
@@ -782,6 +782,56 @@
 }
 
 void
+t_cros_ec_ioctl ()
+{
+  var tb = new UMockdev.Testbed ();
+
+  string device;
+  checked_file_get_contents (Path.build_filename(rootdir + 
"/devices/cros_ec/crosfingerprint.umockdev"), out device);
+  tb_add_from_string (tb, device);
+
+  try {
+      tb.load_ioctl ("/dev/cros_fp", Path.build_filename(rootdir + 
"/devices/cros_ec/crosfingerprint.ioctl"));
+  } catch (Error e) {
+      error ("Cannot load ioctl file: %s", e.message);
+  }
+
+  int fd = Posix.open ("/dev/cros_fp", Posix.O_RDWR, 0);
+  assert_cmpint (fd, CompareOperator.GE, 0);
+
+  Ioctl.cros_ec_command_v2 *s_cmd = malloc (sizeof (Ioctl.cros_ec_command_v2) 
+ 4);
+  assert_cmpint (Posix.ioctl (fd, Ioctl.CROS_EC_DEV_IOCXCMD_V2, s_cmd), 
CompareOperator.EQ, 4);
+  assert_cmpint (Posix.errno, CompareOperator.EQ, 0);
+  uint8 fpmode_data[] = {
+    0x80, 0x00, 0x00, 0x00
+  };
+  assert_cmpint (Posix.memcmp(s_cmd->data, fpmode_data, 4), 
CompareOperator.EQ, 0);
+
+  s_cmd = realloc(s_cmd, sizeof (Ioctl.cros_ec_command_v2) + 48);
+  assert_cmpint (Posix.ioctl (fd, Ioctl.CROS_EC_DEV_IOCXCMD_V2, s_cmd), 
CompareOperator.EQ, 48);
+  assert_cmpint (Posix.errno, CompareOperator.EQ, 0);
+  uint8 fpinfo_data[] = {
+    0x46, 0x50, 0x43, 0x20, 0x09, 0x00, 0x00, 0x00, 0x1B, 0x02, 0x00, 0x00,
+    0x01, 0x00, 0x00, 0x00, 0x94, 0x66, 0x00, 0x00, 0x47, 0x52, 0x45, 0x59,
+    0xA0, 0x00, 0xA0, 0x00, 0x08, 0x00, 0xFF, 0x03, 0x24, 0x14, 0x00, 0x00,
+    0x05, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00
+  };
+  assert_cmpint (Posix.memcmp(s_cmd->data, fpinfo_data, 48), 
CompareOperator.EQ, 0);
+
+  s_cmd = realloc(s_cmd, sizeof (Ioctl.cros_ec_command_v2) + 22);
+  assert_cmpint (Posix.ioctl (fd, Ioctl.CROS_EC_DEV_IOCXCMD_V2, s_cmd), 
CompareOperator.EQ, 22);
+  assert_cmpint (Posix.errno, CompareOperator.EQ, 0);
+  uint8 fpstats_data[] = {
+    0x65, 0x63, 0x01, 0x00, 0xB4, 0x4A, 0x02, 0x00, 0x07, 0xB3, 0x03, 0x00,
+    0xDC, 0x33, 0x50, 0x5A, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00
+  };
+  assert_cmpint (Posix.memcmp(s_cmd->data, fpstats_data, 22), 
CompareOperator.EQ, 0);
+
+  free (s_cmd);
+  Posix.close (fd);
+}
+
+void
 t_tty_stty ()
 {
   var tb = new UMockdev.Testbed ();
@@ -1153,6 +1203,8 @@
 
   Test.add_func ("/umockdev-testbed-vala/hidraw_ioctl", t_hidraw_ioctl);
 
+  Test.add_func ("/umockdev-testbed-vala/cros_ec_ioctl", t_cros_ec_ioctl);
+
   /* tests for mocking TTYs */
   Test.add_func ("/umockdev-testbed-vala/tty_stty", t_tty_stty);
   Test.add_func ("/umockdev-testbed-vala/tty_data", t_tty_data);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/umockdev-0.18.3/tests/test-umockdev.py 
new/umockdev-0.18.4/tests/test-umockdev.py
--- old/umockdev-0.18.3/tests/test-umockdev.py  2024-05-23 09:49:45.000000000 
+0200
+++ new/umockdev-0.18.4/tests/test-umockdev.py  2024-08-02 03:21:59.000000000 
+0200
@@ -155,17 +155,16 @@
             counters[4] = device.get_sysfs_attr('idVendor')
             counters[5] = device.get_property('ID_INPUT')
 
-        syspath = self.testbed.add_device('pci', 'mydev', None, ['idVendor', 
'0815'], ['ID_INPUT', '1'])
-        self.assertNotEqual(syspath, None)
-
         # set up listener for uevent signal
         client = GUdev.Client.new(['pci'])
         client.connect('uevent', on_uevent, counter)
-
         mainloop = GLib.MainLoop()
 
-        # send a signal and run main loop for 0.5 seconds to catch it
-        self.testbed.uevent(syspath, 'add')
+        syspath = self.testbed.add_device('pci', 'mydev', None, ['idVendor', 
'0815'], ['ID_INPUT', '1'])
+        self.assertNotEqual(syspath, None)
+
+        # Run the main loop for 0.5 seconds to catch the "add" uevent, which
+        # should be automatically generated by the call to `add_device()`.
         GLib.timeout_add(500, mainloop.quit)
         mainloop.run()
         self.assertEqual(counter, [1, 0, 0, syspath, '0815', '1'])
@@ -180,6 +179,72 @@
         mainloop.run()
         self.assertEqual(counter, [0, 0, 1, syspath, '0815', '1'])
 
+        counter[2] = 0
+        counter[3] = None
+        counter[4] = None
+        counter[5] = None
+
+        self.testbed.remove_device(syspath)
+
+        # Run the main loop for 0.5 seconds to catch the "remove" uevent, which
+        # should be automatically generated by the call to `remove_device()`.
+        GLib.timeout_add(500, mainloop.quit)
+        mainloop.run()
+        self.assertEqual(counter, [0, 1, 0, syspath, None, '1'])
+
+    def test_remove_usb_parent_device(self):
+        '''testbed removing a USB parent device removes children'''
+
+        counter = {}
+
+        def on_uevent(client, action, device, counters):
+            key = device.get_sysfs_path()
+            counters.setdefault(key, [0, 0])
+            if action == 'add':
+                counters[key][0] += 1
+            elif action == 'remove':
+                counters[key][1] += 1
+
+        # set up listener for uevent signal
+        client = GUdev.Client.new(['usb'])
+        client.connect('uevent', on_uevent, counter)
+        mainloop = GLib.MainLoop()
+
+        parent_syspath = self.testbed.add_device('usb', 'myparentdev', None, 
['idVendor', '0815'], ['ID_INPUT', '1'])
+        self.assertNotEqual(parent_syspath, None)
+
+        child1_syspath = self.testbed.add_device('usb', 'child1', 
parent_syspath, ['idVendor', '0815'], ['ID_INPUT', '1'])
+        self.assertNotEqual(child1_syspath, None)
+
+        child2_syspath = self.testbed.add_device('usb', 'child2', 
parent_syspath, ['idVendor', '0815'], ['ID_INPUT', '1'])
+        self.assertNotEqual(child2_syspath, None)
+
+        # Run the main loop for 0.5 seconds to catch the "add" uevent, which
+        # should be automatically generated by the call to `add_device()`.
+        GLib.timeout_add(500, mainloop.quit)
+        mainloop.run()
+        self.assertIn(parent_syspath, counter)
+        self.assertIn(child1_syspath, counter)
+        self.assertIn(child2_syspath, counter)
+        self.assertEqual(counter[parent_syspath], [1, 0])
+        self.assertEqual(counter[child1_syspath], [1, 0])
+        self.assertEqual(counter[child2_syspath], [1, 0])
+
+        # Just remove the parent, the children should also be removed.
+        self.testbed.remove_device(parent_syspath)
+
+        # Run the main loop for 0.5 seconds to catch the "remove" uevent, which
+        # should be automatically generated by the call to `remove_device()`.
+        GLib.timeout_add(500, mainloop.quit)
+        mainloop.run()
+        self.assertEqual(counter[parent_syspath], [1, 1])
+        self.assertEqual(counter[child1_syspath], [1, 1])
+        self.assertEqual(counter[child2_syspath], [1, 1])
+
+        # Verify that the parent syspath has been removed (and therefore the
+        # children syspaths have also been removed.)
+        self.assertFalse(os.path.exists(parent_syspath))
+
     def test_add_from_string(self):
         self.assertTrue(self.testbed.add_from_string('''P: /devices/dev1
 E: SIMPLE_PROP=1

Reply via email to