rbus 0.1.0 → 0.1.1

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.
data/CHANGELOG.txt CHANGED
@@ -1,9 +1,15 @@
1
1
  =CHANGELOG
2
2
 
3
- RBus 0.1.0 2007-03-28
3
+ R-Bus 0.1.1 2007-03-30
4
+ * Signature guessing code
5
+ * Support for dbus-send style arguments
6
+ * Tutorial updates
7
+ * Bugfixes and more tests
8
+
9
+ R-Bus 0.1.0 2007-03-28
4
10
  * Released as Rubygem
5
11
  * Added rbus-send application
6
12
  * Bugfixes and other updates
7
13
 
8
- RBus 0.0.1 2007-03-26
14
+ R-Bus 0.0.1 2007-03-26
9
15
  * Initial release (source only)
data/Manifest.txt CHANGED
@@ -28,6 +28,7 @@ lib/rbus/bus/bus.rb
28
28
  lib/rbus/bus/proxy.rb
29
29
  lib/rbus/bus/transport.rb
30
30
  lib/rbus/default.rb
31
+ lib/rbus/etc/blankslate.rb
31
32
  lib/rbus/etc/exception.rb
32
33
  lib/rbus/etc/log.rb
33
34
  lib/rbus/etc/types.rb
data/TUTORIAL.txt CHANGED
@@ -101,17 +101,64 @@ Some examples of method calls:
101
101
 
102
102
  == Signatures, introspection and data types
103
103
 
104
- D-Bus
105
- {defines a number of standard data types}[http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-signatures]
106
- that can be used to send and receive data between applications.
107
- R-Bus is able to use Rubys standard types for the most part, as long as there is
108
- a signature available for the conversion. When a new Proxy object is created,
109
- R-Bus will ask the remote application for a list of methods and signatures via
110
- the standard methos +Introspect+. If the application provides such a list,
111
- everything should just work. :)
112
-
113
- If the introspection fails, the Proxy object may not know how to call the
114
- method. In this case you can add the method manually with +method!+:
104
+ D-Bus defines a number of standard
105
+ {data types}[http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-signatures]
106
+ that can be used to send and receive data between applications. Each method and
107
+ signal has a signature that shows how many arguments and of what types it
108
+ expects and/or returns. A few examples of signatures:
109
+
110
+ [+s+] a String
111
+ [+ui+] Uint32, Int32
112
+ [+as+] Array of Strings
113
+ [<tt>a{sas}</tt>] Dict, or Hash in Ruby, with String keys and Arrays of Strings as values.
114
+
115
+ R-Bus is able to use Rubys standard types without any conversion for the most
116
+ part, as long as there is a known signature available for the conversion. This
117
+ signature can be obtained in a number of ways, and the library tries really
118
+ hard to find one:
119
+
120
+ When a new Proxy object is created, R-Bus will ask the remote application for a
121
+ list of methods and signatures via the standard method +Introspect+. If the
122
+ application provides such a list (and most do), everything should just work. :)
123
+
124
+ If the introspection fails, the library tries to guess the signature from the
125
+ arguments the method was called with. It will handle most types except integers
126
+ automatically, as long as the structures aren't too complex. Currently, these
127
+ Ruby classes are properly handled:
128
+
129
+ * String - D-Bus string
130
+ * Symbol - D-Bus string
131
+ * TrueClass and FalseClass - D-Bus boolean
132
+ * Float - D-Bus double
133
+ * Hash - D-Bus array of dicts
134
+ * can not be empty, needs at least one key/value pair
135
+ * Array
136
+ * D-Bus array if all values have the same signature (symbol and string is
137
+ considered to be the same)
138
+ * D-Bus struct if there are mixed values
139
+ * can't handle array of containers
140
+
141
+ So, a call like:
142
+
143
+ object.Method({:key => ['value'], 'key2' => ['value']})
144
+
145
+ will result in the signature <tt>a{sas}</tt>. And so on.
146
+
147
+ Also, you can manually give any arguments in the same form as <em>rbus-send</em>
148
+ (and <em>dbus-send</em>) accepts. This is the value, as a string, prefixed with
149
+ the name of the type and a colon:
150
+
151
+ string:'some string'
152
+ uint32:42
153
+ int16:-25
154
+ array:string:'foo','bar'
155
+ dict:string:uint32:'foo',32,'bar',64
156
+
157
+ See the section on rbus-send at the bottom of this document for the
158
+ specification of the format and some examples.
159
+
160
+ If all this fails, finally you can add the method manually with
161
+ <tt>method!</tt>:
115
162
 
