ruby-dbus 0.16.0 → 0.17.0

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.
data/lib/dbus/object.rb CHANGED
@@ -7,9 +7,11 @@
7
7
  # See the file "COPYING" for the exact licensing terms.
8
8
 
9
9
  require "thread"
10
- require "dbus/core_ext/class/attribute"
10
+ require_relative "core_ext/class/attribute"
11
11
 
12
12
  module DBus
13
+ PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties".freeze
14
+
13
15
  # Exported object type
14
16
  # = Exportable D-Bus object class
15
17
  #
@@ -58,7 +60,7 @@ module DBus
58
60
  meth.rets.zip(retdata).each do |rsig, rdata|
59
61
  reply.add_param(rsig.type, rdata)
60
62
  end
61
- rescue => ex
63
+ rescue StandardError => ex
62
64
  dbus_msg_exc = msg.annotate_exception(ex)
63
65
  reply = ErrorMessage.from_exception(dbus_msg_exc).reply_to(msg)
64
66
  end
@@ -85,45 +87,294 @@ module DBus
85
87
  end
86
88
  end
87
89
 
88
- # Dummy undefined interface class.
89
- class UndefinedInterface < ScriptError
90
+ # Forgetting to declare the interface for a method/signal/property
91
+ # is a ScriptError.
92
+ class UndefinedInterface < ScriptError # rubocop:disable Lint/InheritException
90
93
  def initialize(sym)
