ruby-dbus 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +504 -0
- data/NEWS +137 -0
- data/README +53 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/doc/tutorial/index.html +356 -0
- data/doc/tutorial/index.markdown +467 -0
- data/examples/gdbus/gdbus +255 -0
- data/examples/gdbus/gdbus.glade +184 -0
- data/examples/gdbus/launch.sh +4 -0
- data/examples/no-introspect/nm-test.rb +21 -0
- data/examples/no-introspect/tracker-test.rb +16 -0
- data/examples/rhythmbox/playpause.rb +25 -0
- data/examples/service/call_service.rb +25 -0
- data/examples/service/service_newapi.rb +51 -0
- data/examples/simple/call_introspect.rb +34 -0
- data/examples/utils/listnames.rb +11 -0
- data/examples/utils/notify.rb +19 -0
- data/lib/dbus.rb +91 -0
- data/lib/dbus/auth.rb +258 -0
- data/lib/dbus/bus.rb +816 -0
- data/lib/dbus/core_ext/class/attribute.rb +91 -0
- data/lib/dbus/core_ext/kernel/singleton_class.rb +14 -0
- data/lib/dbus/core_ext/module/remove_method.rb +12 -0
- data/lib/dbus/error.rb +44 -0
- data/lib/dbus/export.rb +132 -0
- data/lib/dbus/introspect.rb +553 -0
- data/lib/dbus/marshall.rb +443 -0
- data/lib/dbus/matchrule.rb +100 -0
- data/lib/dbus/message.rb +310 -0
- data/lib/dbus/type.rb +222 -0
- data/ruby-dbus.gemspec +18 -0
- data/test/binding_test.rb +56 -0
- data/test/bus_driver_test.rb +22 -0
- data/test/dbus-launch-simple +35 -0
- data/test/dbus-limited-session.conf +28 -0
- data/test/server_robustness_test.rb +41 -0
- data/test/server_test.rb +53 -0
- data/test/service_newapi.rb +129 -0
- data/test/session_bus_test_manual.rb +20 -0
- data/test/signal_test.rb +64 -0
- data/test/t1 +4 -0
- data/test/t2.rb +66 -0
- data/test/t3-ticket27.rb +18 -0
- data/test/t5-report-dbus-interface.rb +58 -0
- data/test/t6-loop.rb +82 -0
- data/test/test_env +13 -0
- data/test/test_server +39 -0
- data/test/variant_test.rb +66 -0
- metadata +117 -0
data/ruby-dbus.gemspec
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
require "rubygems"
|
3
|
+
require "rake"
|
4
|
+
|
5
|
+
GEMSPEC = Gem::Specification.new do |s|
|
6
|
+
s.name = "ruby-dbus"
|
7
|
+
# s.rubyforge_project = nil
|
8
|
+
s.summary = "Ruby module for interaction with D-Bus"
|
9
|
+
# s.description = FIXME
|
10
|
+
s.version = File.read("VERSION").strip
|
11
|
+
s.author = "Ruby DBus Team"
|
12
|
+
s.email = "ruby-dbus-devel@lists.luon.net"
|
13
|
+
s.homepage = "http://trac.luon.net/data/ruby-dbus/"
|
14
|
+
s.files = FileList["{doc/tutorial,examples,lib,test}/**/*", "Rakefile", "ruby-dbus.gemspec", "VERSION"].to_a.sort
|
15
|
+
s.require_path = "lib"
|
16
|
+
s.has_rdoc = true
|
17
|
+
s.extra_rdoc_files = ["COPYING", "README", "NEWS"]
|
18
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Test the binding of dbus concepts to ruby concepts
|
3
|
+
require "test/unit"
|
4
|
+
require "dbus"
|
5
|
+
|
6
|
+
class BindingTest < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
@bus = DBus::SessionBus.instance
|
9
|
+
@svc = @bus.service("org.ruby.service")
|
10
|
+
@base = @svc.object "/org/ruby/MyInstance"
|
11
|
+
@base.introspect
|
12
|
+
@base.default_iface = "org.ruby.SampleInterface"
|
13
|
+
end
|
14
|
+
|
15
|
+
# https://trac.luon.net/ruby-dbus/ticket/36#comment:3
|
16
|
+
def test_class_inheritance
|
17
|
+
derived = @svc.object "/org/ruby/MyDerivedInstance"
|
18
|
+
derived.introspect
|
19
|
+
|
20
|
+
# it should inherit from the parent
|
21
|
+
assert_not_nil derived["org.ruby.SampleInterface"]
|
22
|
+
end
|
23
|
+
|
24
|
+
# https://trac.luon.net/ruby-dbus/ticket/36
|
25
|
+
# Interfaces and methods/signals appeared on all classes
|
26
|
+
def test_separation_of_classes
|
27
|
+
test2 = @svc.object "/org/ruby/MyInstance2"
|
28
|
+
test2.introspect
|
29
|
+
|
30
|
+
# it should have its own interface
|
31
|
+
assert_not_nil test2["org.ruby.Test2"]
|
32
|
+
# but not an interface of the Test class
|
33
|
+
assert_nil test2["org.ruby.SampleInterface"]
|
34
|
+
|
35
|
+
# and the parent should not get polluted by the child
|
36
|
+
assert_nil @base["org.ruby.Test2"]
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_translating_errors_into_exceptions
|
40
|
+
# this is a generic call that will reply with the specified error
|
41
|
+
@base.Error "org.example.Fail", "as you wish"
|
42
|
+
assert false, "should have raised"
|
43
|
+
rescue DBus::Error => e
|
44
|
+
assert_equal "org.example.Fail", e.name
|
45
|
+
assert_equal "as you wish", e.message
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_generic_dbus_error
|
49
|
+
# this is a generic call that will reply with the specified error
|
50
|
+
@base.will_raise_error_failed
|
51
|
+
assert false, "should have raised"
|
52
|
+
rescue DBus::Error => e
|
53
|
+
assert_equal "org.freedesktop.DBus.Error.Failed", e.name
|
54
|
+
assert_equal "failed as designed", e.message
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Test the methods of the bus driver
|
3
|
+
require "test/unit"
|
4
|
+
require "dbus"
|
5
|
+
|
6
|
+
def d(msg)
|
7
|
+
puts msg if $DEBUG
|
8
|
+
end
|
9
|
+
|
10
|
+
class BusDriverTest < Test::Unit::TestCase
|
11
|
+
def setup
|
12
|
+
@bus = DBus::SessionBus.instance
|
13
|
+
@svc = @bus.service("org.ruby.service")
|
14
|
+
@svc.object("/").introspect
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_exists
|
18
|
+
assert @svc.exists?, "could not find the service"
|
19
|
+
nonsvc = @bus.service "org.ruby.nosuchservice"
|
20
|
+
assert ! nonsvc.exists?, "found a service that should not exist"
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#! /bin/sh
|
2
|
+
# A wrapper for DBus tests
|
3
|
+
# Reimplementing dbus-launch because it is in dbus-1-x11.rpm
|
4
|
+
# Sets up a private session bus and call the specified program
|
5
|
+
set -o errexit
|
6
|
+
|
7
|
+
# This launches the bus daemon,
|
8
|
+
# exports DBUS_SESSION_BUS_ADDRESS and sets DBUS_SESSION_BUS_PID
|
9
|
+
my_dbus_launch () {
|
10
|
+
# reimplementing dbus-launch because it is in dbus-1-x11.rpm
|
11
|
+
PF=`mktemp dbus.pid.XXXXXX` || exit
|
12
|
+
AF=`mktemp dbus.addr.XXXXXX` || exit
|
13
|
+
RM_FILES="$RM_FILES $PF $AF"
|
14
|
+
|
15
|
+
dbus-daemon --config-file=dbus-limited-session.conf --print-address=3 3>$AF --print-pid=4 4>$PF &
|
16
|
+
# wait for the daemon to print the info
|
17
|
+
TRIES=0
|
18
|
+
while [ ! -s $AF -o ! -s $PF ]; do
|
19
|
+
sleep 0.1
|
20
|
+
TRIES=`expr $TRIES + 1`
|
21
|
+
if [ $TRIES -gt 100 ]; then echo "dbus-daemon failed?"; exit 1; fi
|
22
|
+
done
|
23
|
+
DBUS_SESSION_BUS_PID=$(cat $PF)
|
24
|
+
export DBUS_SESSION_BUS_ADDRESS=$(cat $AF)
|
25
|
+
KILLS="$KILLS $DBUS_SESSION_BUS_PID"
|
26
|
+
# dbus-monitor &
|
27
|
+
}
|
28
|
+
|
29
|
+
my_dbus_launch
|
30
|
+
|
31
|
+
# Clean up at exit.
|
32
|
+
trap "kill \$KILLS; rm -rf \$RM_FILES" EXIT TERM INT
|
33
|
+
|
34
|
+
# run the payload; the return value is passed on
|
35
|
+
"$@"
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<!-- This configuration file controls the testing message bus.
|
2
|
+
It is based on a session bus config. -->
|
3
|
+
|
4
|
+
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
|
5
|
+
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
6
|
+
<busconfig>
|
7
|
+
<!-- Our well-known bus type, don't change this -->
|
8
|
+
<type>session</type>
|
9
|
+
|
10
|
+
<listen>unix:tmpdir=/tmp</listen>
|
11
|
+
<listen>tcp:host=localhost,port=0,family=ipv4</listen>
|
12
|
+
|
13
|
+
<standard_session_servicedirs />
|
14
|
+
|
15
|
+
<policy context="default">
|
16
|
+
<!-- Allow everything to be sent -->
|
17
|
+
<allow send_destination="*" eavesdrop="true"/>
|
18
|
+
<!-- Allow everything to be received -->
|
19
|
+
<allow eavesdrop="true"/>
|
20
|
+
<!-- Allow anyone to own anything -->
|
21
|
+
<allow own="*"/>
|
22
|
+
</policy>
|
23
|
+
|
24
|
+
<!-- Do not increase the limits.
|
25
|
+
Instead, lower some so that we can test resource leaks. -->
|
26
|
+
<limit name="max_match_rules_per_connection">50</limit><!-- was 512 -->
|
27
|
+
|
28
|
+
</busconfig>
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Test that a server survives various error cases
|
3
|
+
require "test/unit"
|
4
|
+
require "dbus"
|
5
|
+
|
6
|
+
class ServerRobustnessTest < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
@bus = DBus::SessionBus.instance
|
9
|
+
@svc = @bus.service("org.ruby.service")
|
10
|
+
end
|
11
|
+
|
12
|
+
# https://trac.luon.net/ruby-dbus/ticket/31
|
13
|
+
# the server should not crash
|
14
|
+
def test_no_such_path_with_introspection
|
15
|
+
obj = @svc.object "/org/ruby/NotMyInstance"
|
16
|
+
obj.introspect
|
17
|
+
assert false, "should have raised"
|
18
|
+
rescue DBus::Error => e
|
19
|
+
assert_no_match(/timeout/, e.to_s)
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_no_such_path_without_introspection
|
23
|
+
obj = @svc.object "/org/ruby/NotMyInstance"
|
24
|
+
ifc = DBus::ProxyObjectInterface.new(obj, "org.ruby.SampleInterface")
|
25
|
+
ifc.define_method("the_answer", "out n:i")
|
26
|
+
ifc.the_answer
|
27
|
+
assert false, "should have raised"
|
28
|
+
rescue DBus::Error => e
|
29
|
+
assert_no_match(/timeout/, e.to_s)
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_a_method_that_raises
|
33
|
+
obj = @svc.object "/org/ruby/MyInstance"
|
34
|
+
obj.introspect
|
35
|
+
obj.default_iface = "org.ruby.SampleInterface"
|
36
|
+
obj.will_raise
|
37
|
+
assert false, "should have raised"
|
38
|
+
rescue DBus::Error => e
|
39
|
+
assert_no_match(/timeout/, e.to_s)
|
40
|
+
end
|
41
|
+
end
|
data/test/server_test.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Test that a server survives various error cases
|
3
|
+
require "test/unit"
|
4
|
+
require "dbus"
|
5
|
+
|
6
|
+
class Foo < DBus::Object
|
7
|
+
dbus_interface "org.ruby.ServerTest" do
|
8
|
+
dbus_signal :signal_without_arguments
|
9
|
+
dbus_signal :signal_with_argument, "epsilon:d"
|
10
|
+
end
|
11
|
+
|
12
|
+
dbus_signal :signal_without_interface
|
13
|
+
rescue DBus::Object::UndefinedInterface => e
|
14
|
+
# raised by the preceding signal declaration
|
15
|
+
end
|
16
|
+
|
17
|
+
class Bar < DBus::Object
|
18
|
+
dbus_interface "org.ruby.ServerTest" do
|
19
|
+
# a valid Ruby symbol but an invalid DBus name; Ticket#38
|
20
|
+
dbus_signal :signal_with_a_bang!
|
21
|
+
end
|
22
|
+
rescue DBus::InvalidMethodName
|
23
|
+
# raised by the preceding signal declaration
|
24
|
+
end
|
25
|
+
|
26
|
+
class ServerTest < Test::Unit::TestCase
|
27
|
+
def setup
|
28
|
+
@bus = DBus::SessionBus.instance
|
29
|
+
@svc = @bus.request_service "org.ruby.server-test"
|
30
|
+
end
|
31
|
+
|
32
|
+
def teardown
|
33
|
+
@bus.proxy.ReleaseName "org.ruby.server-test"
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_unexporting_an_object
|
37
|
+
obj = Foo.new "/org/ruby/Foo"
|
38
|
+
@svc.export obj
|
39
|
+
assert @svc.unexport(obj)
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_unexporting_an_object_not_exported
|
43
|
+
obj = Foo.new "/org/ruby/Foo"
|
44
|
+
assert !@svc.unexport(obj)
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_emiting_signals
|
48
|
+
obj = Foo.new "/org/ruby/Foo"
|
49
|
+
@svc.export obj
|
50
|
+
obj.signal_without_arguments
|
51
|
+
obj.signal_with_argument(-0.1)
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# find the library without external help
|
4
|
+
$:.unshift File.expand_path("../../lib", __FILE__)
|
5
|
+
|
6
|
+
require 'dbus'
|
7
|
+
|
8
|
+
def d(msg)
|
9
|
+
puts "#{$$} #{msg}" if $DEBUG
|
10
|
+
end
|
11
|
+
|
12
|
+
class Test < DBus::Object
|
13
|
+
# Create an interface aggregating all upcoming dbus_method defines.
|
14
|
+
dbus_interface "org.ruby.SampleInterface" do
|
15
|
+
dbus_method :hello, "in name:s, in name2:s" do |name, name2|
|
16
|
+
puts "hello(#{name}, #{name2})"
|
17
|
+
end
|
18
|
+
|
19
|
+
dbus_method :test_variant, "in stuff:v" do |variant|
|
20
|
+
p variant
|
21
|
+
end
|
22
|
+
|
23
|
+
dbus_method :bounce_variant, "in stuff:v, out chaff:v" do |variant|
|
24
|
+
[variant]
|
25
|
+
end
|
26
|
+
|
27
|
+
dbus_method :variant_size, "in stuff:v, out size:u" do |variant|
|
28
|
+
[variant.size]
|
29
|
+
end
|
30
|
+
|
31
|
+
dbus_method :the_answer, "out answer:i" do
|
32
|
+
42
|
33
|
+
end
|
34
|
+
|
35
|
+
dbus_method :will_raise, "" do
|
36
|
+
raise "Handle this"
|
37
|
+
end
|
38
|
+
|
39
|
+
dbus_method :will_raise_error_failed, "" do
|
40
|
+
raise DBus.error, "failed as designed"
|
41
|
+
end
|
42
|
+
|
43
|
+
dbus_method :Error, "in name:s, in description:s" do |name, description|
|
44
|
+
raise DBus.error(name), description
|
45
|
+
end
|
46
|
+
|
47
|
+
dbus_signal :SomethingJustHappened, "toto:s, tutu:u"
|
48
|
+
end
|
49
|
+
|
50
|
+
dbus_interface "org.ruby.AnotherInterface" do
|
51
|
+
dbus_method :ThatsALongMethodNameIThink do
|
52
|
+
puts "ThatsALongMethodNameIThink"
|
53
|
+
end
|
54
|
+
dbus_method :Reverse, "in instr:s, out outstr:s" do |instr|
|
55
|
+
outstr = instr.split(//).reverse.join
|
56
|
+
puts "got: #{instr}, replying: #{outstr}"
|
57
|
+
[outstr]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
dbus_interface "org.ruby.Ticket30" do
|
62
|
+
dbus_method :Sybilla, 'in choices:av, out advice:s' do |choices|
|
63
|
+
["Do #{choices[0]}"]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
dbus_interface "org.ruby.Loop" do
|
68
|
+
# starts doing something long, but returns immediately
|
69
|
+
# and sends a signal when done
|
70
|
+
dbus_method :LongTaskBegin, 'in delay:i' do |delay|
|
71
|
+
# FIXME did not complain about mismatch between signature and block args
|
72
|
+
d "Long task began"
|
73
|
+
task = Thread.new do
|
74
|
+
d "Long task thread started (#{delay}s)"
|
75
|
+
sleep delay
|
76
|
+
d "Long task will signal end"
|
77
|
+
self.LongTaskEnd
|
78
|
+
end
|
79
|
+
task.abort_on_exception = true # protect from test case bugs
|
80
|
+
end
|
81
|
+
|
82
|
+
dbus_signal :LongTaskEnd
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class Derived < Test
|
87
|
+
end
|
88
|
+
|
89
|
+
class Test2 < DBus::Object
|
90
|
+
dbus_interface "org.ruby.Test2" do
|
91
|
+
dbus_method :hi, "in name:s, out greeting:s" do |name|
|
92
|
+
"Hi, #{name}!"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
bus = DBus::SessionBus.instance
|
98
|
+
service = bus.request_service("org.ruby.service")
|
99
|
+
myobj = Test.new("/org/ruby/MyInstance")
|
100
|
+
service.export(myobj)
|
101
|
+
derived = Derived.new "/org/ruby/MyDerivedInstance"
|
102
|
+
service.export derived
|
103
|
+
test2 = Test2.new "/org/ruby/MyInstance2"
|
104
|
+
service.export test2
|
105
|
+
|
106
|
+
# introspect every other connection, Ticket #34
|
107
|
+
# (except the one that activates us - it has already emitted
|
108
|
+
# NOC by the time we run this. Therefore the test for #34 will not work
|
109
|
+
# by running t2.rb alone, one has to run t1 before it; 'rake' does it)
|
110
|
+
mr = DBus::MatchRule.new.from_s "type='signal',interface='org.freedesktop.DBus',member='NameOwnerChanged'"
|
111
|
+
bus.add_match(mr) do |msg|
|
112
|
+
new_unique_name = msg.params[2]
|
113
|
+
unless new_unique_name.empty?
|
114
|
+
d "RRRING #{new_unique_name}"
|
115
|
+
bus.introspect_data(new_unique_name, "/") do
|
116
|
+
# ignore the result
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
puts "listening"
|
122
|
+
main = DBus::Main.new
|
123
|
+
main << bus
|
124
|
+
begin
|
125
|
+
main.run
|
126
|
+
rescue SystemCallError
|
127
|
+
# the test driver will kill the bus, that's OK
|
128
|
+
end
|
129
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "test/unit"
|
3
|
+
require "dbus"
|
4
|
+
|
5
|
+
def d(msg)
|
6
|
+
puts msg if $DEBUG
|
7
|
+
end
|
8
|
+
|
9
|
+
class SessionBusAddressTest < Test::Unit::TestCase
|
10
|
+
def setup
|
11
|
+
# test getting the session bus address even if unset in ENV (Issue#4)
|
12
|
+
ENV.delete "DBUS_SESSION_BUS_ADDRESS"
|
13
|
+
@bus = DBus::SessionBus.instance
|
14
|
+
@svc = @bus.service("org.freedesktop.DBus")
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_connection
|
18
|
+
assert @svc.exists?
|
19
|
+
end
|
20
|
+
end
|
data/test/signal_test.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Test the signal handlers
|
3
|
+
require "test/unit"
|
4
|
+
require "dbus"
|
5
|
+
|
6
|
+
def d(msg)
|
7
|
+
puts "#{$$} #{msg}" if $DEBUG
|
8
|
+
end
|
9
|
+
|
10
|
+
class SignalHandlerTest < Test::Unit::TestCase
|
11
|
+
def setup
|
12
|
+
@session_bus = DBus::SessionBus.instance
|
13
|
+
svc = @session_bus.service("org.ruby.service")
|
14
|
+
@obj = svc.object("/org/ruby/MyInstance")
|
15
|
+
@obj.introspect # necessary
|
16
|
+
@obj.default_iface = "org.ruby.Loop"
|
17
|
+
|
18
|
+
@loop = DBus::Main.new
|
19
|
+
@loop << @session_bus
|
20
|
+
end
|
21
|
+
|
22
|
+
# testing for commit 017c83 (kkaempf)
|
23
|
+
def test_overriding_a_handler
|
24
|
+
counter = 0
|
25
|
+
|
26
|
+
@obj.on_signal "LongTaskEnd" do
|
27
|
+
d "+10"
|
28
|
+
counter += 10
|
29
|
+
end
|
30
|
+
@obj.on_signal "LongTaskEnd" do
|
31
|
+
d "+1"
|
32
|
+
counter += 1
|
33
|
+
end
|
34
|
+
|
35
|
+
d "will begin"
|
36
|
+
@obj.LongTaskBegin 3
|
37
|
+
|
38
|
+
quitter = Thread.new do
|
39
|
+
d "sleep before quit"
|
40
|
+
# FIXME if we sleep for too long
|
41
|
+
# the socket will be drained and we deadlock in a select.
|
42
|
+
# It could be worked around by sending ourselves a Unix signal
|
43
|
+
# (with a dummy handler) to interrupt the select
|
44
|
+
sleep 1
|
45
|
+
d "will quit"
|
46
|
+
@loop.quit
|
47
|
+
end
|
48
|
+
@loop.run
|
49
|
+
|
50
|
+
assert_equal 1, counter
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_too_many_rules
|
54
|
+
100.times do
|
55
|
+
@obj.on_signal "Whichever" do
|
56
|
+
puts "not called"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_removing_a_nonexistent_rule
|
62
|
+
@obj.on_signal "DoesNotExist"
|
63
|
+
end
|
64
|
+
end
|