116
163
  obj.method!(:MethodName, 'as')
117
164
 
@@ -237,13 +284,18 @@ currently missing.</em>
237
284
  === rbus-send
238
285
 
239
286
  R-Bus comes with its own variant of <em>dbus-send</em>, called
240
- <em>{rbus-send}[link:files/bin/rbus-send.html]</em>, which should be pretty much compatible, except for these
241
- known issues:
287
+ <em>{rbus-send}[link:files/bin/rbus-send.html]</em>, which should be pretty much
288
+ compatible, except for:
242
289
 
243
290
  * There is no <tt>--reply-timeout</tt>. Trivial to fix in seconds, though
244
- milli-seconds may not be.
291
+ milli-seconds may not be. Will be added.
245
292
  * Currently dumps the any server answer in YAML[http://www.yaml.org/] instead of
246
293
  the dbus-send format.
294
+ * Does not demand that an interface be specified, meaning you can call, as an
295
+ example, the method <tt>Introspect</tt> instead of the qualified
296
+ <tt>org.freedesktop.DBus.Introspectable.Introspect</tt>, as long as the
297
+ method is unique in the object. As the specification clearly allows this for
298
+ any client, I consider this a feature.
247
299
 
248
300
  The invokation looks like this:
249
301
 
data/bin/rbus-send CHANGED
@@ -49,55 +49,6 @@ require 'optparse'
49
49
  require 'rbus'
50
50
  require 'yaml'
51
51
 
52
- def make_signature # :nodoc:
53
- translation = {
54
- 'byte' => 'y',
55
- 'boolean' => 'b',
56
- 'int16' => 'n',
57
- 'uint16' => 'q',
58
- 'int32' => 'i',
59
- 'uint32' => 'u',
60
- 'int64' => 'x',
61
- 'uint64' => 't',
62
- 'double' => 'd',
63
- 'string' => 's',
64
- 'objpath' => 'o',
65
- 'signature' => 'g',
66
- 'variant' => 'v',
67
- 'array' => 'a',
68
- 'dict' => 'a{',
69
- }
70
-
71
- signature = ''
72
- array = false
73
-
74
- ARGV.map!{|a|
75
- type, arg = a.split(':',2)
76
- fail "Unknown type '#{type}'" unless translation.has_key?(type)
77
- signature << translation[type]
78
- case type
79
- when 'dict'
80
- key,value,arg = arg.split(':',3)
81
- signature << translation[key]
82
- signature << translation[value]
83
- signature << '}'
84
- arg.nil? ? {} : Hash[*arg.split(',')]
85
- when 'array'
86
- array = true
87
- a = arg
88
- redo
89
- when 'variant'
90
- a = arg
91
- redo
92
- else
93
- rv = (array) ? arg.split(',') : arg
94
- array = false
95
- rv
96
- end
97
- }
98
- signature
99
- end
100
-
101
52
  klass = RBus::Signal
102
53
  destination = nil
103
54
  bus = nil
@@ -113,7 +64,7 @@ opts = OptionParser.new do |opts|
113
64
  }
114
65
 
115
66
  opts.on('--print-reply',
116
- 'Block for a reply to the message sent, and print any reply received.') {
67
+ 'Wait for, and print reply.') {
117
68
  print_reply = true
118
69
  klass = RBus::MethodCall
119
70
  }
@@ -122,7 +73,7 @@ opts = OptionParser.new do |opts|
122
73
  bus = RBus.system_bus
123
74
  }
124
75
 
125
- opts.on('--session', 'Send to the session message bus. (This is the default.)') {
76
+ opts.on('--session', 'Send to the session message bus. (default.)') {
126
77
  bus = RBus.session_bus
127
78
  }
128
79
 
@@ -135,6 +86,10 @@ opts = OptionParser.new do |opts|
135
86
  }
