ruby-dbus 0.15.0 → 0.18.0.beta1

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 (69) hide show
  1. checksums.yaml +5 -5
  2. data/NEWS.md +41 -1
  3. data/README.md +3 -5
  4. data/Rakefile +18 -8
  5. data/VERSION +1 -1
  6. data/doc/Reference.md +93 -3
  7. data/examples/doc/_extract_examples +7 -0
  8. data/examples/gdbus/gdbus +31 -24
  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/service_newapi.rb +1 -1
  14. data/examples/simple/call_introspect.rb +1 -0
  15. data/examples/simple/get_id.rb +2 -1
  16. data/examples/simple/properties.rb +2 -0
  17. data/examples/utils/listnames.rb +1 -0
  18. data/examples/utils/notify.rb +1 -0
  19. data/lib/dbus/api_options.rb +9 -0
  20. data/lib/dbus/auth.rb +20 -15
  21. data/lib/dbus/bus.rb +129 -74
  22. data/lib/dbus/bus_name.rb +31 -0
  23. data/lib/dbus/core_ext/class/attribute.rb +1 -1
  24. data/lib/dbus/error.rb +4 -2
  25. data/lib/dbus/introspect.rb +90 -34
  26. data/lib/dbus/logger.rb +3 -1
  27. data/lib/dbus/marshall.rb +119 -87
  28. data/lib/dbus/matchrule.rb +16 -16
  29. data/lib/dbus/message.rb +40 -27
  30. data/lib/dbus/message_queue.rb +26 -18
  31. data/lib/dbus/object.rb +401 -0
  32. data/lib/dbus/object_path.rb +28 -0
  33. data/lib/dbus/proxy_object.rb +23 -2
  34. data/lib/dbus/proxy_object_factory.rb +11 -7
  35. data/lib/dbus/proxy_object_interface.rb +26 -21
  36. data/lib/dbus/type.rb +59 -34
  37. data/lib/dbus/xml.rb +28 -17
  38. data/lib/dbus.rb +10 -8
  39. data/ruby-dbus.gemspec +8 -4
  40. data/spec/async_spec.rb +2 -0
  41. data/spec/binding_spec.rb +2 -0
  42. data/spec/bus_and_xml_backend_spec.rb +2 -0
  43. data/spec/bus_driver_spec.rb +2 -0
  44. data/spec/bus_name_spec.rb +27 -0
  45. data/spec/bus_spec.rb +2 -0
  46. data/spec/byte_array_spec.rb +2 -0
  47. data/spec/client_robustness_spec.rb +27 -0
  48. data/spec/err_msg_spec.rb +2 -0
  49. data/spec/introspect_xml_parser_spec.rb +2 -0
  50. data/spec/introspection_spec.rb +2 -0
  51. data/spec/main_loop_spec.rb +3 -1
  52. data/spec/node_spec.rb +23 -0
  53. data/spec/object_path_spec.rb +25 -0
  54. data/spec/property_spec.rb +64 -5
  55. data/spec/proxy_object_spec.rb +2 -0
  56. data/spec/server_robustness_spec.rb +2 -0
  57. data/spec/server_spec.rb +2 -0
  58. data/spec/service_newapi.rb +39 -70
  59. data/spec/session_bus_spec.rb +3 -1
  60. data/spec/session_bus_spec_manual.rb +2 -0
  61. data/spec/signal_spec.rb +5 -3
  62. data/spec/spec_helper.rb +23 -9
  63. data/spec/thread_safety_spec.rb +2 -0
  64. data/spec/tools/dbus-limited-session.conf +4 -0
  65. data/spec/type_spec.rb +2 -0
  66. data/spec/value_spec.rb +16 -1
  67. data/spec/variant_spec.rb +4 -2
  68. metadata +32 -12
  69. data/lib/dbus/export.rb +0 -131
data/lib/dbus/type.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # dbus/type.rb - module containing low-level D-Bus data type information
2
4
  #
3
5
  # This file is part of the ruby-dbus project
