more specs + cleanups

This commit is contained in:
Colin Surprenant 2011-11-15 16:37:48 -05:00
parent b29ec72695
commit 89396e1ad0
6 changed files with 834 additions and 302 deletions

View File

@ -9,20 +9,20 @@ module RedStorm
@fields = fields.map(&:to_s) @fields = fields.map(&:to_s)
end end
def self.on_receive(*args, &receive_block) def self.on_receive(*args, &on_receive_block)
options = args.last.is_a?(Hash) ? args.pop : {} options = args.last.is_a?(Hash) ? args.pop : {}
method_name = args.first method_name = args.first
self.receive_options.merge!(options) self.receive_options.merge!(options)
@receive_block = block_given? ? receive_block : lambda {|tuple| self.send(method_name, tuple)} @on_receive_block = block_given? ? on_receive_block : lambda {|tuple| self.send(method_name || :on_receive, tuple)}
end end
def self.on_init(method_name = nil, &init_block) def self.on_init(method_name = nil, &on_init_block)
@init_block = block_given? ? init_block : lambda {self.send(method_name)} @on_init_block = block_given? ? on_init_block : lambda {self.send(method_name || :on_init)}
end end
def self.on_close(method_name = nil, &close_block) def self.on_close(method_name = nil, &close_block)
@close_block = block_given? ? close_block : lambda {self.send(method_name)} @close_block = block_given? ? close_block : lambda {self.send(method_name || :on_close)}
end end
# DSL instance methods # DSL instance methods
@ -38,7 +38,7 @@ module RedStorm
# Bolt proxy interface # Bolt proxy interface
def execute(tuple) def execute(tuple)
if (output = instance_exec(tuple, &self.class.receive_block)) && self.class.emit? if (output = instance_exec(tuple, &self.class.on_receive_block)) && self.class.emit?
values = [output].flatten values = [output].flatten
self.class.anchor? ? @collector.emit(tuple, Values.new(*values)) : emit(*values) self.class.anchor? ? @collector.emit(tuple, Values.new(*values)) : emit(*values)
@collector.ack(tuple) if self.class.ack? @collector.ack(tuple) if self.class.ack?
@ -49,7 +49,7 @@ module RedStorm
@collector = collector @collector = collector
@context = context @context = context
@config = config @config = config
instance_exec(&self.class.init_block) instance_exec(&self.class.on_init_block)
end end
def cleanup def cleanup
@ -60,22 +60,27 @@ module RedStorm
declarer.declare(Fields.new(self.class.fields)) declarer.declare(Fields.new(self.class.fields))
end end
# default optional dsl methods/callbacks
def on_init; end
def on_close; end
private private
def self.fields def self.fields
@fields ||= [] @fields ||= []
end end
def self.receive_block def self.on_receive_block
@receive_block ||= lambda {} @on_receive_block ||= lambda {|tuple| self.send(:on_receive, tuple)}
end end
def self.init_block def self.on_init_block
@init_block ||= lambda {} @on_init_block ||= lambda {self.send(:on_init)}
end end
def self.close_block def self.close_block
@close_block ||= lambda {} @close_block ||= lambda {self.send(:on_close)}
end end
def self.receive_options def self.receive_options

View File

@ -13,28 +13,28 @@ module RedStorm
@fields = fields.map(&:to_s) @fields = fields.map(&:to_s)
end end
def self.on_send(*args, &send_block) def self.on_send(*args, &on_send_block)
options = args.last.is_a?(Hash) ? args.pop : {} options = args.last.is_a?(Hash) ? args.pop : {}
method_name = args.first method_name = args.first
self.send_options.merge!(options) self.send_options.merge!(options)
@send_block = block_given? ? send_block : lambda {self.send(method_name)} @on_send_block = block_given? ? on_send_block : lambda {self.send(method_name || :on_send)}
end end
def self.on_init(method_name = nil, &init_block) def self.on_init(method_name = nil, &on_init_block)
@init_block = block_given? ? init_block : lambda {self.send(method_name)} @on_init_block = block_given? ? on_init_block : lambda {self.send(method_name || :on_init)}
end end
def self.on_close(method_name = nil, &close_block) def self.on_close(method_name = nil, &on_close_block)
@close_block = block_given? ? close_block : lambda {self.send(method_name)} @on_close_block = block_given? ? on_close_block : lambda {self.send(method_name || :on_close)}
end end
def self.on_ack(method_name = nil, &ack_block) def self.on_ack(method_name = nil, &on_ack_block)
@ack_block = block_given? ? ack_block : lambda {|msg_id| self.send(method_name, msg_id)} @on_ack_block = block_given? ? on_ack_block : lambda {|msg_id| self.send(method_name || :on_ack, msg_id)}
end end
def self.on_fail(method_name = nil, &fail_block) def self.on_fail(method_name = nil, &on_fail_block)
@fail_block = block_given? ? fail_block : lambda {|msg_id| self.send(method_name, msg_id)} @on_fail_block = block_given? ? on_fail_block : lambda {|msg_id| self.send(method_name || :on_fail, msg_id)}
end end
# DSL instance methods # DSL instance methods
@ -46,7 +46,7 @@ module RedStorm
# Spout proxy interface # Spout proxy interface
def next_tuple def next_tuple
output = instance_exec(&self.class.send_block) output = instance_exec(&self.class.on_send_block)
if self.class.emit? if self.class.emit?
if output if output
values = [output].flatten values = [output].flatten
@ -61,11 +61,11 @@ module RedStorm
@collector = collector @collector = collector
@context = context @context = context
@config = config @config = config
instance_exec(&self.class.init_block) instance_exec(&self.class.on_init_block)
end end
def close def close
instance_exec(&self.class.close_block) instance_exec(&self.class.on_close_block)
end end
def declare_output_fields(declarer) def declare_output_fields(declarer)
@ -77,37 +77,44 @@ module RedStorm
end end
def ack(msg_id) def ack(msg_id)
instance_exec(msg_id, &self.class.ack_block) instance_exec(msg_id, &self.class.on_ack_block)
end end
def fail(msg_id) def fail(msg_id)
instance_exec(msg_id, &self.class.fail_block) instance_exec(msg_id, &self.class.on_fail_block)
end end
# default optional dsl methods/callbacks
def on_init; end
def on_close; end
def on_ack(msg_id); end
def on_fail(msg_id); end
private private
def self.fields def self.fields
@fields ||= [] @fields ||= []
end end
def self.send_block def self.on_send_block
@send_block ||= lambda {} @on_send_block ||= lambda {self.send(:on_send)}
end end
def self.init_block def self.on_init_block
@init_block ||= lambda {} @on_init_block ||= lambda {self.send(:on_init)}
end end
def self.close_block def self.on_close_block
@close_block ||= lambda {} @on_close_block ||= lambda {self.send(:on_close)}
end end
def self.ack_block def self.on_ack_block
@ack_block ||= lambda {} @on_ack_block ||= lambda {|msg_id| self.send(:on_ack, msg_id)}
end end
def self.fail_block def self.on_fail_block
@fail_block ||= lambda {} @on_fail_block ||= lambda {|msg_id| self.send(:on_fail, msg_id)}
end end
def self.send_options def self.send_options

View File

@ -23,10 +23,18 @@ module RedStorm
grouper, params = grouping.first grouper, params = grouping.first
case grouper case grouper
when :shuffle
storm_bolt.shuffleGrouping(source_id)
when :fields when :fields
storm_bolt.fieldsGrouping(source_id, Fields.new(*params)) storm_bolt.fieldsGrouping(source_id, Fields.new(*params))
when :global
storm_bolt.globalGrouping(source_id)
when :shuffle
storm_bolt.shuffleGrouping(source_id)
when :none
storm_bolt.noneGrouping(source_id)
when :all
storm_bolt.allGrouping(source_id)
when :direct
storm_bolt.directGrouping(source_id)
else else
raise("unknown grouper=#{grouper.inspect}") raise("unknown grouper=#{grouper.inspect}")
end end
@ -68,14 +76,14 @@ module RedStorm
def self.spout(spout_class, options = {}) def self.spout(spout_class, options = {})
spout_options = {:id => self.underscore(spout_class), :parallelism => 1}.merge(options) spout_options = {:id => self.underscore(spout_class), :parallelism => 1}.merge(options)
spout = SpoutDefinition.new(spout_class, spout_options[:id], spout_options[:parallelism]) spout = SpoutDefinition.new(spout_class, spout_options[:id], spout_options[:parallelism])
self.spouts << spout self.components << spout
end end
def self.bolt(bolt_class, options = {}, &bolt_block) def self.bolt(bolt_class, options = {}, &bolt_block)
bolt_options = {:id => self.underscore(bolt_class), :parallelism => 1}.merge(options) bolt_options = {:id => self.underscore(bolt_class), :parallelism => 1}.merge(options)
bolt = BoltDefinition.new(bolt_class, bolt_options[:id], bolt_options[:parallelism]) bolt = BoltDefinition.new(bolt_class, bolt_options[:id], bolt_options[:parallelism])
bolt.instance_exec(&bolt_block) bolt.instance_exec(&bolt_block)
self.bolts << bolt self.components << bolt
end end
def self.configure(name = nil, &configure_block) def self.configure(name = nil, &configure_block)
@ -90,7 +98,7 @@ module RedStorm
# topology proxy interface # topology proxy interface
def start(base_class_path, env) def start(base_class_path, env)
self.class.resolve_ids!(self.class.spouts + self.class.bolts) self.class.resolve_ids!(self.class.components)
builder = TopologyBuilder.new builder = TopologyBuilder.new
self.class.spouts.each do |spout| self.class.spouts.each do |spout|
@ -120,28 +128,29 @@ module RedStorm
private private
def self.resolve_ids!(components) def self.resolve_ids!(components)
next_id = 1 next_numeric_id = 1
resolved_names = {} resolved_names = {}
numeric_ids, symbolic_ids = components.map(&:id).partition{|id| id.is_a?(Fixnum)} numeric_components, symbolic_components = components.partition{|c| c.id.is_a?(Fixnum)}
numeric_ids = numeric_components.map(&:id)
# map unused numeric ids to symbolic ids # map unused numeric ids to symbolic ids
symbolic_ids.map(&:to_s).uniq.each do |id| symbolic_components.each do |component|
unless resolved_names.has_key?(id) id = component.id.to_s
next_id += 1 while numeric_ids.include?(next_id) raise("duplicate symbolic id in #{component.clazz.name} on id=#{id}") if resolved_names.has_key?(id)
numeric_ids << next_id next_numeric_id += 1 while numeric_ids.include?(next_numeric_id)
resolved_names[id] = next_id numeric_ids << next_numeric_id
end resolved_names[id] = next_numeric_id
end end
# reassign numeric ids in all components # reassign numeric ids in all components
components.each do |component| components.each do |component|
unless component.id.is_a?(Fixnum) unless component.id.is_a?(Fixnum)
component.id = resolved_names[component.id] || raise("cannot resolve #{component.clazz.name} id=#{component.id.inspect}") component.id = resolved_names[component.id.to_s] || raise("cannot resolve #{component.clazz.name} id=#{component.id.to_s}")
end end
if component.respond_to?(:sources) if component.respond_to?(:sources)
component.sources.map! do |source_id, grouping| component.sources.map! do |source_id, grouping|
id = source_id.is_a?(Fixnum) ? source_id : resolved_names[source_id] || raise("cannot resolve #{component.clazz.name} source id=#{source_id.inspect}") id = source_id.is_a?(Fixnum) ? source_id : resolved_names[source_id.to_s] || raise("cannot resolve #{component.clazz.name} source id=#{source_id.to_s}")
[id, grouping] [id, grouping]
end end
end end
@ -149,11 +158,15 @@ module RedStorm
end end
def self.spouts def self.spouts
@spouts ||= [] self.components.select{|c| c.is_a?(SpoutDefinition)}
end end
def self.bolts def self.bolts
@bolts ||= [] self.components.select{|c| c.is_a?(BoltDefinition)}
end
def self.components
@components ||= []
end end
def self.topology_name def self.topology_name