136
87
  end
137
88
 
89
+ opts.version = RBus::VERSION::STRING
90
+ opts.summary_width = 18
91
+ opts.summary_indent = ""
92
+
138
93
  opts.parse!
139
94
 
140
95
  if ARGV.length < 2
@@ -146,20 +101,11 @@ object_path = ARGV.shift
146
101
  member,interface = ARGV.shift.reverse.split('.',2).map{|s|s.reverse}
147
102
 
148
103
  bus = RBus.session_bus if bus.nil?
149
-
150
- message = klass.new do |m|
151
- m.destination = destination
152
- m.object_path = object_path
153
- m.interface = interface
154
- m.member = member
155
- m.signature = make_signature
156
- m.arguments = ARGV
157
- end
158
-
159
- #puts YAML.dump(message);exit
104
+ object = bus.get_object(destination, object_path)
105
+ object.interface!(interface)
160
106
 
161
107
  if print_reply
162
- puts YAML.dump(bus.message_loop.send_message(message, nil))
108
+ puts YAML.dump(object.__send__(member, *ARGV))
163
109
  else
164
- bus.message_loop.send_message(message, lambda{})
110
+ object.__send__(member, *ARGV){}
165
111
  end
@@ -26,6 +26,9 @@
26
26
  # RBus Example:
27
27
  # Get information about a random HAL device.
28
28
  #
29
+ # At least in my version, HAL does not provide introspection, but
30
+ # the library now handles guessing a lot of arguments automatically.
31
+ #
29
32
 
30
33
  # Add lib to load path during development
31
34
  $: << '../lib/'
@@ -46,9 +49,5 @@ random = devs[rand(devs.size)]
46
49
  random_device = bus.get_object('org.freedesktop.Hal',random)
47
50
  random_device.interface!('org.freedesktop.Hal.Device')
48
51
 
49
- # Define method manually, as HAL doesn't provide introspection, at least
50
- # in my version.
51
- random_device.method!(:GetProperty, 's')
52
-
53
52
  # Print info and device path:
54
53
  puts ("#{random_device.GetProperty('info.product')} (#{random})")
data/lib/rbus/bus/bus.rb CHANGED
@@ -46,9 +46,8 @@ module RBus
46
46
  # Represents a connection to a Bus. It is also a Proxy object for
47
47
  # sending messages to the bus itself.
48
48
  class Bus < Proxy
49
- NAMES = []
50
49
 
51
- attr_reader :message_loop
50
+ attr_reader :message_loop, :transport, :names
52
51
 
53
52
  # Connect to Bus with +server_address+, which can contain multiple
54
53
  # addresses to try, separated by semicolons.
@@ -63,17 +62,16 @@ module RBus
63
62
  # Not used for anything, save at all?
64
63
  @guid = Auth.authorize(@transport)
65
64
 
66
- # Start main message loop.
67
- #@message_loop = Message::Loop.new(@transport).run
68
- @message_loop = Mainloop.new(@transport)
65
+ # Setup mainloop.
66
+ @message_loop = Mainloop.new(self)
69
67
 
70
68
  @well_known_name = 'org.freedesktop.DBus'
71
69
  @object_path = '/org/freedesktop/DBus'
72
70
  @interface = 'org.freedesktop.DBus'
73
- NAMES << Hello()
71
+ @names = [ Hello() ]
74
72
  Introspect()
75
73
 
76
- Log.debug('Bus names:', NAMES)
74
+ Log.debug('Bus names:', @names)
77
75
 
78
76
  end
79
77
 
@@ -22,21 +22,32 @@
22
22
  #++
23
23
  #
24
24
  require 'rexml/document'
25
+ require File.join(File.dirname(__FILE__), '..', 'etc', 'blankslate')
25
26
 
26
27
  module RBus
27
28
 
28
29
  VALID_METHOD_NAME = /^[A-Za-z_][A-Za-z0-9_]{0,254}$/