91
- super "No interface specified for #{sym}"
94
+ super "No interface specified for #{sym}. Enclose it in dbus_interface."
95
+ end
96
+ end
97
+
98
+ # A read-write property accessing an instance variable.
99
+ # A combination of `attr_accessor` and {.dbus_accessor}.
100
+ #
101
+ # PropertiesChanged signal will be emitted whenever `foo_bar=` is used
102
+ # but not when @foo_bar is written directly.
103
+ #
104
+ # @param ruby_name [Symbol] :foo_bar is exposed as FooBar;
105
+ # use dbus_name to override
106
+ # @param type a signature like "s" or "a(uus)" or Type::STRING
107
+ # @param dbus_name [String] if not given it is made
108
+ # by CamelCasing the ruby_name. foo_bar becomes FooBar
109
+ # to convert the Ruby convention to the DBus convention.
110
+ # @return [void]
111
+ def self.dbus_attr_accessor(ruby_name, type, dbus_name: nil)
112
+ attr_accessor(ruby_name)
113
+ dbus_accessor(ruby_name, type, dbus_name: dbus_name)
114
+ end
115
+
116
+ # A read-only property accessing an instance variable.
117
+ # A combination of `attr_reader` and {.dbus_reader}.
118
+ #
119
+ # Whenever the property value gets changed from "inside" the object,
120
+ # you should emit the `PropertiesChanged` signal by calling
121
+ #
122
+ # object[DBus::PROPERTY_INTERFACE].PropertiesChanged(interface_name, {dbus_name.to_s => value}, [])
123
+ #
124
+ # or, omitting the value in the signal,
125
+ #
126
+ # object[DBus::PROPERTY_INTERFACE].PropertiesChanged(interface_name, {}, [dbus_name.to_s])
127
+ #
128
+ # @param (see .dbus_attr_accessor)
129
+ # @return (see .dbus_attr_accessor)
130
+ def self.dbus_attr_reader(ruby_name, type, dbus_name: nil)
131
+ attr_reader(ruby_name)
132
+ dbus_reader(ruby_name, type, dbus_name: dbus_name)
133
+ end
134
+
135
+ # A write-only property accessing an instance variable.
136
+ # A combination of `attr_writer` and {.dbus_writer}.
137
+ #
138
+ # @param (see .dbus_attr_accessor)
139
+ # @return (see .dbus_attr_accessor)
140
+ def self.dbus_attr_writer(ruby_name, type, dbus_name: nil)
141
+ attr_writer(ruby_name)
142
+ dbus_writer(ruby_name, type, dbus_name: dbus_name)
143
+ end
144
+
145
+ # A read-write property using a pair of reader/writer methods
146
+ # (which must already exist).
147
+ # (To directly access an instance variable, use {.dbus_attr_accessor} instead)
148
+ #
149
+ # Uses {.dbus_watcher} to set up the PropertiesChanged signal.
150
+ #
151
+ # @param (see .dbus_attr_accessor)
152
+ # @return (see .dbus_attr_accessor)
153
+ def self.dbus_accessor(ruby_name, type, dbus_name: nil)
154
+ raise UndefinedInterface, ruby_name if @@cur_intf.nil?
155
+
156
+ dbus_name = make_dbus_name(ruby_name, dbus_name: dbus_name)
157
+ property = Property.new(dbus_name, type, :readwrite, ruby_name: ruby_name)
158
+ @@cur_intf.define(property)
159
+
160
+ dbus_watcher(ruby_name, dbus_name: dbus_name)
161
+ end
162
+
163
+ # A read-only property accessing a reader method (which must already exist).
164
+ # (To directly access an instance variable, use {.dbus_attr_reader} instead)
165
+ #
166
+ # Whenever the property value gets changed from "inside" the object,
167
+ # you should emit the `PropertiesChanged` signal by calling
168
+ #
169
+ # object[DBus::PROPERTY_INTERFACE].PropertiesChanged(interface_name, {dbus_name.to_s => value}, [])
170
+ #
171
+ # or, omitting the value in the signal,
172
+ #
173
+ # object[DBus::PROPERTY_INTERFACE].PropertiesChanged(interface_name, {}, [dbus_name.to_s])
174
+ #
175
+ # @param (see .dbus_attr_accessor)
176
+ # @return (see .dbus_attr_accessor)
177
+ def self.dbus_reader(ruby_name, type, dbus_name: nil)
178
+ raise UndefinedInterface, ruby_name if @@cur_intf.nil?
179
+
180
+ dbus_name = make_dbus_name(ruby_name, dbus_name: dbus_name)
181
+ property = Property.new(dbus_name, type, :read, ruby_name: ruby_name)
182
+ @@cur_intf.define(property)
183
+ end
184
+
185
+ # A write-only property accessing a writer method (which must already exist).
186
+ # (To directly access an instance variable, use {.dbus_attr_writer} instead)
187
+ #
188
+ # Uses {.dbus_watcher} to set up the PropertiesChanged signal.
189
+ #
190
+ # @param (see .dbus_attr_accessor)
191
+ # @return (see .dbus_attr_accessor)
192
+ def self.dbus_writer(ruby_name, type, dbus_name: nil)
193
+ raise UndefinedInterface, ruby_name if @@cur_intf.nil?
194
+
195
+ dbus_name = make_dbus_name(ruby_name, dbus_name: dbus_name)
196
+ property = Property.new(dbus_name, type, :write, ruby_name: ruby_name)
197
+ @@cur_intf.define(property)
198
+
199
+ dbus_watcher(ruby_name, dbus_name: dbus_name)
200
+ end
201
+
202
+ # Enables automatic sending of the PropertiesChanged signal.
203
+ # For *ruby_name* `foo_bar`, wrap `foo_bar=` so that it sends
204
+ # the signal for FooBar.
205
+ # The original version remains as `_original_foo_bar=`.
206
+ #
207
+ # @param ruby_name [Symbol] :foo_bar and :foo_bar= both mean the same thing
208
+ # @param dbus_name [String] if not given it is made
209
+ # by CamelCasing the ruby_name. foo_bar becomes FooBar
210
+ # to convert the Ruby convention to the DBus convention.
211
+ # @return [void]
212
+ def self.dbus_watcher(ruby_name, dbus_name: nil)
213
+ raise UndefinedInterface, ruby_name if @@cur_intf.nil?
214
+ cur_intf = @@cur_intf
215
+
216
+ ruby_name = ruby_name.to_s.sub(/=$/, "").to_sym
217
+ ruby_name_eq = "#{ruby_name}=".to_sym
218
+ original_ruby_name_eq = "_original_#{ruby_name_eq}"
219
+
220
+ dbus_name = make_dbus_name(ruby_name, dbus_name: dbus_name)
221
+
222
+ # the argument order is alias_method(new_name, existing_name)
223
+ alias_method original_ruby_name_eq, ruby_name_eq
224
+ define_method ruby_name_eq do |value|
225
+ public_send(original_ruby_name_eq, value)
226
+
227
+ # TODO: respect EmitsChangedSignal to use invalidated_properties instead
228
+ # PropertiesChanged, "interface:s, changed_properties:a{sv}, invalidated_properties:as"
229
+ PropertiesChanged(cur_intf.name, { dbus_name.to_s => value }, [])
92
230
  end
