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.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/NEWS.md +288 -3
  3. data/README.md +3 -5
  4. data/Rakefile +27 -12
  5. data/VERSION +1 -1
  6. data/doc/Reference.md +109 -10
  7. data/examples/doc/_extract_examples +7 -0
  8. data/examples/no-bus/pulseaudio.rb +50 -0
  9. data/examples/no-introspect/nm-test.rb +2 -0
  10. data/examples/no-introspect/tracker-test.rb +3 -1
  11. data/examples/rhythmbox/playpause.rb +2 -1
  12. data/examples/service/call_service.rb +2 -1
  13. data/examples/service/complex-property.rb +21 -0
  14. data/examples/service/service_newapi.rb +3 -3
  15. data/examples/simple/call_introspect.rb +1 -0
  16. data/examples/simple/get_id.rb +6 -3
  17. data/examples/simple/properties.rb +2 -0
  18. data/examples/utils/listnames.rb +10 -1
  19. data/examples/utils/notify.rb +1 -0
  20. data/lib/dbus/api_options.rb +9 -0
  21. data/lib/dbus/auth.rb +307 -217
  22. data/lib/dbus/bus.rb +155 -588
  23. data/lib/dbus/bus_name.rb +12 -8
  24. data/lib/dbus/connection.rb +363 -0
  25. data/lib/dbus/core_ext/class/attribute.rb +1 -1
  26. data/lib/dbus/data.rb +821 -0
  27. data/lib/dbus/emits_changed_signal.rb +83 -0
  28. data/lib/dbus/error.rb +4 -2
  29. data/lib/dbus/introspect.rb +133 -31
  30. data/lib/dbus/logger.rb +6 -3
  31. data/lib/dbus/main.rb +66 -0
  32. data/lib/dbus/marshall.rb +247 -296
  33. data/lib/dbus/matchrule.rb +16 -16
  34. data/lib/dbus/message.rb +66 -57
  35. data/lib/dbus/message_queue.rb +40 -25
  36. data/lib/dbus/node_tree.rb +105 -0
  37. data/lib/dbus/object.rb +442 -33
  38. data/lib/dbus/object_manager.rb +61 -0
  39. data/lib/dbus/object_path.rb +11 -6
  40. data/lib/dbus/object_server.rb +149 -0
  41. data/lib/dbus/org.freedesktop.DBus.xml +97 -0
  42. data/lib/dbus/platform.rb +26 -0
  43. data/lib/dbus/proxy_object.rb +30 -11
  44. data/lib/dbus/proxy_object_factory.rb +13 -7
  45. data/lib/dbus/proxy_object_interface.rb +63 -30
  46. data/lib/dbus/proxy_service.rb +107 -0
  47. data/lib/dbus/raw_message.rb +91 -0
  48. data/lib/dbus/type.rb +319 -86
  49. data/lib/dbus/xml.rb +40 -19
  50. data/lib/dbus.rb +28 -17
  51. data/ruby-dbus.gemspec +13 -6
  52. data/spec/async_spec.rb +2 -0
  53. data/spec/auth_spec.rb +225 -0
  54. data/spec/binding_spec.rb +2 -0
  55. data/spec/bus_and_xml_backend_spec.rb +5 -1
  56. data/spec/bus_connection_spec.rb +93 -0
  57. data/spec/bus_name_spec.rb +3 -1
  58. data/spec/bus_spec.rb +2 -0
  59. data/spec/byte_array_spec.rb +2 -0
  60. data/spec/client_robustness_spec.rb +4 -2
  61. data/spec/connection_spec.rb +37 -0
  62. data/spec/coverage_helper.rb +39 -0
  63. data/spec/data/marshall.yaml +1667 -0
  64. data/spec/data_spec.rb +673 -0
  65. data/spec/dbus_spec.rb +22 -0
  66. data/spec/emits_changed_signal_spec.rb +58 -0
  67. data/spec/err_msg_spec.rb +2 -0
  68. data/spec/introspect_xml_parser_spec.rb +2 -0
  69. data/spec/introspection_spec.rb +2 -0
  70. data/spec/main_loop_spec.rb +17 -1
  71. data/spec/message_spec.rb +21 -0
  72. data/spec/mock-service/cockpit-dbustests.rb +29 -0
  73. data/spec/mock-service/com.redhat.Cockpit.DBusTests.xml +180 -0
  74. data/spec/mock-service/org.ruby.service.service +4 -0
  75. data/spec/mock-service/org.rubygems.ruby_dbus.DBusTests.service +4 -0
  76. data/spec/{service_newapi.rb → mock-service/spaghetti-monster.rb} +122 -75
  77. data/spec/node_spec.rb +65 -0
  78. data/spec/object_manager_spec.rb +33 -0
  79. data/spec/object_path_spec.rb +3 -0
  80. data/spec/object_server_spec.rb +138 -0
  81. data/spec/object_spec.rb +194 -0
  82. data/spec/packet_marshaller_spec.rb +41 -0
  83. data/spec/packet_unmarshaller_spec.rb +248 -0
  84. data/spec/platform_spec.rb +14 -0
  85. data/spec/property_spec.rb +214 -12
  86. data/spec/proxy_object_interface_spec.rb +35 -0
  87. data/spec/proxy_object_spec.rb +2 -0
  88. data/spec/{bus_driver_spec.rb → proxy_service_spec.rb} +15 -8
  89. data/spec/raw_message_spec.rb +32 -0
  90. data/spec/server_robustness_spec.rb +20 -6
  91. data/spec/session_bus_spec.rb +36 -1
  92. data/spec/session_bus_spec_manual.rb +2 -0
  93. data/spec/signal_spec.rb +16 -3
  94. data/spec/spec_helper.rb +25 -33
  95. data/spec/thread_safety_spec.rb +55 -12
  96. data/spec/tools/dbus-launch-simple +9 -6
  97. data/spec/tools/dbus-limited-session.conf +32 -0
  98. data/spec/tools/test_env +26 -6
  99. data/spec/type_spec.rb +214 -6
  100. data/spec/value_spec.rb +16 -1
  101. data/spec/variant_spec.rb +4 -2
  102. data/spec/zzz_quit_spec.rb +16 -0
  103. metadata +92 -20
  104. data/examples/gdbus/gdbus +0 -257
  105. data/examples/gdbus/gdbus.glade +0 -98
  106. data/examples/gdbus/launch.sh +0 -4
  107. data/spec/server_spec.rb +0 -53
  108. 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
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env rspec
2
+ # frozen_string_literal: true
3
+
2
4
  # should report it missing on org.ruby.SampleInterface