View File

@ -3,6 +3,12 @@ require 'red_storm/simple_bolt'
describe RedStorm::SimpleBolt do describe RedStorm::SimpleBolt do
before(:each) do
Object.send(:remove_const, "Bolt1") if Object.const_defined?("Bolt1")
Object.send(:remove_const, "Bolt2") if Object.const_defined?("Bolt2")
Object.send(:remove_const, "Bolt3") if Object.const_defined?("Bolt3")
end
describe "interface" do describe "interface" do
it "should implement bolt proxy" do it "should implement bolt proxy" do
spout = RedStorm::SimpleBolt.new spout = RedStorm::SimpleBolt.new
@ -24,37 +30,37 @@ describe RedStorm::SimpleBolt do
describe "output_field statement" do describe "output_field statement" do
it "should parse single argument" do it "should parse single argument" do
class BoltOutputField1 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
output_fields :f1 output_fields :f1
end end
bolt = BoltOutputField1.new bolt = Bolt1.new
BoltOutputField1.send(:fields).should == ["f1"] Bolt1.send(:fields).should == ["f1"]
end end
it "should parse multiple arguments" do it "should parse multiple arguments" do
class BoltOutputField2 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
output_fields :f1, :f2 output_fields :f1, :f2
end end
BoltOutputField2.send(:fields).should == ["f1", "f2"] Bolt1.send(:fields).should == ["f1", "f2"]
end end
it "should parse string and symbol arguments" do it "should parse string and symbol arguments" do
class BoltOutputField3 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
output_fields :f1, "f2" output_fields :f1, "f2"
end end
BoltOutputField3.send(:fields).should == ["f1", "f2"] Bolt1.send(:fields).should == ["f1", "f2"]
end end
it "should not share state over mutiple classes" do it "should not share state over mutiple classes" do
class BoltOutputField4 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
output_fields :f1 output_fields :f1
end end
class BoltOutputField5 < RedStorm::SimpleBolt class Bolt2 < RedStorm::SimpleBolt
output_fields :f2 output_fields :f2
end end
RedStorm::SimpleBolt.send(:fields).should == [] RedStorm::SimpleBolt.send(:fields).should == []
BoltOutputField4.send(:fields).should == ["f1"] Bolt1.send(:fields).should == ["f1"]
BoltOutputField5.send(:fields).should == ["f2"] Bolt2.send(:fields).should == ["f2"]
end end
end end
@ -76,111 +82,163 @@ describe RedStorm::SimpleBolt do
describe "with block argument" do describe "with block argument" do
it "should parse without options" do it "should parse without options" do
class BoltBlockArgument1 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_receive {} on_receive {}
end end
BoltBlockArgument1.receive_options.should == DEFAULT_RECEIVE_OPTIONS Bolt1.receive_options.should == DEFAULT_RECEIVE_OPTIONS
BoltBlockArgument1.send(:emit?).should be_true Bolt1.send(:emit?).should be_true
BoltBlockArgument1.send(:ack?).should be_false Bolt1.send(:ack?).should be_false
BoltBlockArgument1.send(:anchor?).should be_false Bolt1.send(:anchor?).should be_false
end end
it "should parse :emit option" do it "should parse :emit option" do
class BoltBlockArgument2 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_receive :emit => false do on_receive :emit => false do
end end
end end
BoltBlockArgument2.receive_options.should == DEFAULT_RECEIVE_OPTIONS.merge(:emit => false) Bolt1.receive_options.should == DEFAULT_RECEIVE_OPTIONS.merge(:emit => false)
BoltBlockArgument2.send(:emit?).should be_false Bolt1.send(:emit?).should be_false
end end
it "should parse :ack option" do it "should parse :ack option" do
class BoltBlockArgument3 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_receive :ack => true do on_receive :ack => true do
end end
end end
BoltBlockArgument3.receive_options.should == DEFAULT_RECEIVE_OPTIONS.merge(:ack => true) Bolt1.receive_options.should == DEFAULT_RECEIVE_OPTIONS.merge(:ack => true)
BoltBlockArgument3.send(:ack?).should be_true Bolt1.send(:ack?).should be_true
end end
it "should parse :anchor option" do it "should parse :anchor option" do
class BoltBlockArgument4 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_receive :anchor => true do on_receive :anchor => true do
end end
end end
BoltBlockArgument4.receive_options.should == DEFAULT_RECEIVE_OPTIONS.merge(:anchor => true) Bolt1.receive_options.should == DEFAULT_RECEIVE_OPTIONS.merge(:anchor => true)
BoltBlockArgument4.send(:anchor?).should be_true Bolt1.send(:anchor?).should be_true
end end
it "should parse multiple option" do it "should parse multiple option" do
class BoltBlockArgument5 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_receive :emit => false, :ack =>true, :anchor => true do on_receive :emit => false, :ack =>true, :anchor => true do
end end
end end
BoltBlockArgument5.receive_options.should == DEFAULT_RECEIVE_OPTIONS.merge(:emit =>false, :ack => true, :anchor => true) Bolt1.receive_options.should == DEFAULT_RECEIVE_OPTIONS.merge(:emit =>false, :ack => true, :anchor => true)
BoltBlockArgument5.send(:emit?).should be_false Bolt1.send(:emit?).should be_false
BoltBlockArgument5.send(:ack?).should be_true Bolt1.send(:ack?).should be_true
BoltBlockArgument5.send(:anchor?).should be_true Bolt1.send(:anchor?).should be_true
end end
end end
describe "with method name" do describe "with method name" do
it "should parse without options" do it "should parse without options" do
class BoltMethodName1 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_receive :test_method on_receive :test_method
end end
BoltMethodName1.receive_options.should == DEFAULT_RECEIVE_OPTIONS Bolt1.receive_options.should == DEFAULT_RECEIVE_OPTIONS
BoltMethodName1.send(:emit?).should be_true Bolt1.send(:emit?).should be_true
BoltMethodName1.send(:ack?).should be_false Bolt1.send(:ack?).should be_false
BoltMethodName1.send(:anchor?).should be_false Bolt1.send(:anchor?).should be_false
end end
it "should parse :emit option" do it "should parse :emit option" do
class BoltMethodName2 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_receive :test_method, :emit => false on_receive :test_method, :emit => false
end end
BoltMethodName2.receive_options.should == DEFAULT_RECEIVE_OPTIONS.merge(:emit => false) Bolt1.receive_options.should == DEFAULT_RECEIVE_OPTIONS.merge(:emit => false)
BoltMethodName2.send(:emit?).should be_false Bolt1.send(:emit?).should be_false
end end
it "should parse :ack option" do it "should parse :ack option" do
class BoltMethodName3 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_receive :ack => true do on_receive :ack => true do
end end
end end
BoltMethodName3.receive_options.should == DEFAULT_RECEIVE_OPTIONS.merge(:ack => true) Bolt1.receive_options.should == DEFAULT_RECEIVE_OPTIONS.merge(:ack => true)
BoltMethodName3.send(:ack?).should be_true Bolt1.send(:ack?).should be_true
end end
it "should parse :anchor option" do it "should parse :anchor option" do
class BoltMethodName4 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_receive :anchor => true do on_receive :anchor => true do
end end
end end
BoltMethodName4.receive_options.should == DEFAULT_RECEIVE_OPTIONS.merge(:anchor => true) Bolt1.receive_options.should == DEFAULT_RECEIVE_OPTIONS.merge(:anchor => true)
BoltMethodName4.send(:anchor?).should be_true Bolt1.send(:anchor?).should be_true
end end
it "should parse multiple option" do it "should parse multiple option" do
class BoltMethodName5 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_receive :emit => false, :ack =>true, :anchor => true do on_receive :emit => false, :ack =>true, :anchor => true do
end end
end end
BoltMethodName5.receive_options.should == DEFAULT_RECEIVE_OPTIONS.merge(:emit =>false, :ack => true, :anchor => true) Bolt1.receive_options.should == DEFAULT_RECEIVE_OPTIONS.merge(:emit =>false, :ack => true, :anchor => true)
BoltMethodName5.send(:emit?).should be_false Bolt1.send(:emit?).should be_false
BoltMethodName5.send(:ack?).should be_true Bolt1.send(:ack?).should be_true
BoltMethodName5.send(:anchor?).should be_true Bolt1.send(:anchor?).should be_true
end
end
describe "with default method" do
it "should parse without options" do
class Bolt1 < RedStorm::SimpleBolt
end
Bolt1.receive_options.should == DEFAULT_RECEIVE_OPTIONS
Bolt1.send(:emit?).should be_true
Bolt1.send(:ack?).should be_false
Bolt1.send(:anchor?).should be_false
end
it "should parse :emit option" do
class Bolt1 < RedStorm::SimpleBolt
on_receive :emit => false
end
Bolt1.receive_options.should == DEFAULT_RECEIVE_OPTIONS.merge(:emit => false)
Bolt1.send(:emit?).should be_false
end
it "should parse :ack option" do
class Bolt1 < RedStorm::SimpleBolt
on_receive :ack => true
end
Bolt1.receive_options.should == DEFAULT_RECEIVE_OPTIONS.merge(:ack => true)
Bolt1.send(:ack?).should be_true
end
it "should parse :anchor option" do
class Bolt1 < RedStorm::SimpleBolt
on_receive :anchor => true
end
Bolt1.receive_options.should == DEFAULT_RECEIVE_OPTIONS.merge(:anchor => true)
Bolt1.send(:anchor?).should be_true
end
it "should parse multiple option" do
class Bolt1 < RedStorm::SimpleBolt
on_receive :emit => false, :ack =>true, :anchor => true
end
Bolt1.receive_options.should == DEFAULT_RECEIVE_OPTIONS.merge(:emit =>false, :ack => true, :anchor => true)
Bolt1.send(:emit?).should be_false
Bolt1.send(:ack?).should be_true
Bolt1.send(:anchor?).should be_true
end end
end end
@ -189,21 +247,21 @@ describe RedStorm::SimpleBolt do
describe "on_init statement" do describe "on_init statement" do
it "should parse block argument" do it "should parse block argument" do
class BoltOnInitBlockArgument1 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_init {self.test_block_call} on_init {self.test_block_call}
end end
bolt = BoltOnInitBlockArgument1.new bolt = Bolt1.new
bolt.should_receive(:test_block_call) bolt.should_receive(:test_block_call)
bolt.prepare(nil, nil, nil) bolt.prepare(nil, nil, nil)
end end
it "should parse method name" do it "should parse method name" do
class BoltOnInitMethodName1 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_init :test_method on_init :test_method
end end
bolt = BoltOnInitMethodName1.new bolt = Bolt1.new
bolt.should_receive(:test_method) bolt.should_receive(:test_method)
bolt.prepare(nil, nil, nil) bolt.prepare(nil, nil, nil)
end end
@ -212,21 +270,21 @@ describe RedStorm::SimpleBolt do
describe "on_close statement" do describe "on_close statement" do
it "should parse block argument" do it "should parse block argument" do
class BoltOnCloseBlockArgument1 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_close {self.test_block_call} on_close {self.test_block_call}
end end
bolt = BoltOnCloseBlockArgument1.new bolt = Bolt1.new
bolt.should_receive(:test_block_call) bolt.should_receive(:test_block_call)
bolt.cleanup bolt.cleanup
end end
it "should parse method name" do it "should parse method name" do
class BoltOnCloseMethodName1 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_close :test_method on_close :test_method
end end
bolt = BoltOnCloseMethodName1.new bolt = Bolt1.new
bolt.should_receive(:test_method) bolt.should_receive(:test_method)
bolt.cleanup bolt.cleanup
end end
@ -237,84 +295,171 @@ describe RedStorm::SimpleBolt do
describe "execute" do describe "execute" do
class RedStorm::Values; end
it "should auto emit on single value output" do it "should auto emit on single value output" do
class BoltNextTuple1 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_receive {|tuple| tuple} on_receive {|tuple| tuple}
end end
class Bolt2 < RedStorm::SimpleBolt
on_receive :my_method
def my_method(tuple); tuple; end
end
class Bolt3 < RedStorm::SimpleBolt
def on_receive(tuple); tuple; end
end
collector = mock("Collector") collector = mock("Collector")
RedStorm::Values.should_receive(:new).with("output").exactly(3).times.and_return("values")
collector.should_receive(:emit).with("values").exactly(3).times
class RedStorm::Values; end bolt = Bolt1.new
RedStorm::Values.should_receive(:new).with("output").and_return("values") bolt.prepare(nil, nil, collector)
collector.should_receive(:emit).with("values") bolt.execute("output")
bolt = BoltNextTuple1.new bolt = Bolt2.new
bolt.prepare(nil, nil, collector)
bolt.execute("output")
bolt = Bolt3.new
bolt.prepare(nil, nil, collector) bolt.prepare(nil, nil, collector)
bolt.execute("output") bolt.execute("output")
end end
it "should auto emit on multiple value output" do it "should auto emit on multiple value output" do
class BoltNextTuple2 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_receive {|tuple| tuple} on_receive {|tuple| tuple}
end end
class Bolt2 < RedStorm::SimpleBolt
on_receive :my_method
def my_method(tuple); tuple; end
end
class Bolt3 < RedStorm::SimpleBolt
def on_receive(tuple); tuple; end
end
collector = mock("Collector") collector = mock("Collector")
RedStorm::Values.should_receive(:new).with("output1", "output2").exactly(3).times.and_return("values")
collector.should_receive(:emit).with("values").exactly(3).times
class RedStorm::Values; end bolt = Bolt1.new
RedStorm::Values.should_receive(:new).with("output1", "output2").and_return("values") bolt.prepare(nil, nil, collector)
collector.should_receive(:emit).with("values") bolt.execute(["output1", "output2"])
bolt = BoltNextTuple2.new bolt = Bolt2.new
bolt.prepare(nil, nil, collector)
bolt.execute(["output1", "output2"])
bolt = Bolt3.new
bolt.prepare(nil, nil, collector) bolt.prepare(nil, nil, collector)
bolt.execute(["output1", "output2"]) bolt.execute(["output1", "output2"])
end end
it "should anchor on single value output" do it "should anchor on single value output" do
class BoltNextTuple3 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_receive :anchor => true do |tuple| on_receive :anchor => true do |tuple|
"output" "output"
end end
end end
class Bolt2 < RedStorm::SimpleBolt
on_receive :my_method, :anchor => true
def my_method(tuple)
"output"
end
end
class Bolt3 < RedStorm::SimpleBolt
on_receive :anchor => true
def on_receive(tuple)
"output"
end
end
collector = mock("Collector") collector = mock("Collector")
RedStorm::Values.should_receive(:new).with("output").exactly(3).times.and_return("values")
collector.should_receive(:emit).with("tuple", "values").exactly(3).times
class RedStorm::Values; end bolt = Bolt1.new
RedStorm::Values.should_receive(:new).with("output").and_return("values") bolt.prepare(nil, nil, collector)
collector.should_receive(:emit).with("tuple", "values") bolt.execute("tuple")
bolt = BoltNextTuple3.new bolt = Bolt2.new
bolt.prepare(nil, nil, collector)
bolt.execute("tuple")
bolt = Bolt3.new
bolt.prepare(nil, nil, collector) bolt.prepare(nil, nil, collector)
bolt.execute("tuple") bolt.execute("tuple")
end end
it "should ack on single value output" do it "should ack on single value output" do
class BoltNextTuple4 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_receive :anchor => true, :ack => true do |tuple| on_receive :anchor => true, :ack => true do |tuple|
"output" "output"
end end
end end
class Bolt2 < RedStorm::SimpleBolt
on_receive :my_method, :anchor => true, :ack => true
def my_method(tuple)
"output"
end
end
class Bolt3 < RedStorm::SimpleBolt
on_receive :anchor => true, :ack => true
def on_receive(tuple)
"output"
end
end
collector = mock("Collector") collector = mock("Collector")
RedStorm::Values.should_receive(:new).with("output").exactly(3).times.and_return("values")
collector.should_receive(:emit).with("tuple", "values").exactly(3).times
collector.should_receive(:ack).with("tuple").exactly(3).times
class RedStorm::Values; end bolt = Bolt1.new
RedStorm::Values.should_receive(:new).with("output").and_return("values") bolt.prepare(nil, nil, collector)
collector.should_receive(:emit).with("tuple", "values") bolt.execute("tuple")
collector.should_receive(:ack).with("tuple")
bolt = BoltNextTuple4.new bolt = Bolt2.new
bolt.prepare(nil, nil, collector)
bolt.execute("tuple")
bolt = Bolt3.new
bolt.prepare(nil, nil, collector) bolt.prepare(nil, nil, collector)
bolt.execute("tuple") bolt.execute("tuple")
end end
it "should not emit" do it "should not emit" do
class BoltNextTuple5 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_receive :emit => false do |tuple| on_receive :emit => false do |tuple|
tuple tuple
end end
end end
collector = mock("Collector") class Bolt2 < RedStorm::SimpleBolt
on_receive :my_method, :emit => false
def my_method(tuple)
tuple
end
end
class Bolt3 < RedStorm::SimpleBolt
on_receive :emit => false
def on_receive(tuple)
tuple
end
end
class RedStorm::Values; end collector = mock("Collector")
RedStorm::Values.should_receive(:new).never RedStorm::Values.should_receive(:new).never
collector.should_receive(:emit).never collector.should_receive(:emit).never
bolt = BoltNextTuple5.new bolt = Bolt1.new
bolt.prepare(nil, nil, collector)
bolt.execute("output")
bolt = Bolt2.new
bolt.prepare(nil, nil, collector)
bolt.execute("output")
bolt = Bolt3.new
bolt.prepare(nil, nil, collector) bolt.prepare(nil, nil, collector)
bolt.execute("output") bolt.execute("output")
end end
@ -322,12 +467,39 @@ describe RedStorm::SimpleBolt do
describe "prepare" do describe "prepare" do
it "should assing collector, context, config and call init block" do it "should assing collector, context, config and call init block" do
class BoltPrepare1 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_init {trigger} on_init {trigger}
end end
bolt = BoltPrepare1.new class Bolt2 < RedStorm::SimpleBolt
bolt.should_receive(:trigger).once on_init :my_method
def my_method; trigger; end
end
class Bolt3 < RedStorm::SimpleBolt
def on_init; trigger; end
end
bolt = Bolt1.new
bolt.should_receive(:trigger).once
bolt.config.should be_nil
bolt.context.should be_nil
bolt.collector.should be_nil
bolt.prepare("config", "context", "collector")
bolt.config.should == "config"
bolt.context.should == "context"
bolt.collector.should == "collector"
bolt = Bolt2.new
bolt.should_receive(:trigger).once
bolt.config.should be_nil
bolt.context.should be_nil
bolt.collector.should be_nil
bolt.prepare("config", "context", "collector")
bolt.config.should == "config"
bolt.context.should == "context"
bolt.collector.should == "collector"
bolt = Bolt3.new
bolt.should_receive(:trigger).once
bolt.config.should be_nil bolt.config.should be_nil
bolt.context.should be_nil bolt.context.should be_nil
bolt.collector.should be_nil bolt.collector.should be_nil
@ -340,22 +512,37 @@ describe RedStorm::SimpleBolt do
describe "cleanup" do describe "cleanup" do
it "should call close block" do it "should call close block" do
class BoltClose1 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
on_close {trigger} on_close {trigger}
end end
bolt = BoltClose1.new class Bolt2 < RedStorm::SimpleBolt
bolt.should_receive(:trigger).once on_close :my_method
def my_method; trigger; end
end
class Bolt3 < RedStorm::SimpleBolt
def on_close; trigger; end
end
bolt = Bolt1.new
bolt.should_receive(:trigger).once
bolt.cleanup
bolt = Bolt2.new
bolt.should_receive(:trigger).once
bolt.cleanup
bolt = Bolt3.new
bolt.should_receive(:trigger).once
bolt.cleanup bolt.cleanup
end end
end end
describe "declare_output_fields" do describe "declare_output_fields" do
it "should declare fields" do it "should declare fields" do
class BoltDeclare1 < RedStorm::SimpleBolt class Bolt1 < RedStorm::SimpleBolt
output_fields :f1, :f2 output_fields :f1, :f2
end end
bolt = BoltDeclare1.new bolt = Bolt1.new
class RedStorm::Fields; end class RedStorm::Fields; end
declarer = mock("Declarer") declarer = mock("Declarer")
declarer.should_receive(:declare).with("fields") declarer.should_receive(:declare).with("fields")

