ruby-dbus 0.16.0 → 0.25.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 +288 -3
- data/README.md +3 -5
- data/Rakefile +27 -12
- data/VERSION +1 -1
- data/doc/Reference.md +109 -10
- data/examples/doc/_extract_examples +7 -0
- data/examples/no-bus/pulseaudio.rb +50 -0
- data/examples/no-introspect/nm-test.rb +2 -0
- data/examples/no-introspect/tracker-test.rb +3 -1
- data/examples/rhythmbox/playpause.rb +2 -1
- data/examples/service/call_service.rb +2 -1
- data/examples/service/complex-property.rb +21 -0
- data/examples/service/service_newapi.rb +3 -3
- data/examples/simple/call_introspect.rb +1 -0
- data/examples/simple/get_id.rb +6 -3
- data/examples/simple/properties.rb +2 -0
- data/examples/utils/listnames.rb +10 -1
- data/examples/utils/notify.rb +1 -0
- data/lib/dbus/api_options.rb +9 -0
- data/lib/dbus/auth.rb +307 -217
- data/lib/dbus/bus.rb +155 -588
- data/lib/dbus/bus_name.rb +12 -8
- data/lib/dbus/connection.rb +363 -0
- data/lib/dbus/core_ext/class/attribute.rb +1 -1
- data/lib/dbus/data.rb +821 -0
- data/lib/dbus/emits_changed_signal.rb +83 -0
- data/lib/dbus/error.rb +4 -2
- data/lib/dbus/introspect.rb +133 -31
- data/lib/dbus/logger.rb +6 -3
- data/lib/dbus/main.rb +66 -0
- data/lib/dbus/marshall.rb +247 -296
- data/lib/dbus/matchrule.rb +16 -16
- data/lib/dbus/message.rb +66 -57
- data/lib/dbus/message_queue.rb +40 -25
- data/lib/dbus/node_tree.rb +105 -0
- data/lib/dbus/object.rb +442 -33
- data/lib/dbus/object_manager.rb +61 -0
- data/lib/dbus/object_path.rb +11 -6
- data/lib/dbus/object_server.rb +149 -0
- data/lib/dbus/org.freedesktop.DBus.xml +97 -0
- data/lib/dbus/platform.rb +26 -0
- data/lib/dbus/proxy_object.rb +30 -11
- data/lib/dbus/proxy_object_factory.rb +13 -7
- data/lib/dbus/proxy_object_interface.rb +63 -30
- data/lib/dbus/proxy_service.rb +107 -0
- data/lib/dbus/raw_message.rb +91 -0
- data/lib/dbus/type.rb +319 -86
- data/lib/dbus/xml.rb +40 -19
- data/lib/dbus.rb +28 -17
- data/ruby-dbus.gemspec +13 -6
- data/spec/async_spec.rb +2 -0
- data/spec/auth_spec.rb +225 -0
- data/spec/binding_spec.rb +2 -0
- data/spec/bus_and_xml_backend_spec.rb +5 -1
- data/spec/bus_connection_spec.rb +93 -0
- data/spec/bus_name_spec.rb +3 -1
- data/spec/bus_spec.rb +2 -0
- data/spec/byte_array_spec.rb +2 -0
- data/spec/client_robustness_spec.rb +4 -2
- data/spec/connection_spec.rb +37 -0
- data/spec/coverage_helper.rb +39 -0
- data/spec/data/marshall.yaml +1667 -0
- data/spec/data_spec.rb +673 -0
- data/spec/dbus_spec.rb +22 -0
- data/spec/emits_changed_signal_spec.rb +58 -0
- data/spec/err_msg_spec.rb +2 -0
- data/spec/introspect_xml_parser_spec.rb +2 -0
- data/spec/introspection_spec.rb +2 -0
- data/spec/main_loop_spec.rb +17 -1
- data/spec/message_spec.rb +21 -0
- data/spec/mock-service/cockpit-dbustests.rb +29 -0
- data/spec/mock-service/com.redhat.Cockpit.DBusTests.xml +180 -0
- data/spec/mock-service/org.ruby.service.service +4 -0
- data/spec/mock-service/org.rubygems.ruby_dbus.DBusTests.service +4 -0
- data/spec/{service_newapi.rb → mock-service/spaghetti-monster.rb} +122 -75
- data/spec/node_spec.rb +65 -0
- data/spec/object_manager_spec.rb +33 -0
- data/spec/object_path_spec.rb +3 -0
- data/spec/object_server_spec.rb +138 -0
- data/spec/object_spec.rb +194 -0
- data/spec/packet_marshaller_spec.rb +41 -0
- data/spec/packet_unmarshaller_spec.rb +248 -0
- data/spec/platform_spec.rb +14 -0
- data/spec/property_spec.rb +214 -12
- data/spec/proxy_object_interface_spec.rb +35 -0
- data/spec/proxy_object_spec.rb +2 -0
- data/spec/{bus_driver_spec.rb → proxy_service_spec.rb} +15 -8
- data/spec/raw_message_spec.rb +32 -0
- data/spec/server_robustness_spec.rb +20 -6
- data/spec/session_bus_spec.rb +36 -1
- data/spec/session_bus_spec_manual.rb +2 -0
- data/spec/signal_spec.rb +16 -3
- data/spec/spec_helper.rb +25 -33
- data/spec/thread_safety_spec.rb +55 -12
- data/spec/tools/dbus-launch-simple +9 -6
- data/spec/tools/dbus-limited-session.conf +32 -0
- data/spec/tools/test_env +26 -6
- data/spec/type_spec.rb +214 -6
- data/spec/value_spec.rb +16 -1
- data/spec/variant_spec.rb +4 -2
- data/spec/zzz_quit_spec.rb +16 -0
- metadata +92 -20
- data/examples/gdbus/gdbus +0 -257
- data/examples/gdbus/gdbus.glade +0 -98
- data/examples/gdbus/launch.sh +0 -4
- data/spec/server_spec.rb +0 -53
- data/spec/tools/test_server +0 -39
|
@@ -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/err_msg_spec.rb
CHANGED
data/spec/introspection_spec.rb
CHANGED
data/spec/main_loop_spec.rb
CHANGED
|
@@ -1,8 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env rspec
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
2
4
|
# Test the main loop
|
|
3
5
|
require_relative "spec_helper"
|
|
4
6
|
require "dbus"
|
|
5
7
|
|
|
8
|
+
describe "DBus.logger" do
|
|
9
|
+
it "will log debug messages if $DEBUG is true" do
|
|
10
|
+
logger_old = DBus.logger
|
|
11
|
+
DBus.logger = nil
|
|
12
|
+
debug_old = $DEBUG
|
|
13
|
+
$DEBUG = true
|
|
14
|
+
|
|
15
|
+
DBus.logger.debug "this debug message will always be shown"
|
|
16
|
+
|
|
17
|
+
$DEBUG = debug_old
|
|
18
|
+
DBus.logger = logger_old
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
6
22
|
describe "MainLoopTest" do
|
|
7
23
|
before(:each) do
|
|
8
24
|
@session_bus = DBus::ASessionBus.new
|
|
@@ -70,7 +86,7 @@ describe "MainLoopTest" do
|
|
|
70
86
|
@obj.on_signal "LongTaskEnd"
|
|
71
87
|
end
|
|
72
88
|
|
|
73
|
-
it "tests loop quit" do
|
|
89
|
+
it "tests loop quit", slow: true do
|
|
74
90
|
test_loop_quit 1
|
|
75
91
|
end
|
|
76
92
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env rspec
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "spec_helper"
|
|
5
|
+
require "dbus"
|
|
6
|
+
|
|
7
|
+
# Pedantic full coverage test.
|
|
8
|
+
# The happy paths are covered via calling classes
|
|
9
|
+
describe DBus::Message do
|
|
10
|
+
describe "#marshall" do
|
|
11
|
+
it "raises when the object path is /org/freedesktop/DBus/Local" do
|
|
12
|
+
m = DBus::Message.new(DBus::Message::SIGNAL)
|
|
13
|
+
# the path is valid, it just must not be sent
|
|
14
|
+
m.path = DBus::ObjectPath.new("/org/freedesktop/DBus/Local")
|
|
15
|
+
m.interface = "org.example.spam"
|
|
16
|
+
m.member = "Spam"
|
|
17
|
+
|
|
18
|
+
expect { m.marshall }.to raise_error(RuntimeError, /Cannot send a message with the reserved path/)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "../coverage_helper"
|
|
5
|
+
SimpleCov.command_name "Cockpit Tests (#{Process.pid})" if Object.const_defined? "SimpleCov"
|
|
6
|
+
|
|
7
|
+
# find the library without external help
|
|
8
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
|
9
|
+
require "dbus"
|
|
10
|
+
|
|
11
|
+
SERVICE_NAME = "org.rubygems.ruby_dbus.DBusTests"
|
|
12
|
+
ROOT_OPATH = "/otree/frobber"
|
|
13
|
+
|
|
14
|
+
class DBusTests < DBus::Object
|
|
15
|
+
FROBBER_INTERFACE = "com.redhat.Cockpit.DBusTests.Frobber"
|
|
16
|
+
|
|
17
|
+
dbus_interface FROBBER_INTERFACE do
|
|
18
|
+
dbus_method :HelloWorld, "in greeting:s, out response:s" do |greeting|
|
|
19
|
+
# TODO: return the same thing as the original implementation
|
|
20
|
+
# and try substituting it?
|
|
21
|
+
[format("Word! You said `%s'. I'm Skeleton, btw!", greeting)]
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
bus = DBus::SessionBus.instance
|
|
27
|
+
bus.object_server.export(DBusTests.new(ROOT_OPATH))
|
|
28
|
+
bus.request_name(SERVICE_NAME)
|
|
29
|
+
DBus::Main.new.tap { |m| m << bus }.run
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
<node>
|
|
2
|
+
<!--
|
|
3
|
+
This file is part of Cockpit.
|
|
4
|
+
|
|
5
|
+
Copyright (C) 2013 Red Hat, Inc.
|
|
6
|
+
|
|
7
|
+
Cockpit is free software; you can redistribute it and/or modify it
|
|
8
|
+
under the terms of the GNU Lesser General Public License as published by
|
|
9
|
+
the Free Software Foundation; either version 2.1 of the License, or
|
|
10
|
+
(at your option) any later version.
|
|
11
|
+
|
|
12
|
+
Cockpit is distributed in the hope that it will be useful, but
|
|
13
|
+
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
15
|
+
Lesser General Public License for more details.
|
|
16
|
+
|
|
17
|
+
You should have received a copy of the GNU Lesser General Public License
|
|
18
|
+
along with Cockpit; If not, see <http://www.gnu.org/licenses/>.
|
|
19
|
+
-->
|
|
20
|
+
|
|
21
|
+
<interface name="com.redhat.Cockpit.DBusTests.Alpha">
|
|
22
|
+
</interface>
|
|
23
|
+
|
|
24
|
+
<interface name="com.redhat.Cockpit.DBusTests.Frobber">
|
|
25
|
+
<method name="HelloWorld">
|
|
26
|
+
<arg name="greeting" direction="in" type="s"/>
|
|
27
|
+
<arg name="response" direction="out" type="s"/>
|
|
28
|
+
</method>
|
|
29
|
+
|
|
30
|
+
<method name="NeverReturn">
|
|
31
|
+
</method>
|
|
32
|
+
|
|
33
|
+
<method name="TestPrimitiveTypes">
|
|
34
|
+
<arg direction="in" type="y" name="val_byte" />
|
|
35
|
+
<arg direction="in" type="b" name="val_boolean" />
|
|
36
|
+
<arg direction="in" type="n" name="val_int16" />
|
|
37
|
+
<arg direction="in" type="q" name="val_uint16" />
|
|
38
|
+
<arg direction="in" type="i" name="val_int32" />
|
|
39
|
+
<arg direction="in" type="u" name="val_uint32" />
|
|
40
|
+
<arg direction="in" type="x" name="val_int64" />
|
|
41
|
+
<arg direction="in" type="t" name="val_uint64" />
|
|
42
|
+
<arg direction="in" type="d" name="val_double" />
|
|
43
|
+
<arg direction="in" type="s" name="val_string" />
|
|
44
|
+
<arg direction="in" type="o" name="val_objpath" />
|
|
45
|
+
<arg direction="in" type="g" name="val_signature" />
|
|
46
|
+
<arg direction="in" type="ay" name="val_bytestring" />
|
|
47
|
+
<arg direction="out" type="y" name="ret_byte" />
|
|
48
|
+
<arg direction="out" type="b" name="ret_boolean" />
|
|
49
|
+
<arg direction="out" type="n" name="ret_int16" />
|
|
50
|
+
<arg direction="out" type="q" name="ret_uint16" />
|
|
51
|
+
<arg direction="out" type="i" name="ret_int32" />
|
|
52
|
+
<arg direction="out" type="u" name="ret_uint32" />
|
|
53
|
+
<arg direction="out" type="x" name="ret_int64" />
|
|
54
|
+
<arg direction="out" type="t" name="ret_uint64" />
|
|
55
|
+
<arg direction="out" type="d" name="ret_double" />
|
|
56
|
+
<arg direction="out" type="s" name="ret_string" />
|
|
57
|
+
<arg direction="out" type="o" name="ret_objpath" />
|
|
58
|
+
<arg direction="out" type="g" name="ret_signature" />
|
|
59
|
+
<arg direction="out" type="ay" name="ret_bytestring" />
|
|
60
|
+
</method>
|
|
61
|
+
|
|
62
|
+
<method name="TestNonPrimitiveTypes">
|
|
63
|
+
<arg direction="in" type="a{ss}" name="dict_s_to_s" />
|
|
64
|
+
<arg direction="in" type="a{s(ii)}" name="dict_s_to_pairs" />
|
|
65
|
+
<arg direction="in" type="(iss)" name="a_struct" />
|
|
66
|
+
<arg direction="in" type="as" name="array_of_strings" />
|
|
67
|
+
<arg direction="in" type="ao" name="array_of_objpaths" />
|
|
68
|
+
<arg direction="in" type="ag" name="array_of_signatures" />
|
|
69
|
+
<arg direction="in" type="aay" name="array_of_bytestrings" />
|
|
70
|
+
<arg direction="out" type="s" name="result" />
|
|
71
|
+
</method>
|
|
72
|
+
|
|
73
|
+
<method name="TestAsv">
|
|
74
|
+
<arg direction="in" type="a{sv}" name="asv" />
|
|
75
|
+
<arg direction="out" type="s" name="result" />
|
|
76
|
+
</method>
|
|
77
|
+
|
|
78
|
+
<method name="TestVariant">
|
|
79
|
+
<arg direction="in" type="v" name="v" />
|
|
80
|
+
</method>
|
|
81
|
+
|
|
82
|
+
<method name="RequestSignalEmission">
|
|
83
|
+
<arg direction="in" type="i" name="which_one" />
|
|
84
|
+
</method>
|
|
85
|
+
|
|
86
|
+
<method name="RequestPropertyMods"/>
|
|
87
|
+
|
|
88
|
+
<method name="RequestMultiPropertyMods"/>
|
|
89
|
+
|
|
90
|
+
<method name="UnimplementedMethod"/>
|
|
91
|
+
|
|
92
|
+
<method name="PropertyCancellation"/>
|
|
93
|
+
|
|
94
|
+
<signal name="TestSignal">
|
|
95
|
+
<arg type="i" name="val_int32"/>
|
|
96
|
+
<arg type="as" name="array_of_strings" />
|
|
97
|
+
<arg type="ao" name="array_of_objpaths" />
|
|
98
|
+
<arg type="a{s(ii)}" name="dict_s_to_pairs" />
|
|
99
|
+
</signal>
|
|
100
|
+
|
|
101
|
+
<signal name="AnotherSignal">
|
|
102
|
+
<arg type="s" name="word" />
|
|
103
|
+
</signal>
|
|
104
|
+
|
|
105
|
+
<method name="DeleteAllObjects"/>
|
|
106
|
+
|
|
107
|
+
<method name="CreateObject">
|
|
108
|
+
<arg direction="in" type="o" name="at_path" />
|
|
109
|
+
</method>
|
|
110
|
+
|
|
111
|
+
<method name="DeleteObject">
|
|
112
|
+
<arg direction="in" type="o" name="path" />
|
|
113
|
+
</method>
|
|
114
|
+
|
|
115
|
+
<method name="AddAlpha"/>
|
|
116
|
+
<method name="RemoveAlpha"/>
|
|
117
|
+
|
|
118
|
+
<method name="CreateClique">
|
|
119
|
+
<arg direction="in" type="s" name="name" />
|
|
120
|
+
<arg direction="out" type="o" name="member" />
|
|
121
|
+
</method>
|
|
122
|
+
|
|
123
|
+
<method name="EmitHidden">
|
|
124
|
+
<arg direction="in" type="s" name="name" />
|
|
125
|
+
</method>
|
|
126
|
+
|
|
127
|
+
<method name="ClaimOtherName">
|
|
128
|
+
<arg name="name" direction="in" type="s"/>
|
|
129
|
+
</method>
|
|
130
|
+
|
|
131
|
+
<method name="ReleaseOtherName">
|
|
132
|
+
<arg name="name" direction="in" type="s"/>
|
|
133
|
+
</method>
|
|
134
|
+
|
|
135
|
+
<method name="TellMeYourName">
|
|
136
|
+
<arg direction="out" name="name" type="s"/>
|
|
137
|
+
</method>
|
|
138
|
+
|
|
139
|
+
<method name="MakeTestFd">
|
|
140
|
+
<arg direction="in" name="type" type="s"/>
|
|
141
|
+
<arg direction="out" name="fd" type="h"/>
|
|
142
|
+
</method>
|
|
143
|
+
|
|
144
|
+
<property name="y" type="y" access="readwrite"/>
|
|
145
|
+
<property name="b" type="b" access="readwrite"/>
|
|
146
|
+
<property name="n" type="n" access="readwrite"/>
|
|
147
|
+
<property name="q" type="q" access="readwrite"/>
|
|
148
|
+
<property name="i" type="i" access="readwrite"/>
|
|
149
|
+
<property name="u" type="u" access="readwrite"/>
|
|
150
|
+
<property name="x" type="x" access="readwrite"/>
|
|
151
|
+
<property name="t" type="t" access="readwrite"/>
|
|
152
|
+
<property name="d" type="d" access="readwrite"/>
|
|
153
|
+
<property name="s" type="s" access="readwrite"/>
|
|
154
|
+
<property name="o" type="o" access="readwrite"/>
|
|
155
|
+
<property name="g" type="g" access="readwrite"/>
|
|
156
|
+
<property name="ay" type="ay" access="readwrite"/>
|
|
157
|
+
<property name="as" type="as" access="readwrite"/>
|
|
158
|
+
<property name="aay" type="aay" access="readwrite"/>
|
|
159
|
+
<property name="ao" type="ao" access="readwrite"/>
|
|
160
|
+
<property name="ag" type="ag" access="readwrite"/>
|
|
161
|
+
<property name="FinallyNormalName" type="s" access="readwrite"/>
|
|
162
|
+
<property name="ReadonlyProperty" type="s" access="read"/>
|
|
163
|
+
<property name="WriteonlyProperty" type="s" access="write"/>
|
|
164
|
+
</interface>
|
|
165
|
+
|
|
166
|
+
<interface name="com.redhat.Cockpit.DBusTests.Clique">
|
|
167
|
+
<property name="Friend" type="o" access="read"/>
|
|
168
|
+
</interface>
|
|
169
|
+
|
|
170
|
+
<interface name="com.redhat.Cockpit.DBusTests.Hidden">
|
|
171
|
+
<property name="Name" type="s" access="read"/>
|
|
172
|
+
</interface>
|
|
173
|
+
|
|
174
|
+
</node>
|
|
175
|
+
|
|
176
|
+
<!--
|
|
177
|
+
Local Variables:
|
|
178
|
+
indent-tabs-mode: nil
|
|
179
|
+
End:
|
|
180
|
+
-->
|
|
@@ -1,25 +1,63 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
|
-
#
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# This file was formerly named spec/service_newapi.rb, after the example
|
|
5
|
+
# which it mutated from.
|
|
6
|
+
# Spaghetti monster is a better name,
|
|
7
|
+
# reflecting on its evolution and current nature :'-)
|
|
8
|
+
|
|
9
|
+
require_relative "../coverage_helper"
|
|
10
|
+
SimpleCov.command_name "Service Tests (#{Process.pid})" if Object.const_defined? "SimpleCov"
|
|
3
11
|
|
|
4
|
-
require_relative "spec_helper"
|
|
5
|
-
SimpleCov.command_name "Service Tests" if Object.const_defined? "SimpleCov"
|
|
6
12
|
# find the library without external help
|
|
7
|
-
$LOAD_PATH.unshift File.expand_path("../../lib",
|
|
13
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
|
|
8
14
|
|
|
9
15
|
require "dbus"
|
|
10
16
|
|
|
11
|
-
|
|
17
|
+
SERVICE_NAME = "org.ruby.service"
|
|
18
|
+
|
|
19
|
+
class TestChild < DBus::Object
|
|
20
|
+
def initialize(opath)
|
|
21
|
+
@name = opath.split("/").last.capitalize
|
|
22
|
+
super
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
dbus_interface "org.ruby.TestChild" do
|
|
26
|
+
dbus_reader_attr_accessor :name, "s"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
12
29
|
|
|
13
30
|
class Test < DBus::Object
|
|
14
|
-
|
|
31
|
+
Point2D = Struct.new(:x, :y)
|
|
32
|
+
|
|
33
|
+
attr_writer :main_loop
|
|
34
|
+
|
|
35
|
+
include DBus::ObjectManager
|
|
36
|
+
|
|
37
|
+
INTERFACE = "org.ruby.SampleInterface"
|
|
15
38
|
def initialize(path)
|
|
16
39
|
super path
|
|
17
40
|
@read_me = "READ ME"
|
|
18
41
|
@read_or_write_me = "READ OR WRITE ME"
|
|
42
|
+
@my_struct = ["three", "strings", "in a struct"].freeze
|
|
43
|
+
@my_array = [42, 43]
|
|
44
|
+
@my_dict = {
|
|
45
|
+
"one" => 1,
|
|
46
|
+
"two" => "dva",
|
|
47
|
+
"three" => [3, 3, 3]
|
|
48
|
+
}
|
|
49
|
+
@my_variant = @my_array.dup
|
|
50
|
+
# 201 is a RET instruction for ZX Spectrum which has turned 40 recently
|
|
51
|
+
@my_byte = 201
|
|
52
|
+
@main_loop = nil
|
|
19
53
|
end
|
|
20
54
|
|
|
21
55
|
# Create an interface aggregating all upcoming dbus_method defines.
|
|
22
56
|
dbus_interface INTERFACE do
|
|
57
|
+
dbus_method :quit, "" do
|
|
58
|
+
@main_loop&.quit
|
|
59
|
+
end
|
|
60
|
+
|
|
23
61
|
dbus_method :hello, "in name:s, in name2:s" do |name, name2|
|
|
24
62
|
puts "hello(#{name}, #{name2})"
|
|
25
63
|
end
|
|
@@ -59,6 +97,60 @@ class Test < DBus::Object
|
|
|
59
97
|
dbus_method :mirror_byte_array, "in bytes:ay, out mirrored:ay" do |bytes|
|
|
60
98
|
[bytes]
|
|
61
99
|
end
|
|
100
|
+
|
|
101
|
+
dbus_method :Coordinates, "out coords:(dd)" do
|
|
102
|
+
coords = [3.0, 4.0].freeze
|
|
103
|
+
[coords]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
dbus_method :Coordinates2, "out coords:(dd)" do
|
|
107
|
+
coords = Point2D.new(5.0, 12.0)
|
|
108
|
+
[coords]
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Two OUT arguments
|
|
112
|
+
dbus_method :EvenOdd, "in numbers:ai, out even:ai, out odd:ai" do |numbers|
|
|
113
|
+
even, odd = numbers.partition(&:even?)
|
|
114
|
+
[even, odd]
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Properties:
|
|
118
|
+
# ReadMe:string, returns "READ ME" at first, then what WriteMe received
|
|
119
|
+
# WriteMe:string
|
|
120
|
+
# ReadOrWriteMe:string, returns "READ OR WRITE ME" at first
|
|
121
|
+
dbus_attr_accessor :read_or_write_me, "s"
|
|
122
|
+
dbus_attr_reader :read_me, "s"
|
|
123
|
+
|
|
124
|
+
def write_me=(value)
|
|
125
|
+
raise "We don't talk about Bruno" if value =~ /Bruno/
|
|
126
|
+
|
|
127
|
+
@read_me = value
|
|
128
|
+
end
|
|
129
|
+
dbus_writer :write_me, "s"
|
|
130
|
+
|
|
131
|
+
dbus_attr_writer :password, "s"
|
|
132
|
+
|
|
133
|
+
# a property that raises when client tries to read it
|
|
134
|
+
def explosive
|
|
135
|
+
raise "Something failed"
|
|
136
|
+
end
|
|
137
|
+
dbus_reader :explosive, "s"
|
|
138
|
+
|
|
139
|
+
dbus_attr_accessor :my_struct, "(sss)"
|
|
140
|
+
dbus_attr_accessor :my_array, "aq"
|
|
141
|
+
dbus_attr_accessor :my_dict, "a{sv}"
|
|
142
|
+
dbus_attr_accessor :my_variant, "v"
|
|
143
|
+
|
|
144
|
+
dbus_attr_accessor :my_byte, "y"
|
|
145
|
+
|
|
146
|
+
# to test dbus_properties_changed
|
|
147
|
+
dbus_method :SetTwoProperties, "in read_me:s, in byte:y" do |read_me, byte|
|
|
148
|
+
@read_me = read_me
|
|
149
|
+
@my_byte = byte
|
|
150
|
+
dbus_properties_changed(INTERFACE,
|
|
151
|
+
{ "ReadMe" => read_me, "MyByte" => byte },
|
|
152
|
+
[])
|
|
153
|
+
end
|
|
62
154
|
end
|
|
63
155
|
|
|
64
156
|
# closing and reopening the same interface
|
|
@@ -90,11 +182,29 @@ class Test < DBus::Object
|
|
|
90
182
|
end
|
|
91
183
|
end
|
|
92
184
|
|
|
185
|
+
dbus_interface "org.ruby.TestParent" do
|
|
186
|
+
dbus_method :New, "in name:s, out opath:o" do |name|
|
|
187
|
+
child = TestChild.new("#{path}/#{name}")
|
|
188
|
+
object_server.export(child)
|
|
189
|
+
[child.path]
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
dbus_method :Delete, "in opath:o" do |opath|
|
|
193
|
+
raise ArgumentError unless opath.start_with?(path)
|
|
194
|
+
|
|
195
|
+
object_server.unexport(opath)
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
93
199
|
dbus_interface "org.ruby.Duplicates" do
|
|
94
200
|
dbus_method :the_answer, "out answer:i" do
|
|
95
201
|
[0]
|
|
96
202
|
end
|
|
203
|
+
|
|
97
204
|
dbus_method :interfaces, "out answer:i" do
|
|
205
|
+
# 'Shadowed' from the Ruby side, meaning ProxyObject#interfaces
|
|
206
|
+
# will return the list of interfaces rather than calling this method.
|
|
207
|
+
# Calling it with busctl will work just fine.
|
|
98
208
|
raise "This DBus method is currently shadowed by ProxyObject#interfaces"
|
|
99
209
|
end
|
|
100
210
|
end
|
|
@@ -118,72 +228,6 @@ class Test < DBus::Object
|
|
|
118
228
|
dbus_signal :LongTaskStart
|
|
119
229
|
dbus_signal :LongTaskEnd
|
|
120
230
|
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
231
|
end
|
|
188
232
|
|
|
189
233
|
class Derived < Test
|
|
@@ -198,13 +242,14 @@ class Test2 < DBus::Object
|
|
|
198
242
|
end
|
|
199
243
|
|
|
200
244
|
bus = DBus::SessionBus.instance
|
|
201
|
-
service = bus.
|
|
245
|
+
service = bus.object_server
|
|
202
246
|
myobj = Test.new("/org/ruby/MyInstance")
|
|
203
247
|
service.export(myobj)
|
|
204
248
|
derived = Derived.new "/org/ruby/MyDerivedInstance"
|
|
205
249
|
service.export derived
|
|
206
250
|
test2 = Test2.new "/org/ruby/MyInstance2"
|
|
207
251
|
service.export test2
|
|
252
|
+
bus.request_name(SERVICE_NAME)
|
|
208
253
|
|
|
209
254
|
# introspect every other connection, Ticket #34
|
|
210
255
|
# (except the one that activates us - it has already emitted
|
|
@@ -221,11 +266,13 @@ bus.add_match(mr) do |msg|
|
|
|
221
266
|
end
|
|
222
267
|
end
|
|
223
268
|
|
|
224
|
-
|
|
269
|
+
DBus.logger.info "Service #{SERVICE_NAME} listening, with ruby-#{RUBY_VERSION}"
|
|
225
270
|
main = DBus::Main.new
|
|
226
271
|
main << bus
|
|
272
|
+
myobj.main_loop = main
|
|
227
273
|
begin
|
|
228
274
|
main.run
|
|
229
|
-
rescue SystemCallError
|
|
275
|
+
rescue SystemCallError, SignalException => e
|
|
276
|
+
DBus.logger.info "Service #{SERVICE_NAME} got #{e.inspect}, exiting"
|
|
230
277
|
# the test driver will kill the bus, that's OK
|
|
231
278
|
end
|