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 2022-05-26 18:43:59
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/rubygem-ruby-dbus (Old)
 and      /work/SRC/openSUSE:Factory/.rubygem-ruby-dbus.new.2254 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "rubygem-ruby-dbus"

Thu May 26 18:43:59 2022 rev:28 rq:979195 version:0.18.0.beta6

Changes:
--------
--- /work/SRC/openSUSE:Factory/rubygem-ruby-dbus/rubygem-ruby-dbus.changes      
2022-04-30 00:44:55.414919439 +0200
+++ 
/work/SRC/openSUSE:Factory/.rubygem-ruby-dbus.new.2254/rubygem-ruby-dbus.changes
    2022-05-26 18:44:06.085180859 +0200
@@ -1,0 +2,11 @@
+Wed May 25 13:20:39 UTC 2022 - Martin Vidner <mvid...@suse.com>
+
+- 0.18.0.beta6
+ API:
+ * Data::Base#value returns plain Ruby types;
+   Data::Container#exact_value contains Data::Base (gh#mvidner/ruby-dbus#114).
+ * Data::Base#initialize and .from_typed allow plain or exact values, validate
+   argument types.
+ * Implement #== (converting) and #eql? (strict) for Data::Base and DBus::Type.
+
+-------------------------------------------------------------------

Old:
----
  ruby-dbus-0.18.0.beta5.gem

New:
----
  ruby-dbus-0.18.0.beta6.gem

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

Other differences:
------------------
++++++ rubygem-ruby-dbus.spec ++++++
--- /var/tmp/diff_new_pack.PK4Fku/_old  2022-05-26 18:44:06.585181442 +0200
+++ /var/tmp/diff_new_pack.PK4Fku/_new  2022-05-26 18:44:06.585181442 +0200
@@ -24,7 +24,7 @@
 #
 
 Name:           rubygem-ruby-dbus
-Version:        0.18.0.beta5
+Version:        0.18.0.beta6
 Release:        0
 %define mod_name ruby-dbus
 %define mod_full_name %{mod_name}-%{version}

++++++ ruby-dbus-0.18.0.beta5.gem -> ruby-dbus-0.18.0.beta6.gem ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/NEWS.md new/NEWS.md
--- old/NEWS.md 2022-04-27 10:47:47.000000000 +0200
+++ new/NEWS.md 2022-05-25 15:29:26.000000000 +0200
@@ -2,6 +2,17 @@
 
 ## Unreleased
 