@@ -9,13 +11,31 @@
9
11
  # See the file "COPYING" for the exact licensing terms.
10
12
 
11
13
  module DBus
14
+ # Like a {Signature} but containing only a single complete type.
15
+ #
16
+ # For documentation purposes only.
17
+ class SingleCompleteType < String; end
18
+
19
+ # Zero or more {SingleCompleteType}s; its own type code is "g".
20
+ # For example "ssv" for a method taking two Strings and a Variant/
21
+ #
22
+ # For documentation purposes only.
23
+ class Signature < String; end
24
+
25
+ # Similar to {Signature} but for {DBus::Object.define_method},
26
+ # contains names and direction of the parameters.
27
+ # For example "in query:s, in case_sensitive:b, out results:ao".
28
+ #
29
+ # For documentation purposes only.
30
+ class Prototype < String; end
31
+
12
32
  # = D-Bus type module
13
33
  #
14
34
  # This module containts the constants of the types specified in the D-Bus
15
35
  # protocol.
16
36
  module Type
17
37
  # Mapping from type number to name and alignment.
18
- TypeMapping = {
38
+ TYPE_MAPPING = {
19
39
  0 => ["INVALID", nil],
20
40
  "y" => ["BYTE", 1],
21
41
  "b" => ["BOOLEAN", 4],
@@ -36,7 +56,7 @@ module DBus
36
56
  "h" => ["UNIX_FD", 4]
37
57
  }.freeze
38
58
  # Defines the set of constants
39
- TypeMapping.each_pair do |key, value|
59
+ TYPE_MAPPING.each_pair do |key, value|
40
60
  Type.const_set(value.first, key)
41
61
  end
42
62
 
@@ -55,16 +75,17 @@ module DBus
55
75
 
56
76
  # Create a new type instance for type number _sigtype_.
57
77
  def initialize(sigtype)
58
- if !TypeMapping.keys.member?(sigtype)
78
+ if !TYPE_MAPPING.keys.member?(sigtype)
59
79
  raise SignatureException, "Unknown key in signature: #{sigtype.chr}"
60
80
  end
81
+
61
82
  @sigtype = sigtype
62
83
  @members = []
63
84
  end
64
85
 
65
86
  # Return the required alignment for the type.
66
87
  def alignment
67
- TypeMapping[@sigtype].last
88
+ TYPE_MAPPING[@sigtype].last
68
89
  end
69
90
 
70
91
  # Return a string representation of the type according to the
@@ -72,36 +93,38 @@ module DBus
72
93
  def to_s
73
94
  case @sigtype
74
95
  when STRUCT
75
- "(" + @members.collect(&:to_s).join + ")"
96
+ "(#{@members.collect(&:to_s).join})"
76
97
  when ARRAY
77
- "a" + child.to_s
98
+ "a#{child}"
78
99
  when DICT_ENTRY
79
- "{" + @members.collect(&:to_s).join + "}"
100
+ "{#{@members.collect(&:to_s).join}}"
80
101
  else
81
- if !TypeMapping.keys.member?(@sigtype)
102
+ if !TYPE_MAPPING.keys.member?(@sigtype)
82
103
  raise NotImplementedError
83
104
  end
105
+
84
106
  @sigtype.chr
85
107
  end
86
108
  end
87
109
 
88
- # Add a new member type _a_.
89
- def <<(a)
110
+ # Add a new member type _item_.
111
+ def <<(item)
90
112
  if ![STRUCT, ARRAY, DICT_ENTRY].member?(@sigtype)
91
113
  raise SignatureException
92
114
  end
93
115
  raise SignatureException if @sigtype == ARRAY && !@members.empty?
116
+
94
117
  if @sigtype == DICT_ENTRY
95
- if @members.size == 2
118
+ case @members.size
119
+ when 2
96
120
  raise SignatureException, "Dict entries have exactly two members"
97
- end
98
- if @members.empty?
99
- if [STRUCT, ARRAY, DICT_ENTRY].member?(a.sigtype)
121
+ when 0
122
+ if [STRUCT, ARRAY, DICT_ENTRY].member?(item.sigtype)
100
123
  raise SignatureException, "Dict entry keys must be basic types"
101
124
  end
102
125
  end
103
126
  end
104
- @members << a
127
+ @members << item
105
128
  end
106
129
 
107
130
  # Return the first contained member type.
@@ -110,19 +133,20 @@ module DBus
110
133
  end
111
134
 
112
135
  def inspect
113
- s = TypeMapping[@sigtype].first
136
+ s = TYPE_MAPPING[@sigtype].first
114
137
  if [STRUCT, ARRAY].member?(@sigtype)
115
- s += ": " + @members.inspect
138
+ s += ": #{@members.inspect}"
116
139
  end
117
140
  s
118
141
  end
119
- end # class Type
142
+ end
120
143
 
121
144
  # = D-Bus type parser class
122
145
  #
123
146
  # Helper class to parse a type signature in the protocol.
124
147
  class Parser
125
148
  # Create a new parser for the given _signature_.
149
+ # @param signature [Signature]
126
150
  def initialize(signature)
127
151
  @signature = signature
128
152
  @idx = 0
@@ -135,30 +159,31 @@ module DBus
135
159
  c
136
160
  end
137
161
 
138
- # Parse one character _c_ of the signature.
139
- def parse_one(c)
162
+ # Parse one character _char_ of the signature.
163
+ def parse_one(char)
140
164
  res = nil
141
- case c
165
+ case char
142
166
  when "a"
143
167
  res = Type.new(ARRAY)
144
- c = nextchar
145
- raise SignatureException, "Parse error in #{@signature}" if c.nil?
146
- child = parse_one(c)
168
+ char = nextchar
169
+ raise SignatureException, "Parse error in #{@signature}" if char.nil?
170
+
171
+ child = parse_one(char)
147
172
  res << child
148
173
  when "("
149
174
  res = Type.new(STRUCT)
150
- while (c = nextchar) && c != ")"
151
- res << parse_one(c)
175
+ while (char = nextchar) && char != ")"
176
+ res << parse_one(char)
152
177
  end
153
- raise SignatureException, "Parse error in #{@signature}" if c.nil?
178
+ raise SignatureException, "Parse error in #{@signature}" if char.nil?
154
179
  when "{"
155
180
  res = Type.new(DICT_ENTRY)
156
- while (c = nextchar) && c != "}"
157
- res << parse_one(c)
181
+ while (char = nextchar) && char != "}"
182
+ res << parse_one(char)
158
183
  end
159
- raise SignatureException, "Parse error in #{@signature}" if c.nil?
184
+ raise SignatureException, "Parse error in #{@signature}" if char.nil?
160
185
  else
161
- res = Type.new(c)
186
+ res = Type.new(char)
162
187
  end
163
188
  res
164
189
  end
@@ -172,8 +197,8 @@ module DBus
172
197
  end
173
198
  ret
174
199
  end
175
- end # class Parser
176
- end # module Type
200
+ end
201
+ end
177
202
 
178
203
  # shortcuts
179
204
 
@@ -188,4 +213,4 @@ module DBus
188
213
  [type(string_type), value]
189
214
  end
190
215
  module_function :variant
191
- end # module DBus
216
+ end
data/lib/dbus/xml.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # dbus/xml.rb - introspection parser, rexml/nokogiri abstraction
2
4
  #
3
5
  # This file is part of the ruby-dbus project
@@ -26,14 +28,23 @@ module DBus
26
28
  attr_accessor :backend
27
29
  end
28
30
  # Creates a new parser for XML data in string _xml_.
31
+ # @param xml [String]
29
32
  def initialize(xml)
30
33
  @xml = xml
31
34
  end
32
35
 
33
36
  class AbstractXML
37
+ # @!method initialize(xml)
38
+ # @abstract
39
+
40
+ # @!method each(xpath)
41
+ # @abstract
42
+ # yields nodes which match xpath of type AbstractXML::Node
43
+
34
44
  def self.have_nokogiri?
35
45
  Object.const_defined?("Nokogiri")
36
46
  end
47
+
37
48
  class Node
38
49
  def initialize(node)
39
50
  @node = node
@@ -46,12 +57,6 @@ module DBus
46
57
  # yields child nodes which match xpath of type AbstractXML::Node
47
58
  def each(xpath); end
48
59
  end
49
- # required methods
50
- # initialize parser with xml string
51
- def initialize(xml); end
52
-
53
- # yields nodes which match xpath of type AbstractXML::Node
54
- def each(xpath); end
55
60
  end
56
61
 
57
62
  class NokogiriParser < AbstractXML
@@ -64,7 +69,9 @@ module DBus
64
69
  @node.search(path).each { |node| block.call NokogiriNode.new(node) }
65
70
  end
66
71
  end
72
+
67
73
  def initialize(xml)
74
+ super()
68
75
  @doc = Nokogiri.XML(xml)
69
76
  end
70
77
 
@@ -83,7 +90,9 @@ module DBus
83
90
  @node.elements.each(path) { |node| block.call REXMLNode.new(node) }
84
91
  end
85
92
  end
93
+
86
94
  def initialize(xml)
95
+ super()
87
96
  @doc = REXML::Document.new(xml)
88
97
  end
89
98
 
@@ -136,28 +145,30 @@ module DBus
136
145
  ######################################################################
137
146
  private
138
147
 
139
- # Parses a method signature XML element _e_ and initialises
140
- # method/signal _m_.
141
- def parse_methsig(e, m)
142
- e.each("arg") do |ae|
148
+ # Parses a method signature XML element *elem* and initialises
149
+ # method/signal *methsig*.
150
+ # @param elem [AbstractXML::Node]
151
+ def parse_methsig(elem, methsig)
152
+ elem.each("arg") do |ae|
143
153
  name = ae["name"]
144
154
  dir = ae["direction"]
145
155
  sig = ae["type"]
146
- if m.is_a?(DBus::Signal)
156
+ case methsig
157
+ when DBus::Signal
147
158
  # Direction can only be "out", ignore it
148
- m.add_fparam(name, sig)
149
- elsif m.is_a?(DBus::Method)
159
+ methsig.add_fparam(name, sig)
160
+ when DBus::Method
150
161
  case dir
151
162
  # This is a method, so dir defaults to "in"
152
163
  when "in", nil
153
- m.add_fparam(name, sig)
164
+ methsig.add_fparam(name, sig)
154
165
  when "out"
155
- m.add_return(name, sig)
166
+ methsig.add_return(name, sig)
156
167
  end
157
168
  else
158
169
  raise NotImplementedError, dir
159
170
  end
160
171
  end
161
172
  end
162
- end # class IntrospectXMLParser
163
- end # module DBus
173
+ end
174
+ end
data/lib/dbus.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # dbus.rb - Module containing the low-level D-Bus implementation
2
4
  #
3
5
  # This file is part of the ruby-dbus project
@@ -11,14 +13,16 @@
11
13
  require_relative "dbus/api_options"
12
14
  require_relative "dbus/auth"
13
15
  require_relative "dbus/bus"
16
+ require_relative "dbus/bus_name"
14
17
  require_relative "dbus/error"
15
- require_relative "dbus/export"
16
18
  require_relative "dbus/introspect"
17
19
  require_relative "dbus/logger"
18
20
  require_relative "dbus/marshall"
19
21
  require_relative "dbus/matchrule"
20
22
  require_relative "dbus/message"
21
23
  require_relative "dbus/message_queue"
24
+ require_relative "dbus/object"
25
+ require_relative "dbus/object_path"
22
26
  require_relative "dbus/proxy_object"
23
27
  require_relative "dbus/proxy_object_factory"
24
28
  require_relative "dbus/proxy_object_interface"
@@ -26,22 +30,20 @@ require_relative "dbus/type"
26
30
  require_relative "dbus/xml"
27
31
 
28
32
  require "socket"
29
- require "thread"
30
-
31
33
  # = D-Bus main module
32
34
  #
33
35
  # Module containing all the D-Bus modules and classes.
34
36
  module DBus
35
37
  # Default socket name for the system bus.
36
- SystemSocketName = "unix:path=/var/run/dbus/system_bus_socket".freeze
38
+ SYSTEM_BUS_ADDRESS = "unix:path=/var/run/dbus/system_bus_socket"
37
39
 
38
40
  # Byte signifying big endianness.
39
- BIG_END = "B".freeze
41
+ BIG_END = "B"
40
42
  # Byte signifying little endianness.
41
- LIL_END = "l".freeze
43
+ LIL_END = "l"
42
44
 
43
45
  # Byte signifying the host's endianness.
44
- HOST_END = if [0x01020304].pack("L").unpack("V")[0] == 0x01020304
46
+ HOST_END = if [0x01020304].pack("L").unpack1("V") == 0x01020304
45
47
  LIL_END
46
48
  else
47
49
  BIG_END
@@ -67,4 +69,4 @@ module DBus
67
69
  # Exception raised when invalid introspection data is parsed/used.
68
70
  class InvalidIntrospectionData < Exception
69
71
  end
70
- end # module DBus
72
+ end
data/ruby-dbus.gemspec CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # -*- ruby -*-
2
4
  require "rubygems"
3
5
 
@@ -7,7 +9,7 @@ GEMSPEC = Gem::Specification.new do |s|
7
9
  s.summary = "Ruby module for interaction with D-Bus"
8
10
  s.description = "Pure Ruby module for interaction with D-Bus IPC system"
9
11
  s.version = File.read("VERSION").strip
10
- s.license = "LGPL v2.1"
12
+ s.license = "LGPL-2.1"
11
13
  s.author = "Ruby DBus Team"
12
14
  s.email = "martin.github@vidner.net"
13
15
  s.homepage = "https://github.com/mvidner/ruby-dbus"
@@ -18,15 +20,17 @@ GEMSPEC = Gem::Specification.new do |s|
18
20
  ]