93
231
  end
94
232
 
95
233
  # Defines an exportable method on the object with the given name _sym_,
96
234
  # _prototype_ and the code in a block.
97
- def self.dbus_method(sym, protoype = "", &block)
235
+ # @param prototype [Prototype]
236
+ def self.dbus_method(sym, prototype = "", &block)
98
237
  raise UndefinedInterface, sym if @@cur_intf.nil?
99
- @@cur_intf.define(Method.new(sym.to_s).from_prototype(protoype))
100
- define_method(Object.make_method_name(@@cur_intf.name, sym.to_s), &block)
238
+ @@cur_intf.define(Method.new(sym.to_s).from_prototype(prototype))
239
+
240
+ ruby_name = Object.make_method_name(@@cur_intf.name, sym.to_s)
241
+ # ::Module#define_method(name) { body }
242
+ define_method(ruby_name, &block)
101
243
  end
102
244
 
103
245
  # Emits a signal from the object with the given _interface_, signal
104
246
  # _sig_ and arguments _args_.
247
+ # @param intf [Interface]
248
+ # @param sig [Signal]
249
+ # @param args arguments for the signal
105
250
  def emit(intf, sig, *args)
106
251
  @service.bus.emit(@service, self, intf, sig, *args)
107
252
  end
108
253
 
109
254
  # Defines a signal for the object with a given name _sym_ and _prototype_.
110
- def self.dbus_signal(sym, protoype = "")
255
+ def self.dbus_signal(sym, prototype = "")
111
256
  raise UndefinedInterface, sym if @@cur_intf.nil?
112
257
  cur_intf = @@cur_intf
113
- signal = Signal.new(sym.to_s).from_prototype(protoype)
114
- cur_intf.define(Signal.new(sym.to_s).from_prototype(protoype))
258
+ signal = Signal.new(sym.to_s).from_prototype(prototype)
259
+ cur_intf.define(Signal.new(sym.to_s).from_prototype(prototype))
260
+
261
+ # ::Module#define_method(name) { body }
115
262
  define_method(sym.to_s) do |*args|
116
263
  emit(cur_intf, signal, *args)
117
264
  end
118
265
  end
119
266
 
120
- ####################################################################
121
-
122
267
  # Helper method that returns a method name generated from the interface
123
268
  # name _intfname_ and method name _methname_.
124
269
  # @api private
125
270
  def self.make_method_name(intfname, methname)
126
271
  "#{intfname}%%#{methname}"
127
272
  end