+## Ruby D-Bus 0.18.0.beta6 - 2022-05-25
+
+API:
+ * Data::Base#value returns plain Ruby types;
+   Data::Container#exact_value contains Data::Base ([#114][]).
+ * Data::Base#initialize and .from_typed allow plain or exact values, validate
+   argument types.
+ * Implement #== (converting) and #eql? (strict) for Data::Base and DBus::Type.
+
+[#114]: https://github.com/mvidner/ruby-dbus/pull/114
+
 ## Ruby D-Bus 0.18.0.beta5 - 2022-04-27
 
 API:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/VERSION new/VERSION
--- old/VERSION 2022-04-27 10:47:47.000000000 +0200
+++ new/VERSION 2022-05-25 15:29:26.000000000 +0200
@@ -1 +1 @@
-0.18.0.beta5
+0.18.0.beta6
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/data.rb new/lib/dbus/data.rb
--- old/lib/dbus/data.rb        2022-04-27 10:47:47.000000000 +0200
+++ new/lib/dbus/data.rb        2022-05-25 15:29:26.000000000 +0200
@@ -35,7 +35,7 @@
     # construct an appropriate {Data::Base} instance.
     #
     # @param type [SingleCompleteType,Type]
-    # @param value [::Object]
+    # @param value [::Object,Data::Base] a plain value; exact values also 
allowed
     # @return [Data::Base]
     # @raise TypeError
     def make_typed(type, value)
@@ -58,9 +58,13 @@
       # @!method self.fixed?
       # @return [Boolean]
 
-      # @return appropriately-typed, valid value
+      # @return [::Object] a valid value, plain-Ruby typed.
+      # @see Data::Container#exact_value
       attr_reader :value
 
+      # @!method self.type_code
+      # @return [String] a single-character string, for example "a" for arrays
+
       # @!method type
       # @abstract
       # Note that for Variants type=="v",
@@ -91,11 +95,18 @@
 
       # Hash key equality
       # See https://ruby-doc.org/core-3.0.0/Object.html#method-i-eql-3F
-      alias eql? ==
+      # Stricter than #== (RSpec: eq), 1==1.0 but 1.eql(1.0)->false
+      def eql?(other)
+        return false unless other.class == self.class
+
+        other.value.eql?(@value)
+        # TODO: this should work, now check derived classes, exact_value
+      end
 
       # @param type [Type]
       def self.assert_type_matches_class(type)
-        raise ArgumentError unless type.sigtype == type_code
+        raise ArgumentError, "Expecting #{type_code.inspect} for class 
#{self}, got #{type.sigtype.inspect}" \
+          unless type.sigtype == type_code
       end
     end
 
@@ -480,7 +491,7 @@
         Byte
       end
 
-      # @return [Array<Type>]
+      # @return [::Array<Type>]
       def self.validate_raw!(value)
         DBus.types(value)
       rescue Type::SignatureException => e
@@ -510,6 +521,29 @@
       # For containers, the type varies among instances
       # @see Base#type
       attr_reader :type
+
+      # @return something that is, or contains, {Data::Base}.
+      #   Er, this docs kinda sucks.
+      def exact_value
+        @value
+      end
+
+      def value
+        @value.map(&:value)
+      end
+
+      # Hash key equality
+      # See https://ruby-doc.org/core-3.0.0/Object.html#method-i-eql-3F
+      # Stricter than #== (RSpec: eq), 1==1.0 but 1.eql(1.0)->false
+      def eql?(other)
+        return false unless other.class == self.class
+
+        other.exact_value.eql?(exact_value)
+      end
+
+      # def ==(other)
+      #   eql?(other) || super
+      # end
     end
 
     # An Array, or a Dictionary (Hash).
@@ -538,16 +572,17 @@
       # @param type [Type]
       # @return [Data::Array]
       def self.from_typed(value, type:)
-        assert_type_matches_class(type)
-        # TODO: validation
-        member_type = type.child
+        new(value, type: type) # initialize(::Array<Data::Base>)
+      end
 
-        # TODO: Dict??
-        items = value.map do |i|
-          Data.make_typed(member_type, i)
+      def value
+        v = super
+        if type.child.sigtype == Type::DICT_ENTRY
+          # BTW this makes a copy so mutating it is pointless
+          v.to_h
+        else
+          v
         end
-
-        new(items, type: type) # initialize(::Array<Data::Base>)
       end
 
       # FIXME: should Data::Array be mutable?
@@ -556,13 +591,27 @@
       # TODO: specify type or guess type?
       # Data is the exact type, so its constructor should be exact
       # and guesswork should be clearly labeled
+
+      # @param value [Data::Array,Enumerable]
       # @param type [SingleCompleteType,Type]
       def initialize(value, type:)
-        type = DBus.type(type) unless type.is_a?(Type)
+        type = Type::Factory.make_type(type)
         self.class.assert_type_matches_class(type)
         @type = type
-        # TODO: copy from another Data::Array
-        super(value)
+
+        typed_value = case value
+                      when Data::Array
+                        raise ArgumentError, "Specified type is #{type} but 
value type is #{value.type}" \
+                          unless value.type == type
+
+                        value.exact_value
+                      else
+                        # TODO: Dict??
+                        value.map do |i|
+                          Data.make_typed(type.child, i)
+                        end
+                      end
+        super(typed_value)
       end
     end
 
@@ -590,25 +639,72 @@
       # @param type [Type]
       # @return [Struct]
       def self.from_typed(value, type:)
-        # TODO: validation
-        member_types = type.members
-        raise unless value.size == member_types.size
-
-        items = member_types.zip(value).map do |item_type, item|
-          Data.make_typed(item_type, item)
-        end
-
-        new(items, type: type) # initialize(::Array<Data::Base>)
+        new(value, type: type)
       end
 
+      # @param value [Data::Struct,Enumerable]
+      # @param type [SingleCompleteType,Type]
       def initialize(value, type:)
+        type = Type::Factory.make_type(type)
         self.class.assert_type_matches_class(type)
         @type = type
-        super(value)
+
+        typed_value = case value
+                      when self.class
+                        raise ArgumentError, "Specified type is #{type} but 
value type is #{value.type}" \
+                          unless value.type == type
+
+                        value.exact_value
+                      else
+                        member_types = type.members
+                        unless value.size == member_types.size
+                          raise ArgumentError, "Specified type has 
#{member_types.size} members " \
+                                               "but value has #{value.size} 
members"
+                        end
+
+                        member_types.zip(value).map do |item_type, item|
+                          Data.make_typed(item_type, item)
+                        end
+                      end
+        super(typed_value)
+      end
+
+      def ==(other)
+        case other
+        when ::Struct
+          @value.size == other.size &&
+            @value.zip(other.to_a).all? { |i, other_i| i == other_i }
+        else
+          super
+        end
+      end
+    end
+
+    # Dictionary/Hash entry.
+    # TODO: shouldn't instantiate?
+    class DictEntry < Struct
+      def self.type_code
+        "e"
+      end
+
+      # @param value [::Array]
+      def self.from_items(value, mode:, type:) # rubocop:disable 
Lint/UnusedMethodArgument
+        value.freeze
+        # DictEntry ignores the :exact mode
+        value
+      end
+
+      # @param value [::Object] (#size, #each)
+      # @param type [Type]
+      # @return [DictEntry]
+      def self.from_typed(value, type:)
+        new(value, type: type)
       end
     end
 
-    # A generic type
+    # A generic type.
+    #
+    # Implementation note: @value is a {Data::Base}.
     class Variant < Container
       def self.type_code
         "v"
@@ -618,6 +714,10 @@
         1
       end
 
+      def value
+        @value.value
+      end
+
       # @param member_type [Type]
       def self.from_items(value, mode:, member_type:)
         return value if mode == :plain
@@ -631,7 +731,7 @@
       def self.from_typed(value, type:)
         assert_type_matches_class(type)
 
-        # decide on type of value
+        # nil: decide on type of value
         new(value, member_type: nil)
       end
 
@@ -659,60 +759,23 @@
       # @param member_type [Type,nil]
       def initialize(value, member_type:)
         # TODO: validate that the given *member_type* matches *value*
-        if value.is_a?(self.class)
+        case value
+        when Data::Variant
           # Copy the contained value instead of boxing it more
           # TODO: except perhaps for round-tripping in exact mode?
           @member_type = value.member_type
-          value = value.value
+          value = value.exact_value
+        when Data::Base
+          @member_type = member_type || value.type
+          raise ArgumentError, "Variant type #{@member_type} does not match 
value type #{value.type}" \
+            unless @member_type == value.type
         else
           @member_type = member_type || self.class.guess_type(value)
+          value = Data.make_typed(@member_type, value)
         end
         super(value)
       end
     end
-
-    # Dictionary/Hash entry.
-    # TODO: shouldn't instantiate?
-    class DictEntry < Container
-      def self.type_code
-        "e"
-      end
-
-      def self.alignment
-        8
-      end
-
-      # @param value [::Array]
-      def self.from_items(value, mode:, type:) # rubocop:disable 
Lint/UnusedMethodArgument
-        value.freeze
-        # DictEntry ignores the :exact mode
-        value
-      end
-
-      # @param value [::Object] (#size, #each)
-      # @param type [Type]
-      # @return [DictEntry]
-      def self.from_typed(value, type:)
-        assert_type_matches_class(type)
-        member_types = type.members
-        # assert member_types.size == 2
-        # TODO: duplicated from Struct. Inherit/delegate?
-        # TODO: validation
-        raise unless value.size == member_types.size
-
-        items = member_types.zip(value).map do |item_type, item|
-          Data.make_typed(item_type, item)
-        end
-
-        new(items, type: type) # initialize(::Array<Data::Base>)
-      end
-
-      def initialize(value, type:)
-        self.class.assert_type_matches_class(type)
-        @type = type
-        super(value)
-      end
-    end
 
     consts = constants.map { |c_sym| const_get(c_sym) }
     classes = consts.find_all { |c| c.respond_to?(:type_code) }
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-04-27 10:47:47.000000000 +0200
+++ new/lib/dbus/marshall.rb    2022-05-25 15:29:26.000000000 +0200
@@ -250,10 +250,10 @@
         when Type::VARIANT
           append_variant(val)
         when Type::ARRAY
-          val = val.value if val.is_a?(Data::Array)
+          val = val.exact_value if val.is_a?(Data::Array)
           append_array(type.child, val)
         when Type::STRUCT, Type::DICT_ENTRY
-          val = val.value if val.is_a?(Data::Struct) || 
val.is_a?(Data::DictEntry)
+          val = val.exact_value if val.is_a?(Data::Struct) || 
val.is_a?(Data::DictEntry)
           unless val.is_a?(Array) || val.is_a?(Struct)
             type_name = Type::TYPE_MAPPING[type.sigtype].first
             raise TypeException, "#{type_name} expects an Array or Struct, 
seen #{val.class}"
@@ -284,7 +284,10 @@
       vartype = nil
       if val.is_a?(DBus::Data::Variant)
         vartype = val.member_type
-        vardata = val.value
+        vardata = val.exact_value
+      elsif val.is_a?(DBus::Data::Container)
+        vartype = val.type
+        vardata = val.exact_value
       elsif val.is_a?(DBus::Data::Base)
         vartype = val.type
         vardata = val.value
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lib/dbus/type.rb new/lib/dbus/type.rb
--- old/lib/dbus/type.rb        2022-04-27 10:47:47.000000000 +0200
+++ new/lib/dbus/type.rb        2022-05-25 15:29:26.000000000 +0200
@@ -107,6 +107,29 @@
       freeze
     end
 
+    # A Type is equal to
+    # - another Type with the same string representation
+    # - a String ({SingleCompleteType}) describing the type
+    def ==(other)
+      case other
+      when ::String
+        to_s == other
+      else
+        eql?(other)
+      end
+    end
+
+    # A Type is eql? to
+    # - another Type with the same string representation
+    #
+    # Hash key equality
+    # See https://ruby-doc.org/core-3.0.0/Object.html#method-i-eql-3F
+    def eql?(other)
+      return false unless other.is_a?(Type)
+
+      @sigtype == other.sigtype && @members == other.members
+    end
+
     # Return the required alignment for the type.
     def alignment
       TYPE_MAPPING[@sigtype].last
@@ -157,7 +180,7 @@
 
     def inspect
       s = TYPE_MAPPING[@sigtype].first
-      if [STRUCT, ARRAY].member?(@sigtype)
+      if [STRUCT, ARRAY, DICT_ENTRY].member?(@sigtype)
         s += ": #{@members.inspect}"
       end
       s
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/metadata new/metadata
--- old/metadata        2022-04-27 10:47:47.000000000 +0200
+++ new/metadata        2022-05-25 15:29:26.000000000 +0200
@@ -1,14 +1,14 @@
 --- !ruby/object:Gem::Specification
 name: ruby-dbus
 version: !ruby/object:Gem::Version
-  version: 0.18.0.beta5
+  version: 0.18.0.beta6
 platform: ruby
 authors:
 - Ruby DBus Team
-autorequire: 
+autorequire:
 bindir: bin
 cert_chain: []
-date: 2022-04-27 00:00:00.000000000 Z
+date: 2022-05-25 00:00:00.000000000 Z
 dependencies:
 - !ruby/object:Gem::Dependency
   name: rexml
@@ -202,7 +202,7 @@
 licenses:
 - LGPL-2.1
 metadata: {}
-post_install_message: 
+post_install_message:
 rdoc_options: []
 require_paths:
 - lib
@@ -217,9 +217,8 @@
     - !ruby/object:Gem::Version
       version: 1.3.1
 requirements: []
-rubyforge_project: 
-rubygems_version: 2.7.6.3
-signing_key: 
+rubygems_version: 3.3.0.dev
+signing_key:
 specification_version: 4
 summary: Ruby module for interaction with D-Bus
 test_files: []
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spec/data_spec.rb new/spec/data_spec.rb
--- old/spec/data_spec.rb       2022-04-27 10:47:47.000000000 +0200
+++ new/spec/data_spec.rb       2022-05-25 15:29:26.000000000 +0200
@@ -6,14 +6,140 @@
 
 # The from_raw methods are tested in packet_unmarshaller_spec.rb
 
+RSpec.shared_examples "#== and #eql? work for basic types" do |*args|
+  plain_a = args.fetch(0, 22)
+  plain_b = args.fetch(1, 222)
+
+  context "with #{plain_a.inspect} and #{plain_b.inspect}" do
+    describe "#eql?" do
+      it "returns true for same class and value" do
+        a = described_class.new(plain_a)
+        b = described_class.new(plain_a)
+        expect(a).to eql(b)
+      end
+
+      it "returns false for same class, different value" do
+        a = described_class.new(plain_a)
+        b = described_class.new(plain_b)
+        expect(a).to_not eql(b)
+      end
+
+      it "returns false for same value but plain class" do
+        a = described_class.new(plain_a)
+        b = plain_a
+        expect(a).to_not eql(b)
+      end
+    end
+
+    describe "#==" do
+      it "returns true for same class and value" do
+        a = described_class.new(plain_a)
+        b = described_class.new(plain_a)
+        expect(a).to eq(b)
+      end
+
+      it "returns false for same class, different value" do
+        a = described_class.new(plain_a)
+        b = described_class.new(plain_b)
+        expect(a).to_not eq(b)
+      end
+
+      it "returns true for same value but plain class" do
+        a = described_class.new(plain_a)
+        b = plain_a
+        expect(a).to eq(b)
+      end
+    end
+  end
+end
+
+RSpec.shared_examples "#== and #eql? work for container types (1 value)" do 
|plain_a, a_kwargs|
+  a1 = described_class.new(plain_a, **a_kwargs)
+  a2 = described_class.new(plain_a, **a_kwargs)
+
+  context "with #{plain_a.inspect}, #{a_kwargs.inspect}" do
+    describe "#eql?" do
+      it "returns true for same class and value" do
+        expect(a1).to eql(a2)
+      end
+
+      it "returns false for same value but plain class" do
+        expect(a1).to_not eql(plain_a)
+      end
+    end
+
+    describe "#==" do
+      it "returns true for same class and value" do
+        expect(a1).to eq(a2)
+      end
+
+      it "returns true for same value but plain class" do
+        expect(a1).to eq(plain_a)
+      end
+    end
+  end
+end
+
+RSpec.shared_examples "#== and #eql? work for container types (inequal)" do 
|plain_a, a_kwargs, plain_b, b_kwargs|
+  # RSpec note: if the shared_examples is used via include_examples more than
+  # once in a single context, `let` would take value from just one of them.
+  # So use plain assignment.
+  a = described_class.new(plain_a, **a_kwargs)
+  b = described_class.new(plain_b, **b_kwargs)
+
+  include_examples "#== and #eql? work for container types (1 value)", 
plain_a, a_kwargs
+
+  context "with #{plain_a.inspect}, #{a_kwargs.inspect} and 
#{plain_b.inspect}, #{b_kwargs.inspect}" do
+    describe "#eql?" do
+      it "returns false for same class, different value" do
+        expect(a).to_not eql(b)
+      end
+    end
+
+    describe "#==" do
+      it "returns false for same class, different value" do
+        expect(a).to_not eq(b)
+      end
+    end
+  end
+end
+
+RSpec.shared_examples "#== and #eql? work for container types (equal)" do 
|plain_a, a_kwargs, plain_b, b_kwargs|
+  a = described_class.new(plain_a, **a_kwargs)
+  b = described_class.new(plain_b, **b_kwargs)
+
+  include_examples "#== and #eql? work for container types (1 value)", 
plain_a, a_kwargs
+
+  context "with #{plain_a.inspect}, #{a_kwargs.inspect} and 
#{plain_b.inspect}, #{b_kwargs.inspect}" do
+    describe "#eql?" do
+      it "returns true for same class, differently expressed value" do
+        expect(a).to eql(b)
+      end
+    end
+
+    describe "#==" do
+      it "returns true for same class, differently expressed value" do
+        expect(a).to eq(b)
+      end
+    end
+
+    describe "#==" do
+      it "returns true for plain, differently expressed value" do
+        expect(a).to eq(plain_b)
+        expect(b).to eq(plain_a)
+      end
+    end
+  end
+end
+
 RSpec.shared_examples "constructor accepts numeric range" do |min, max|
   describe "#initialize" do
     it "accepts the min value #{min}" do
-      expect(described_class.new(min).value).to eq(min)
+      expect(described_class.new(min).value).to eql(min)
     end
 
     it "accepts the max value #{max}" do
-      expect(described_class.new(max).value).to eq(max)
+      expect(described_class.new(max).value).to eql(max)
     end
 
     it "raises on too small a value #{min - 1}" do
@@ -34,27 +160,30 @@
   describe "#initialize" do
     Array(plain_list).each do |plain|
       it "accepts the plain value #{plain.inspect}" do
-        expect(described_class.new(plain).value).to eq(plain)
+        expect(described_class.new(plain).value).to eql(plain)
+        expect(described_class.new(plain)).to eq(plain)
       end
 
       it "accepts the typed value #{plain.inspect}" do
         typed = described_class.new(plain)
-        expect(described_class.new(typed).value).to eq(plain)
+        expect(described_class.new(typed).value).to eql(plain)
+        expect(described_class.new(typed)).to eq(plain)
       end
     end
   end
 end
 
+# FIXME: decide eq and eql here
 RSpec.shared_examples "constructor (kwargs) accepts values" do |list|
   describe "#initialize" do
     list.each do |value, kwargs_hash|
       it "accepts the plain value #{value.inspect}, #{kwargs_hash.inspect}" do
-        expect(described_class.new(value, **kwargs_hash).value).to eq(value)
+        expect(described_class.new(value, **kwargs_hash)).to eq(value)
       end
 
       it "accepts the typed value #{value.inspect}, #{kwargs_hash.inspect}" do
         typed = described_class.new(value, **kwargs_hash)
-        expect(described_class.new(typed, **kwargs_hash).value).to eq(value)
+        expect(described_class.new(typed, **kwargs_hash)).to eq(value)
       end
     end
   end
@@ -93,36 +222,43 @@
   # Kick InvalidPacketException out of here?
 
   describe DBus::Data::Byte do
+    include_examples "#== and #eql? work for basic types"
     include_examples "constructor accepts numeric range", 0, 2**8 - 1
     include_examples "constructor accepts plain or typed values", 42
   end
 
   describe DBus::Data::Int16 do
+    include_examples "#== and #eql? work for basic types"
     include_examples "constructor accepts numeric range", -2**15, 2**15 - 1
     include_examples "constructor accepts plain or typed values", 42
   end
 
   describe DBus::Data::UInt16 do
+    include_examples "#== and #eql? work for basic types"
     include_examples "constructor accepts numeric range", 0, 2**16 - 1
     include_examples "constructor accepts plain or typed values", 42
   end
 
   describe DBus::Data::Int32 do
+    include_examples "#== and #eql? work for basic types"
     include_examples "constructor accepts numeric range", -2**31, 2**31 - 1
     include_examples "constructor accepts plain or typed values", 42
   end
 
   describe DBus::Data::UInt32 do
+    include_examples "#== and #eql? work for basic types"
     include_examples "constructor accepts numeric range", 0, 2**32 - 1
     include_examples "constructor accepts plain or typed values", 42
   end
 
   describe DBus::Data::Int64 do
+    include_examples "#== and #eql? work for basic types"
     include_examples "constructor accepts numeric range", -2**63, 2**63 - 1
     include_examples "constructor accepts plain or typed values", 42
   end
 
   describe DBus::Data::UInt64 do
+    include_examples "#== and #eql? work for basic types"
     include_examples "constructor accepts numeric range", 0, 2**64 - 1
     include_examples "constructor accepts plain or typed values", 42
   end
@@ -142,10 +278,12 @@
       end
     end
 
+    include_examples "#== and #eql? work for basic types", false, true
     include_examples "constructor accepts plain or typed values", false
   end
 
   describe DBus::Data::Double do
+    include_examples "#== and #eql? work for basic types"
     include_examples "constructor accepts plain or typed values", Math::PI
 
     describe "#initialize" do
@@ -183,6 +321,7 @@
         ["\xF4\x90\xC0\xC0", DBus::InvalidPacketException, "not in UTF-8"]
       ]
 
