ruby-dbus 0.18.0.beta5 → 0.18.0.beta6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f8b0c43d3f27f0877e52c0adfb8014374829f97bcd38be6b9fabda1d5da8413c
4
- data.tar.gz: 000eadf163b0fab2ef4ab39de81a79714b34392cd81b3be68e12587ddfa93372
3
+ metadata.gz: 54a45385340217271e3fb445cddf6afcddb9892c4bf75b503e7859390f4d2ed7
4
+ data.tar.gz: 3c4f71745992c5afece87e34909e67f451717c9398ac6efb6235cc64ad1d1b0c
5
5
  SHA512:
6
- metadata.gz: c2206dcd935fed4e3711b88b2c0c265e5a335700f9137d2c3972f419791d9c25198d0acf9ba7aaecdbc6a25e540005c64321e5165c6c644838fb3557355861ac
7
- data.tar.gz: 212cb8bdcd75e3f35622843f262cdb80eaa07c1919a7d17ffdf601e05c627556343b7855a014f60a220c8a757c201431d66799a6025a98d084aef6cc12f7d8bb
6
+ metadata.gz: 864aaaaa867ea04247515d875d836560a558b7a3d780712a41dcd52214d95e47e857d640d66a3573eaf4df778a0320f89ad2c59918c005a2fc80adb8a63074cb
7
+ data.tar.gz: cabd9d699d8b7aad7c5f77a83aa07389b59c11b34b1219822909a031774b078d0bf001a1bce9bb5912be42caa4adba7608906ebc76dde57ff9f06d13afd7850f
data/NEWS.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## Ruby D-Bus 0.18.0.beta6 - 2022-05-25
6
+
7
+ API:
8
+ * Data::Base#value returns plain Ruby types;
9
+ Data::Container#exact_value contains Data::Base ([#114][]).
10
+ * Data::Base#initialize and .from_typed allow plain or exact values, validate
11
+ argument types.
12
+ * Implement #== (converting) and #eql? (strict) for Data::Base and DBus::Type.
13
+
14
+ [#114]: https://github.com/mvidner/ruby-dbus/pull/114
15
+
5
16
  ## Ruby D-Bus 0.18.0.beta5 - 2022-04-27
6
17
 
7
18
  API:
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.18.0.beta5
1
+ 0.18.0.beta6
data/lib/dbus/data.rb CHANGED
@@ -35,7 +35,7 @@ module DBus
35
35
  # construct an appropriate {Data::Base} instance.
36
36
  #
37
37
  # @param type [SingleCompleteType,Type]
38
- # @param value [::Object]
38
+ # @param value [::Object,Data::Base] a plain value; exact values also allowed
39
39
  # @return [Data::Base]
40
40
  # @raise TypeError
41
41
  def make_typed(type, value)
@@ -58,9 +58,13 @@ module DBus
58
58
  # @!method self.fixed?
59
59
  # @return [Boolean]
60
60
 
61
- # @return appropriately-typed, valid value
61
+ # @return [::Object] a valid value, plain-Ruby typed.
62
+ # @see Data::Container#exact_value
62
63
  attr_reader :value
63
64
 
65
+ # @!method self.type_code
66
+ # @return [String] a single-character string, for example "a" for arrays
67
+
64
68
  # @!method type
65
69
  # @abstract
66
70
  # Note that for Variants type=="v",
@@ -91,11 +95,18 @@ module DBus
91
95
 
92
96
  # Hash key equality
93
97
  # See https://ruby-doc.org/core-3.0.0/Object.html#method-i-eql-3F
94
- alias eql? ==
98
+ # Stricter than #== (RSpec: eq), 1==1.0 but 1.eql(1.0)->false
99
+ def eql?(other)
100
+ return false unless other.class == self.class
101
+
102
+ other.value.eql?(@value)
103
+ # TODO: this should work, now check derived classes, exact_value
104
+ end
95
105
 
96
106
  # @param type [Type]
97
107
  def self.assert_type_matches_class(type)
98
- raise ArgumentError unless type.sigtype == type_code
108
+ raise ArgumentError, "Expecting #{type_code.inspect} for class #{self}, got #{type.sigtype.inspect}" \
109
+ unless type.sigtype == type_code
99
110
  end
100
111
  end
101
112
 
@@ -480,7 +491,7 @@ module DBus
480
491
  Byte
481
492
  end
482
493
 
483
- # @return [Array<Type>]
494
+ # @return [::Array<Type>]
484
495
  def self.validate_raw!(value)
485
496
  DBus.types(value)
486
497
  rescue Type::SignatureException => e
@@ -510,6 +521,29 @@ module DBus
510
521
  # For containers, the type varies among instances
511
522
  # @see Base#type
512
523
  attr_reader :type
524
+
525
+ # @return something that is, or contains, {Data::Base}.
526
+ # Er, this docs kinda sucks.
527
+ def exact_value
528
+ @value
529
+ end
530
+
531
+ def value
532
+ @value.map(&:value)
533
+ end
534
+
535
+ # Hash key equality
536
+ # See https://ruby-doc.org/core-3.0.0/Object.html#method-i-eql-3F
537
+ # Stricter than #== (RSpec: eq), 1==1.0 but 1.eql(1.0)->false
538
+ def eql?(other)
539
+ return false unless other.class == self.class
540
+
541
+ other.exact_value.eql?(exact_value)
542
+ end
543
+
544
+ # def ==(other)
545
+ # eql?(other) || super
546
+ # end
513
547
  end
514
548
 
515
549
  # An Array, or a Dictionary (Hash).
@@ -538,16 +572,17 @@ module DBus
538
572
  # @param type [Type]
539
573
  # @return [Data::Array]
540
574
  def self.from_typed(value, type:)
541
- assert_type_matches_class(type)
542
- # TODO: validation
543
- member_type = type.child
575
+ new(value, type: type) # initialize(::Array<Data::Base>)
576
+ end
544
577
 
545
- # TODO: Dict??
546
- items = value.map do |i|
547
- Data.make_typed(member_type, i)
578
+ def value
579
+ v = super
580
+ if type.child.sigtype == Type::DICT_ENTRY
581
+ # BTW this makes a copy so mutating it is pointless
582
+ v.to_h
583
+ else
584
+ v
548
585
  end
549
-
550
- new(items, type: type) # initialize(::Array<Data::Base>)
551
586
  end
552
587
 
553
588
  # FIXME: should Data::Array be mutable?
@@ -556,13 +591,27 @@ module DBus
556
591
  # TODO: specify type or guess type?
557
592
  # Data is the exact type, so its constructor should be exact
558
593
  # and guesswork should be clearly labeled
594
+
595
+ # @param value [Data::Array,Enumerable]
559
596
  # @param type [SingleCompleteType,Type]
560
597
  def initialize(value, type:)
561
- type = DBus.type(type) unless type.is_a?(Type)
598
+ type = Type::Factory.make_type(type)
562
599
  self.class.assert_type_matches_class(type)
563
600
  @type = type
564
- # TODO: copy from another Data::Array
565
- super(value)
601
+
602
+ typed_value = case value
603
+ when Data::Array
604
+ raise ArgumentError, "Specified type is #{type} but value type is #{value.type}" \
605
+ unless value.type == type
606
+
607
+ value.exact_value
608
+ else
609
+ # TODO: Dict??
610
+ value.map do |i|
611
+ Data.make_typed(type.child, i)
612
+ end
613
+ end
614
+ super(typed_value)
566
615
  end
567
616
  end
568
617
 
@@ -590,25 +639,72 @@ module DBus
590
639
  # @param type [Type]
591
640
  # @return [Struct]
592
641
  def self.from_typed(value, type:)
593
- # TODO: validation
594
- member_types = type.members
595
- raise unless value.size == member_types.size
596
-
597
- items = member_types.zip(value).map do |item_type, item|
598
- Data.make_typed(item_type, item)
599
- end
600
-
601
- new(items, type: type) # initialize(::Array<Data::Base>)
642
+ new(value, type: type)
602
643
  end
603
644
 
645
+ # @param value [Data::Struct,Enumerable]
646
+ # @param type [SingleCompleteType,Type]
604
647
  def initialize(value, type:)
648
+ type = Type::Factory.make_type(type)
605
649
  self.class.assert_type_matches_class(type)
606
650
  @type = type
607
- super(value)
651
+
652
+ typed_value = case value
653
+ when self.class
654
+ raise ArgumentError, "Specified type is #{type} but value type is #{value.type}" \
655
+ unless value.type == type
656
+
657
+ value.exact_value
658
+ else
659
+ member_types = type.members
660
+ unless value.size == member_types.size
661
+ raise ArgumentError, "Specified type has #{member_types.size} members " \
662
+ "but value has #{value.size} members"
663
+ end
664
+
665
+ member_types.zip(value).map do |item_type, item|
666
+ Data.make_typed(item_type, item)
667
+ end
668
+ end
669
+ super(typed_value)
670
+ end
671
+
672
+ def ==(other)
673
+ case other
674
+ when ::Struct
675
+ @value.size == other.size &&
676
+ @value.zip(other.to_a).all? { |i, other_i| i == other_i }
677
+ else
678
+ super
679
+ end
680
+ end
681
+ end
682
+
683
+ # Dictionary/Hash entry.
684
+ # TODO: shouldn't instantiate?
685
+ class DictEntry < Struct
686
+ def self.type_code
687
+ "e"
688
+ end
689
+
690
+ # @param value [::Array]
691
+ def self.from_items(value, mode:, type:) # rubocop:disable Lint/UnusedMethodArgument
692
+ value.freeze
693
+ # DictEntry ignores the :exact mode
694
+ value
695
+ end
696
+
697
+ # @param value [::Object] (#size, #each)
698
+ # @param type [Type]
699
+ # @return [DictEntry]
700
+ def self.from_typed(value, type:)
701
+ new(value, type: type)
608
702
  end
609
703
  end
610
704
 
611
- # A generic type
705
+ # A generic type.
706
+ #
707
+ # Implementation note: @value is a {Data::Base}.
612
708
  class Variant < Container
613
709
  def self.type_code
614
710
  "v"
@@ -618,6 +714,10 @@ module DBus
618
714
  1
619
715
  end
620
716
 
717
+ def value
718
+ @value.value
719
+ end
720
+
621
721
  # @param member_type [Type]
622
722
  def self.from_items(value, mode:, member_type:)
623
723
  return value if mode == :plain
@@ -631,7 +731,7 @@ module DBus
631
731
  def self.from_typed(value, type:)
632
732
  assert_type_matches_class(type)
633
733
 
634
- # decide on type of value
734
+ # nil: decide on type of value
635
735
  new(value, member_type: nil)
636
736
  end
637
737
 
@@ -659,61 +759,24 @@ module DBus
659
759
  # @param member_type [Type,nil]
660
760
  def initialize(value, member_type:)
661
761
  # TODO: validate that the given *member_type* matches *value*
662
- if value.is_a?(self.class)
762
+ case value
763
+ when Data::Variant
663
764
  # Copy the contained value instead of boxing it more
664
765
  # TODO: except perhaps for round-tripping in exact mode?
665
766
  @member_type = value.member_type
666
- value = value.value
767
+ value = value.exact_value
768
+ when Data::Base
769
+ @member_type = member_type || value.type
770
+ raise ArgumentError, "Variant type #{@member_type} does not match value type #{value.type}" \
771
+ unless @member_type == value.type
667
772
  else
668
773
  @member_type = member_type || self.class.guess_type(value)
774
+ value = Data.make_typed(@member_type, value)
669
775
  end
670
776
  super(value)
671
777
  end
672
778
  end
673
779
 
674
- # Dictionary/Hash entry.
675
- # TODO: shouldn't instantiate?
676
- class DictEntry < Container
677
- def self.type_code
678
- "e"
679
- end
680
-
681
- def self.alignment
682
- 8
683
- end
684
-
685
- # @param value [::Array]
686
- def self.from_items(value, mode:, type:) # rubocop:disable Lint/UnusedMethodArgument
687
- value.freeze
688
- # DictEntry ignores the :exact mode
689
- value
690
- end
691
-
692
- # @param value [::Object] (#size, #each)
693
- # @param type [Type]
694
- # @return [DictEntry]
695
- def self.from_typed(value, type:)
696
- assert_type_matches_class(type)
697
- member_types = type.members
698
- # assert member_types.size == 2
699
- # TODO: duplicated from Struct. Inherit/delegate?
700
- # TODO: validation
701
- raise unless value.size == member_types.size
702
-
703
- items = member_types.zip(value).map do |item_type, item|
704
- Data.make_typed(item_type, item)
705
- end
706
-
707
- new(items, type: type) # initialize(::Array<Data::Base>)
708
- end
709
-
710
- def initialize(value, type:)
711
- self.class.assert_type_matches_class(type)
712
- @type = type
713
- super(value)
714
- end
715
- end
716
-
717
780
  consts = constants.map { |c_sym| const_get(c_sym) }
718
781
  classes = consts.find_all { |c| c.respond_to?(:type_code) }
719
782
  by_type_code = classes.map { |cl| [cl.type_code, cl] }.to_h
data/lib/dbus/marshall.rb CHANGED
@@ -250,10 +250,10 @@ module DBus
250
250
  when Type::VARIANT
251
251
  append_variant(val)
252
252
  when Type::ARRAY
253
- val = val.value if val.is_a?(Data::Array)
253
+ val = val.exact_value if val.is_a?(Data::Array)
254
254
  append_array(type.child, val)
255
255
  when Type::STRUCT, Type::DICT_ENTRY
256
- val = val.value if val.is_a?(Data::Struct) || val.is_a?(Data::DictEntry)
256
+ val = val.exact_value if val.is_a?(Data::Struct) || val.is_a?(Data::DictEntry)
257
257
  unless val.is_a?(Array) || val.is_a?(Struct)
258
258
  type_name = Type::TYPE_MAPPING[type.sigtype].first
259
259
  raise TypeException, "#{type_name} expects an Array or Struct, seen #{val.class}"
@@ -284,7 +284,10 @@ module DBus
284
284
  vartype = nil
285
285
  if val.is_a?(DBus::Data::Variant)
286
286
  vartype = val.member_type
287
- vardata = val.value
287
+ vardata = val.exact_value
288
+ elsif val.is_a?(DBus::Data::Container)
289
+ vartype = val.type
290
+ vardata = val.exact_value
288
291
  elsif val.is_a?(DBus::Data::Base)
289
292
  vartype = val.type
290
293
  vardata = val.value
data/lib/dbus/type.rb CHANGED
@@ -107,6 +107,29 @@ module DBus
107
107
  freeze
108
108
  end
109
109
 
110
+ # A Type is equal to
111
+ # - another Type with the same string representation
112
+ # - a String ({SingleCompleteType}) describing the type
113
+ def ==(other)
114
+ case other
115
+ when ::String
116
+ to_s == other
117
+ else
118
+ eql?(other)
119
+ end
120
+ end
121
+
122
+ # A Type is eql? to
123
+ # - another Type with the same string representation
124
+ #
125
+ # Hash key equality
126
+ # See https://ruby-doc.org/core-3.0.0/Object.html#method-i-eql-3F
127
+ def eql?(other)
128
+ return false unless other.is_a?(Type)
129
+
130
+ @sigtype == other.sigtype && @members == other.members
131
+ end
132
+
110
133
  # Return the required alignment for the type.
111
134
  def alignment
112
135
  TYPE_MAPPING[@sigtype].last
@@ -157,7 +180,7 @@ module DBus
157
180
 
158
181
  def inspect
159
182
  s = TYPE_MAPPING[@sigtype].first
160
- if [STRUCT, ARRAY].member?(@sigtype)
183
+ if [STRUCT, ARRAY, DICT_ENTRY].member?(@sigtype)
161
184
  s += ": #{@members.inspect}"
162
185
  end
163
186
  s
data/spec/data_spec.rb CHANGED
@@ -6,14 +6,140 @@ require "dbus"
6
6
 
7
7
  # The from_raw methods are tested in packet_unmarshaller_spec.rb
8
8
 
9
+ RSpec.shared_examples "#== and #eql? work for basic types" do |*args|
10
+ plain_a = args.fetch(0, 22)
11
+ plain_b = args.fetch(1, 222)
12
+
13
+ context "with #{plain_a.inspect} and #{plain_b.inspect}" do
14
+ describe "#eql?" do
15
+ it "returns true for same class and value" do
16
+ a = described_class.new(plain_a)
17
+ b = described_class.new(plain_a)
18
+ expect(a).to eql(b)
19
+ end
20
+
21
+ it "returns false for same class, different value" do
22
+ a = described_class.new(plain_a)
23
+ b = described_class.new(plain_b)
24
+ expect(a).to_not eql(b)
25
+ end
26
+
27
+ it "returns false for same value but plain class" do
28
+ a = described_class.new(plain_a)
29
+ b = plain_a
30
+ expect(a).to_not eql(b)
31
+ end
32
+ end
33
+
34
+ describe "#==" do
35
+ it "returns true for same class and value" do
36
+ a = described_class.new(plain_a)
37
+ b = described_class.new(plain_a)
38
+ expect(a).to eq(b)
39
+ end
40
+
41
+ it "returns false for same class, different value" do
42
+ a = described_class.new(plain_a)
43
+ b = described_class.new(plain_b)
44
+ expect(a).to_not eq(b)
45
+ end
46
+
47
+ it "returns true for same value but plain class" do
48
+ a = described_class.new(plain_a)
49
+ b = plain_a
50
+ expect(a).to eq(b)
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ RSpec.shared_examples "#== and #eql? work for container types (1 value)" do |plain_a, a_kwargs|
57
+ a1 = described_class.new(plain_a, **a_kwargs)
58
+ a2 = described_class.new(plain_a, **a_kwargs)
59
+
60
+ context "with #{plain_a.inspect}, #{a_kwargs.inspect}" do
61
+ describe "#eql?" do
62
+ it "returns true for same class and value" do
63
+ expect(a1).to eql(a2)
64
+ end
65
+
66
+ it "returns false for same value but plain class" do
67
+ expect(a1).to_not eql(plain_a)
68
+ end
69
+ end
70
+
71
+ describe "#==" do
72
+ it "returns true for same class and value" do
73
+ expect(a1).to eq(a2)
74
+ end
75
+
76
+ it "returns true for same value but plain class" do
77
+ expect(a1).to eq(plain_a)
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ RSpec.shared_examples "#== and #eql? work for container types (inequal)" do |plain_a, a_kwargs, plain_b, b_kwargs|
84
+ # RSpec note: if the shared_examples is used via include_examples more than
85
+ # once in a single context, `let` would take value from just one of them.
86
+ # So use plain assignment.
87
+ a = described_class.new(plain_a, **a_kwargs)
88
+ b = described_class.new(plain_b, **b_kwargs)
89
+
90
+ include_examples "#== and #eql? work for container types (1 value)", plain_a, a_kwargs
91
+
92
+ context "with #{plain_a.inspect}, #{a_kwargs.inspect} and #{plain_b.inspect}, #{b_kwargs.inspect}" do
93
+ describe "#eql?" do
94
+ it "returns false for same class, different value" do
95
+ expect(a).to_not eql(b)
96
+ end
97
+ end
98
+
99
+ describe "#==" do
100
+ it "returns false for same class, different value" do
101
+ expect(a).to_not eq(b)
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ RSpec.shared_examples "#== and #eql? work for container types (equal)" do |plain_a, a_kwargs, plain_b, b_kwargs|
108
+ a = described_class.new(plain_a, **a_kwargs)
109
+ b = described_class.new(plain_b, **b_kwargs)
110
+
111
+ include_examples "#== and #eql? work for container types (1 value)", plain_a, a_kwargs
112
+
113
+ context "with #{plain_a.inspect}, #{a_kwargs.inspect} and #{plain_b.inspect}, #{b_kwargs.inspect}" do
114
+ describe "#eql?" do
115
+ it "returns true for same class, differently expressed value" do
116
+ expect(a).to eql(b)
117
+ end
118
+ end
119
+
120
+ describe "#==" do
121
+ it "returns true for same class, differently expressed value" do
122
+ expect(a).to eq(b)
123
+ end
124
+ end
125
+
126
+ describe "#==" do
127
+ it "returns true for plain, differently expressed value" do
128
+ expect(a).to eq(plain_b)
129
+ expect(b).to eq(plain_a)
130
+ end
131
+ end
132
+ end
133
+ end
134
+
9
135
  RSpec.shared_examples "constructor accepts numeric range" do |min, max|
10
136
  describe "#initialize" do
11
137
  it "accepts the min value #{min}" do
12
- expect(described_class.new(min).value).to eq(min)
138
+ expect(described_class.new(min).value).to eql(min)
13
139
  end
14
140
 
15
141
  it "accepts the max value #{max}" do
16
- expect(described_class.new(max).value).to eq(max)
142
+ expect(described_class.new(max).value).to eql(max)
17
143
  end
18
144
 
19
145
  it "raises on too small a value #{min - 1}" do
@@ -34,27 +160,30 @@ RSpec.shared_examples "constructor accepts plain or typed values" do |plain_list
34
160
  describe "#initialize" do
35
161
  Array(plain_list).each do |plain|
36
162
  it "accepts the plain value #{plain.inspect}" do
37
- expect(described_class.new(plain).value).to eq(plain)
163
+ expect(described_class.new(plain).value).to eql(plain)
164
+ expect(described_class.new(plain)).to eq(plain)
38
165
  end
39
166
 
40
167
  it "accepts the typed value #{plain.inspect}" do
41
168
  typed = described_class.new(plain)
42
- expect(described_class.new(typed).value).to eq(plain)
169
+ expect(described_class.new(typed).value).to eql(plain)
170
+ expect(described_class.new(typed)).to eq(plain)
43
171
  end
44
172
  end
45
173
  end
46
174
  end
47
175
 
176
+ # FIXME: decide eq and eql here
48
177
  RSpec.shared_examples "constructor (kwargs) accepts values" do |list|
49
178
  describe "#initialize" do
50
179
  list.each do |value, kwargs_hash|
51
180
  it "accepts the plain value #{value.inspect}, #{kwargs_hash.inspect}" do
52
- expect(described_class.new(value, **kwargs_hash).value).to eq(value)
181
+ expect(described_class.new(value, **kwargs_hash)).to eq(value)
53
182
  end
54
183
 
55
184
  it "accepts the typed value #{value.inspect}, #{kwargs_hash.inspect}" do
56
185
  typed = described_class.new(value, **kwargs_hash)
57
- expect(described_class.new(typed, **kwargs_hash).value).to eq(value)
186
+ expect(described_class.new(typed, **kwargs_hash)).to eq(value)
58
187
  end
59
188
  end
60
189
  end
@@ -93,36 +222,43 @@ describe DBus::Data do
93
222
  # Kick InvalidPacketException out of here?
94
223
 
95
224
  describe DBus::Data::Byte do
225
+ include_examples "#== and #eql? work for basic types"
96
226
  include_examples "constructor accepts numeric range", 0, 2**8 - 1
97
227
  include_examples "constructor accepts plain or typed values", 42
98
228
  end
99
229
 
100
230
  describe DBus::Data::Int16 do
231
+ include_examples "#== and #eql? work for basic types"
101
232
  include_examples "constructor accepts numeric range", -2**15, 2**15 - 1
102
233
  include_examples "constructor accepts plain or typed values", 42
103
234
  end
104
235
 
105
236
  describe DBus::Data::UInt16 do
237
+ include_examples "#== and #eql? work for basic types"
106
238
  include_examples "constructor accepts numeric range", 0, 2**16 - 1
107
239
  include_examples "constructor accepts plain or typed values", 42
108
240
  end
109
241
 
110
242
  describe DBus::Data::Int32 do
243
+ include_examples "#== and #eql? work for basic types"
111
244
  include_examples "constructor accepts numeric range", -2**31, 2**31 - 1
112
245
  include_examples "constructor accepts plain or typed values", 42
113
246
  end
114
247
 
115
248
  describe DBus::Data::UInt32 do
249
+ include_examples "#== and #eql? work for basic types"
116
250
  include_examples "constructor accepts numeric range", 0, 2**32 - 1
117
251
  include_examples "constructor accepts plain or typed values", 42
118
252
  end
119
253
 
120
254
  describe DBus::Data::Int64 do
255
+ include_examples "#== and #eql? work for basic types"
121
256
  include_examples "constructor accepts numeric range", -2**63, 2**63 - 1
122
257
  include_examples "constructor accepts plain or typed values", 42
123
258
  end
124
259
 
125
260
  describe DBus::Data::UInt64 do
261
+ include_examples "#== and #eql? work for basic types"
126
262
  include_examples "constructor accepts numeric range", 0, 2**64 - 1
127
263
  include_examples "constructor accepts plain or typed values", 42
128
264
  end
@@ -142,10 +278,12 @@ describe DBus::Data do
142
278
  end
143
279
  end
144
280
 
281
+ include_examples "#== and #eql? work for basic types", false, true
145
282
  include_examples "constructor accepts plain or typed values", false
146
283
  end
147
284
 
148
285
  describe DBus::Data::Double do
286
+ include_examples "#== and #eql? work for basic types"
149
287
  include_examples "constructor accepts plain or typed values", Math::PI
150
288
 
151
289
  describe "#initialize" do
@@ -183,6 +321,7 @@ describe DBus::Data do
183
321
  ["\xF4\x90\xC0\xC0", DBus::InvalidPacketException, "not in UTF-8"]
184
322
  ]