273
+
274
+ # TODO: borrow a proven implementation
275
+ # @param str [String]
276
+ # @return [String]
277
+ # @api private
278
+ def self.camelize(str)
279
+ str.split(/_/).map(&:capitalize).join("")
280
+ end
281
+
282
+ # Make a D-Bus conventional name, CamelCased.
283
+ # @param ruby_name [String,Symbol] eg :do_something
284
+ # @param dbus_name [String,Symbol,nil] use this if given
285
+ # @return [Symbol] eg DoSomething
286
+ def self.make_dbus_name(ruby_name, dbus_name: nil)
287
+ dbus_name ||= camelize(ruby_name.to_s)
288
+ dbus_name.to_sym
289
+ end
290
+
291
+ # @param interface_name [String]
292
+ # @param property_name [String]
293
+ # @return [Property]
294
+ # @raise [DBus::Error]
295
+ # @api private
296
+ def dbus_lookup_property(interface_name, property_name)
297
+ # what should happen for unknown properties
298
+ # plasma: InvalidArgs (propname), UnknownInterface (interface)
299
+ # systemd: UnknownProperty
300
+ interface = intfs[interface_name]
301
+ if !interface
302
+ raise DBus.error("org.freedesktop.DBus.Error.UnknownProperty"),
303
+ "Property '#{interface_name}.#{property_name}' (on object '#{@path}') not found: no such interface"
304
+ end
305
+
306
+ property = interface.properties[property_name.to_sym]
307
+ if !property
308
+ raise DBus.error("org.freedesktop.DBus.Error.UnknownProperty"),
309
+ "Property '#{interface_name}.#{property_name}' (on object '#{@path}') not found"
310
+ end
311
+
312
+ property
313
+ end
314
+
315
+ ####################################################################
316
+
317
+ # use the above defined methods to declare the property-handling
318
+ # interfaces and methods
319
+
320
+ dbus_interface PROPERTY_INTERFACE do
321
+ dbus_method :Get, "in interface_name:s, in property_name:s, out value:v" do |interface_name, property_name|
322
+ property = dbus_lookup_property(interface_name, property_name)
323
+
324
+ if property.readable?
325
+ ruby_name = property.ruby_name
326
+ value = public_send(ruby_name)
327
+ [value]
328
+ else
329
+ raise DBus.error("org.freedesktop.DBus.Error.PropertyWriteOnly"),
330
+ "Property '#{interface_name}.#{property_name}' (on object '#{@path}') is not readable"
331
+ end
332
+ end
333
+
334
+ dbus_method :Set, "in interface_name:s, in property_name:s, in val:v" do |interface_name, property_name, value|
335
+ property = dbus_lookup_property(interface_name, property_name)
336
+
337
+ if property.writable?
338
+ ruby_name_eq = "#{property.ruby_name}="
339
+ public_send(ruby_name_eq, value)
340
+ else
341
+ raise DBus.error("org.freedesktop.DBus.Error.PropertyReadOnly"),
342
+ "Property '#{interface_name}.#{property_name}' (on object '#{@path}') is not writable"
343
+ end
344
+ end
345
+
346
+ dbus_method :GetAll, "in interface_name:s, out value:a{sv}" do |interface_name|
347
+ interface = intfs[interface_name]
348
+ if !interface
349
+ raise DBus.error("org.freedesktop.DBus.Error.UnknownProperty"),
350
+ "Properties '#{interface_name}.*' (on object '#{@path}') not found: no such interface"
351
+ end
352
+
353
+ p_hash = {}
354
+ interface.properties.each do |p_name, property|
355
+ next unless property.readable?
356
+
357
+ ruby_name = property.ruby_name
358
+ begin
359
+ # D-Bus spec says:
360
+ # > If GetAll is called with a valid interface name for which some
361
+ # > properties are not accessible to the caller (for example, due
362
+ # > to per-property access control implemented in the service),
363
+ # > those properties should be silently omitted from the result
364
+ # > array.
365
+ # so we will silently omit properties that fail to read.
366
+ # Get'ting them individually will send DBus.Error
367
+ p_hash[p_name.to_s] = public_send(ruby_name)
368
+ rescue StandardError
369
+ DBus.logger.debug "Property '#{interface_name}.#{p_name}' (on object '#{@path}')" \
370
+ " has raised during GetAll, omitting it"
371
+ end
372
+ end
373
+
374
+ [p_hash]
375
+ end
376
+
377
+ dbus_signal :PropertiesChanged, "interface:s, changed_properties:a{sv}, invalidated_properties:as"
378
+ end
128
379
  end