29
-
30
- # BlankSlate is a superclass that empties (almost) all instance methods
31
- # from it's subclasses.
32
- # See: http://onestepback.org/index.cgi/Tech/Ruby/BlankSlate.rdoc
33
- class BlankSlate
34
- instance_methods.each { |m| undef_method m unless m =~ /^__|[!\?]$/ }
35
- end
30
+ PREFIX_TO_SIG = {
31
+ 'byte' => 'y',
32
+ 'boolean' => 'b',
33
+ 'int16' => 'n',
34
+ 'uint16' => 'q',
35
+ 'int32' => 'i',
36
+ 'uint32' => 'u',
37
+ 'int64' => 'x',
38
+ 'uint64' => 't',
39
+ 'double' => 'd',
40
+ 'string' => 's',
41
+ 'objpath' => 'o',
42
+ 'signature' => 'g',
43
+ 'variant' => 'v',
44
+ 'array' => 'a',
45
+ 'dict' => 'a{',
46
+ }
36
47
 
37
48
  # The object that represents the remote bus object.
38
49
  class Proxy < BlankSlate
39
-
50
+
40
51
  # Parses Introspect() XML into a hash with
41
52
  # {method => signature}
42
53
  def self.parse_introspect(xml)
@@ -52,7 +63,7 @@ module RBus
52
63
  end
53
64
  methods
54
65
  end
55
-
66
+
56
67
  def initialize(bus, well_known_name, object_path)
57
68
  @bus = bus
58
69
  @message_loop = @bus.message_loop
@@ -60,7 +71,6 @@ module RBus
60
71
  @object_path = object_path
61
72
  Introspect()
62
73
  end
63
-
64
74
  def Introspect # :nodoc:
65
75
  # TODO: store interfaces as well, if ever needed
66
76
  interface = @interface
@@ -107,6 +117,77 @@ module RBus
107
117
  def method!(name, signature)
108
118
  @methods[name.to_s] = signature
109
119
  end
120
+
121
+ # Parse arguments and guess signature from a few types
122
+ # Handles [dr]bus-send type arguments also
123
+ def parse_arguments!(arguments)
124
+
125
+ strip = lambda{|s|s.sub!(/^'/,'');s.sub!(/'$/,'')}
126
+
127
+ signature = ''
128
+ array = false
129
+ arguments.map! do |value|
130
+ case value
131
+ when TrueClass, FalseClass
132
+ signature << 'b'
133
+ when Float
134
+ signature << 'd'
135
+ when Hash
136
+ signature << 'a{'
137
+ fail "Can't guess signature for empty hash" if value.empty?
138
+ k_sig = parse_arguments!([value.keys.first])
139
+ v_sig = parse_arguments!([value.values.first])
140
+ signature << k_sig
141
+ signature << v_sig
142
+ signature << '}'
143
+ when Array
144
+ a_sig = parse_arguments!(value)
145
+ #puts a_sig
146
+
147
+ # TODO: this only covers simple types
148
+ sq = a_sig.squeeze
149
+ if sq.length == 1 || sq[0] == ?a && sq.length == 2
150
+ signature << 'a' << sq
151
+ else
152
+ signature << "(#{a_sig})"
153
+ end
154
+ when Symbol
155
+ signature << 's'
156
+ when String
157
+ type, arg = value.split(':',2)
158
+ if PREFIX_TO_SIG.has_key?(type)
159
+ signature << PREFIX_TO_SIG[type]
160
+ strip.call(arg)
161
+ case type
162
+ when 'dict'
163
+ key_s,val_s,arg = arg.split(':',3)
164
+ strip.call(arg)
165
+ value = arg.nil? ? {} : Hash[*arg.split(/'?,'?/)]
166
+ signature << PREFIX_TO_SIG[key_s]
167
+ signature << PREFIX_TO_SIG[val_s]
168
+ signature << '}'
169
+ when 'array'
170
+ array = true
171
+ value = arg
172
+ redo
173
+ when 'variant'
174
+ value = arg
175
+ redo
176
+ else
177
+ value = (array) ? arg.split(/'?,'?/) : arg
178
+ array = false
179
+ end
180
+ else
181
+ signature << 's'
182
+ end
183
+ else
184
+ fail "Failed to guess signature for '#{value.class}'"
185
+ end
186
+ value
187
+ end
188
+
189
+ return signature
190
+ end
110
191
 
