Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package rubygem-ruby-dbus for 
openSUSE:Factory checked in at 2023-01-20 17:37:29
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-ruby-dbus (Old)
 and      /work/SRC/openSUSE:Factory/.rubygem-ruby-dbus.new.32243 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rubygem-ruby-dbus"

Fri Jan 20 17:37:29 2023 rev:32 rq:1059383 version:0.19.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/rubygem-ruby-dbus/rubygem-ruby-dbus.changes      
2022-07-14 16:33:19.292574393 +0200
+++ 
/work/SRC/openSUSE:Factory/.rubygem-ruby-dbus.new.32243/rubygem-ruby-dbus.changes
   2023-01-20 17:37:30.692133387 +0100
@@ -1,0 +2,16 @@
+Wed Jan 18 12:08:21 UTC 2023 - Martin Vidner <mvid...@suse.com>
+
+- 0.19.0
+ API:
+ * Added a ObjectManager mix-in to implement the service-side
+   ObjectManager interface.
+
+ Bug fixes:
+ * dbus_attr_accessor and friends validate the signature
+ * (gh#mvidner/ruby-dbus#120).
+ * Declare the Introspectable interface in exported
+ * objects (gh#mvidner/ruby-dbus#99).
+ * Do reply with an error when calling a nonexisting object
+   with an existing path prefix (gh#mvidner/ruby-dbus#121).
+
+-------------------------------------------------------------------

Old:
----
  ruby-dbus-0.18.1.gem

New:
----
  ruby-dbus-0.19.0.gem

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

Other differences:
------------------
++++++ rubygem-ruby-dbus.spec ++++++
--- /var/tmp/diff_new_pack.qwLRAY/_old  2023-01-20 17:37:31.336136949 +0100
+++ /var/tmp/diff_new_pack.qwLRAY/_new  2023-01-20 17:37:31.340136971 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package rubygem-ruby-dbus
 #
-# Copyright (c) 2022 SUSE LLC
+# Copyright (c) 2023 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -24,7 +24,7 @@
 #
 
 Name:           rubygem-ruby-dbus
-Version:        0.18.1
+Version:        0.19.0
 Release:        0
 %define mod_name ruby-dbus
 %define mod_full_name %{mod_name}-%{version}

++++++ ruby-dbus-0.18.1.gem -> ruby-dbus-0.19.0.gem ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/NEWS.md new/NEWS.md
--- old/NEWS.md 2022-07-13 08:19:38.000000000 +0200
+++ new/NEWS.md 2023-01-18 14:34:24.000000000 +0100
@@ -2,6 +2,23 @@
 
 ## Unreleased
 
+## Ruby D-Bus 0.19.0 - 2023-01-18
+
+API:
+ * Added a ObjectManager mix-in to implement the service-side
+   [ObjectManager][objmgr] interface.
+
+Bug fixes:
+ * dbus_attr_accessor and friends validate the signature ([#120][]).
+ * Declare the Introspectable interface in exported objects([#99][]).
+ * Do reply with an error when calling a nonexisting object
+   with an existing path prefix([#121][]).
+
+[#120]: https://github.com/mvidner/ruby-dbus/issues/120
+[#99]: https://github.com/mvidner/ruby-dbus/issues/99
+[#121]: https://github.com/mvidner/ruby-dbus/issues/121
+[objmgr]: 
https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager
+
 ## Ruby D-Bus 0.18.1 - 2022-07-13
 
 No changes since 0.18.0.beta8.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/VERSION new/VERSION
--- old/VERSION 2022-07-13 08:19:38.000000000 +0200
+++ new/VERSION 2023-01-18 14:34:24.000000000 +0100
@@ -1 +1 @@
-0.18.1
+0.19.0
Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/dbus/bus.rb new/lib/dbus/bus.rb
--- old/lib/dbus/bus.rb 2022-07-13 08:19:38.000000000 +0200
+++ new/lib/dbus/bus.rb 2023-01-18 14:34:24.000000000 +0100
@@ -76,6 +76,7 @@
     def export(obj)
       obj.service = self
       get_node(obj.path, create: true).object = obj
+      object_manager_for(obj)&.object_added(obj)
     end
 
     # Undo exporting an object _obj_.
@@ -93,6 +94,7 @@
       parent_node = get_node(parent_path, create: false)
       return false unless parent_node
 
+      object_manager_for(obj)&.object_removed(obj)
       obj.service = nil
       parent_node.delete(node_name).object
     end
@@ -112,18 +114,51 @@
         end
         n = n[elem]
       end
-      if n.nil?
-        DBus.logger.debug "Warning, unknown object #{path}"
-      end
       n
     end
 
+    # Find the (closest) parent of *object*
+    # implementing the ObjectManager interface, or nil
+    # @return [DBus::Object,nil]
+    def object_manager_for(object)
+      path = object.path
+      node_chain = get_node_chain(path)
+      om_node = node_chain.reverse_each.find do |node|
+        node.object&.is_a? DBus::ObjectManager
+      end
+      om_node&.object
+    end
+
+    # All objects (not paths) under this path (except itself).
+    # @param path [ObjectPath]
+    # @return [Array<DBus::Object>]
+    # @raise ArgumentError if the *path* does not exist
+    def descendants_for(path)
+      node = get_node(path, create: false)
+      raise ArgumentError, "Object path #{path} doesn't exist" if node.nil?
+
+      node.descendant_objects
+    end
+
     #########
 
     private
 
     #########
 
+    # @raise ArgumentError if the *path* does not exist
+    def get_node_chain(path)
+      n = @root
+      result = [n]
+      path.sub(%r{^/}, "").split("/").each do |elem|
+        n = n[elem]
+        raise ArgumentError, "Object path #{path} doesn't exist" if n.nil?
+
+        result.push(n)
+      end
+      result
+    end
+
     # Perform a recursive retrospection on the given current _node_
     # on the given _path_.
     def rec_introspect(node, path)
@@ -198,6 +233,15 @@
                              .join(",")
       "#{s}{#{contents_sub_inspect}}"
     end
+
+    # All objects (not paths) under this path (except itself).
+    # @return [Array<DBus::Object>]
+    def descendant_objects
+      children_objects = values.map(&:object).compact
+      descendants = values.map(&:descendant_objects)
+      flat_descendants = descendants.reduce([], &:+)
+      children_objects + flat_descendants
+    end
   end
 
   # FIXME: rename Connection to Bus?
@@ -233,7 +277,6 @@
       @method_call_msgs = {}
       @signal_matchrules = {}
       @proxy = nil
-      @object_root = Node.new("/")
     end
 
     # Dispatch all messages that are available in the queue,
@@ -561,23 +604,22 @@
           DBus.logger.debug "Got method call on /org/freedesktop/DBus"
         end
         node = @service.get_node(msg.path, create: false)
-        if !node
-          reply = Message.error(msg, 
"org.freedesktop.DBus.Error.UnknownObject",
-                                "Object #{msg.path} doesn't exist")
-          @message_queue.push(reply)
-        # handle introspectable as an exception:
-        elsif msg.interface == "org.freedesktop.DBus.Introspectable" &&
-              msg.member == "Introspect"
+        # introspect a known path even if there is no object on it
+        if node &&
+           msg.interface == "org.freedesktop.DBus.Introspectable" &&
+           msg.member == "Introspect"
           reply = Message.new(Message::METHOD_RETURN).reply_to(msg)
           reply.sender = @unique_name
           xml = node.to_xml(msg.path)
           reply.add_param(Type::STRING, xml)
           @message_queue.push(reply)
+        # dispatch for an object
+        elsif node&.object
+          node.object.dispatch(msg)
         else
-          obj = node.object
-          return if obj.nil? # FIXME, pushes no reply
-
-          obj&.dispatch(msg)
+          reply = Message.error(msg, 
"org.freedesktop.DBus.Error.UnknownObject",
+                                "Object #{msg.path} doesn't exist")
+          @message_queue.push(reply)
         end
       when DBus::Message::SIGNAL
         # the signal can match multiple different rules
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/dbus/introspect.rb new/lib/dbus/introspect.rb
--- old/lib/dbus/introspect.rb  2022-07-13 08:19:38.000000000 +0200
+++ new/lib/dbus/introspect.rb  2023-01-18 14:34:24.000000000 +0100
@@ -270,7 +270,7 @@
   class Property
     # @return [Symbol] The name of the property, for example FooBar.
     attr_reader :name
-    # @return [SingleCompleteType]
+    # @return [Type]
     attr_reader :type
     # @return [Symbol] :read :write or :readwrite
     attr_reader :access
@@ -282,6 +282,7 @@
 
     def initialize(name, type, access, ruby_name:)
       @name = name.to_sym
+      type = DBus.type(type) unless type.is_a?(Type)
       @type = type
       @access = access
       @ruby_name = ruby_name
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/dbus/marshall.rb new/lib/dbus/marshall.rb
--- old/lib/dbus/marshall.rb    2022-07-13 08:19:38.000000000 +0200
+++ new/lib/dbus/marshall.rb    2023-01-18 14:34:24.000000000 +0100
@@ -327,7 +327,7 @@
         # Damn ruby rocks here
         val = val.to_a
       end
-      # If string is recieved and ay is expected, explode the string
+      # If string is received and ay is expected, explode the string
       if val.is_a?(String) && child_type.sigtype == Type::BYTE
         val = val.bytes
       end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/dbus/object.rb new/lib/dbus/object.rb
--- old/lib/dbus/object.rb      2022-07-13 08:19:38.000000000 +0200
+++ new/lib/dbus/object.rb      2023-01-18 14:34:24.000000000 +0100
@@ -89,8 +89,11 @@
           # while the superclass keeps the old one.
           self.intfs = intfs.merge(name => @@cur_intf)
         end
-        yield
-        @@cur_intf = nil
+        begin
+          yield
+        ensure
+          @@cur_intf = nil
+        end
       end
     end
 
@@ -122,7 +125,8 @@
     #
     # @param ruby_name [Symbol] :foo_bar is exposed as FooBar;
     #   use dbus_name to override
-    # @param type a signature like "s" or "a(uus)" or Type::STRING
+    # @param type [Type,SingleCompleteType]
+    #   a signature like "s" or "a(uus)" or Type::STRING
     # @param dbus_name [String] if not given it is made
     #   by CamelCasing the ruby_name. foo_bar becomes FooBar
     #   to convert the Ruby convention to the DBus convention.
@@ -387,6 +391,23 @@
       property
     end
 
+    # Generates information about interfaces and properties of the object
+    #
+    # Returns a hash containing interfaces names as keys. Each value is the
+    # same hash that would be returned by the
+    # org.freedesktop.DBus.Properties.GetAll() method for that combination of
+    # object path and interface. If an interface has no properties, the empty
+    # hash is returned.
+    #
+    # @return [Hash{String => Hash{String => Data::Base}}] interface -> 
property -> value
+    def interfaces_and_properties
+      get_all_method = 
self.class.make_method_name("org.freedesktop.DBus.Properties", :GetAll)
+
+      intfs.keys.each_with_object({}) do |interface, hash|
+        hash[interface] = public_send(get_all_method, interface).first
+      end
+    end
+
     ####################################################################
 
     # use the above defined methods to declare the property-handling
@@ -459,5 +480,12 @@
 
       dbus_signal :PropertiesChanged, "interface:s, changed_properties:a{sv}, 
invalidated_properties:as"
     end
+
+    dbus_interface "org.freedesktop.DBus.Introspectable" do
+      dbus_method :Introspect, "out xml_data:s" do
+        # The body is not used, Connection#process handles it instead
+        # which is more efficient and handles paths without objects.
+      end
+    end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/dbus/object_manager.rb 
new/lib/dbus/object_manager.rb
--- old/lib/dbus/object_manager.rb      1970-01-01 01:00:00.000000000 +0100
+++ new/lib/dbus/object_manager.rb      2023-01-18 14:34:24.000000000 +0100
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+# This file is part of the ruby-dbus project
+# Copyright (C) 2022 José Iván López González
+# Copyright (C) 2022 Martin Vidner
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License, version 2.1 as published by the Free Software Foundation.
+# See the file "COPYING" for the exact licensing terms.
+
+module DBus
+  # A mixin for {DBus::Object} implementing
+  # 
{https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager
+  # org.freedesktop.DBus.ObjectManager}.
+  #
+  # {Service#export} and {Service#unexport} will look for an ObjectManager
+  # parent in the path hierarchy. If found, it will emit InterfacesAdded
+  # or InterfacesRemoved, as appropriate.
+  module ObjectManager
+    OBJECT_MANAGER_INTERFACE = "org.freedesktop.DBus.ObjectManager"
+
+    # @return [Hash{ObjectPath => Hash{String => Hash{String => Data::Base}}}]
+    #   object -> interface -> property -> value
+    def managed_objects
+      # FIXME: also fix the "service" concept
+      descendant_objects = @service.descendants_for(path)
+      descendant_objects.each_with_object({}) do |obj, hash|
+        hash[obj.path] = obj.interfaces_and_properties
+      end
+    end
+
+    # @param object [DBus::Object]
+    # @return [void]
+    def object_added(object)
+      InterfacesAdded(object.path, object.interfaces_and_properties)
+    end
+
+    # @param object [DBus::Object]
+    # @return [void]
+    def object_removed(object)
+      InterfacesRemoved(object.path, object.intfs.keys)
+    end
+
+    def self.included(base)
+      base.class_eval do
+        dbus_interface OBJECT_MANAGER_INTERFACE do
+          dbus_method :GetManagedObjects, "out res:a{oa{sa{sv}}}" do
+            [managed_objects]
+          end
+
+          dbus_signal :InterfacesAdded, "object:o, 
interfaces_and_properties:a{sa{sv}}"
+          dbus_signal :InterfacesRemoved, "object:o, interfaces:as"
+        end
+      end
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/dbus.rb new/lib/dbus.rb
--- old/lib/dbus.rb     2022-07-13 08:19:38.000000000 +0200
+++ new/lib/dbus.rb     2023-01-18 14:34:24.000000000 +0100
@@ -24,6 +24,7 @@
 require_relative "dbus/message"
 require_relative "dbus/message_queue"
 require_relative "dbus/object"
+require_relative "dbus/object_manager"
 require_relative "dbus/object_path"
 require_relative "dbus/proxy_object"
 require_relative "dbus/proxy_object_factory"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata        2022-07-13 08:19:38.000000000 +0200
+++ new/metadata        2023-01-18 14:34:25.000000000 +0100
@@ -1,14 +1,14 @@
 --- !ruby/object:Gem::Specification
 name: ruby-dbus
 version: !ruby/object:Gem::Version
-  version: 0.18.1
+  version: 0.19.0
 platform: ruby
 authors:
 - Ruby DBus Team
 autorequire: 
 bindir: bin
 cert_chain: []
-date: 2022-07-13 00:00:00.000000000 Z
+date: 2023-01-18 00:00:00.000000000 Z
 dependencies:
 - !ruby/object:Gem::Dependency
   name: rexml
@@ -155,6 +155,7 @@
 - lib/dbus/message.rb
 - lib/dbus/message_queue.rb
 - lib/dbus/object.rb
+- lib/dbus/object_manager.rb
 - lib/dbus/object_path.rb
 - lib/dbus/proxy_object.rb
 - lib/dbus/proxy_object_factory.rb
@@ -179,6 +180,7 @@
 - spec/introspection_spec.rb
 - spec/main_loop_spec.rb
 - spec/node_spec.rb
+- spec/object_manager_spec.rb
 - spec/object_path_spec.rb
 - spec/object_spec.rb
 - spec/packet_marshaller_spec.rb
@@ -188,6 +190,7 @@
 - spec/server_robustness_spec.rb
 - spec/server_spec.rb
 - spec/service_newapi.rb
+- spec/service_spec.rb
 - spec/session_bus_spec.rb
 - spec/session_bus_spec_manual.rb
 - spec/signal_spec.rb
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spec/node_spec.rb new/spec/node_spec.rb
--- old/spec/node_spec.rb       2022-07-13 08:19:38.000000000 +0200
+++ new/spec/node_spec.rb       2023-01-18 14:34:24.000000000 +0100
@@ -20,4 +20,50 @@
       expect(parent.inspect).to match(/<DBus::Node [0-9a-f]+ {child0 => 
{},child1 => {},child2 => {}}>/)
     end
   end
+
+  describe "#descendant_objects" do
+    let(:manager_path) { "/org/example/FooManager" }
+    let(:child_paths) do
+      [
+        # note that "/org/example/FooManager/good"
+        # is a path under a managed object but there is no object there
+        "/org/example/FooManager/good/1",
+        "/org/example/FooManager/good/2",
+        "/org/example/FooManager/good/3",
+        "/org/example/FooManager/bad/1",
+        "/org/example/FooManager/bad/2"
+      ]
+    end
+
+    let(:non_child_paths) do
+      [
+        "/org/example/BarManager/good/1",
+        "/org/example/BarManager/good/2"
+      ]
+    end
+
+    context "on the bus" do
+      let(:bus) { DBus::ASessionBus.new }
+      let(:service) do
+        # if we used org.ruby.service it would be a name collision
+        # ... which would not break the test for lucky reasons
+        bus.request_service("org.ruby.service.scratch")
+      end
+
+      before do
+        service.export(DBus::Object.new(manager_path))
+        non_child_paths.each do |p|
+          service.export(DBus::Object.new(p))
+        end
+      end
+
+      it "returns just the descendants of the specified objects" do
+        child_exported_objects = child_paths.map { |p| DBus::Object.new(p) }
+        child_exported_objects.each { |obj| service.export(obj) }
+
+        node = service.get_node(manager_path, create: false)
+        expect(node.descendant_objects).to eq child_exported_objects
+      end
+    end
+  end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spec/object_manager_spec.rb 
new/spec/object_manager_spec.rb
--- old/spec/object_manager_spec.rb     1970-01-01 01:00:00.000000000 +0100
+++ new/spec/object_manager_spec.rb     2023-01-18 14:34:24.000000000 +0100
@@ -0,0 +1,33 @@
+#!/usr/bin/env rspec
+# frozen_string_literal: true
+
+require_relative "spec_helper"
+require "dbus"
+
+describe DBus::ObjectManager do
+  describe "GetManagedObjects" do
+    let(:bus) { DBus::ASessionBus.new }
+    let(:service) { bus["org.ruby.service"] }
+    let(:obj) { service["/org/ruby/MyInstance"] }
+    let(:parent_iface) { obj["org.ruby.TestParent"] }
+    let(:om_iface) { obj["org.freedesktop.DBus.ObjectManager"] }
+
+    it "returns the interfaces and properties of currently managed objects" do
+      c1_opath = parent_iface.New("child1")
+      c2_opath = parent_iface.New("child2")
+
+      parent_iface.Delete(c1_opath)
+      expected_gmo = {
+        "/org/ruby/MyInstance/child2" => {
+          "org.freedesktop.DBus.Introspectable" => {},
+          "org.freedesktop.DBus.Properties" => {},
+          "org.ruby.TestChild" => { "Name" => "Child2" }
+        }
+      }
+      expect(om_iface.GetManagedObjects).to eq(expected_gmo)
+
+      parent_iface.Delete(c2_opath)
+      expect(om_iface.GetManagedObjects).to eq({})
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spec/object_spec.rb new/spec/object_spec.rb
--- old/spec/object_spec.rb     2022-07-13 08:19:38.000000000 +0200
+++ new/spec/object_spec.rb     2023-01-18 14:34:24.000000000 +0100
@@ -61,6 +61,16 @@
         end
       end.to raise_error(DBus::Object::UndefinedInterface)
     end
+
+    it "fails when the signature is invalid" do
+      expect do
+        ObjectTest.instance_exec do
+          dbus_interface "org.ruby.ServerTest" do
+            dbus_reader :foo2, "!"
+          end
+        end
+      end.to raise_error(DBus::Type::SignatureException)
+    end
   end
 
   describe ".dbus_reader, when paired with attr_accessor" do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spec/server_robustness_spec.rb 
new/spec/server_robustness_spec.rb
--- old/spec/server_robustness_spec.rb  2022-07-13 08:19:38.000000000 +0200
+++ new/spec/server_robustness_spec.rb  2023-01-18 14:34:24.000000000 +0100
@@ -16,7 +16,7 @@
   it "tests no such path with introspection" do
     obj = @svc.object "/org/ruby/NotMyInstance"
     expect { obj.introspect }.to raise_error(DBus::Error) do |e|
-      expect(e).to_not match(/timeout/)
+      expect(e.message).to_not match(/timeout/)
     end
   end
 
@@ -25,7 +25,19 @@
     ifc = DBus::ProxyObjectInterface.new(obj, "org.ruby.SampleInterface")
     ifc.define_method("the_answer", "out n:i")
     expect { ifc.the_answer }.to raise_error(DBus::Error) do |e|
-      expect(e).to_not match(/timeout/)
+      expect(e.message).to_not match(/timeout/)
+    end
+  end
+
+  context "an existing path without an object" do
+    let(:obj) { @svc.object "/org" }
+
+    it "errors without a timeout" do
+      ifc = DBus::ProxyObjectInterface.new(obj, "org.ruby.SampleInterface")
+      ifc.define_method("the_answer", "out n:i")
+      expect { ifc.the_answer }.to raise_error(DBus::Error) do |e|
+        expect(e.message).to_not match(/timeout/)
+      end
     end
   end
 
@@ -33,7 +45,7 @@
     obj = @svc.object "/org/ruby/MyInstance"
     obj.default_iface = "org.ruby.SampleInterface"
     expect { obj.will_raise }.to raise_error(DBus::Error) do |e|
-      expect(e).to_not match(/timeout/)
+      expect(e.message).to_not match(/timeout/)
     end
   end
 
@@ -41,7 +53,7 @@
     obj = @svc.object "/org/ruby/MyInstance"
     obj.default_iface = "org.ruby.SampleInterface"
     expect { obj.will_raise_name_error }.to raise_error(DBus::Error) do |e|
-      expect(e).to_not match(/timeout/)
+      expect(e.message).to_not match(/timeout/)
     end
   end
 
@@ -51,7 +63,7 @@
     ifc = DBus::ProxyObjectInterface.new(obj, "org.ruby.SampleInterface")
     ifc.define_method("not_the_answer", "out n:i")
     expect { ifc.not_the_answer }.to raise_error(DBus::Error) do |e|
-      expect(e).to_not match(/timeout/)
+      expect(e.message).to_not match(/timeout/)
     end
   end
 
@@ -60,7 +72,7 @@
     ifc = DBus::ProxyObjectInterface.new(obj, "org.ruby.NoSuchInterface")
     ifc.define_method("the_answer", "out n:i")
     expect { ifc.the_answer }.to raise_error(DBus::Error) do |e|
-      expect(e).to_not match(/timeout/)
+      expect(e.message).to_not match(/timeout/)
     end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spec/service_newapi.rb new/spec/service_newapi.rb
--- old/spec/service_newapi.rb  2022-07-13 08:19:38.000000000 +0200
+++ new/spec/service_newapi.rb  2023-01-18 14:34:24.000000000 +0100
@@ -10,11 +10,24 @@
 
 PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"
 
+class TestChild < DBus::Object
+  def initialize(opath)
+    @name = opath.split("/").last.capitalize
+    super
+  end
+
+  dbus_interface "org.ruby.TestChild" do
+    dbus_attr_reader :name, "s"
+  end
+end
+
 class Test < DBus::Object
   Point2D = Struct.new(:x, :y)
 
   attr_writer :main_loop
 
+  include DBus::ObjectManager
+
   INTERFACE = "org.ruby.SampleInterface"
   def initialize(path)
     super path
@@ -155,6 +168,21 @@
     end
   end
 
+  dbus_interface "org.ruby.TestParent" do
+    dbus_method :New, "in name:s, out opath:o" do |name|
+      child = TestChild.new("#{path}/#{name}")
+      @service.export(child)
+      [child.path]
+    end
+
+    dbus_method :Delete, "in opath:o" do |opath|
+      raise ArgumentError unless opath.start_with?(path)
+
+      obj = @service.get_node(opath)&.object
+      @service.unexport(obj)
+    end
+  end
+
   dbus_interface "org.ruby.Duplicates" do
     dbus_method :the_answer, "out answer:i" do
       [0]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spec/service_spec.rb new/spec/service_spec.rb
--- old/spec/service_spec.rb    1970-01-01 01:00:00.000000000 +0100
+++ new/spec/service_spec.rb    2023-01-18 14:34:24.000000000 +0100
@@ -0,0 +1,18 @@
+#!/usr/bin/env rspec
+# frozen_string_literal: true
+
+require_relative "spec_helper"
+require "dbus"
+
+describe "DBus::Service (server role)" do
+  let(:bus) { DBus::ASessionBus.new }
+  # This is the client role, but the server role API is bad
+  # and for the one test there is no difference
+  let(:service) { bus["org.ruby.service"] }
+
+  describe "#descendants_for" do
+    it "raises for not existing path" do
+      expect { service.descendants_for("/notthere") }.to 
raise_error(ArgumentError)
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spec/tools/dbus-limited-session.conf 
new/spec/tools/dbus-limited-session.conf
--- old/spec/tools/dbus-limited-session.conf    2022-07-13 08:19:38.000000000 
+0200
+++ new/spec/tools/dbus-limited-session.conf    2023-01-18 14:34:24.000000000 
+0100
@@ -24,6 +24,7 @@
   <!-- Do not increase the limits.
        Instead, lower some so that we can test resource leaks. -->
   <limit name="max_match_rules_per_connection">50</limit><!-- was 512 -->
+  <limit name="reply_timeout">5000</limit><!-- 5 seconds -->
 
   <!--
 dbus-daemon[1700]: [session uid=1001 pid=1700] Unable to set up new 
connection: Failed to get AppArmor confinement information of socket peer: 
Protocol not available

Reply via email to