+      include_examples "#== and #eql? work for basic types", "foo", "bar"
       include_examples "constructor accepts plain or typed values", good
       include_examples "constructor rejects values from this list", bad
 
@@ -206,6 +345,7 @@
         # TODO: others
       ]
 
+      include_examples "#== and #eql? work for basic types", "/foo", "/bar"
       include_examples "constructor accepts plain or typed values", good
       include_examples "constructor rejects values from this list", bad
 
@@ -231,6 +371,7 @@
         # TODO: others
       ]
 
+      include_examples "#== and #eql? work for basic types", "aah", "aaaaah"
       include_examples "constructor accepts plain or typed values", good
       include_examples "constructor rejects values from this list", bad
 
@@ -262,6 +403,14 @@
         # TODO: others
       ]
 
+      include_examples "#== and #eql? work for container types (inequal)",
+                       [1, 2, 3], { type: "aq" },
+                       [3, 2, 1], { type: "aq" }
+
+      include_examples "#== and #eql? work for container types (inequal)",
+                       [[1, 2, 3]], { type: "aaq" },
+                       [[3, 2, 1]], { type: "aaq" }
+
       include_examples "constructor (kwargs) accepts values", good
       include_examples "constructor (kwargs) rejects values", bad
 
@@ -315,6 +464,14 @@
         # TODO: others
       ]
 