19
21
  s.require_path = "lib"
20
22
 
21
- s.required_ruby_version = ">= 2.0.0"
23
+ s.required_ruby_version = ">= 2.4.0"
24
+
25
+ s.add_dependency "rexml"
22
26
 
23
27
  # This is optional
24
28
  # s.add_runtime_dependency "nokogiri"
25
29
 
26
- s.add_development_dependency "coveralls"
27
30
  s.add_development_dependency "packaging_rake_tasks"
28
31
  s.add_development_dependency "rake"
29
32
  s.add_development_dependency "rspec", "~> 3"
30
- s.add_development_dependency "rubocop", "= 0.41.2"
33
+ s.add_development_dependency "rubocop", "= 1.0"
31
34
  s.add_development_dependency "simplecov"
35
+ s.add_development_dependency "simplecov-lcov"
32
36
  end
data/spec/async_spec.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env rspec
2
+ # frozen_string_literal: true
3
+
2
4
  # Test the binding of dbus concepts to ruby concepts
3
5
  require_relative "spec_helper"
4
6
  require "dbus"
data/spec/binding_spec.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env rspec
2
+ # frozen_string_literal: true
3
+
2
4
  # Test the binding of dbus concepts to ruby concepts
3
5
  require_relative "spec_helper"
4
6
 
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env rspec
2
+ # frozen_string_literal: true
3
+
2
4
  # Test the bus class