185
323
 
324
+ include_examples "#== and #eql? work for basic types", "foo", "bar"
186
325
  include_examples "constructor accepts plain or typed values", good
187
326
  include_examples "constructor rejects values from this list", bad
188
327
 
@@ -206,6 +345,7 @@ describe DBus::Data do
206
345
  # TODO: others
207
346
  ]
208
347
 
348
+ include_examples "#== and #eql? work for basic types", "/foo", "/bar"
209
349
  include_examples "constructor accepts plain or typed values", good
210
350
  include_examples "constructor rejects values from this list", bad
211
351
 
@@ -231,6 +371,7 @@ describe DBus::Data do
231
371
  # TODO: others
232
372
  ]
233
373
 
374
+ include_examples "#== and #eql? work for basic types", "aah", "aaaaah"
234
375
  include_examples "constructor accepts plain or typed values", good
235
376
  include_examples "constructor rejects values from this list", bad
236
377
 
@@ -262,6 +403,14 @@ describe DBus::Data do
262
403
  # TODO: others
263
404
  ]
264
405
 
406
+ include_examples "#== and #eql? work for container types (inequal)",
407
+ [1, 2, 3], { type: "aq" },
408
+ [3, 2, 1], { type: "aq" }
409
+
410
+ include_examples "#== and #eql? work for container types (inequal)",
411
+ [[1, 2, 3]], { type: "aaq" },
412
+ [[3, 2, 1]], { type: "aaq" }
413
+
265
414
  include_examples "constructor (kwargs) accepts values", good