View File

@ -3,6 +3,12 @@ require 'red_storm/simple_spout'
describe RedStorm::SimpleSpout do describe RedStorm::SimpleSpout do
before(:each) do
Object.send(:remove_const, "Spout1") if Object.const_defined?("Spout1")
Object.send(:remove_const, "Spout2") if Object.const_defined?("Spout2")
Object.send(:remove_const, "Spout3") if Object.const_defined?("Spout3")
end
describe "interface" do describe "interface" do
it "should implement spout proxy" do it "should implement spout proxy" do
spout = RedStorm::SimpleSpout.new spout = RedStorm::SimpleSpout.new
@ -46,37 +52,36 @@ describe RedStorm::SimpleSpout do
describe "output_field statement" do describe "output_field statement" do
it "should parse single argument" do it "should parse single argument" do
class Test1 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
output_fields :f1 output_fields :f1
end end
test1 = Test1.new Spout1.send(:fields).should == ["f1"]
Test1.send(:fields).should == ["f1"]
end end
it "should parse multiple arguments" do it "should parse multiple arguments" do
class Test2 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
output_fields :f1, :f2 output_fields :f1, :f2
end end
Test2.send(:fields).should == ["f1", "f2"] Spout1.send(:fields).should == ["f1", "f2"]
end end
it "should parse string and symbol arguments" do it "should parse string and symbol arguments" do
class Test3 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
output_fields :f1, "f2" output_fields :f1, "f2"
end end
Test3.send(:fields).should == ["f1", "f2"] Spout1.send(:fields).should == ["f1", "f2"]
end end
it "should not share state over mutiple classes" do it "should not share state over mutiple classes" do
class Test4 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
output_fields :f1 output_fields :f1
end end
class Test5 < RedStorm::SimpleSpout class Spout2 < RedStorm::SimpleSpout
output_fields :f2 output_fields :f2
end end
RedStorm::SimpleSpout.send(:fields).should == [] RedStorm::SimpleSpout.send(:fields).should == []
Test4.send(:fields).should == ["f1"] Spout1.send(:fields).should == ["f1"]
Test5.send(:fields).should == ["f2"] Spout2.send(:fields).should == ["f2"]
end end
end end
@ -90,29 +95,29 @@ describe RedStorm::SimpleSpout do
describe "with block argument" do describe "with block argument" do
it "should parse without options" do it "should parse without options" do
class BlockArgument1 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
on_send {self.test_method} on_send {self.test_method}
end end
BlockArgument1.send_options.should == DEFAULT_SEND_OPTIONS Spout1.send_options.should == DEFAULT_SEND_OPTIONS
spout = BlockArgument1.new spout = Spout1.new
spout.should_receive(:test_method) spout.should_receive(:test_method)
BlockArgument1.should_receive(:emit?).and_return(false) Spout1.should_receive(:emit?).and_return(false)
spout.next_tuple spout.next_tuple
end end
it "should parse :emit option" do it "should parse :emit option" do
class BlockArgument2 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
on_send :emit => false do on_send :emit => false do
self.test_method self.test_method
end end
end end
BlockArgument2.send_options.should == DEFAULT_SEND_OPTIONS.merge(:emit => false) Spout1.send_options.should == DEFAULT_SEND_OPTIONS.merge(:emit => false)
BlockArgument2.send(:emit?).should be_false Spout1.send(:emit?).should be_false
spout = BlockArgument2.new spout = Spout1.new
spout.should_receive(:test_method) spout.should_receive(:test_method)
spout.next_tuple spout.next_tuple
end end
@ -121,51 +126,92 @@ describe RedStorm::SimpleSpout do
describe "with method name" do describe "with method name" do
it "should parse without options" do it "should parse without options" do
class MethodName1 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
on_send :test_method on_send :test_method
end end
MethodName1.send_options.should == DEFAULT_SEND_OPTIONS Spout1.send_options.should == DEFAULT_SEND_OPTIONS
spout = MethodName1.new spout = Spout1.new
spout.should_receive(:test_method) spout.should_receive(:test_method)
MethodName1.should_receive(:emit?).and_return(false) Spout1.should_receive(:emit?).and_return(false)
spout.next_tuple spout.next_tuple
end end
it "should parse :emit option" do it "should parse :emit option" do
class MethodName2 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
on_send :test_method, :emit => false on_send :test_method, :emit => false
end end
MethodName2.send_options.should == DEFAULT_SEND_OPTIONS.merge(:emit => false) Spout1.send_options.should == DEFAULT_SEND_OPTIONS.merge(:emit => false)
MethodName2.send(:emit?).should be_false Spout1.send(:emit?).should be_false
spout = MethodName2.new spout = Spout1.new
spout.should_receive(:test_method)
spout.next_tuple
end
end
describe "with method" do
it "should parse without options" do
class Spout1 < RedStorm::SimpleSpout
def on_send; test_method; end
end
Spout1.send_options.should == DEFAULT_SEND_OPTIONS
spout = Spout1.new
spout.should_receive(:test_method)
Spout1.should_receive(:emit?).and_return(false)
spout.next_tuple
end
it "should parse :emit option" do
class Spout1 < RedStorm::SimpleSpout
on_send :emit => false
def on_send; test_method; end
end
Spout1.send_options.should == DEFAULT_SEND_OPTIONS.merge(:emit => false)
Spout1.send(:emit?).should be_false
spout = Spout1.new
spout.should_receive(:test_method) spout.should_receive(:test_method)
spout.next_tuple spout.next_tuple
end end
end end
end end
describe "on_init statement" do describe "on_init statement" do
it "should parse block argument" do it "should parse block argument" do
class OnInitBlockArgument1 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
on_init {self.test_block_call} on_init {self.test_block_call}
end end
spout = OnInitBlockArgument1.new spout = Spout1.new
spout.should_receive(:test_block_call) spout.should_receive(:test_block_call)
spout.open(nil, nil, nil) spout.open(nil, nil, nil)
end end
it "should parse method name" do it "should parse method name" do
class OnInitMethodName1 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
on_init :test_method on_init :test_method
end end
spout = OnInitMethodName1.new spout = Spout1.new
spout.should_receive(:test_method)
spout.open(nil, nil, nil)
end
it "should call method" do
class Spout1 < RedStorm::SimpleSpout
def on_init; test_method; end
end
spout = Spout1.new
spout.should_receive(:test_method) spout.should_receive(:test_method)
spout.open(nil, nil, nil) spout.open(nil, nil, nil)
end end
@ -174,21 +220,31 @@ describe RedStorm::SimpleSpout do
describe "on_close statement" do describe "on_close statement" do
it "should parse block argument" do it "should parse block argument" do
class OnCloseBlockArgument1 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
on_close {self.test_block_call} on_close {self.test_block_call}
end end
spout = OnCloseBlockArgument1.new spout = Spout1.new
spout.should_receive(:test_block_call) spout.should_receive(:test_block_call)
spout.close spout.close
end end
it "should parse method name" do it "should parse method name" do
class OnCloseMethodName1 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
on_close :test_method on_close :test_method
end end
spout = OnCloseMethodName1.new spout = Spout1.new
spout.should_receive(:test_method)
spout.close
end
it "should call method" do
class Spout1 < RedStorm::SimpleSpout
def on_close; test_method; end
end
spout = Spout1.new
spout.should_receive(:test_method) spout.should_receive(:test_method)
spout.close spout.close
end end
@ -197,21 +253,31 @@ describe RedStorm::SimpleSpout do
describe "on_ack statement" do describe "on_ack statement" do
it "should parse block argument" do it "should parse block argument" do
class OnAckBlockArgument1 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
on_ack {|msg_id| self.test_block_call(msg_id)} on_ack {|msg_id| self.test_block_call(msg_id)}
end end
spout = OnAckBlockArgument1.new spout = Spout1.new
spout.should_receive(:test_block_call).with("test") spout.should_receive(:test_block_call).with("test")
spout.ack("test") spout.ack("test")
end end
it "should parse method name" do it "should parse method name" do
class OnAckMethodName1 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
on_ack :test_method on_ack :test_method
end end
spout = OnAckMethodName1.new spout = Spout1.new
spout.should_receive(:test_method).with("test")
spout.ack("test")
end
it "should call method " do
class Spout1 < RedStorm::SimpleSpout
def on_ack(msg_id); test_method(msg_id); end
end
spout = Spout1.new
spout.should_receive(:test_method).with("test") spout.should_receive(:test_method).with("test")
spout.ack("test") spout.ack("test")
end end
@ -220,21 +286,31 @@ describe RedStorm::SimpleSpout do
describe "on_fail statement" do describe "on_fail statement" do
it "should parse block argument" do it "should parse block argument" do
class OnFailBlockArgument1 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
on_fail {|msg_id| self.test_block_call(msg_id)} on_fail {|msg_id| self.test_block_call(msg_id)}
end end
spout = OnFailBlockArgument1.new spout = Spout1.new
spout.should_receive(:test_block_call).with("test") spout.should_receive(:test_block_call).with("test")
spout.fail("test") spout.fail("test")
end end
it "should parse method name" do it "should parse method name" do
class OnFailMethodName1 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
on_fail :test_method on_fail :test_method
end end
spout = OnFailMethodName1.new spout = Spout1.new
spout.should_receive(:test_method).with("test")
spout.fail("test")
end
it "should parse method name" do
class Spout1 < RedStorm::SimpleSpout
def on_fail(msg_id); test_method(msg_id); end
end
spout = Spout1.new
spout.should_receive(:test_method).with("test") spout.should_receive(:test_method).with("test")
spout.fail("test") spout.fail("test")
end end
@ -244,67 +320,130 @@ describe RedStorm::SimpleSpout do
describe "spout" do describe "spout" do
class RedStorm::Values; end
describe "next_tuple" do describe "next_tuple" do
it "should auto emit on single value output" do it "should auto emit on single value output" do
class SpoutNextTuple1 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
on_send {"output"} on_send {"output"}
end end
class Spout2 < RedStorm::SimpleSpout
on_send :my_method
def my_method; "output"; end
end
class Spout3 < RedStorm::SimpleSpout
def on_send; "output"; end
end
collector = mock("Collector") collector = mock("Collector")
RedStorm::Values.should_receive(:new).with("output").exactly(3).times.and_return("values")
collector.should_receive(:emit).with("values").exactly(3).times
class RedStorm::Values; end spout = Spout1.new
RedStorm::Values.should_receive(:new).with("output").and_return("values") spout.open(nil, nil, collector)
collector.should_receive(:emit).with("values") spout.next_tuple
spout = SpoutNextTuple1.new spout = Spout2.new
spout.open(nil, nil, collector)
spout.next_tuple
spout = Spout3.new
spout.open(nil, nil, collector) spout.open(nil, nil, collector)
spout.next_tuple spout.next_tuple
end end
it "should auto emit on multiple values output" do it "should auto emit on multiple values output" do
class SpoutNextTuple2 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
on_send {["output1", "output2"]} on_send {["output1", "output2"]}
end end
class Spout2 < RedStorm::SimpleSpout
on_send :my_method
def my_method; ["output1", "output2"]; end
end
class Spout3 < RedStorm::SimpleSpout
def on_send; ["output1", "output2"]; end
end
collector = mock("Collector") collector = mock("Collector")
RedStorm::Values.should_receive(:new).with("output1", "output2").exactly(3).times.and_return("values")
collector.should_receive(:emit).with("values").exactly(3).times
class RedStorm::Values; end spout = Spout1.new
RedStorm::Values.should_receive(:new).with("output1", "output2").and_return("values") spout.open(nil, nil, collector)
collector.should_receive(:emit).with("values") spout.next_tuple
spout = SpoutNextTuple2.new spout = Spout2.new
spout.open(nil, nil, collector)
spout.next_tuple
spout = Spout3.new
spout.open(nil, nil, collector) spout.open(nil, nil, collector)
spout.next_tuple spout.next_tuple
end end
it "should sleep on nil output" do it "should sleep on nil output" do
class SpoutNextTuple2 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
on_send {nil} on_send {nil}
end end
collector = mock("Collector") class Spout2 < RedStorm::SimpleSpout
on_send :my_method
def my_method; nil; end
end
class Spout3 < RedStorm::SimpleSpout
def on_send; nil; end
end
class RedStorm::Values; end collector = mock("Collector")
RedStorm::Values.should_receive(:new).never RedStorm::Values.should_receive(:new).never
collector.should_receive(:emit).never collector.should_receive(:emit).never
spout = SpoutNextTuple2.new spout = Spout1.new
spout.should_receive(:sleep)
spout.open(nil, nil, collector)
spout.next_tuple
spout = Spout2.new
spout.should_receive(:sleep)
spout.open(nil, nil, collector)
spout.next_tuple
spout = Spout3.new
spout.should_receive(:sleep) spout.should_receive(:sleep)
spout.open(nil, nil, collector) spout.open(nil, nil, collector)
spout.next_tuple spout.next_tuple
end end
it "should respect :emit => false" do it "should respect :emit => false" do
class SpoutNextTuple3 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
on_send :emit => false do on_send :emit => false do
"output" "output"
end end
end end
collector = mock("Collector") class Spout2 < RedStorm::SimpleSpout
on_send :my_method, :emit => false
def my_method; "output"; end
end
class Spout3 < RedStorm::SimpleSpout
on_send :emit => false
def on_send; "output" end
end
class RedStorm::Values; end collector = mock("Collector")
RedStorm::Values.should_receive(:new).never RedStorm::Values.should_receive(:new).never
collector.should_receive(:emit).never collector.should_receive(:emit).never
spout = SpoutNextTuple3.new spout = Spout1.new
spout.should_receive(:sleep).never
spout.open(nil, nil, collector)
spout.next_tuple
spout = Spout2.new
spout.should_receive(:sleep).never
spout.open(nil, nil, collector)
spout.next_tuple
spout = Spout3.new
spout.should_receive(:sleep).never spout.should_receive(:sleep).never
spout.open(nil, nil, collector) spout.open(nil, nil, collector)
spout.next_tuple spout.next_tuple
@ -313,12 +452,39 @@ describe RedStorm::SimpleSpout do
describe "open" do describe "open" do
it "should assing collector, context, config and call init block" do it "should assing collector, context, config and call init block" do
class SpoutPrepare1 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
on_init {trigger} on_init {trigger}
end end
spout = SpoutPrepare1.new class Spout2 < RedStorm::SimpleSpout
spout.should_receive(:trigger).once on_init :my_method
def my_method; trigger; end
end
class Spout3 < RedStorm::SimpleSpout
def on_init; trigger; end
end
spout = Spout1.new
spout.should_receive(:trigger).once
spout.config.should be_nil
spout.context.should be_nil
spout.collector.should be_nil
spout.open("config", "context", "collector")
spout.config.should == "config"
spout.context.should == "context"
spout.collector.should == "collector"
spout = Spout2.new
spout.should_receive(:trigger).once
spout.config.should be_nil
spout.context.should be_nil
spout.collector.should be_nil
spout.open("config", "context", "collector")
spout.config.should == "config"
spout.context.should == "context"
spout.collector.should == "collector"
spout = Spout3.new
spout.should_receive(:trigger).once
spout.config.should be_nil spout.config.should be_nil
spout.context.should be_nil spout.context.should be_nil
spout.collector.should be_nil spout.collector.should be_nil
@ -331,22 +497,37 @@ describe RedStorm::SimpleSpout do
describe "close" do describe "close" do
it "should call close block" do it "should call close block" do
class SpoutClose1 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
on_close {trigger} on_close {trigger}
end end
spout = SpoutClose1.new class Spout2 < RedStorm::SimpleSpout
spout.should_receive(:trigger).once on_close :my_method
def my_method; trigger; end
end
class Spout3 < RedStorm::SimpleSpout
def on_close; trigger; end
end
spout = Spout1.new
spout.should_receive(:trigger).once
spout.close
spout = Spout2.new
spout.should_receive(:trigger).once
spout.close
spout = Spout2.new
spout.should_receive(:trigger).once
spout.close spout.close
end end
end end
describe "declare_output_fields" do describe "declare_output_fields" do
it "should declare fields" do it "should declare fields" do
class SpoutDeclare1 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
output_fields :f1, :f2 output_fields :f1, :f2
end end
spout = SpoutDeclare1.new spout = Spout1.new
class RedStorm::Fields; end class RedStorm::Fields; end
declarer = mock("Declarer") declarer = mock("Declarer")
declarer.should_receive(:declare).with("fields") declarer.should_receive(:declare).with("fields")
@ -358,20 +539,36 @@ describe RedStorm::SimpleSpout do
describe "is_distributed" do describe "is_distributed" do
it "should report is_distributed" do it "should report is_distributed" do
RedStorm::SimpleSpout.is_distributed?.should be_false RedStorm::SimpleSpout.is_distributed?.should be_false
class SpoutIsDistributed1 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
set :is_distributed => true set :is_distributed => true
end end
spout = SpoutIsDistributed1.new spout = Spout1.new
spout.is_distributed.should be_true spout.is_distributed.should be_true
end end
end end
describe "ack" do describe "ack" do
it "should call ack block" do it "should call ack block" do
class SpoutAck1 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
on_ack {|msg_id| trigger(msg_id)} on_ack {|msg_id| trigger(msg_id)}
end end
spout = SpoutAck1.new class Spout2 < RedStorm::SimpleSpout
on_ack :my_method
def my_method(msg_id) trigger(msg_id); end
end
class Spout3 < RedStorm::SimpleSpout
def on_ack(msg_id) trigger(msg_id); end
end
spout = Spout1.new
spout.should_receive(:trigger).once.with("test")
spout.ack("test")
spout = Spout2.new
spout.should_receive(:trigger).once.with("test")
spout.ack("test")
spout = Spout3.new
spout.should_receive(:trigger).once.with("test") spout.should_receive(:trigger).once.with("test")
spout.ack("test") spout.ack("test")
end end
@ -379,10 +576,26 @@ describe RedStorm::SimpleSpout do
describe "fail" do describe "fail" do
it "should call fail block" do it "should call fail block" do
class SpoutFail1 < RedStorm::SimpleSpout class Spout1 < RedStorm::SimpleSpout
on_fail {|msg_id| trigger(msg_id)} on_fail {|msg_id| trigger(msg_id)}
end end
spout = SpoutFail1.new class Spout2 < RedStorm::SimpleSpout
on_fail :my_method
def my_method(msg_id) trigger(msg_id); end
end
class Spout3 < RedStorm::SimpleSpout
def on_fail(msg_id) trigger(msg_id); end
end
spout = Spout1.new
spout.should_receive(:trigger).once.with("test")
spout.fail("test")
spout = Spout2.new
spout.should_receive(:trigger).once.with("test")
spout.fail("test")
spout = Spout3.new
spout.should_receive(:trigger).once.with("test") spout.should_receive(:trigger).once.with("test")
spout.fail("test") spout.fail("test")
end end