129
380
  end
@@ -44,6 +44,7 @@ module DBus
44
44
  end
45
45
 
46
46
  # Returns the interfaces of the object.
47
+ # @return [Array<String>] names of the interfaces
47
48
  def interfaces
48
49
  introspect unless introspected
49
50
  @interfaces.keys
@@ -129,6 +130,11 @@ module DBus
129
130
  ####################################################
130
131
  private
131
132
 
133
+ # rubocop:disable Style/MethodMissing
134
+ # but https://github.com/rubocop-hq/ruby-style-guide#no-method-missing
135
+ # and http://blog.marc-andre.ca/2010/11/15/methodmissing-politely/
136
+ # have a point to be investigated
137
+
132
138
  # Handles all unkown methods, mostly to route method calls to the
133
139
  # default interface.
134
140
  def method_missing(name, *args, &reply_handler)
@@ -150,5 +156,6 @@ module DBus
150
156
  raise NoMethodError, "undefined method `#{name}' for DBus interface `#{@default_iface}' on object `#{@path}'"
151
157
  end
152
158
  end
159
+ # rubocop:enable Style/MethodMissing
153
160
  end # class ProxyObject
154
161
  end
@@ -87,6 +87,7 @@ module DBus
87
87
  end
88
88
 
89
89
  # Defines a proxied method on the interface.
90
+ # Better name: declare_method
90
91
  def define_method(methodname, prototype)
91
92
  m = Method.new(methodname)
92
93
  m.from_prototype(prototype)
data/lib/dbus/type.rb CHANGED
@@ -9,6 +9,24 @@
9
9
  # See the file "COPYING" for the exact licensing terms.
10
10
 
11
11
  module DBus
12
+ # Like a {Signature} but containing only a single complete type.
13
+ #
14
+ # For documentation purposes only.
15
+ class SingleCompleteType < String; end
16
+
17
+ # Zero or more {SingleCompleteType}s; its own type code is "g".
18
+ # For example "ssv" for a method taking two Strings and a Variant/
19
+ #
20
+ # For documentation purposes only.
21
+ class Signature < String; end
22
+
23
+ # Similar to {Signature} but for {DBus::Object.define_method},
24
+ # contains names and direction of the parameters.
25
+ # For example "in query:s, in case_sensitive:b, out results:ao".
26
+ #
27
+ # For documentation purposes only.
28
+ class Prototype < String; end
29
+
12
30
  # = D-Bus type module
13
31
  #
14
32
  # This module containts the constants of the types specified in the D-Bus
data/ruby-dbus.gemspec CHANGED
@@ -18,15 +18,17 @@ GEMSPEC = Gem::Specification.new do |s|
18
18
  ]
19
19
  s.require_path = "lib"
20
20
 
21
- s.required_ruby_version = ">= 2.0.0"
21
+ s.required_ruby_version = ">= 2.1.0"
22
+
23
+ s.add_dependency "rexml"
22
24
 
23
25
  # This is optional
24
26
  # s.add_runtime_dependency "nokogiri"
25
27
 
26
- s.add_development_dependency "coveralls"
27
28
  s.add_development_dependency "packaging_rake_tasks"
28
29
  s.add_development_dependency "rake"
29
30
  s.add_development_dependency "rspec", "~> 3"
30
- s.add_development_dependency "rubocop", "= 0.41.2"
31
+ s.add_development_dependency "rubocop", "= 0.50.0"
31
32
  s.add_development_dependency "simplecov"
33
+ s.add_development_dependency "simplecov-lcov"
32
34
  end
@@ -70,7 +70,7 @@ describe "MainLoopTest" do
70
70
  @obj.on_signal "LongTaskEnd"
71
71
  end