+      include_examples "#== and #eql? work for container types (inequal)",
+                       [1, 2, 3], { type: qqq },
+                       [3, 2, 1], { type: qqq }
+
+      include_examples "#== and #eql? work for container types (equal)",
+                       three_words.new(*integers), { type: qqq },
+                       [1, 2, 3], { type: qqq }
+
       include_examples "constructor (kwargs) accepts values", good
       # include_examples "constructor (kwargs) rejects values", bad
 
@@ -325,6 +482,108 @@
             .to be_a(described_class)
         end
       end
+
+      describe "#initialize" do
+        it "converts type to Type" do
+          value = [1, 2, 3]
+          type = "(uuu)"
+          result = described_class.new(value, type: type)
+          expect(result.type).to be_a DBus::Type
+        end
+
+        it "checks that type matches class" do
+          value = [1, 2, 3]
+          type = T::Array[T::INT32]
+          expect { described_class.new(value, type: type) }
+            .to raise_error(ArgumentError, /Expecting "r"/)
+        end
+
+        it "checks type of a Data::Struct value" do
+          value1 = [1, 2, 3]
+          type1 = "(uuu)"
+          result1 = described_class.new(value1, type: type1)
+
+          value2 = result1
+          type2 = "(xxx)"
+          expect { described_class.new(value2, type: type2) }
+            .to raise_error(ArgumentError, /value type is .uuu./)
+        end
+
+        it "checks that size of type and value match" do
+          value = [1, 2, 3, 4]
+          type = "(uuu)"
+          expect { described_class.new(value, type: type) }
+            .to raise_error(ArgumentError, /type has 3 members.*value has 4 
members/)
+        end
+
+        it "converts value to ::Array of Data::Base" do
+          value = three_words.new(*integers)
+          type = T::Struct[T::INT32, T::INT32, T::INT32]
+          result = described_class.new(value, type: type)
+
+          expect(result.exact_value).to be_an(::Array)
+          expect(result.exact_value[0]).to be_a(DBus::Data::Base)
+        end
+      end
+    end
+
+    describe DBus::Data::DictEntry do
+      describe ".from_typed" do
+        it "creates new instance from given object and type" do
+          type = T::Hash[String, T::INT16].child
+          expect(described_class.from_typed(["test", 12], type: type))
+            .to be_a(described_class)
+        end
+      end
+
+      describe "#initialize" do
+        it "checks that type matches class" do
+          value = [1, 2]
+          type = T::Array[T::INT32]
+
+          expect { described_class.new(value, type: type) }
+            .to raise_error(ArgumentError, /Expecting "e"/)
+        end
+
+        it "checks type of a Data::DictEntry value" do
+          value1 = [1, 2]
+          type1 = T::Hash[T::UINT32, T::UINT32].child
+          result1 = described_class.new(value1, type: type1)
+
+          value2 = result1
+          type2 = T::Hash[T::UINT64, T::UINT64].child
+          expect { described_class.new(value2, type: type2) }
+            .to raise_error(ArgumentError, /value type is .uu./)
+        end
+
+        it "checks that size of type and value match" do
+          value = [1, 2, 3]
+          type = T::Hash[T::UINT32, T::UINT32].child
+          expect { described_class.new(value, type: type) }
+            .to raise_error(ArgumentError, /type has 2 members.*value has 3 
members/)
+        end
+
+        it "converts value to ::Array of Data::Base" do
+          two_words = ::Struct.new(:k, :v)
+          value = two_words.new(1, 2)
+          type = T::Hash[T::UINT32, T::UINT32].child
+          result = described_class.new(value, type: type)
+
+          expect(result.exact_value).to be_an(::Array)
+          expect(result.exact_value[0]).to be_a(DBus::Data::Base)
+        end
+
+        it "takes a plain value" do
+          input = ["test", 23]
+
+          type = T::Hash[String, T::INT16].child
+          value = described_class.new(input, type: type)
+
+          expect(value).to be_a(described_class)
+          expect(value.type.to_s).to eq "{sn}"
+          expect(value.value).to eql input
+        end
+      end
     end
 
     describe DBus::Data::Variant do