View File

@ -3,9 +3,15 @@ require 'red_storm/simple_topology'
describe RedStorm::SimpleTopology do describe RedStorm::SimpleTopology do
before(:each) do
Object.send(:remove_const, "Topology1") if Object.const_defined?("Topology1")
Object.send(:remove_const, "Topology2") if Object.const_defined?("Topology2")
Object.send(:remove_const, "Topology3") if Object.const_defined?("Topology3")
end
it "should set default topology name" do it "should set default topology name" do
class DefaultTopologyName < RedStorm::SimpleTopology; end class Topology1 < RedStorm::SimpleTopology; end
DefaultTopologyName.topology_name.should == "default_topology_name" Topology1.topology_name.should == "topology1"
end end
@ -31,21 +37,24 @@ describe RedStorm::SimpleTopology do
class SpoutClass2; end class SpoutClass2; end
it "should parse single spout without options" do it "should parse single spout without options" do
RedStorm::SimpleTopology::SpoutDefinition.should_receive(:new).with(SpoutClass1, "spout_class1", 1).and_return("spout_definition") spout = RedStorm::SimpleTopology::SpoutDefinition.new(SpoutClass1, "spout_class1", 1)
class TopologySpout1 < RedStorm::SimpleTopology RedStorm::SimpleTopology::SpoutDefinition.should_receive(:new).with(SpoutClass1, "spout_class1", 1).and_return(spout)
class Topology1 < RedStorm::SimpleTopology
spout SpoutClass1 spout SpoutClass1
end end
TopologySpout1.spouts.should == ["spout_definition"] Topology1.spouts.should == [spout]
end end
it "should parse multiple spouts with options" do it "should parse multiple spouts with options" do
RedStorm::SimpleTopology::SpoutDefinition.should_receive(:new).with(SpoutClass1, "id1", 2).and_return("spout_definition1") spout1 = RedStorm::SimpleTopology::SpoutDefinition.new(SpoutClass1, "id1", 2)
RedStorm::SimpleTopology::SpoutDefinition.should_receive(:new).with(SpoutClass2, "id2", 3).and_return("spout_definition2") spout2 = RedStorm::SimpleTopology::SpoutDefinition.new(SpoutClass2, "id2", 3)
class TopologySpout2 < RedStorm::SimpleTopology RedStorm::SimpleTopology::SpoutDefinition.should_receive(:new).with(SpoutClass1, "id1", 2).and_return(spout1)
RedStorm::SimpleTopology::SpoutDefinition.should_receive(:new).with(SpoutClass2, "id2", 3).and_return(spout2)
class Topology1 < RedStorm::SimpleTopology
spout SpoutClass1, :id => "id1", :parallelism => 2 spout SpoutClass1, :id => "id1", :parallelism => 2
spout SpoutClass2, :id => "id2", :parallelism => 3 spout SpoutClass2, :id => "id2", :parallelism => 3
end end
TopologySpout2.spouts.should == ["spout_definition1", "spout_definition2"] Topology1.spouts.should == [spout1, spout2]
end end
end end
@ -56,7 +65,7 @@ describe RedStorm::SimpleTopology do
class BoltClass2; end class BoltClass2; end
it "should parse single bolt without options" do it "should parse single bolt without options" do
bolt_definition = mock("BoltDefinition") bolt_definition = RedStorm::SimpleTopology::BoltDefinition.new(BoltClass1, "bolt_class1", 1)
RedStorm::SimpleTopology::BoltDefinition.should_receive(:new).with(BoltClass1, "bolt_class1", 1).and_return(bolt_definition) RedStorm::SimpleTopology::BoltDefinition.should_receive(:new).with(BoltClass1, "bolt_class1", 1).and_return(bolt_definition)
bolt_definition.should_receive(:source).with(1, {:fields => ["f1"]}) bolt_definition.should_receive(:source).with(1, {:fields => ["f1"]})
class TopologyBolt1 < RedStorm::SimpleTopology class TopologyBolt1 < RedStorm::SimpleTopology
@ -68,25 +77,25 @@ describe RedStorm::SimpleTopology do
end end
it "should parse single bolt with options" do it "should parse single bolt with options" do
bolt_definition = mock("BoltDefinition") bolt_definition = RedStorm::SimpleTopology::BoltDefinition.new(BoltClass1, "id", 2)
RedStorm::SimpleTopology::BoltDefinition.should_receive(:new).with(BoltClass1, "id", 2).and_return(bolt_definition) RedStorm::SimpleTopology::BoltDefinition.should_receive(:new).with(BoltClass1, "id", 2).and_return(bolt_definition)
bolt_definition.should_receive(:source).with(1, :shuffle) bolt_definition.should_receive(:source).with(1, :shuffle)
class TopologyBolt2 < RedStorm::SimpleTopology class Topology1 < RedStorm::SimpleTopology
bolt BoltClass1, :id => "id", :parallelism => 2 do bolt BoltClass1, :id => "id", :parallelism => 2 do
source 1, :shuffle source 1, :shuffle
end end
end end
TopologyBolt2.bolts.should == [bolt_definition] Topology1.bolts.should == [bolt_definition]
end end
it "should parse multiple bolt with options" do it "should parse multiple bolt with options" do
bolt_definition1 = mock("BoltDefinition") bolt_definition1 = RedStorm::SimpleTopology::BoltDefinition.new(BoltClass1, "id1", 2)
bolt_definition2 = mock("BoltDefinition") bolt_definition2 = RedStorm::SimpleTopology::BoltDefinition.new(BoltClass2, "id2", 3)
RedStorm::SimpleTopology::BoltDefinition.should_receive(:new).with(BoltClass1, "id1", 2).and_return(bolt_definition1) RedStorm::SimpleTopology::BoltDefinition.should_receive(:new).with(BoltClass1, "id1", 2).and_return(bolt_definition1)
RedStorm::SimpleTopology::BoltDefinition.should_receive(:new).with(BoltClass2, "id2", 3).and_return(bolt_definition2) RedStorm::SimpleTopology::BoltDefinition.should_receive(:new).with(BoltClass2, "id2", 3).and_return(bolt_definition2)
bolt_definition1.should_receive(:source).with(1, :shuffle) bolt_definition1.should_receive(:source).with(1, :shuffle)
bolt_definition2.should_receive(:source).with(2, {:fields => ["f1"]}) bolt_definition2.should_receive(:source).with(2, {:fields => ["f1"]})
class TopologyBolt3 < RedStorm::SimpleTopology class Topology1 < RedStorm::SimpleTopology
bolt BoltClass1, :id => "id1", :parallelism => 2 do bolt BoltClass1, :id => "id1", :parallelism => 2 do
source 1, :shuffle source 1, :shuffle
end end
@ -94,7 +103,7 @@ describe RedStorm::SimpleTopology do
source 2, :fields => ["f1"] source 2, :fields => ["f1"]
end end
end end
TopologyBolt3.bolts.should == [bolt_definition1, bolt_definition2] Topology1.bolts.should == [bolt_definition1, bolt_definition2]
end end
end end
@ -102,52 +111,52 @@ describe RedStorm::SimpleTopology do
describe "configure statement" do describe "configure statement" do
it "should parse name options only" do it "should parse name options only" do
class TopologyConfigure1 < RedStorm::SimpleTopology class Topology1 < RedStorm::SimpleTopology
configure "name" configure "name"
end end
TopologyConfigure1.topology_name.should == "name" Topology1.topology_name.should == "name"
end end
it "should parse configuration block only" do it "should parse configuration block only" do
class TopologyConfigure2 < RedStorm::SimpleTopology class Topology1 < RedStorm::SimpleTopology
configure {trigger} configure {trigger}
end end
topology = TopologyConfigure2.new topology = Topology1.new
topology.should_receive(:trigger) topology.should_receive(:trigger)
topology.instance_exec(&TopologyConfigure2.configure_block) topology.instance_exec(&Topology1.configure_block)
end end
it "should parse name and configuration block" do it "should parse name and configuration block" do
class TopologyConfigure3 < RedStorm::SimpleTopology class Topology1 < RedStorm::SimpleTopology
configure "name" do configure "name" do
trigger trigger
end end
end end
TopologyConfigure3.topology_name.should == "name" Topology1.topology_name.should == "name"
topology = TopologyConfigure3.new topology = Topology1.new
topology.should_receive(:trigger) topology.should_receive(:trigger)
topology.instance_exec(&TopologyConfigure3.configure_block) topology.instance_exec(&Topology1.configure_block)
end end
end end
define "on_submit statement" do define "on_submit statement" do
it "should parse block param only" do it "should parse block param only" do
class TopologyOnsubmit1 < RedStorm::SimpleTopology class Topology1 < RedStorm::SimpleTopology
on_submit {|env| trigger(env)} on_submit {|env| trigger(env)}
end end
topology = TopologyOnsubmit1.new topology = Topology1.new
topology.should_receive(:trigger).with("env") topology.should_receive(:trigger).with("env")
topology.instance_exec("env", &TopologyOnsubmit1.submit_block) topology.instance_exec("env", &Topology1.submit_block)
end end
it "should method name param only" do it "should method name param only" do
class TopologyOnsubmit1 < RedStorm::SimpleTopology class Topology1 < RedStorm::SimpleTopology
on_submit :my_method on_submit :my_method
end end
topology = TopologyOnsubmit1.new topology = Topology1.new
topology.should_receive(:my_method).with("env") topology.should_receive(:my_method).with("env")
topology.instance_exec("env", &TopologyOnsubmit1.submit_block) topology.instance_exec("env", &Topology1.submit_block)
end end
end end
end end
@ -160,9 +169,10 @@ describe RedStorm::SimpleTopology do
class RedStorm::JRubySpout; end class RedStorm::JRubySpout; end
class RedStorm::JRubyBolt; end class RedStorm::JRubyBolt; end
class RedStorm::Config; end class RedStorm::Config; end
class RedStorm::Fields; end
it "should start in :local env" do it "should start in :local env" do
class TopologyStart1 < RedStorm::SimpleTopology; end class Topology1 < RedStorm::SimpleTopology; end
builder = mock(RedStorm::TopologyBuilder) builder = mock(RedStorm::TopologyBuilder)
RedStorm::TopologyBuilder.should_receive(:new).and_return(builder) RedStorm::TopologyBuilder.should_receive(:new).and_return(builder)
@ -172,29 +182,29 @@ describe RedStorm::SimpleTopology do
configurator.should_receive(:config).and_return("config") configurator.should_receive(:config).and_return("config")
cluster = mock(RedStorm::LocalCluster) cluster = mock(RedStorm::LocalCluster)
RedStorm::LocalCluster.should_receive(:new).and_return(cluster) RedStorm::LocalCluster.should_receive(:new).and_return(cluster)
cluster.should_receive(:submitTopology).with("topology_start1", "config", "topology") cluster.should_receive(:submitTopology).with("topology1", "config", "topology")
TopologyStart1.new.start("base_path", :local) Topology1.new.start("base_path", :local)
end end
it "should start in :cluster env" do it "should start in :cluster env" do
class TopologyStart2 < RedStorm::SimpleTopology; end class Topology1 < RedStorm::SimpleTopology; end
builder = mock(RedStorm::TopologyBuilder) builder = mock(RedStorm::TopologyBuilder)
RedStorm::TopologyBuilder.should_receive(:new).and_return(builder) RedStorm::TopologyBuilder.should_receive(:new).and_return(builder)
builder.should_receive(:createTopology).and_return("topology") builder.should_receive(:createTopology).and_return("topology")
configurator = mock(RedStorm::SimpleTopology::Configurator) configurator = mock(RedStorm::SimpleTopology::Configurator)
RedStorm::SimpleTopology::Configurator.should_receive(:new).and_return(configurator) RedStorm::SimpleTopology::Configurator.should_receive(:new).and_return(configurator)
configurator.should_receive(:config).and_return("config") configurator.should_receive(:config).and_return("config")
RedStorm::StormSubmitter.should_receive("submitTopology").with("topology_start2", "config", "topology") RedStorm::StormSubmitter.should_receive("submitTopology").with("topology1", "config", "topology")
TopologyStart2.new.start("base_path", :cluster) Topology1.new.start("base_path", :cluster)
end end
it "should raise for invalid env" do it "should raise for invalid env" do
class TopologyStart3 < RedStorm::SimpleTopology; end class Topology1 < RedStorm::SimpleTopology; end
lambda {TopologyStart3.new.start("base_path", :toto)}.should raise_error lambda {Topology1.new.start("base_path", :toto)}.should raise_error
end end
it "should build spouts" do it "should build spouts" do
class TopologyStart4 < RedStorm::SimpleTopology class Topology1 < RedStorm::SimpleTopology
spout SpoutClass1 spout SpoutClass1
spout SpoutClass2 spout SpoutClass2
end end
@ -213,19 +223,19 @@ describe RedStorm::SimpleTopology do
builder.should_receive("setSpout").with(2, jruby_spout2, 1) builder.should_receive("setSpout").with(2, jruby_spout2, 1)
configurator.should_receive(:config).and_return("config") configurator.should_receive(:config).and_return("config")
builder.should_receive(:createTopology).and_return("topology") builder.should_receive(:createTopology).and_return("topology")
RedStorm::StormSubmitter.should_receive("submitTopology").with("topology_start4", "config", "topology") RedStorm::StormSubmitter.should_receive("submitTopology").with("topology1", "config", "topology")
TopologyStart4.new.start("base_path", :cluster) Topology1.new.start("base_path", :cluster)
end end
it "should build bolts" do it "should build bolts" do
bolt_definition1 = mock("BoltDefinition") bolt_definition1 = RedStorm::SimpleTopology::BoltDefinition.new(BoltClass1, "id1", 2)
bolt_definition2 = mock("BoltDefinition") bolt_definition2 = RedStorm::SimpleTopology::BoltDefinition.new(BoltClass2, "id2", 3)
RedStorm::SimpleTopology::BoltDefinition.should_receive(:new).with(BoltClass1, "id1", 2).and_return(bolt_definition1) RedStorm::SimpleTopology::BoltDefinition.should_receive(:new).with(BoltClass1, "id1", 2).and_return(bolt_definition1)
RedStorm::SimpleTopology::BoltDefinition.should_receive(:new).with(BoltClass2, "id2", 3).and_return(bolt_definition2) RedStorm::SimpleTopology::BoltDefinition.should_receive(:new).with(BoltClass2, "id2", 3).and_return(bolt_definition2)
bolt_definition1.should_receive(:source).with(1, :shuffle) bolt_definition1.should_receive(:source).with(1, :shuffle)
bolt_definition2.should_receive(:source).with(2, {:fields => ["f1"]}) bolt_definition2.should_receive(:source).with(2, {:fields => ["f1"]})
class TopologyStart5 < RedStorm::SimpleTopology class Topology1 < RedStorm::SimpleTopology
bolt BoltClass1, :id => "id1", :parallelism => 2 do bolt BoltClass1, :id => "id1", :parallelism => 2 do
source 1, :shuffle source 1, :shuffle
end end
@ -260,13 +270,98 @@ describe RedStorm::SimpleTopology do
configurator.should_receive(:config).and_return("config") configurator.should_receive(:config).and_return("config")
builder.should_receive(:createTopology).and_return("topology") builder.should_receive(:createTopology).and_return("topology")
RedStorm::StormSubmitter.should_receive("submitTopology").with("topology_start5", "config", "topology") RedStorm::StormSubmitter.should_receive("submitTopology").with("topology1", "config", "topology")
TopologyStart5.new.start("base_path", :cluster) Topology1.new.start("base_path", :cluster)
end
describe "grouping" do
before(:each) do
builder = mock(RedStorm::TopologyBuilder)
configurator = mock(RedStorm::SimpleTopology::Configurator)
jruby_bolt = mock(RedStorm::JRubyBolt)
@declarer = mock("InputDeclarer")
RedStorm::TopologyBuilder.should_receive(:new).and_return(builder)
RedStorm::SimpleTopology::Configurator.should_receive(:new).and_return(configurator)
RedStorm::JRubyBolt.should_receive(:new).with("base_path", "BoltClass1").and_return(jruby_bolt)
builder.should_receive("setBolt").with(1, jruby_bolt, 1).and_return(@declarer)
configurator.should_receive(:config).and_return("config")
builder.should_receive(:createTopology).and_return("topology")
RedStorm::StormSubmitter.should_receive("submitTopology").with("topology1", "config", "topology")
end
it "should support fields" do
class Topology1 < RedStorm::SimpleTopology
bolt BoltClass1 do
source 1, :fields => "f1"
end
end
RedStorm::Fields.should_receive(:new).with("f1").and_return("fields")
@declarer.should_receive("fieldsGrouping").with(1, "fields")
Topology1.new.start("base_path", :cluster)
end
it "should support shuffle" do
class Topology1 < RedStorm::SimpleTopology
bolt BoltClass1 do
source 1, :shuffle
end
end
@declarer.should_receive("shuffleGrouping").with(1)
Topology1.new.start("base_path", :cluster)
end
it "should support none" do
class Topology1 < RedStorm::SimpleTopology
bolt BoltClass1 do
source 1, :none
end
end
@declarer.should_receive("noneGrouping").with(1)
Topology1.new.start("base_path", :cluster)
end
it "should support global" do
class Topology1 < RedStorm::SimpleTopology
bolt BoltClass1 do
source 1, :global
end
end
@declarer.should_receive("globalGrouping").with(1)
Topology1.new.start("base_path", :cluster)
end
it "should support all" do
class Topology1 < RedStorm::SimpleTopology
bolt BoltClass1 do
source 1, :all
end
end
@declarer.should_receive("allGrouping").with(1)
Topology1.new.start("base_path", :cluster)
end
it "should support direct" do
class Topology1 < RedStorm::SimpleTopology
bolt BoltClass1 do
source 1, :direct
end
end
@declarer.should_receive("directGrouping").with(1)
Topology1.new.start("base_path", :cluster)
end
end end
it "should configure" do it "should configure" do
class TopologyStart6 < RedStorm::SimpleTopology class Topology1 < RedStorm::SimpleTopology
configure do configure do
debug true debug true
max_task_parallelism 3 max_task_parallelism 3
@ -281,13 +376,13 @@ describe RedStorm::SimpleTopology do
builder = mock(RedStorm::TopologyBuilder) builder = mock(RedStorm::TopologyBuilder)
RedStorm::TopologyBuilder.should_receive(:new).and_return(builder) RedStorm::TopologyBuilder.should_receive(:new).and_return(builder)
builder.should_receive(:createTopology).and_return("topology") builder.should_receive(:createTopology).and_return("topology")
RedStorm::StormSubmitter.should_receive("submitTopology").with("topology_start6", config, "topology") RedStorm::StormSubmitter.should_receive("submitTopology").with("topology1", config, "topology")
TopologyStart6.new.start("base_path", :cluster) Topology1.new.start("base_path", :cluster)
end end
it "should provide local cluster reference" do it "should provide local cluster reference" do
class TopologyStart7 < RedStorm::SimpleTopology; end class Topology1 < RedStorm::SimpleTopology; end
builder = mock(RedStorm::TopologyBuilder) builder = mock(RedStorm::TopologyBuilder)
RedStorm::TopologyBuilder.should_receive(:new).and_return(builder) RedStorm::TopologyBuilder.should_receive(:new).and_return(builder)
@ -298,16 +393,16 @@ describe RedStorm::SimpleTopology do
cluster = mock(RedStorm::LocalCluster) cluster = mock(RedStorm::LocalCluster)
RedStorm::LocalCluster.should_receive(:new).and_return(cluster) RedStorm::LocalCluster.should_receive(:new).and_return(cluster)
cluster.should_receive(:submitTopology).with("topology_start7", "config", "topology").and_return("cluster") cluster.should_receive(:submitTopology).with("topology1", "config", "topology").and_return("cluster")
topology = TopologyStart7.new topology = Topology1.new
topology.start("base_path", :local) topology.start("base_path", :local)
topology.cluster.should == cluster topology.cluster.should == cluster
end end
it "should keep numeric ids" do it "should keep numeric ids" do
class TopologyNumericIds1 < RedStorm::SimpleTopology class Topology1 < RedStorm::SimpleTopology
spout SpoutClass1, :id => 1 spout SpoutClass1, :id => 1
bolt BoltClass1, :id => 2 do bolt BoltClass1, :id => 2 do
@ -315,19 +410,19 @@ describe RedStorm::SimpleTopology do
end end
end end
TopologyNumericIds1.spouts.first.id.should == 1 Topology1.spouts.first.id.should == 1
TopologyNumericIds1.bolts.first.id.should == 2 Topology1.bolts.first.id.should == 2
TopologyNumericIds1.bolts.first.sources.first.should == [1, {:shuffle => nil}] Topology1.bolts.first.sources.first.should == [1, {:shuffle => nil}]
TopologyNumericIds1.resolve_ids!(TopologyNumericIds1.spouts + TopologyNumericIds1.bolts) Topology1.resolve_ids!(Topology1.spouts + Topology1.bolts)
TopologyNumericIds1.spouts.first.id.should == 1 Topology1.spouts.first.id.should == 1
TopologyNumericIds1.bolts.first.id.should == 2 Topology1.bolts.first.id.should == 2
TopologyNumericIds1.bolts.first.sources.first.should == [1, {:shuffle => nil}] Topology1.bolts.first.sources.first.should == [1, {:shuffle => nil}]
end end
it "should resolve explicit symbolic ids" do it "should resolve explicit symbolic ids" do
class TopologySymbolicIds1 < RedStorm::SimpleTopology class Topology1 < RedStorm::SimpleTopology
spout SpoutClass1, :id => "id1" spout SpoutClass1, :id => "id1"
bolt BoltClass1, :id => "id2" do bolt BoltClass1, :id => "id2" do
@ -335,19 +430,19 @@ describe RedStorm::SimpleTopology do
end end
end end
TopologySymbolicIds1.spouts.first.id.should == "id1" Topology1.spouts.first.id.should == "id1"
TopologySymbolicIds1.bolts.first.id.should == "id2" Topology1.bolts.first.id.should == "id2"
TopologySymbolicIds1.bolts.first.sources.first.should == ["id1", {:shuffle => nil}] Topology1.bolts.first.sources.first.should == ["id1", {:shuffle => nil}]
TopologySymbolicIds1.resolve_ids!(TopologySymbolicIds1.spouts + TopologySymbolicIds1.bolts) Topology1.resolve_ids!(Topology1.spouts + Topology1.bolts)
TopologySymbolicIds1.spouts.first.id.should == 1 Topology1.spouts.first.id.should == 1
TopologySymbolicIds1.bolts.first.id.should == 2 Topology1.bolts.first.id.should == 2
TopologySymbolicIds1.bolts.first.sources.first.should == [1, {:shuffle => nil}] Topology1.bolts.first.sources.first.should == [1, {:shuffle => nil}]
end end
it "should resolve implicit symbolic ids" do it "should resolve implicit symbolic ids" do
class TopologySymbolicIds2 < RedStorm::SimpleTopology class Topology1 < RedStorm::SimpleTopology
spout SpoutClass1 spout SpoutClass1
bolt BoltClass1 do bolt BoltClass1 do
@ -355,19 +450,19 @@ describe RedStorm::SimpleTopology do
end end
end end
TopologySymbolicIds2.spouts.first.id.should == "spout_class1" Topology1.spouts.first.id.should == "spout_class1"
TopologySymbolicIds2.bolts.first.id.should == "bolt_class1" Topology1.bolts.first.id.should == "bolt_class1"
TopologySymbolicIds2.bolts.first.sources.first.should == ["spout_class1", {:shuffle => nil}] Topology1.bolts.first.sources.first.should == ["spout_class1", {:shuffle => nil}]
TopologySymbolicIds2.resolve_ids!(TopologySymbolicIds2.spouts + TopologySymbolicIds2.bolts) Topology1.resolve_ids!(Topology1.spouts + Topology1.bolts)
TopologySymbolicIds2.spouts.first.id.should == 1 Topology1.spouts.first.id.should == 1
TopologySymbolicIds2.bolts.first.id.should == 2 Topology1.bolts.first.id.should == 2
TopologySymbolicIds2.bolts.first.sources.first.should == [1, {:shuffle => nil}] Topology1.bolts.first.sources.first.should == [1, {:shuffle => nil}]
end end
it "should raise on unresolvable" do it "should raise on unresolvable" do
class TopologySymbolicIds3 < RedStorm::SimpleTopology class Topology1 < RedStorm::SimpleTopology
spout SpoutClass1 spout SpoutClass1
bolt BoltClass1 do bolt BoltClass1 do
@ -375,11 +470,23 @@ describe RedStorm::SimpleTopology do
end end
end end
TopologySymbolicIds3.spouts.first.id.should == "spout_class1" Topology1.spouts.first.id.should == "spout_class1"
TopologySymbolicIds3.bolts.first.id.should == "bolt_class1" Topology1.bolts.first.id.should == "bolt_class1"
TopologySymbolicIds3.bolts.first.sources.first.should == ["dummy", {:shuffle => nil}] Topology1.bolts.first.sources.first.should == ["dummy", {:shuffle => nil}]
lambda {TopologySymbolicIds3.resolve_ids!(TopologySymbolicIds3.spouts + TopologySymbolicIds3.bolts)}.should raise_error RuntimeError, "cannot resolve BoltClass1 source id=\"dummy\"" lambda {Topology1.resolve_ids!(Topology1.spouts + Topology1.bolts)}.should raise_error RuntimeError, "cannot resolve BoltClass1 source id=dummy"
end
it "should raise on duplicate conflict" do
class Topology1 < RedStorm::SimpleTopology
spout SpoutClass1
spout SpoutClass1
end
Topology1.spouts.first.id.should == "spout_class1"
Topology1.spouts.last.id.should == "spout_class1"
lambda {Topology1.resolve_ids!(Topology1.spouts)}.should raise_error RuntimeError, "duplicate symbolic id in SpoutClass1 on id=spout_class1"
end end
end end