72
72
 
73
- it "tests loop quit" do
73
+ it "tests loop quit", slow: true do
74
74
  test_loop_quit 1
75
75
  end
76
76
 
@@ -4,8 +4,8 @@ require "dbus"
4
4
 
5
5
  describe "PropertyTest" do
6
6
  before(:each) do
7
- session_bus = DBus::ASessionBus.new
8
- @svc = session_bus.service("org.ruby.service")
7
+ @session_bus = DBus::ASessionBus.new
8
+ @svc = @session_bus.service("org.ruby.service")
9
9
  @obj = @svc.object("/org/ruby/MyInstance")
10
10
  @iface = @obj["org.ruby.SampleInterface"]
11
11
  end
@@ -21,6 +21,10 @@ describe "PropertyTest" do
21
21
  expect(iface["ReadMe"]).to eq("READ ME")
22
22
  end
23
23
 
24
+ it "gets an error when reading a property whose implementation raises" do
25
+ expect { @iface["Explosive"] }.to raise_error(DBus::Error, /Something failed/)
26
+ end
27
+
24
28
  it "tests property nonreading" do
25
29
  expect { @iface["WriteMe"] }.to raise_error(DBus::Error, /not readable/)
26
30
  end
@@ -31,7 +35,7 @@ describe "PropertyTest" do
31
35
  end
32
36
 
33
37
  # https://github.com/mvidner/ruby-dbus/pull/19
34
- it "tests service select timeout" do
38
+ it "tests service select timeout", slow: true do
35
39
  @iface["ReadOrWriteMe"] = "VALUE"
36
40
  expect(@iface["ReadOrWriteMe"]).to eq("VALUE")
37
41
  # wait for the service to become idle
@@ -64,4 +68,50 @@ describe "PropertyTest" do
64
68
  it "tests unknown property writing" do
65
69
  expect { @iface["Spoon"] = "FPRK" }.to raise_error(DBus::Error, /not found/)
66
70
  end
71
+
72
+ it "errors for a property on an unknown interface" do
73
+ # our idiomatic way would error out on interface lookup already,
74
+ # so do it the low level way
75
+ prop_if = @obj[DBus::PROPERTY_INTERFACE]
76
+ expect { prop_if.Get("org.ruby.NoSuchInterface", "SomeProperty") }.to raise_error(DBus::Error) do |e|
77
+ expect(e.name).to match(/UnknownProperty/)
78
+ expect(e.message).to match(/no such interface/)
79
+ end
80
+ end
81
+
82
+ it "errors for GetAll on an unknown interface" do
83
+ # no idiomatic way?
84
+ # so do it the low level way
85
+ prop_if = @obj[DBus::PROPERTY_INTERFACE]
86
+ expect { prop_if.GetAll("org.ruby.NoSuchInterface") }.to raise_error(DBus::Error) do |e|
87
+ expect(e.name).to match(/UnknownProperty/)
88
+ expect(e.message).to match(/no such interface/)
89
+ end
90
+ end
91
+
92
+ it "receives a PropertiesChanged signal", slow: true do
93
+ received = {}
94
+
95
+ # TODO: for client side, provide a helper on_properties_changed,
96
+ # or automate it even more in ProxyObject, ProxyObjectInterface
97
+ prop_if = @obj[DBus::PROPERTY_INTERFACE]
98
+ prop_if.on_signal("PropertiesChanged") do |_interface_name, changed_props, _invalidated_props|
99
+ received.merge!(changed_props)
100
+ end
101
+
102
+ @iface["ReadOrWriteMe"] = "VALUE"
103
+
104
+ # loop to process the signal. complicated :-( see signal_spec.rb
105
+ loop = DBus::Main.new
106
+ loop << @session_bus
107
+ quitter = Thread.new do
108
+ sleep 1
109
+ loop.quit
110
+ end
111
+ loop.run
112
+ # quitter has told loop.run to quit
113
+ quitter.join
114
+
115
+ expect(received["ReadOrWriteMe"]).to eq("VALUE")
116
+ end
67
117
  end
