ruby-dbus 0.18.0.beta5 → 0.18.0.beta8
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 +43 -0
- data/VERSION +1 -1
- data/doc/Reference.md +13 -4
- data/lib/dbus/bus.rb +3 -7
- data/lib/dbus/data.rb +165 -68
- data/lib/dbus/emits_changed_signal.rb +83 -0
- data/lib/dbus/introspect.rb +44 -4
- data/lib/dbus/marshall.rb +6 -3
- data/lib/dbus/object.rb +84 -22
- data/lib/dbus/proxy_object_factory.rb +2 -0
- data/lib/dbus/proxy_object_interface.rb +37 -9
- data/lib/dbus/type.rb +26 -2
- data/lib/dbus/xml.rb +4 -0
- data/lib/dbus.rb +1 -0
- data/spec/data_spec.rb +342 -14
- data/spec/emits_changed_signal_spec.rb +58 -0
- data/spec/object_spec.rb +138 -0
- data/spec/packet_unmarshaller_spec.rb +2 -16
- data/spec/property_spec.rb +35 -2
- data/spec/service_newapi.rb +13 -0
- data/spec/type_spec.rb +40 -0
- metadata +5 -2
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
|
@@ -64,7 +193,7 @@ RSpec.shared_examples "constructor rejects values from this list" do |bad_list|
|
|
64
193
|
describe "#initialize" do
|
65
194
|
bad_list.each do |(value, exc_class, msg_substr)|
|
66
195
|
it "rejects #{value.inspect} with #{exc_class}: #{msg_substr}" do
|
67
|
-
msg_re = Regexp.new(Regexp.quote(msg_substr))
|
196
|
+
msg_re = Regexp.try_convert(msg_substr) || Regexp.new(Regexp.quote(msg_substr))
|
68
197
|
expect { described_class.new(value) }.to raise_error(exc_class, msg_re)
|
69
198
|
end
|
70
199
|
end
|
@@ -75,7 +204,7 @@ RSpec.shared_examples "constructor (kwargs) rejects values" do |bad_list|
|
|
75
204
|
describe "#initialize" do
|
76
205
|
bad_list.each do |(value, kwargs_hash, exc_class, msg_substr)|
|
77
206
|
it "rejects #{value.inspect}, #{kwargs_hash.inspect} with #{exc_class}: #{msg_substr}" do
|
78
|
-
msg_re = Regexp.new(Regexp.quote(msg_substr))
|
207
|
+
msg_re = Regexp.try_convert(msg_substr) || Regexp.new(Regexp.quote(msg_substr))
|
79
208
|
expect { described_class.new(value, **kwargs_hash) }.to raise_error(exc_class, msg_re)
|
80
209
|
end
|
81
210
|
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
|
|
@@ -246,8 +387,9 @@ describe DBus::Data do
|
|
246
387
|
|
247
388
|
describe "containers" do
|
248
389
|
describe DBus::Data::Array do
|
390
|
+
aq = DBus::Data::Array.new([1, 2, 3], type: "aq")
|
391
|
+
|
249
392
|
good = [
|
250
|
-
# [[1, 2, 3], type: nil],
|
251
393
|
[[1, 2, 3], { type: "aq" }],
|
252
394
|
[[1, 2, 3], { type: T::Array[T::UINT16] }],
|
253
395
|
[[1, 2, 3], { type: T::Array["q"] }],
|
@@ -257,11 +399,24 @@ describe DBus::Data do
|
|
257
399
|
|
258
400
|
bad = [
|
259
401
|
# undesirable type guessing
|
260
|
-
|
261
|
-
|
262
|
-
|
402
|
+
[[1, 2, 3], { type: nil }, ArgumentError, /Expecting DBus::Type.*got nil/],
|
403
|
+
[[1, 2, 3], { type: "!" }, DBus::Type::SignatureException, "Unknown type code"],
|
404
|
+
[aq, { type: "q" }, ArgumentError, "Expecting \"a\""],
|
405
|
+
[aq, { type: "ao" }, ArgumentError,
|
406
|
+
"Specified type is ARRAY: [OBJECT_PATH] but value type is ARRAY: [UINT16]"]
|
407
|
+
# TODO: how to handle these?
|
408
|
+
# [{1 => 2, 3 => 4}, { type: "aq" }, ArgumentError, "?"],
|
409
|
+
# [/i am not an array/, { type: "aq" }, ArgumentError, "?"],
|
263
410
|
]
|
264
411
|
|
412
|
+
include_examples "#== and #eql? work for container types (inequal)",
|
413
|
+
[1, 2, 3], { type: "aq" },
|
414
|
+
[3, 2, 1], { type: "aq" }
|
415
|
+
|
416
|
+
include_examples "#== and #eql? work for container types (inequal)",
|
417
|
+
[[1, 2, 3]], { type: "aaq" },
|
418
|
+
[[3, 2, 1]], { type: "aaq" }
|
419
|
+
|
265
420
|
include_examples "constructor (kwargs) accepts values", good
|
266
421
|
include_examples "constructor (kwargs) rejects values", bad
|
267
422
|
|
@@ -315,6 +470,14 @@ describe DBus::Data do
|
|
315
470
|
# TODO: others
|
316
471
|
]
|
317
472
|
|
473
|
+
include_examples "#== and #eql? work for container types (inequal)",
|
474
|
+
[1, 2, 3], { type: qqq },
|
475
|
+
[3, 2, 1], { type: qqq }
|
476
|
+
|
477
|
+
include_examples "#== and #eql? work for container types (equal)",
|
478
|
+
three_words.new(*integers), { type: qqq },
|
479
|
+
[1, 2, 3], { type: qqq }
|
480
|
+
|
318
481
|
include_examples "constructor (kwargs) accepts values", good
|
319
482
|
# include_examples "constructor (kwargs) rejects values", bad
|
320
483
|
|
@@ -325,6 +488,108 @@ describe DBus::Data do
|
|
325
488
|
.to be_a(described_class)
|
326
489
|
end
|
327
490
|
end
|
491
|
+
|
492
|
+
describe "#initialize" do
|
493
|
+
it "converts type to Type" do
|
494
|
+
value = [1, 2, 3]
|
495
|
+
type = "(uuu)"
|
496
|
+
result = described_class.new(value, type: type)
|
497
|
+
expect(result.type).to be_a DBus::Type
|
498
|
+
end
|
499
|
+
|
500
|
+
it "checks that type matches class" do
|
501
|
+
value = [1, 2, 3]
|
502
|
+
type = T::Array[T::INT32]
|
503
|
+
expect { described_class.new(value, type: type) }
|
504
|
+
.to raise_error(ArgumentError, /Expecting "r"/)
|
505
|
+
end
|
506
|
+
|
507
|
+
it "checks type of a Data::Struct value" do
|
508
|
+
value1 = [1, 2, 3]
|
509
|
+
type1 = "(uuu)"
|
510
|
+
result1 = described_class.new(value1, type: type1)
|
511
|
+
|
512
|
+
value2 = result1
|
513
|
+
type2 = "(xxx)"
|
514
|
+
expect { described_class.new(value2, type: type2) }
|
515
|
+
.to raise_error(ArgumentError, /value type is STRUCT.*UINT32/)
|
516
|
+
end
|
517
|
+
|
518
|
+
it "checks that size of type and value match" do
|
519
|
+
value = [1, 2, 3, 4]
|
520
|
+
type = "(uuu)"
|
521
|
+
expect { described_class.new(value, type: type) }
|
522
|
+
.to raise_error(ArgumentError, /type has 3 members.*value has 4 members/)
|
523
|
+
end
|
524
|
+
|
525
|
+
it "converts value to ::Array of Data::Base" do
|
526
|
+
value = three_words.new(*integers)
|
527
|
+
type = T::Struct[T::INT32, T::INT32, T::INT32]
|
528
|
+
result = described_class.new(value, type: type)
|
529
|
+
|
530
|
+
expect(result.exact_value).to be_an(::Array)
|
531
|
+
expect(result.exact_value[0]).to be_a(DBus::Data::Base)
|
532
|
+
end
|
533
|
+
end
|
534
|
+
end
|
535
|
+
|
536
|
+
describe DBus::Data::DictEntry do
|
537
|
+
describe ".from_typed" do
|
538
|
+
it "creates new instance from given object and type" do
|
539
|
+
type = T::Hash[String, T::INT16].child
|
540
|
+
expect(described_class.from_typed(["test", 12], type: type))
|
541
|
+
.to be_a(described_class)
|
542
|
+
end
|
543
|
+
end
|
544
|
+
|
545
|
+
describe "#initialize" do
|
546
|
+
it "checks that type matches class" do
|
547
|
+
value = [1, 2]
|
548
|
+
type = T::Array[T::INT32]
|
549
|
+
|
550
|
+
expect { described_class.new(value, type: type) }
|
551
|
+
.to raise_error(ArgumentError, /Expecting "e"/)
|
552
|
+
end
|
553
|
+
|
554
|
+
it "checks type of a Data::DictEntry value" do
|
555
|
+
value1 = [1, 2]
|
556
|
+
type1 = T::Hash[T::UINT32, T::UINT32].child
|
557
|
+
result1 = described_class.new(value1, type: type1)
|
558
|
+
|
559
|
+
value2 = result1
|
560
|
+
type2 = T::Hash[T::UINT64, T::UINT64].child
|
561
|
+
expect { described_class.new(value2, type: type2) }
|
562
|
+
.to raise_error(ArgumentError, /value type is DICT_ENTRY.*UINT32/)
|
563
|
+
end
|
564
|
+
|
565
|
+
it "checks that size of type and value match" do
|
566
|
+
value = [1, 2, 3]
|
567
|
+
type = T::Hash[T::UINT32, T::UINT32].child
|
568
|
+
expect { described_class.new(value, type: type) }
|
569
|
+
.to raise_error(ArgumentError, /type has 2 members.*value has 3 members/)
|
570
|
+
end
|
571
|
+
|
572
|
+
it "converts value to ::Array of Data::Base" do
|
573
|
+
two_words = ::Struct.new(:k, :v)
|
574
|
+
value = two_words.new(1, 2)
|
575
|
+
type = T::Hash[T::UINT32, T::UINT32].child
|
576
|
+
result = described_class.new(value, type: type)
|
577
|
+
|
578
|
+
expect(result.exact_value).to be_an(::Array)
|
579
|
+
expect(result.exact_value[0]).to be_a(DBus::Data::Base)
|
580
|
+
end
|
581
|
+
|
582
|
+
it "takes a plain value" do
|
583
|
+
input = ["test", 23]
|
584
|
+
|
585
|
+
type = T::Hash[String, T::INT16].child
|
586
|
+
value = described_class.new(input, type: type)
|
587
|
+
|
588
|
+
expect(value).to be_a(described_class)
|
589
|
+
expect(value.type.to_s).to eq "{sn}"
|
590
|
+
expect(value.value).to eql input
|
591
|
+
end
|
592
|
+
end
|
328
593
|
end
|
329
594
|
|
330
595
|
describe DBus::Data::Variant do
|
@@ -337,9 +602,72 @@ describe DBus::Data do
|
|
337
602
|
expect(value.member_type.to_s).to eq "s"
|
338
603
|
end
|
339
604
|
end
|
340
|
-
end
|
341
605
|
|
342
|
-
|
606
|
+
describe "#initialize" do
|
607
|
+
it "takes a plain value" do
|
608
|
+
input = 42
|
609
|
+
|
610
|
+
type = DBus.type(T::INT16)
|
611
|
+
value = described_class.new(input, member_type: type)
|
612
|
+
expect(value).to be_a(described_class)
|
613
|
+
expect(value.type.to_s).to eq "v"
|
614
|
+
expect(value.member_type.to_s).to eq "n"
|
615
|
+
expect(value.value).to eq 42
|
616
|
+
end
|
617
|
+
|
618
|
+
# FIXME: verify that @value has the correct class
|
619
|
+
it "takes an exact value" do
|
620
|
+
input = DBus::Data::Int16.new(42)
|
621
|
+
|
622
|
+
type = DBus.type(T::INT16)
|
623
|
+
value = described_class.new(input, member_type: type)
|
624
|
+
expect(value).to be_a(described_class)
|
625
|
+
expect(value.type.to_s).to eq "v"
|
626
|
+
expect(value.member_type.to_s).to eq "n"
|
627
|
+
expect(value.value).to eq 42
|
628
|
+
end
|
629
|
+
|
630
|
+
it "checks the type of the exact value" do
|
631
|
+
input = DBus::Data::UInt16.new(42)
|
632
|
+
|
633
|
+
type = DBus.type(T::INT16)
|
634
|
+
expect { described_class.new(input, member_type: type) }
|
635
|
+
.to raise_error(ArgumentError, /Variant type n does not match value type q/)
|
636
|
+
end
|
637
|
+
end
|
638
|
+
|
639
|
+
include_examples "#== and #eql? work for container types (1 value)",
|
640
|
+
"/foo", { member_type: DBus.type(T::STRING) }
|
641
|
+
|
642
|
+
describe "DBus.variant compatibility" do
|
643
|
+
let(:v) { DBus.variant("o", "/foo") }
|
644
|
+
|
645
|
+
describe "#[]" do
|
646
|
+
it "returns the type for 0" do
|
647
|
+
expect(v[0]).to eq DBus.type(DBus::Type::OBJECT_PATH)
|
648
|
+
end
|
649
|
+
|
650
|
+
it "returns the value for 1" do
|
651
|
+
expect(v[1]).to eq DBus::ObjectPath.new("/foo")
|
652
|
+
end
|
653
|
+
|
654
|
+
it "returns an error for other indices" do
|
655
|
+
expect { v[2] }.to raise_error(ArgumentError, /DBus.variant can only be indexed with 0 or 1/)
|
656
|
+
end
|
657
|
+
end
|
658
|
+
|
659
|
+
describe "#first" do
|
660
|
+
it "returns the type" do
|
661
|
+
expect(v.first).to eq DBus.type(DBus::Type::OBJECT_PATH)
|
662
|
+
end
|
663
|
+
end
|
664
|
+
|
665
|
+
describe "#last" do
|
666
|
+
it "returns the value" do
|
667
|
+
expect(v.last).to eq DBus::ObjectPath.new("/foo")
|
668
|
+
end
|
669
|
+
end
|
670
|
+
end
|
343
671
|
end
|
344
672
|
end
|
345
673
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/bin/env rspec
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative "spec_helper"
|
5
|
+
require "dbus"
|
6
|
+
|
7
|
+
describe DBus::EmitsChangedSignal do
|
8
|
+
describe "#initialize" do
|
9
|
+
it "accepts a simple value" do
|
10
|
+
expect(described_class.new(:const).value).to eq :const
|
11
|
+
end
|
12
|
+
|
13
|
+
it "avoids nil by asking the interface" do
|
14
|
+
ifc = DBus::Interface.new("org.example.Foo")
|
15
|
+
ifc.emits_changed_signal = described_class.new(:invalidates)
|
16
|
+
|
17
|
+
expect(described_class.new(nil, interface: ifc).value).to eq :invalidates
|
18
|
+
end
|
19
|
+
|
20
|
+
it "fails for unknown value" do
|
21
|
+
expect { described_class.new(:huh) }.to raise_error(ArgumentError, /Seen :huh/)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "fails for 2 nils" do
|
25
|
+
expect { described_class.new(nil, interface: nil) }.to raise_error(ArgumentError, /Both/)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#==" do
|
30
|
+
it "is true for two different objects with the same value" do
|
31
|
+
const_a = described_class.new(:const)
|
32
|
+
const_b = described_class.new(:const)
|
33
|
+
expect(const_a == const_b).to be true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#to_xml" do
|
38
|
+
it "uses a string value" do
|
39
|
+
expect(described_class.new(:const).to_xml)
|
40
|
+
.to eq " <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"const\"/>\n"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#to_s" do
|
45
|
+
it "uses a string value" do
|
46
|
+
expect(described_class.new(:const).to_s).to eq "const"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe DBus::Interface do
|
52
|
+
describe ".emits_changed_signal=" do
|
53
|
+
it "only allows an EmitsChangedSignal as argument" do
|
54
|
+
ifc = described_class.new("org.ruby.Interface")
|
55
|
+
expect { ifc.emits_changed_signal = :const }.to raise_error(TypeError)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/spec/object_spec.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
#!/usr/bin/env rspec
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative "spec_helper"
|
5
|
+
require "dbus"
|
6
|
+
|
7
|
+
class ObjectTest < DBus::Object
|
8
|
+
T = DBus::Type unless const_defined? "T"
|
9
|
+
|
10
|
+
dbus_interface "org.ruby.ServerTest" do
|
11
|
+
dbus_attr_writer :write_me, T::Struct[String, String]
|
12
|
+
|
13
|
+
attr_accessor :read_only_for_dbus
|
14
|
+
|
15
|
+
dbus_reader :read_only_for_dbus, T::STRING, emits_changed_signal: :invalidates
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe DBus::Object do
|
20
|
+
describe ".dbus_attr_writer" do
|
21
|
+
describe "the declared assignment method" do
|
22
|
+
# Slightly advanced RSpec:
|
23
|
+
# https://rspec.info/documentation/3.9/rspec-expectations/RSpec/Matchers.html#satisfy-instance_method
|
24
|
+
let(:a_struct_in_a_variant) do
|
25
|
+
satisfying { |x| x.is_a?(DBus::Data::Variant) && x.member_type.to_s == "(ss)" }
|
26
|
+
# ^ This formatting keeps the matcher on a single line
|
27
|
+
# which enables RSpec to cite it if it fails, instead of saying "block".
|
28
|
+
end
|
29
|
+
|
30
|
+
it "emits PropertyChanged with correctly typed argument" do
|
31
|
+
obj = ObjectTest.new("/test")
|
32
|
+
expect(obj).to receive(:PropertiesChanged).with(
|
33
|
+
"org.ruby.ServerTest",
|
34
|
+
{
|
35
|
+
"WriteMe" => a_struct_in_a_variant
|
36
|
+
},
|
37
|
+
[]
|
38
|
+
)
|
39
|
+
# bug: call PC with simply the assigned value,
|
40
|
+
# which will need type guessing
|
41
|
+
obj.write_me = ["two", "strings"]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe ".dbus_accessor" do
|
47
|
+
it "can only be used within a dbus_interface" do
|
48
|
+
expect do
|
49
|
+
ObjectTest.instance_exec do
|
50
|
+
dbus_accessor :foo, DBus::Type::STRING
|
51
|
+
end
|
52
|
+
end.to raise_error(DBus::Object::UndefinedInterface)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe ".dbus_reader" do
|
57
|
+
it "can only be used within a dbus_interface" do
|
58
|
+
expect do
|
59
|
+
ObjectTest.instance_exec do
|
60
|
+
dbus_reader :foo, DBus::Type::STRING
|
61
|
+
end
|
62
|
+
end.to raise_error(DBus::Object::UndefinedInterface)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe ".dbus_reader, when paired with attr_accessor" do
|
67
|
+
describe "the declared assignment method" do
|
68
|
+
it "emits PropertyChanged" do
|
69
|
+
obj = ObjectTest.new("/test")
|
70
|
+
expect(obj).to receive(:PropertiesChanged).with(
|
71
|
+
"org.ruby.ServerTest",
|
72
|
+
{},
|
73
|
+
["ReadOnlyForDbus"]
|
74
|
+
)
|
75
|
+
obj.read_only_for_dbus = "myvalue"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe ".dbus_writer" do
|
81
|
+
it "can only be used within a dbus_interface" do
|
82
|
+
expect do
|
83
|
+
ObjectTest.instance_exec do
|
84
|
+
dbus_writer :foo, DBus::Type::STRING
|
85
|
+
end
|
86
|
+
end.to raise_error(DBus::Object::UndefinedInterface)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe ".dbus_watcher" do
|
91
|
+
it "can only be used within a dbus_interface" do
|
92
|
+
expect do
|
93
|
+
ObjectTest.instance_exec do
|
94
|
+
dbus_watcher :foo
|
95
|
+
end
|
96
|
+
end.to raise_error(DBus::Object::UndefinedInterface)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe ".dbus_method" do
|
101
|
+
it "can only be used within a dbus_interface" do
|
102
|
+
expect do
|
103
|
+
ObjectTest.instance_exec do
|
104
|
+
dbus_method :foo do
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end.to raise_error(DBus::Object::UndefinedInterface)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe ".emits_changed_signal" do
|
112
|
+
it "raises UndefinedInterface when so" do
|
113
|
+
expect { ObjectTest.emits_changed_signal = false }
|
114
|
+
.to raise_error DBus::Object::UndefinedInterface
|
115
|
+
end
|
116
|
+
|
117
|
+
it "assigns to the current interface" do
|
118
|
+
ObjectTest.instance_exec do
|
119
|
+
dbus_interface "org.ruby.Interface" do
|
120
|
+
self.emits_changed_signal = false
|
121
|
+
end
|
122
|
+
end
|
123
|
+
ecs = ObjectTest.intfs["org.ruby.Interface"].emits_changed_signal
|
124
|
+
expect(ecs).to eq false
|
125
|
+
end
|
126
|
+
|
127
|
+
it "only can be assigned once" do
|
128
|
+
expect do
|
129
|
+
Class.new(DBus::Object) do
|
130
|
+
dbus_interface "org.ruby.Interface" do
|
131
|
+
self.emits_changed_signal = false
|
132
|
+
self.emits_changed_signal = :invalidates
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end.to raise_error(RuntimeError, /assigned more than once/)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|