ruby-dbus 0.15.0 → 0.18.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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