3
5
  require_relative "spec_helper"
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
 
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env rspec
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "spec_helper"
5
+ require "dbus"
6
+
7
+ describe DBus::BusName do
8
+ describe ".valid?" do
9
+ it "recognizes valid bus names" do
10
+ expect(described_class.valid?("org.freedesktop.DBus")).to be_truthy
11
+ expect(described_class.valid?(":1.42")).to be_truthy
12
+ expect(described_class.valid?("org._7_zip.Archiver")).to be_truthy
13
+ end
14
+
15
+ it "recognizes invalid bus names" do
16
+ expect(described_class.valid?("")).to be_falsey
17
+ expect(described_class.valid?("Empty..Component")).to be_falsey
18
+ expect(described_class.valid?(".Empty.First.Component")).to be_falsey
19
+ expect(described_class.valid?("Empty.Last.Component.")).to be_falsey
20
+ expect(described_class.valid?("Invalid.Ch@r@cter")).to be_falsey
21
+ expect(described_class.valid?("/Invalid-Character")).to be_falsey
22
+ long_name = "a.#{"long." * 100}name"
23
+ expect(described_class.valid?(long_name)).to be_falsey
24
+ expect(described_class.valid?("org.7_zip.Archiver")).to be_falsey
25
+ end
26
+ end
27
+ end
data/spec/bus_spec.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env rspec
2
+ # frozen_string_literal: true
3
+
2
4
  # Test the bus class
