ruby-dbus 0.18.1 → 0.20.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.
- checksums.yaml +4 -4
- data/NEWS.md +26 -0
- data/VERSION +1 -1
- data/examples/simple/get_id.rb +4 -2
- data/lib/dbus/auth.rb +305 -218
- data/lib/dbus/bus.rb +57 -15
- data/lib/dbus/introspect.rb +2 -1
- data/lib/dbus/marshall.rb +1 -1
- data/lib/dbus/message_queue.rb +19 -12
- data/lib/dbus/object.rb +31 -3
- data/lib/dbus/object_manager.rb +58 -0
- data/lib/dbus.rb +1 -0
- data/spec/auth_spec.rb +225 -0
- data/spec/node_spec.rb +46 -0
- data/spec/object_manager_spec.rb +33 -0
- data/spec/object_spec.rb +10 -0
- data/spec/proxy_object_interface_spec.rb +35 -0
- data/spec/server_robustness_spec.rb +18 -6
- data/spec/service_newapi.rb +34 -0
- data/spec/service_spec.rb +18 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/thread_safety_spec.rb +55 -12
- data/spec/tools/dbus-limited-session.conf +15 -0
- metadata +8 -4
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env rspec
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative "spec_helper"
|
5
|
+
require "dbus"
|
6
|
+
|
7
|
+
describe DBus::ProxyObjectInterface do
|
8
|
+
# TODO: tag tests that need a service, eg "needs-service"
|
9
|
+
# TODO: maybe remove this and rely on a packaged tool
|
10
|
+
around(:each) do |example|
|
11
|
+
with_private_bus do
|
12
|
+
with_service_by_activation(&example)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:bus) { DBus::ASessionBus.new }
|
17
|
+
|
18
|
+
context "when calling org.ruby.service" do
|
19
|
+
let(:svc) { bus["org.ruby.service"] }
|
20
|
+
|
21
|
+
# This is white box testing, knowing the implementation
|
22
|
+
# A better way would be structuring it according to the D-Bus Spec
|
23
|
+
# Or testing the service side doing the right thing? (What if our bugs cancel out)
|
24
|
+
describe "#define_method_from_descriptor" do
|
25
|
+
it "can call a method with multiple OUT arguments" do
|
26
|
+
obj = svc["/org/ruby/MyInstance"]
|
27
|
+
ifc = obj["org.ruby.SampleInterface"]
|
28
|
+
|
29
|
+
even, odd = ifc.EvenOdd([3, 1, 4, 1, 5, 9, 2, 6])
|
30
|
+
expect(even).to eq [4, 2, 6]
|
31
|
+
expect(odd).to eq [3, 1, 1, 5, 9]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -16,7 +16,7 @@ describe "ServerRobustnessTest" do
|
|
16
16
|
it "tests no such path with introspection" do
|
17
17
|
obj = @svc.object "/org/ruby/NotMyInstance"
|
18
18
|
expect { obj.introspect }.to raise_error(DBus::Error) do |e|
|
19
|
-
expect(e).to_not match(/timeout/)
|
19
|
+
expect(e.message).to_not match(/timeout/)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
@@ -25,7 +25,19 @@ describe "ServerRobustnessTest" do
|
|
25
25
|
ifc = DBus::ProxyObjectInterface.new(obj, "org.ruby.SampleInterface")
|
26
26
|
ifc.define_method("the_answer", "out n:i")
|
27
27
|
expect { ifc.the_answer }.to raise_error(DBus::Error) do |e|
|
28
|
-
expect(e).to_not match(/timeout/)
|
28
|
+
expect(e.message).to_not match(/timeout/)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "an existing path without an object" do
|
33
|
+
let(:obj) { @svc.object "/org" }
|
34
|
+
|
35
|
+
it "errors without a timeout" do
|
36
|
+
ifc = DBus::ProxyObjectInterface.new(obj, "org.ruby.SampleInterface")
|
37
|
+
ifc.define_method("the_answer", "out n:i")
|
38
|
+
expect { ifc.the_answer }.to raise_error(DBus::Error) do |e|
|
39
|
+
expect(e.message).to_not match(/timeout/)
|
40
|
+
end
|
29
41
|
end
|
30
42
|
end
|
31
43
|
|
@@ -33,7 +45,7 @@ describe "ServerRobustnessTest" do
|
|
33
45
|
obj = @svc.object "/org/ruby/MyInstance"
|
34
46
|
obj.default_iface = "org.ruby.SampleInterface"
|
35
47
|
expect { obj.will_raise }.to raise_error(DBus::Error) do |e|
|
36
|
-
expect(e).to_not match(/timeout/)
|
48
|
+
expect(e.message).to_not match(/timeout/)
|
37
49
|
end
|
38
50
|
end
|
39
51
|
|
@@ -41,7 +53,7 @@ describe "ServerRobustnessTest" do
|
|
41
53
|
obj = @svc.object "/org/ruby/MyInstance"
|
42
54
|
obj.default_iface = "org.ruby.SampleInterface"
|
43
55
|
expect { obj.will_raise_name_error }.to raise_error(DBus::Error) do |e|
|
44
|
-
expect(e).to_not match(/timeout/)
|
56
|
+
expect(e.message).to_not match(/timeout/)
|
45
57
|
end
|
46
58
|
end
|
47
59
|
|
@@ -51,7 +63,7 @@ describe "ServerRobustnessTest" do
|
|
51
63
|
ifc = DBus::ProxyObjectInterface.new(obj, "org.ruby.SampleInterface")
|
52
64
|
ifc.define_method("not_the_answer", "out n:i")
|
53
65
|
expect { ifc.not_the_answer }.to raise_error(DBus::Error) do |e|
|
54
|
-
expect(e).to_not match(/timeout/)
|
66
|
+
expect(e.message).to_not match(/timeout/)
|
55
67
|
end
|
56
68
|
end
|
57
69
|
|
@@ -60,7 +72,7 @@ describe "ServerRobustnessTest" do
|
|
60
72
|
ifc = DBus::ProxyObjectInterface.new(obj, "org.ruby.NoSuchInterface")
|
61
73
|
ifc.define_method("the_answer", "out n:i")
|
62
74
|
expect { ifc.the_answer }.to raise_error(DBus::Error) do |e|
|
63
|
-
expect(e).to_not match(/timeout/)
|
75
|
+
expect(e.message).to_not match(/timeout/)
|
64
76
|
end
|
65
77
|
end
|
66
78
|
end
|
data/spec/service_newapi.rb
CHANGED
@@ -10,11 +10,24 @@ require "dbus"
|
|
10
10
|
|
11
11
|
PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties"
|
12
12
|
|
13
|
+
class TestChild < DBus::Object
|
14
|
+
def initialize(opath)
|
15
|
+
@name = opath.split("/").last.capitalize
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
dbus_interface "org.ruby.TestChild" do
|
20
|
+
dbus_attr_reader :name, "s"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
13
24
|
class Test < DBus::Object
|
14
25
|
Point2D = Struct.new(:x, :y)
|
15
26
|
|
16
27
|
attr_writer :main_loop
|
17
28
|
|
29
|
+
include DBus::ObjectManager
|
30
|
+
|
18
31
|
INTERFACE = "org.ruby.SampleInterface"
|
19
32
|
def initialize(path)
|
20
33
|
super path
|
@@ -89,6 +102,12 @@ class Test < DBus::Object
|
|
89
102
|
[coords]
|
90
103
|
end
|
91
104
|
|
105
|
+
# Two OUT arguments
|
106
|
+
dbus_method :EvenOdd, "in numbers:ai, out even:ai, out odd:ai" do |numbers|
|
107
|
+
even, odd = numbers.partition(&:even?)
|
108
|
+
[even, odd]
|
109
|
+
end
|
110
|
+
|
92
111
|
# Properties:
|
93
112
|
# ReadMe:string, returns "READ ME" at first, then what WriteMe received
|
94
113
|
# WriteMe:string
|
@@ -155,6 +174,21 @@ class Test < DBus::Object
|
|
155
174
|
end
|
156
175
|
end
|
157
176
|
|
177
|
+
dbus_interface "org.ruby.TestParent" do
|
178
|
+
dbus_method :New, "in name:s, out opath:o" do |name|
|
179
|
+
child = TestChild.new("#{path}/#{name}")
|
180
|
+
@service.export(child)
|
181
|
+
[child.path]
|
182
|
+
end
|
183
|
+
|
184
|
+
dbus_method :Delete, "in opath:o" do |opath|
|
185
|
+
raise ArgumentError unless opath.start_with?(path)
|
186
|
+
|
187
|
+
obj = @service.get_node(opath)&.object
|
188
|
+
@service.unexport(obj)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
158
192
|
dbus_interface "org.ruby.Duplicates" do
|
159
193
|
dbus_method :the_answer, "out answer:i" do
|
160
194
|
[0]
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env rspec
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative "spec_helper"
|
5
|
+
require "dbus"
|
6
|
+
|
7
|
+
describe "DBus::Service (server role)" do
|
8
|
+
let(:bus) { DBus::ASessionBus.new }
|
9
|
+
# This is the client role, but the server role API is bad
|
10
|
+
# and for the one test there is no difference
|
11
|
+
let(:service) { bus["org.ruby.service"] }
|
12
|
+
|
13
|
+
describe "#descendants_for" do
|
14
|
+
it "raises for not existing path" do
|
15
|
+
expect { service.descendants_for("/notthere") }.to raise_error(ArgumentError)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -31,7 +31,7 @@ if coverage
|
|
31
31
|
c.single_report_path = "coverage/lcov.info"
|
32
32
|
end
|
33
33
|
|
34
|
-
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
34
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new [
|
35
35
|
SimpleCov::Formatter::HTMLFormatter,
|
36
36
|
SimpleCov::Formatter::LcovFormatter
|
37
37
|
]
|
data/spec/thread_safety_spec.rb
CHANGED
@@ -5,28 +5,71 @@
|
|
5
5
|
require_relative "spec_helper"
|
6
6
|
require "dbus"
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
class TestSignalRace < DBus::Object
|
9
|
+
dbus_interface "org.ruby.ServerTest" do
|
10
|
+
dbus_signal :signal_without_arguments
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Run *count* threads all doing *body*, wait for their finish
|
15
|
+
def race_threads(count, &body)
|
16
|
+
jobs = count.times.map do |j|
|
17
|
+
Thread.new do
|
18
|
+
Thread.current.abort_on_exception = true
|
19
|
+
|
20
|
+
body.call(j)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
jobs.each(&:join)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Repeat *count* times: { random sleep, *body* }, printing progress
|
27
|
+
def repeat_with_jitter(count, &body)
|
28
|
+
count.times do |i|
|
29
|
+
sleep 0.1 * rand
|
30
|
+
print "#{i} "
|
31
|
+
$stdout.flush
|
15
32
|
|
33
|
+
body.call
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "thread safety" do
|
38
|
+
context "R/W: when the threads call methods with return values" do
|
39
|
+
it "it works with separate bus connections" do
|
40
|
+
race_threads(5) do |_j|
|
16
41
|
# use separate connections to avoid races
|
17
42
|
bus = DBus::ASessionBus.new
|
18
43
|
svc = bus.service("org.ruby.service")
|
19
44
|
obj = svc.object("/org/ruby/MyInstance")
|
20
45
|
obj.default_iface = "org.ruby.SampleInterface"
|
21
46
|
|
22
|
-
10
|
23
|
-
print "#{i} "
|
24
|
-
$stdout.flush
|
47
|
+
repeat_with_jitter(10) do
|
25
48
|
expect(obj.the_answer[0]).to eq(42)
|
26
|
-
sleep 0.1 * rand
|
27
49
|
end
|
28
50
|
end
|
51
|
+
puts
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "W/O: when the threads only send signals" do
|
56
|
+
it "it works with a shared separate bus connection" do
|
57
|
+
race_threads(5) do |j|
|
58
|
+
# shared connection
|
59
|
+
bus = DBus::SessionBus.instance
|
60
|
+
# hackish: we do not actually request the name
|
61
|
+
svc = DBus::Service.new("org.ruby.server-test#{j}", bus)
|
62
|
+
|
63
|
+
obj = TestSignalRace.new "/org/ruby/Foo"
|
64
|
+
svc.export obj
|
65
|
+
|
66
|
+
repeat_with_jitter(10) do
|
67
|
+
obj.signal_without_arguments
|
68
|
+
end
|
69
|
+
|
70
|
+
svc.unexport(obj)
|
71
|
+
end
|
72
|
+
puts
|
29
73
|
end
|
30
|
-
jobs.each(&:join)
|
31
74
|
end
|
32
75
|
end
|
@@ -7,6 +7,20 @@
|
|
7
7
|
<!-- Our well-known bus type, don't change this -->
|
8
8
|
<type>session</type>
|
9
9
|
|
10
|
+
<!-- Authentication:
|
11
|
+
This was useful during refactoring, but meanwhile RSpec mocking has
|
12
|
+
replaced it. -->
|
13
|
+
<!-- Explicitly list all known authentication mechanisms,
|
14
|
+
their order is not important.
|
15
|
+
By default the daemon allows all but this lets me disable some. -->
|
16
|
+
<auth>EXTERNAL</auth>
|
17
|
+
<auth>DBUS_COOKIE_SHA1</auth>
|
18
|
+
<auth>ANONYMOUS</auth>
|
19
|
+
<!-- Insecure, other users could call us and exploit debug APIs/bugs -->
|
20
|
+
<!--
|
21
|
+
<allow_anonymous/>
|
22
|
+
-->
|
23
|
+
|
10
24
|
<listen>unix:tmpdir=/tmp</listen>
|
11
25
|
<listen>tcp:host=127.0.0.1</listen>
|
12
26
|
|
@@ -24,6 +38,7 @@
|
|
24
38
|
<!-- Do not increase the limits.
|
25
39
|
Instead, lower some so that we can test resource leaks. -->
|
26
40
|
<limit name="max_match_rules_per_connection">50</limit><!-- was 512 -->
|
41
|
+
<limit name="reply_timeout">5000</limit><!-- 5 seconds -->
|
27
42
|
|
28
43
|
<!--
|
29
44
|
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
|
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.
|
4
|
+
version: 0.20.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ruby DBus Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-03-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rexml
|
@@ -155,6 +155,7 @@ files:
|
|
155
155
|
- lib/dbus/message.rb
|
156
156
|
- lib/dbus/message_queue.rb
|
157
157
|
- lib/dbus/object.rb
|
158
|
+
- lib/dbus/object_manager.rb
|
158
159
|
- lib/dbus/object_path.rb
|
159
160
|
- lib/dbus/proxy_object.rb
|
160
161
|
- lib/dbus/proxy_object_factory.rb
|
@@ -164,6 +165,7 @@ files:
|
|
164
165
|
- lib/dbus/xml.rb
|
165
166
|
- ruby-dbus.gemspec
|
166
167
|
- spec/async_spec.rb
|
168
|
+
- spec/auth_spec.rb
|
167
169
|
- spec/binding_spec.rb
|
168
170
|
- spec/bus_and_xml_backend_spec.rb
|
169
171
|
- spec/bus_driver_spec.rb
|
@@ -179,15 +181,18 @@ files:
|
|
179
181
|
- spec/introspection_spec.rb
|
180
182
|
- spec/main_loop_spec.rb
|
181
183
|
- spec/node_spec.rb
|
184
|
+
- spec/object_manager_spec.rb
|
182
185
|
- spec/object_path_spec.rb
|
183
186
|
- spec/object_spec.rb
|
184
187
|
- spec/packet_marshaller_spec.rb
|
185
188
|
- spec/packet_unmarshaller_spec.rb
|
186
189
|
- spec/property_spec.rb
|
190
|
+
- spec/proxy_object_interface_spec.rb
|
187
191
|
- spec/proxy_object_spec.rb
|
188
192
|
- spec/server_robustness_spec.rb
|
189
193
|
- spec/server_spec.rb
|
190
194
|
- spec/service_newapi.rb
|
195
|
+
- spec/service_spec.rb
|
191
196
|
- spec/session_bus_spec.rb
|
192
197
|
- spec/session_bus_spec_manual.rb
|
193
198
|
- spec/signal_spec.rb
|
@@ -220,8 +225,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
220
225
|
- !ruby/object:Gem::Version
|
221
226
|
version: '0'
|
222
227
|
requirements: []
|
223
|
-
|
224
|
-
rubygems_version: 2.7.6.3
|
228
|
+
rubygems_version: 3.3.0.dev
|
225
229
|
signing_key:
|
226
230
|
specification_version: 4
|
227
231
|
summary: Ruby module for interaction with D-Bus
|