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 +4 -4
- data/NEWS.md +11 -0
- data/VERSION +1 -1
- data/lib/dbus/data.rb +136 -73
- data/lib/dbus/marshall.rb +6 -3
- data/lib/dbus/type.rb +24 -1
- data/spec/data_spec.rb +300 -8
- data/spec/packet_unmarshaller_spec.rb +2 -16
- data/spec/type_spec.rb +40 -0
- metadata +6 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 54a45385340217271e3fb445cddf6afcddb9892c4bf75b503e7859390f4d2ed7
|
4
|
+
data.tar.gz: 3c4f71745992c5afece87e34909e67f451717c9398ac6efb6235cc64ad1d1b0c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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
|
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
|
-
|
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
|
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
|
-
|
542
|
-
|
543
|
-
member_type = type.child
|
575
|
+
new(value, type: type) # initialize(::Array<Data::Base>)
|
576
|
+
end
|
544
577
|
|
545
|
-
|
546
|
-
|
547
|
-
|
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 =
|
598
|
+
type = Type::Factory.make_type(type)
|
562
599
|
self.class.assert_type_matches_class(type)
|
563
600
|
@type = type
|
564
|
-
|
565
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
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.
|
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.
|
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.
|
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
|
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
|
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
|
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
|
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)
|
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)
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
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-
|
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
|
-
|
221
|
-
|
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: []
|