@@ -59,6 +59,26 @@ class Test < DBus::Object
59
59
  dbus_method :mirror_byte_array, "in bytes:ay, out mirrored:ay" do |bytes|
60
60
  [bytes]
61
61
  end
62
+
63
+ # Properties:
64
+ # ReadMe:string, returns "READ ME" at first, then what WriteMe received
65
+ # WriteMe:string
66
+ # ReadOrWriteMe:string, returns "READ OR WRITE ME" at first
67
+ dbus_attr_accessor :read_or_write_me, "s"
68
+ dbus_attr_reader :read_me, "s"
69
+
70
+ def write_me=(value)
71
+ @read_me = value
72
+ end
73
+ dbus_writer :write_me, "s"
74
+
75
+ dbus_attr_writer :password, "s"
76
+
77
+ # a property that raises when client tries to read it
78
+ def explosive
79
+ raise "Something failed"
80
+ end
81
+ dbus_reader :explosive, "s"
62
82
  end
63
83
 
64
84
  # closing and reopening the same interface
@@ -118,72 +138,6 @@ class Test < DBus::Object
118
138
  dbus_signal :LongTaskStart
119
139
  dbus_signal :LongTaskEnd
120
140
  end
121
-
122
- # Properties:
123
- # ReadMe:string, returns "READ ME" at first, then what WriteMe received
124
- # WriteMe:string
125
- # ReadOrWriteMe:string, returns "READ OR WRITE ME" at first
126
- dbus_interface PROPERTY_INTERFACE do
127
- dbus_method :Get, "in interface:s, in propname:s, out value:v" do |interface, propname|
128
- unless interface == INTERFACE
129
- raise DBus.error("org.freedesktop.DBus.Error.UnknownInterface"),
130
- "Interface '#{interface}' not found on object '#{@path}'"
131
- end
132
-
133
- case propname
134
- when "ReadMe"
135
- [@read_me]
136
- when "ReadOrWriteMe"
137
- [@read_or_write_me]
138
- when "WriteMe"
139
- raise DBus.error("org.freedesktop.DBus.Error.InvalidArgs"),
140
- "Property '#{interface}.#{propname}' (on object '#{@path}') is not readable"
141
- else
142
- # what should happen for unknown properties
143
- # plasma: InvalidArgs (propname), UnknownInterface (interface)
144
- raise DBus.error("org.freedesktop.DBus.Error.InvalidArgs"),
145
- "Property '#{interface}.#{propname}' not found on object '#{@path}'"
146
- end
147
- end
148
-
149
- dbus_method :Set, "in interface:s, in propname:s, in value:v" do |interface, propname, value|
150
- unless interface == INTERFACE
151
- raise DBus.error("org.freedesktop.DBus.Error.UnknownInterface"),
152
- "Interface '#{interface}' not found on object '#{@path}'"
153
- end
154
-
155
- case propname
156
- when "ReadMe"
157
- raise DBus.error("org.freedesktop.DBus.Error.InvalidArgs"),
158
- "Property '#{interface}.#{propname}' (on object '#{@path}') is not writable"
159
- when "ReadOrWriteMe"
160
- @read_or_write_me = value
161
- self.PropertiesChanged(interface, { propname => value }, [])
162
- when "WriteMe"
163
- @read_me = value
164
- self.PropertiesChanged(interface, { "ReadMe" => value }, [])
165
- else
166
- raise DBus.error("org.freedesktop.DBus.Error.InvalidArgs"),
167
- "Property '#{interface}.#{propname}' not found on object '#{@path}'"
168
- end
169
- end
170
-
171
- dbus_method :GetAll, "in interface:s, out value:a{sv}" do |interface|
172
- unless interface == INTERFACE
173
- raise DBus.error("org.freedesktop.DBus.Error.UnknownInterface"),
174
- "Interface '#{interface}' not found on object '#{@path}'"
175
- end
176
-
177
- [
178
- {
179
- "ReadMe" => @read_me,
180
- "ReadOrWriteMe" => @read_or_write_me
181
- }
182
- ]
183
- end
184
-
185
- dbus_signal :PropertiesChanged, "interface:s, changed_properties:a{sv}, invalidated_properties:as"
186
- end
187
141
  end