266
415
  include_examples "constructor (kwargs) rejects values", bad
267
416
 
@@ -315,6 +464,14 @@ describe DBus::Data do
315
464
  # TODO: others
316
465
  ]
317
466
 
467
+ include_examples "#== and #eql? work for container types (inequal)",
468
+ [1, 2, 3], { type: qqq },
469
+ [3, 2, 1], { type: qqq }
470
+
471
+ include_examples "#== and #eql? work for container types (equal)",
472
+ three_words.new(*integers), { type: qqq },
473
+ [1, 2, 3], { type: qqq }
474
+
318
475
  include_examples "constructor (kwargs) accepts values", good
319
476
  # include_examples "constructor (kwargs) rejects values", bad
320
477
 
@@ -325,6 +482,108 @@ describe DBus::Data do
325
482
  .to be_a(described_class)
326
483
  end
327
484
  end
485
+
486
+ describe "#initialize" do
487
+ it "converts type to Type" do
488
+ value = [1, 2, 3]
489
+ type = "(uuu)"
490
+ result = described_class.new(value, type: type)
491
+ expect(result.type).to be_a DBus::Type
492
+ end
493
+
494
+ it "checks that type matches class" do
495
+ value = [1, 2, 3]
496
+ type = T::Array[T::INT32]
497
+ expect { described_class.new(value, type: type) }
498
+ .to raise_error(ArgumentError, /Expecting "r"/)
499
+ end
500
+
501
+ it "checks type of a Data::Struct value" do
502
+ value1 = [1, 2, 3]
503
+ type1 = "(uuu)"
504
+ result1 = described_class.new(value1, type: type1)
505
+
506
+ value2 = result1
507
+ type2 = "(xxx)"
508
+ expect { described_class.new(value2, type: type2) }
509
+ .to raise_error(ArgumentError, /value type is .uuu./)
510
+ end
511
+
512
+ it "checks that size of type and value match" do
513
+ value = [1, 2, 3, 4]
514
+ type = "(uuu)"
515
+ expect { described_class.new(value, type: type) }
516
+ .to raise_error(ArgumentError, /type has 3 members.*value has 4 members/)
517
+ end
518
+
519
+ it "converts value to ::Array of Data::Base" do
520
+ value = three_words.new(*integers)
521
+ type = T::Struct[T::INT32, T::INT32, T::INT32]
522
+ result = described_class.new(value, type: type)
523
+
524
+ expect(result.exact_value).to be_an(::Array)
525
+ expect(result.exact_value[0]).to be_a(DBus::Data::Base)
526
+ end
527
+ end
528
+ end
529
+
530
+ describe DBus::Data::DictEntry do
531
+ describe ".from_typed" do
532
+ it "creates new instance from given object and type" do
533
+ type = T::Hash[String, T::INT16].child
534
+ expect(described_class.from_typed(["test", 12], type: type))
535
+ .to be_a(described_class)
536
+ end
537
+ end
538
+
539
+ describe "#initialize" do
540
+ it "checks that type matches class" do
541
+ value = [1, 2]
542
+ type = T::Array[T::INT32]
543
+
544
+ expect { described_class.new(value, type: type) }
545
+ .to raise_error(ArgumentError, /Expecting "e"/)
546
+ end
547
+
548
+ it "checks type of a Data::DictEntry value" do
549
+ value1 = [1, 2]
550
+ type1 = T::Hash[T::UINT32, T::UINT32].child
551
+ result1 = described_class.new(value1, type: type1)
552
+
553
+ value2 = result1
554
+ type2 = T::Hash[T::UINT64, T::UINT64].child
555
+ expect { described_class.new(value2, type: type2) }
556
+ .to raise_error(ArgumentError, /value type is .uu./)
557
+ end
558
+
559
+ it "checks that size of type and value match" do
560
+ value = [1, 2, 3]
561
+ type = T::Hash[T::UINT32, T::UINT32].child
562
+ expect { described_class.new(value, type: type) }
563
+ .to raise_error(ArgumentError, /type has 2 members.*value has 3 members/)
564
+ end
565
+
566
+ it "converts value to ::Array of Data::Base" do
567
+ two_words = ::Struct.new(:k, :v)
568
+ value = two_words.new(1, 2)
569
+ type = T::Hash[T::UINT32, T::UINT32].child
570
+ result = described_class.new(value, type: type)
571
+
572
+ expect(result.exact_value).to be_an(::Array)
573
+ expect(result.exact_value[0]).to be_a(DBus::Data::Base)
574
+ end
575
+
576
+ it "takes a plain value" do
577
+ input = ["test", 23]
578
+
579
+ type = T::Hash[String, T::INT16].child
580
+ value = described_class.new(input, type: type)
581
+
582
+ expect(value).to be_a(described_class)
583
+ expect(value.type.to_s).to eq "{sn}"
584
+ expect(value.value).to eql input
585
+ end
586
+ end
328
587
  end