3
5
  require_relative "spec_helper"
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
 
4
6
  require "dbus"
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env rspec
2
+ # frozen_string_literal: true
3
+
4
+ # Test that a client survives various error cases
5
+ require_relative "spec_helper"
6
+ require "dbus"
7
+
8
+ describe "ClientRobustnessTest" do
9
+ before(:each) do
10
+ @bus = DBus::ASessionBus.new
11
+ @svc = @bus.service("org.ruby.service")
12
+ end
13
+
14
+ context "when the bus name is invalid" do
15
+ it "tells the user the bus name is invalid" do
16
+ # user mistake, should be "org.ruby.service"
17
+ expect { @bus.service(".org.ruby.service") }.to raise_error(DBus::Error, /Invalid bus name/)
18
+ end
19
+ end
20
+
21
+ context "when the object path is invalid" do
22
+ it "tells the user the path is invalid" do
23
+ # user mistake, should be "/org/ruby/MyInstance"
24
+ expect { @svc.object("org.ruby.MyInstance") }.to raise_error(DBus::Error, /Invalid object path/)
25
+ end
26
+ end
27
+ 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,4 +1,6 @@
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"
@@ -70,7 +72,7 @@ describe "MainLoopTest" do
70
72
  @obj.on_signal "LongTaskEnd"
