spec/interpreter/interpreter_spec.rb in nudge-0.1.0 vs spec/interpreter/interpreter_spec.rb in nudge-0.1.1
- old
+ new
@@ -43,10 +43,17 @@
@ii.steps = 100
@ii.reset("channel x")
@ii.steps.should == 0
end
+ it "#reset should reset the #sensors Hash" do
+ @ii.register_sensor("z") {1201}
+ @ii.reset
+ @ii.sensors["z"].should == nil
+ end
+
+
it "should load a complex CodeBlock as a single item on the exec stack" do
myCode = "block {\ndo foo\n do bar\n block {\ndo baz}}"
@ii.reset(myCode)
@ii.stacks.should include(:exec)
@ii.stacks[:exec].depth.should == 1
@@ -228,11 +235,36 @@
lambda{@ii.peek(99)}.should raise_error(ArgumentError)
end
end
+describe "Interpreter#depth" do
+ before(:each) do
+ @ii = Interpreter.new()
+ @ii.clear_stacks
+ end
+
+ it "should invoke a particular stack's #depth method" do
+ 30.times { @ii.stacks[:donut].push(ValuePoint.new("donut", "0")) }
+ lambda{@ii.depth(:donut)}.should_not raise_error
+ @ii.depth(:donut).should == 30
+ end
+
+ it "should return 0 if the stack doesn't exist" do
+ lambda{@ii.depth(:nonexistent)}.should_not raise_error
+ @ii.depth(:nonexistent).should == 0
+ end
+
+ it "should validate the stackname as a symbol" do
+ lambda{@ii.depth("not there")}.should raise_error(ArgumentError)
+ lambda{@ii.depth(99)}.should raise_error(ArgumentError)
+ end
+end
+
+
+
describe "Interpreter#peek_value" do
before(:each) do
@ii = Interpreter.new()
@ii.clear_stacks
end
@@ -415,10 +447,14 @@
puts @ii.stacks[:exec].depth
@ii.run
@ii.steps.should == 0
end
+ it "should #fire_all_sensors at the end of running" do
+ @ii.should_receive(:fire_all_sensors)
+ @ii.run
+ end
end
describe "resetting" do
it "should clear the steps" do
@@ -456,5 +492,71 @@
ii.variables.keys.should == ["a"]
ii.reset
ii.variables.keys.should == ["a"]
end
end
+
+
+describe "sensors" do
+ before(:each) do
+ @ii = Interpreter.new
+ end
+
+ describe "register_sensor" do
+ it "should add a sensor block to the #sensors Hash" do
+ lambda{@ii.register_sensor("y") {}}.should_not raise_error
+ @ii.sensors.length.should == 1
+ @ii.sensors["y"].should be_a_kind_of(Proc)
+ end
+
+ it "should take a string name, validated as such" do
+ lambda{@ii.register_sensor("z")}.should_not raise_error
+ lambda{@ii.register_sensor(8)}.should raise_error(ArgumentError)
+ end
+
+ it "should take a block, which is called when the sensor is fired" do
+ @ii.register_sensor("y") {|x| 9}
+ @ii.sensors["y"].call.should == 9
+ end
+
+ it "should have access to the Interpreter state through a parameter" do
+ @ii.push(:int, 10202)
+ @ii.register_sensor("x1") {|interpreter| interpreter.peek_value(:int)}
+ @ii.sensors["x1"].call(@ii).should == 10202
+ end
+ end
+
+ describe "clear_sensors" do
+ it "should reset the #sensors Hash to empty" do
+ @ii.register_sensor("y1") {|x| 1}
+ @ii.register_sensor("y2") {|x| 2}
+ @ii.register_sensor("y3") {|x| 4}
+ @ii.sensors.keys.should == ["y1", "y2", "y3"]
+ @ii.reset_sensors
+ @ii.sensors.should == {}
+ end
+ end
+
+ describe "Interpreter#fire_all_sensors(name)" do
+ it "should call all registered sensors and return a Hash of results" do
+ @ii.register_sensor("y1") {|x| 1}
+ @ii.register_sensor("y2") {|x| 2}
+ @ii.register_sensor("y3") {|x| 4}
+ @ii.fire_all_sensors.should == {"y1"=>1, "y2"=>2, "y3"=>4}
+ end
+
+ it "should return an empty Hash if nothing is registered" do
+ @ii.fire_all_sensors.should == {}
+ end
+ end
+
+ describe "interrogating Interpreter state" do
+ it "should be possible to read anything about the Interpreter state" do
+ @ii.reset("block {value «int» value «int»}\n«int» 88\n«int» 11")
+ @ii.register_sensor("steps") {|me| me.steps}
+ @ii.register_sensor("top_int") {|me| me.pop_value(:int)}
+ @ii.register_sensor("second_int") {|me| me.pop_value(:int)}
+ 3.times {@ii.step} # so as not to fire sensors at the end
+ @ii.fire_all_sensors.should == {"steps"=>3, "top_int"=>11, "second_int"=>88}
+ end
+ end
+end
\ No newline at end of file