111
192
  # Routes all method calls to remote object
112
193
  def method_missing(name, *args, &block) # :nodoc:
@@ -124,14 +205,25 @@ module RBus
124
205
  m.object_path = @object_path
125
206
  m.interface = @interface if @interface
126
207
  m.member = method
127
- m.arguments = args
128
- if !args.empty? && @methods.has_key?(method)
208
+ if !args.empty?
209
+ begin
210
+ # always walk arguments because 'key:value' is always a valid arg
211
+ signature = parse_arguments!(args)
212
+ rescue RuntimeError => e
213
+ # re-bomb unless other signature
214
+ raise e unless @methods.has_key?(method)
215
+ end
216
+ if !@methods.has_key?(method)
217
+ method!(name, signature)
218
+ end
129
219
  Log.debug('Signature: ' + @methods[method])
130
220
  m.signature = @methods[method]
131
221
  end
222
+ m.arguments = args
132
223
  end
133
224
  Log.debug(block_given? ? 'Block given' : 'Block NOT given')
134
225
  @message_loop.send_message(call, block_given? ? block : nil)
135
226
  end
136
227
  end
137
228
  end
229
+
@@ -0,0 +1,8 @@
1
+ module RBus
2
+ # BlankSlate is a superclass that empties (almost) all instance methods
3
+ # from it's subclasses.
4
+ # See: http://onestepback.org/index.cgi/Tech/Ruby/BlankSlate.rdoc
5
+ class BlankSlate
6
+ instance_methods.each { |m| undef_method m unless m =~ /^__|\W$|^should/ }
7
+ end
8
+ end
@@ -27,7 +27,7 @@ module RBus #:nodoc:
27
27
 
28
28
  MAJOR = 0
29
29
  MINOR = 1
30
- TINY = 0
30
+ TINY = 1
31
31
 
32
32
  STRING = [MAJOR, MINOR, TINY].join('.')
33
33
  end
@@ -30,9 +30,10 @@ module RBus
30
30
  include Observable
31
31
  include MonitorMixin
32
32
 
33
- def initialize(transport)
33
+ def initialize(bus)
34
34
  super()
35
- @transport = transport
35
+ @bus = bus
36
+ @transport = @bus.transport
36
37
  @writer = Message::Writer.new(@transport)
37
38
  @reader = Message::Reader.new(@transport)
38
39
  setup
@@ -50,10 +51,10 @@ module RBus
50
51
  def handle_incoming(message)
51
52
  return if message.nil?
52
53
 
53
- # - empty NAMES is when Bus is connecting only
54
- # - empty destination is for signals only
55
- # - otherwise, NAMES must include the destination
56
- return unless Bus::NAMES.empty? || message.destination.nil? || Bus::NAMES.include?(message.destination)
54
+ # - names.nil? is when Bus is connecting only
55
+ # - destination.empty? is for signals only
56
+ # - otherwise, names must include the destination
57
+ return unless @bus.names.nil? || message.destination.nil? || @bus.names.include?(message.destination)
57
58
 
58
59
  # The audience is listening... broadcast the new message.
59
60
  changed
data/spec/bus_spec.rb CHANGED
@@ -25,7 +25,6 @@ require File.dirname(__FILE__) + '/helpers/spec_helper'
25
25
  require File.dirname(__FILE__) + '/helpers/bus_mocks'
26
26
 
27
27
  module RBus
28
-
29
28
  module BusSpecHelper
30
29
  def setup_mocks
31
30
  @transport = mock('Transport')
@@ -37,7 +36,6 @@ module RBus
37
36
  Message::Reader.stub!(:new).and_return(@message_reader)
38
37
 
39
38
  message_loop = mock('Mainloop', :null_object => true)
40
- #message_loop.stub!(:run).and_return(message_loop)
41
39
  message_loop.stub!(:send_message)
42
40
  Mainloop.stub!(:new).and_return(message_loop)
43
41
 
@@ -45,7 +43,8 @@ module RBus
45
43
  Bus.stub!(:get_object).and_return(@proxy)
46
44
 
47
45
  Transport.stub!(:connect).and_return(@transport)
