Note that two tests to deal with weak ref's have been marked pending, as that
functionality can wait until it is required.
---
lib/puppet/events.rb | 32 +++++++++++++++++++++++-
spec/unit/events.rb | 65 +++++++++++++++++++++++++++----------------------
2 files changed, 66 insertions(+), 31 deletions(-)
mode change 100644 => 100755 spec/unit/events.rb
diff --git a/lib/puppet/events.rb b/lib/puppet/events.rb
index 4d179ed..3bf66d9 100644
--- a/lib/puppet/events.rb
+++ b/lib/puppet/events.rb
@@ -1,4 +1,5 @@
require 'puppet'
+require 'weakref'
module Puppet::Events
module Publisher
@@ -11,24 +12,44 @@ module Puppet::Events
! ! @private_publisher
end
- def create_subscriber_entry(subscriber, method = nil, &block)
+ def create_subscriber_entry(subscriber, callback)
+ subscriber = WeakRef.new(subscriber)
+ { :subscriber => subscriber,
+ :block => (callback.respond_to?(:call) ? callback :
Proc.new { |e| subscriber.send(callback, e) } )
+ }
end
end
-
+
def self.included(target_class)
target_class.extend ClassMethods
end
def subscriber_callbacks
+ @subscriber_callbacks ||= []
+ end
+
+ def subscriber_callbacks=(val)
+ @subscriber_callbacks = val
end
def subscribe(subscriber, method = nil, &block)
+ raise ArgumentError, "Cannot call subscribe and specify both a
method and a block" if method and block
+ subscriber_callbacks <<
self.class.create_subscriber_entry(subscriber, method.nil? ? block: method)
+ self
end
def raise_event(event)
+ if private_publisher?
+ Puppet::Events.propagate_event event, subscriber_callbacks,
:no_global => true
+ else
+ Puppet::Events.propagate_event(event, subscriber_callbacks)
+ end
end
+ # needs to remove all subscriptions for that subscriber -- can't just
assume one subscription
def unsubscribe(subscriber)
+ subscriber_callbacks.delete_if {|subscription|
subscription[:subscriber] == subscriber }
+ self
end
def private_publisher?
@@ -45,9 +66,16 @@ module Puppet::Events
end
def propagate_event(event, callbacks, options = {})
+ # Probably want something like this in the future:
+ #raise ArgumentError, "Need to provide an event to
propagate_event, not %s" % event.class unless event.class == 'Puppet::Event'
+ callbacks.each do |cb|
+ cb.call(event)
+ end
+ Puppet::Events.notify_global_subscribers(event) unless
options[:no_global]
end
def notify_global_subscribers(event)
+ raise_event(event)
end
end
end
diff --git a/spec/unit/events.rb b/spec/unit/events.rb
old mode 100644
new mode 100755
index 7bd7744..8475737
--- a/spec/unit/events.rb
+++ b/spec/unit/events.rb
@@ -32,7 +32,7 @@ describe Puppet::Events do
end
it 'should raise an exception if no event is provided' do
- lambda { @target.propagate_event }.should raise_error {|e|
e.message ~ 'provide an event'}
+ lambda { @target.propagate_event }.should
raise_error(ArgumentError, /wrong number of arguments/)
end
it 'should pass event to each callback in sequence' do
@@ -46,7 +46,7 @@ describe Puppet::Events do
Proc.new {|e| listener.send(sym, e)}
end
- @target.propagate_event(@event, callbacks)
+ @target.propagate_event(@event, callbacks, :no_global => :true)
end
it 'should notify global subscribers by default' do
@@ -113,7 +113,7 @@ describe Puppet::Events::Publisher do
it 'should provide propagate_event with :no_global flag if the
publisher is private' do
@publisher.stubs(:private_publisher?).returns(true)
- Puppet::Events.expects(:propagate_events).with(@event, @callbacks,
{:no_global => true})
+ Puppet::Events.expects(:propagate_event).with(@event, @callbacks,
:no_global => true)
@publisher.raise_event(@event)
end
end
@@ -126,43 +126,44 @@ describe Puppet::Events::Publisher do
describe 'with a callback block' do
it 'should pass block through unaltered' do
block = Proc.new {|e| e}
- entry = @publisher.class.create_subscriber_entry(@subscriber,
&block)
+ entry = @publisher.class.create_subscriber_entry(@subscriber,
block)
entry.size.should == 2
- entry[1].should == block
+ entry[:block].should == block
end
it 'should have a weak reference to the subscriber' do
- entry = @publisher.class.create_subscriber_entry(@subscriber)
{|e| e}
+ entry = @publisher.class.create_subscriber_entry(@subscriber,
Proc.new { |e| :blah })
entry.size.should == 2
- entry[0].should == @subscriber
- entry[0].respond_to?(:weakref_alive?).should be_true
+ entry[:subscriber].should == @subscriber
+ entry[:subscriber].respond_to?(:weakref_alive?).should be_true
end
end
describe 'with a method name' do
- it 'should create a block that invokes the method name on a weak
ref to the subscriber' do
+ it 'should create a block that invokes the method name' do
class << @subscriber
attr_accessor :weakref, :last_received
def callback(e)
self.last_received = e
- self.weakref = self.respond_to(:weakref_alive?)
+ puts "callback receiver is #{self.class}"
+ self.weakref = self.respond_to?(:weakref_alive?)
end
end
-
+ pending "handling of weakref's inside a singleton, in an array"
entry = @publisher.class.create_subscriber_entry(@subscriber,
:callback)
entry.size.should == 2
event = stub 'event'
- entry[1].call(event)
- @publisher.last_received.should == event
- @publisher.weakref.should be_true
+ entry[:block].call(event)
+ @subscriber.last_received.should == event
+ @subscriber.weakref.should be_true
end
it 'should have a weak reference to the subscriber' do
entry = @publisher.class.create_subscriber_entry(@subscriber,
:callback)
entry.size.should == 2
- entry[0].should == @publisher
- entry[0].respond_to(:weakref_alive?).should be_true
+ entry[:subscriber].should == @subscriber
+ entry[:subscriber].respond_to?(:weakref_alive?).should be_true
end
end
end
@@ -181,19 +182,18 @@ describe Puppet::Events::Publisher do
end
describe 'subscribe' do
- it 'should throw an exception if subscribe invoked with both symbol
and block' do
- lambda { @publisher.subscribe(Object.new, :some_method) {|x|
x.object_id} }.should raise_error() {|error|
- error.message.should =~ /specify both a method and a block/
- }
+ it 'should throw an exception if subscribe invoked with both method
and block' do
+ lambda { @publisher.subscribe(Object.new, :some_method) {|x|
x.object_id} }.should raise_error(ArgumentError, /specify both a method and a
block/)
end
- it 'should get subscription entry via class.create_subscription_entry'
do
+ it 'should get subscriber entry via class.create_subscriber_entry' do
sub_a = stub 'sub_a'
sub_b = stub 'sub_b'
sub_seq = sequence 'sub_seq'
a_block = Proc.new {|e| e}
- @class.expects(:create_subscription_entry).with(sub_a,
a_block).in_sequence(sub_seq)
- @class.expects(:create_subscription_entry).with(sub_b,
:foo).in_sequence(sub_seq)
+ @class.expects(:create_subscriber_entry).with(sub_a,
a_block).in_sequence(sub_seq)
+ @class.expects(:create_subscriber_entry).with(sub_b,
:foo).in_sequence(sub_seq)
+
@publisher.subscribe(sub_a, &a_block)
@publisher.subscribe(sub_b, :foo)
end
@@ -202,14 +202,14 @@ describe Puppet::Events::Publisher do
subscriber = mock 'subscriber'
subscriber.expects(:foo)
@publisher.subscribe(subscriber, :foo)
- @publisher.subscriber_callbacks.each {|cb| cb.call}
+ @publisher.subscriber_callbacks.each {|cb|
cb[:block].call(@publisher)}
end
it 'should put subscription entry for block in subscriber_callbacks' do
subscriber = mock 'subscriber'
subscriber.expects(:in_block)
@publisher.subscribe(subscriber) { subscriber.in_block }
- @publisher.subscriber_callbacks.each {|cb| cb.call}
+ @publisher.subscriber_callbacks.each {|cb|
cb[:block].call(@publisher)}
end
it 'should put subscriber_callbacks in order of subscription' do
@@ -219,21 +219,28 @@ describe Puppet::Events::Publisher do
p
end
- @publisher.subscriber_callbacks.should == callbacks
+ @publisher.subscriber_callbacks.collect do |subscription|
+ subscription[:subscriber]
+ end.should == callbacks
end
it 'should remove subscriber_callbacks for subscribers who
unsubscribed' do
consumers = (1..3).collect {|x| Proc.new {|e| e} }
consumers.each {|c| @publisher.subscribe(c, &c) }
@publisher.unsubscribe(consumers[1])
- @publisher.subscriber_callbacks.should == [0,2].collect {|c|
consumers[c]}
+ @publisher.subscriber_callbacks.collect do |subscription|
+ subscription[:subscriber]
+ end.should == [0,2].collect {|c| consumers[c]}
end
it 'should remove subscriber_callbacks for subscribers who passed on'
do
+ pending "Decision on when to clean up the subscriber_callbacks"
consumers = (1..3).collect {|x| Proc.new {|e| e} }
consumers.each {|c| @publisher.subscribe(c, &c) }
- consumers.first.stubs(:weakref_alive?).returns(false)
- @publisher.subscriber_callbacks.should == [1,2].collect {|c|
consumers[c]}
+ consumers.first.expects(:weakref_alive?).returns(false)
+ @publisher.subscriber_callbacks.collect do |subscription|
+ subscription[:subscriber]
+ end.should == [1,2].collect {|c| consumers[c]}
end
end
end
--
1.6.3.3
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Puppet Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/puppet-dev?hl=en
-~----------~----~----~----~------~----~------~--~---