329
588
 
330
589
  describe DBus::Data::Variant do
@@ -337,9 +596,42 @@ describe DBus::Data do
337
596
  expect(value.member_type.to_s).to eq "s"
338
597
  end
339
598
  end
340
- end
341
599
 
342
- describe DBus::Data::DictEntry do
600
+ describe "#initialize" do
601
+ it "takes a plain value" do
602
+ input = 42
603
+
604
+ type = DBus.type(T::INT16)
605
+ value = described_class.new(input, member_type: type)
606
+ expect(value).to be_a(described_class)
607
+ expect(value.type.to_s).to eq "v"
608
+ expect(value.member_type.to_s).to eq "n"
609
+ expect(value.value).to eq 42
610
+ end
611
+
612
+ # FIXME: verify that @value has the correct class
613
+ it "takes an exact value" do
614
+ input = DBus::Data::Int16.new(42)
615
+
616
+ type = DBus.type(T::INT16)
617
+ value = described_class.new(input, member_type: type)
618
+ expect(value).to be_a(described_class)
619
+ expect(value.type.to_s).to eq "v"
620
+ expect(value.member_type.to_s).to eq "n"
621
+ expect(value.value).to eq 42
622
+ end
623
+
624
+ it "checks the type of the exact value" do
625
+ input = DBus::Data::UInt16.new(42)
626
+
627
+ type = DBus.type(T::INT16)
628
+ expect { described_class.new(input, member_type: type) }
629
+ .to raise_error(ArgumentError, /Variant type n does not match value type q/)
630
+ end
631
+ end
632
+
633
+ include_examples "#== and #eql? work for container types (1 value)",
634
+ "/foo", { member_type: DBus.type(T::STRING) }
343
635
  end
