rbus 0.1.0 → 0.1.1

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