188
142
 
189
143
  class Derived < Test
data/spec/signal_spec.rb CHANGED
@@ -29,7 +29,7 @@ describe "SignalHandlerTest" do
29
29
  end
30
30
 
31
31
  # testing for commit 017c83 (kkaempf)
32
- it "tests overriding a handler" do
32
+ it "tests overriding a handler", slow: true do
33
33
  DBus.logger.debug "Inside test_overriding_a_handler"
34
34
  counter = 0
35
35
 
@@ -52,7 +52,7 @@ describe "SignalHandlerTest" do
52
52
  expect(counter).to eq(1)
53
53
  end
54
54
 
55
- it "tests on signal overload" do
55
+ it "tests on signal overload", slow: true do
56
56
  DBus.logger.debug "Inside test_on_signal_overload"
57
57
  counter = 0
58
58
  started = false
@@ -74,7 +74,7 @@ describe "SignalHandlerTest" do
74
74
  expect { @intf.on_signal "to", "many", "yarrrrr!" }.to raise_error(ArgumentError)
75
75
  end
76
76
 
77
- it "is possible to add signal handlers from within handlers" do
77
+ it "is possible to add signal handlers from within handlers", slow: true do
78
78
  ended = false
79
79
  @intf.on_signal "LongTaskStart" do
80
80
  @intf.on_signal "LongTaskEnd" do
data/spec/spec_helper.rb CHANGED
@@ -2,8 +2,7 @@ coverage = if ENV["COVERAGE"]
2
2
  ENV["COVERAGE"] == "true"
3
3
  else
4
4
  # heuristics: enable for interactive builds (but not in OBS)
5
- # or in Travis
6
- ENV["DISPLAY"] || ENV["TRAVIS"]
5
+ ENV["DISPLAY"]
7
6
  end
8
7
 
9
8
  if coverage
@@ -15,11 +14,24 @@ if coverage
15
14
  # do not cover the activesupport helpers
16
15
  SimpleCov.add_filter "/core_ext/"
17
16
 
18
- # use coveralls for on-line code coverage reporting at Travis CI
19
- if ENV["TRAVIS"]
20
- require "coveralls"
21
- end
22
17
  SimpleCov.start
18
+
19
+ # additionally use the LCOV format for on-line code coverage reporting at CI
20
+ if ENV["COVERAGE_LCOV"] == "true"
21
+ require "simplecov-lcov"
22
+
23
+ SimpleCov::Formatter::LcovFormatter.config do |c|
24
+ c.report_with_single_file = true
25
+ # this is the default Coveralls GitHub Action location
26
+ # https://github.com/marketplace/actions/coveralls-github-action
27
+ c.single_report_path = "coverage/lcov.info"
28
+ end
29
+
30
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
31
+ SimpleCov::Formatter::HTMLFormatter,
32
+ SimpleCov::Formatter::LcovFormatter
33
+ ]
34
+ end
23
35
  end
24
36
 
25
37
  $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
@@ -25,4 +25,8 @@
25
25
  Instead, lower some so that we can test resource leaks. -->
26
26
  <limit name="max_match_rules_per_connection">50</limit><!-- was 512 -->
27
27
 
28
+ <!--
29
+ dbus-daemon[1700]: [session uid=1001 pid=1700] Unable to set up new connection: Failed to get AppArmor confinement information of socket peer: Protocol not available
30
+ -->
31
+ <apparmor mode="disabled"/>
28
32
  </busconfig>