48
- Auth.stub!(:authorize).and_return(fake_guid)
46
+ Auth.stub!(:authorize).and_return(fake_guid)
47
+
49
48
  end
50
49
 
51
50
  def fake_guid
@@ -61,15 +60,15 @@ module RBus
61
60
  end
62
61
 
63
62
  specify "should be a Bus object" do
64
- @bus.should_be_an_instance_of(Bus)
63
+ @bus.should be_an_instance_of(Bus)
65
64
  end
66
65
 
67
66
  specify "should respond to get_object" do
68
- @bus.should_respond_to :get_object
67
+ @bus.should respond_to(:get_object)
69
68
  end
70
69
 
71
70
  specify "should barf on empty address" do
72
- lambda{Bus.new('')}.should_raise InvalidAddressException
71
+ lambda{Bus.new('')}.should raise_error(InvalidAddressException)
73
72
  end
74
73
 
75
74
  end
@@ -94,15 +93,15 @@ module RBus
94
93
  end
95
94
 
96
95
  specify "should be a Bus object" do
97
- @bus.should_be_a_kind_of(Bus)
96
+ @bus.should be_a_kind_of(Bus)
98
97
  end
99
98
 
100
99
  specify "should be a singleton" do
101
- @bus.should == (RBus.session_bus)
100
+ @bus.should equal(RBus.session_bus)
102
101
  end
103
102
 
104
103
  specify "should be a SessionBus object" do
105
- @bus.should_be_an_instance_of(SessionBus)
104
+ @bus.should be_an_instance_of(SessionBus)
106
105
  end
107
106
 
108
107
  end
@@ -132,8 +131,6 @@ module RBus
132
131
 
133
132
  end
134
133
 
135
-
136
-
137
134
  context "System bus" do
138
135
  include BusSpecHelper
139
136
  setup do
@@ -142,15 +139,15 @@ module RBus
142
139
  end
143
140
 
144
141
  specify "should be a Bus object" do
145
- @bus.should_be_a_kind_of(Bus)
142
+ @bus.should be_a_kind_of(Bus)
146
143
  end
147
144
 
148
145
  specify "should be a singleton" do
149
- @bus.should == (RBus.system_bus)
146
+ @bus.should equal(RBus.system_bus)
150
147
  end
151
148
 
152
149
  specify "should be a SystemBus object" do
153
- @bus.should_be_an_instance_of(SystemBus)
150
+ @bus.should be_an_instance_of(SystemBus)
154
151
  end
155
152
 
156
153
  end
@@ -30,13 +30,16 @@ module RBus
30
30
  @transport = mock('Transport')
31
31
  @transport.stub!(:send)
32
32
  @transport.stub!(:read)
33
-
33
+
34
+ @bus = mock('Bus')
35
+ @bus.stub!(:transport).and_return(@transport)
36
+ @bus.stub!(:names).and_return([':1.31'])
37
+
34
38
  @message = mock('Message', :null_object => true)
35
39
  @message.stub!(:serial).and_return(1)
36
40
  @message.stub!(:message).and_return("string")
37
41
 
38
42
  @message.stub!(:destination).and_return(":1.31")
39
- Bus::NAMES[0] = ':1.31'
40
43
 
41
44
  @message_reader = mock('Message::Reader', :null_object => true)
42
45
  @message_reader.stub!(:read_message).and_return(@message)
@@ -46,7 +49,7 @@ module RBus
46
49
  @message_writer.stub!(:send_message)
47
50
  Writer::stub!(:new).and_return(@message_writer)
48
51
 
49
- @message_loop = Mainloop.new(@transport)
52
+ @message_loop = Mainloop.new(@bus)
50
53
 
51
54
  Thread.abort_on_exception = true
52
55
  end
data/spec/message_spec.rb CHANGED
@@ -48,7 +48,7 @@ module RBus
48
48
  specify "multi-threaded should still give all unique values" do
49
49
  threads = []
50
50
  serials = []
51
- 1337.times do
51
+ 50.times do
52
52
  threads << Thread.new do
53
53
  select(nil,nil,nil,rand)
54
54
  serials << Message::SerialGenerator.get_unique
