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