344
636
  end
345
637
  end
@@ -48,14 +48,7 @@ RSpec.shared_examples "parses good data" do |cases|
48
48
  result = results.first
49
49
 
50
50
  expect(result).to be_a(DBus::Data::Base)
51
- if expected.is_a?(Hash)
52
- expect(result.value.size).to eq(expected.size)
53
- result.value.each_key do |result_key|
54
- expect(result.value[result_key]).to eq(expected[result_key.value])
55
- end
56
- else
57
- expect(result.value).to eq(expected)
58
- end
51
+ expect(result.value).to eq(expected)
59
52
 
60
53
  expect(remaining_buffer(subject)).to be_empty
61
54
  end
@@ -106,14 +99,7 @@ describe DBus::PacketUnmarshaller do
106
99
  result = results.first
107
100
 
108
101
  expect(result).to be_a(DBus::Data::Base)
109
- if expected.is_a?(Hash)
110
- expect(result.value.size).to eq(expected.size)
111
- result.value.each_key do |result_key|
112
- expect(result.value[result_key]).to eq(expected[result_key.value])
113
- end
114
- else
115
- expect(result.value).to eq(expected)
116
- end
102
+ expect(result.value).to eq(expected)
117
103
 
118
104
  expect(remaining_buffer(subject)).to be_empty