data/spec/proxy_spec.rb CHANGED
@@ -62,6 +62,7 @@ module RBus
62
62
  m.arguments.should == ['a string',2,3,[2,3]]
63
63
  b.should == nil
64
64
  }
65
+ @proxy.method!(:Hola, 'suuau')
65
66
  @proxy.Hola('a string', 2,3,[2,3])
66
67
  end
67
68
 
@@ -115,6 +116,75 @@ module RBus
115
116
  specify "should raise on too long name (>255)" do
116
117
  lambda{@proxy.abcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijkabcdefghijk}.should_raise(InvalidNameException)
117
118
  end
119
+
120
+ end
121
+
122
+ context "Signature guesses" do
123
+ setup do
124
+ @well_known_name = 'org.rubyforge.rbus'
125
+ @object_path = '/org/rubyforge/rbus'
126
+ @message_loop = mock('MessageLoop')
127
+ @message_loop.stub!(:send_message)
128
+ @bus = mock('Bus')
129
+ @bus.stub!(:message_loop).and_return(@message_loop)
130
+ @proxy = Proxy.new(@bus, @well_known_name, @object_path)
131
+ end
132
+
133
+ specify "should parse mixed singles" do
134
+ args = [true, false,'something','string:string2', 'uint32:13']
135
+ @proxy.parse_arguments!(args).should == 'bbssu'
136
+ args.should == [true,false,'something','string2', '13']
137
+ end
138
+
139
+ specify "should parse struct of int,string" do
140
+ args = [['int32:-13','12']]
141
+ @proxy.parse_arguments!(args).should == '(is)'
142
+ args.should == [['-13','12']]
143
+ end
144
+
145
+ specify "should parse array of ints" do
146
+ args = [['int32:-13','int32:12']]
147
+ @proxy.parse_arguments!(args).should == 'ai'
148
+ args.should == [['-13','12']]
149
+ end
118
150
 
151
+ specify "should parse array of array of string" do
152
+ args = [[['','12']]]
153
+ @proxy.parse_arguments!(args).should == 'aas'
154
+ end
155
+
156
+ specify "should parse array of string" do
157
+ args = ["array:string:'foo','bar'"]
158
+ @proxy.parse_arguments!(args).should == 'as'
159
+ args.should == [['foo','bar']]
160
+ end
161
+
162
+ specify "should parse dict of string => uint32" do
163
+ args = ["dict:string:uint32:'foo',32,'bar',64"]
164
+ @proxy.parse_arguments!(args).should == 'a{su}'
165
+ args.should == [{'foo' => '32', 'bar' => '64'}]
166
+ end
167
+
168
+
169
+ specify "should parse hash with s => s" do
170
+ args = [{'a' => 'a', 'b' => 'c'}]
171
+ @proxy.parse_arguments!(args).should == 'a{ss}'
172
+ end
173
+
174
+ specify "should parse hash with s => as" do
175
+ args = [{:koss => ['haha'], 'bass' => ['lass']}]
176
+ @proxy.parse_arguments!(args).should == 'a{sas}'
177
+ end
178
+
179
+ specify "should fail on parse empty hash" do
180
+ args = [{}]
181
+ lambda{@proxy.parse_arguments!(args)}.should_raise
182
+ end
183
+
184
+ specify "should parse float" do
185
+ args = [1.23]
186
+ @proxy.parse_arguments!(args).should == 'd'
187
+ end
188
+
119
189
  end
120
190
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
3
3
  specification_version: 1
4
4
  name: rbus
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.0
7
- date: 2007-03-28 00:00:00 +02:00
6
+ version: 0.1.1
7
+ date: 2007-03-30 00:00:00 +02:00
8
8
  summary: A native implementation of the D-Bus protocol.
9
9
  require_paths:
10
10
  - lib
@@ -59,6 +59,7 @@ files:
59
59
  - lib/rbus/bus/proxy.rb
60
60
  - lib/rbus/bus/transport.rb
61
61
  - lib/rbus/default.rb
62
+ - lib/rbus/etc/blankslate.rb
62
63
  - lib/rbus/etc/exception.rb
63
64
  - lib/rbus/etc/log.rb
64
65
  - lib/rbus/etc/types.rb