@@ -337,9 +596,42 @@
           expect(value.member_type.to_s).to eq "s"
         end
       end
-    end
 
-    describe DBus::Data::DictEntry do
+      describe "#initialize" do
+        it "takes a plain value" do
+          input = 42
+
+          type = DBus.type(T::INT16)
+          value = described_class.new(input, member_type: type)
+          expect(value).to be_a(described_class)
+          expect(value.type.to_s).to eq "v"
+          expect(value.member_type.to_s).to eq "n"
+          expect(value.value).to eq 42
+        end
+
+        # FIXME: verify that @value has the correct class
+        it "takes an exact value" do
+          input = DBus::Data::Int16.new(42)
+
+          type = DBus.type(T::INT16)
+          value = described_class.new(input, member_type: type)
+          expect(value).to be_a(described_class)
+          expect(value.type.to_s).to eq "v"
+          expect(value.member_type.to_s).to eq "n"
+          expect(value.value).to eq 42
+        end
+
+        it "checks the type of the exact value" do
+          input = DBus::Data::UInt16.new(42)
+
+          type = DBus.type(T::INT16)
+          expect { described_class.new(input, member_type: type) }
+            .to raise_error(ArgumentError, /Variant type n does not match 
value type q/)
+        end
+      end
+
+      include_examples "#== and #eql? work for container types (1 value)",
+                       "/foo", { member_type: DBus.type(T::STRING) }
     end
   end
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spec/packet_unmarshaller_spec.rb 
new/spec/packet_unmarshaller_spec.rb
--- old/spec/packet_unmarshaller_spec.rb        2022-04-27 10:47:47.000000000 
+0200
+++ new/spec/packet_unmarshaller_spec.rb        2022-05-25 15:29:26.000000000 
+0200
@@ -48,14 +48,7 @@
         result = results.first
 
         expect(result).to be_a(DBus::Data::Base)