119
105
  end
data/spec/type_spec.rb CHANGED
@@ -82,6 +82,46 @@ describe DBus do
82
82
  end
83
83
 
84
84
  describe DBus::Type do
85
+ let(:as1) { DBus.type("as") }
86
+ let(:as2) { DBus.type("as") }
87
+ let(:aas) { DBus.type("aas") }
88
+
89
+ describe "#==" do
90
+ it "is true for same types" do
91
+ expect(as1).to eq(as2)
92
+ end
93
+
94
+ it "is true for a type and its string representation" do
95
+ expect(as1).to eq("as")
96
+ end
97
+
98
+ it "is false for different types" do
99
+ expect(as1).to_not eq(aas)
100
+ end
101
+
102
+ it "is false for a type and a different string" do
103
+ expect(as1).to_not eq("aas")
104
+ end
105
+ end
106
+
107
+ describe "#eql?" do
108
+ it "is true for same types" do
109
+ expect(as1).to eql(as2)
110
+ end
111
+
112
+ it "is false for a type and its string representation" do
113
+ expect(as1).to_not eql("as")
114
+ end
115
+
116
+ it "is false for different types" do
117
+ expect(as1).to_not eql(aas)
118
+ end
119
+
120
+ it "is false for a type and a different string" do
121
+ expect(as1).to_not eql("aas")
122
+ end
123
+ end
124
+
85
125
  describe "#<<" do
86
126
  it "raises if the argument is not a Type" do
87
127
  t = DBus::Type.new(DBus::Type::ARRAY)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-dbus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.0.beta5
4
+ version: 0.18.0.beta6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ruby DBus Team
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-27 00:00:00.000000000 Z
11
+ date: 2022-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rexml
@@ -202,7 +202,7 @@ homepage: https://github.com/mvidner/ruby-dbus
202
202
  licenses:
203
203
  - LGPL-2.1
204
204
  metadata: {}
205
- post_install_message:
205
+ post_install_message:
206
206
  rdoc_options: []
207
207
  require_paths:
208
208
  - lib
@@ -217,9 +217,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
217
217
  - !ruby/object:Gem::Version
218
218
  version: 1.3.1
219
219
  requirements: []
220
- rubyforge_project:
221
- rubygems_version: 2.7.6.3
222
- signing_key:
220
+ rubygems_version: 3.3.0.dev
221
+ signing_key:
223
222
  specification_version: 4
224
223
  summary: Ruby module for interaction with D-Bus
225
224
  test_files: []