ruby-dbus 0.18.0.beta5 → 0.18.0.beta8

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -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
- ## [[1, 2, 3], { type: nil }, DBus::InvalidPacketException, "Unknown type code"],
261
- ## [[1, 2, 3], { type: "!" }, DBus::InvalidPacketException, "Unknown type code"]
262
- # TODO: others
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
- describe DBus::Data::DictEntry do
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
@@ -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