71
73
  end
72
74
 
73
- it "tests loop quit" do
75
+ it "tests loop quit", slow: true do
74
76
  test_loop_quit 1
75
77
  end
76
78
 
data/spec/node_spec.rb ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env rspec
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "spec_helper"
5
+ require "dbus"
6
+
7
+ describe DBus::Node do
8
+ describe "#inspect" do
9
+ # the behavior needs improvement
10
+ it "shows the node, poorly" do
11
+ parent = described_class.new("parent")
12
+ parent.object = DBus::Object.new("/parent")
13
+
14
+ 3.times do |i|
15
+ child_name = "child#{i}"
16
+ child = described_class.new(child_name)
17
+ parent[child_name] = child
18
+ end
19
+
20
+ expect(parent.inspect).to match(/<DBus::Node [0-9a-f]+ {child0 => {},child1 => {},child2 => {}}>/)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env rspec
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "spec_helper"
5
+ require "dbus"
6
+
7
+ describe DBus::ObjectPath do
8
+ describe ".valid?" do
9
+ it "recognizes valid paths" do
10
+ expect(described_class.valid?("/")).to be_truthy
11
+ expect(described_class.valid?("/99Numbers/_And_Underscores/anywhere")).to be_truthy
12
+ long_name = "/A23456789" * 42
13
+ # no 255 character limit for object paths
14
+ expect(described_class.valid?(long_name)).to be_truthy
15
+ end
16
+
17
+ it "recognizes invalid paths" do
18
+ expect(described_class.valid?("")).to be_falsey
19
+ expect(described_class.valid?("/Empty//Component")).to be_falsey
20
+ expect(described_class.valid?("/EmptyLastComponent/")).to be_falsey
21
+ expect(described_class.valid?("/Invalid Character")).to be_falsey
22
+ expect(described_class.valid?("/Invalid-Character")).to be_falsey
23
+ end
24
+ end
25
+ end