3
5
  # (on object...) instead of on DBus::Proxy::ObjectInterface
4
6
  require_relative "spec_helper"
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env rspec
2
+ # frozen_string_literal: true
3
+
2
4
  require_relative "spec_helper"
3
5
  require "dbus"
4
6
 
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env rspec
2
+ # frozen_string_literal: true
3
+
2
4
  require_relative "spec_helper"
3
5
  require "dbus"
4
6
 
@@ -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
+ -->
@@ -0,0 +1,4 @@
1
+ [D-BUS Service]
2
+ Name=org.ruby.service
3
+ # ... will replace the directory with the current one
4
+ Exec=/usr/bin/spaghetti-monster.rb
@@ -0,0 +1,4 @@
1
+ [D-BUS Service]
2
+ Name=org.rubygems.ruby_dbus.DBusTests
3
+ # ... will replace the directory with the current one
4
+ Exec=/usr/bin/cockpit-dbustests.rb
@@ -1,25 +1,63 @@
1
1
  #!/usr/bin/env ruby
2
- # -*- coding: utf-8 -*-
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", __FILE__)
13
+ $LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
8
14
 
9
15
  require "dbus"
10
16
 
11
- PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties".freeze
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
- INTERFACE = "org.ruby.SampleInterface".freeze
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.request_service("org.ruby.service")
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
- puts "listening, with ruby-#{RUBY_VERSION}"
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