-        if expected.is_a?(Hash)
-          expect(result.value.size).to eq(expected.size)
-          result.value.each_key do |result_key|
-            expect(result.value[result_key]).to eq(expected[result_key.value])
-          end
-        else
-          expect(result.value).to eq(expected)
-        end
+        expect(result.value).to eq(expected)
 
         expect(remaining_buffer(subject)).to be_empty
       end
@@ -106,14 +99,7 @@
           result = results.first
 
           expect(result).to be_a(DBus::Data::Base)
-          if expected.is_a?(Hash)
-            expect(result.value.size).to eq(expected.size)
-            result.value.each_key do |result_key|
-              expect(result.value[result_key]).to 
eq(expected[result_key.value])
-            end
-          else
-            expect(result.value).to eq(expected)
-          end
+          expect(result.value).to eq(expected)
 
           expect(remaining_buffer(subject)).to be_empty
         end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/spec/type_spec.rb new/spec/type_spec.rb
--- old/spec/type_spec.rb       2022-04-27 10:47:47.000000000 +0200
+++ new/spec/type_spec.rb       2022-05-25 15:29:26.000000000 +0200
@@ -82,6 +82,46 @@
   end
 
   describe DBus::Type do
+    let(:as1) { DBus.type("as") }
+    let(:as2) { DBus.type("as") }
+    let(:aas) { DBus.type("aas") }
+
+    describe "#==" do
+      it "is true for same types" do
+        expect(as1).to eq(as2)
+      end
+
+      it "is true for a type and its string representation" do
+        expect(as1).to eq("as")
+      end
+
+      it "is false for different types" do
+        expect(as1).to_not eq(aas)
+      end
+
+      it "is false for a type and a different string" do
+        expect(as1).to_not eq("aas")
+      end
+    end
+
+    describe "#eql?" do
+      it "is true for same types" do
+        expect(as1).to eql(as2)
+      end
+
+      it "is false for a type and its string representation" do
+        expect(as1).to_not eql("as")
+      end
+
+      it "is false for different types" do
+        expect(as1).to_not eql(aas)
+      end
+
+      it "is false for a type and a different string" do
+        expect(as1).to_not eql("aas")
+      end
+    end
+
     describe "#<<" do
       it "raises if the argument is not a Type" do
         t = DBus::Type.new(DBus::Type::ARRAY)

Reply via email to