diff options
| author | Brice Figureau <brice-puppet@daysofwonder.com> | 2009-07-28 19:56:34 +0200 |
|---|---|---|
| committer | James Turnbull <james@lovedthanlost.net> | 2009-08-01 11:15:29 +1000 |
| commit | 3ebf148bf3d82d25e690aec6ec49975e0837e604 (patch) | |
| tree | b94504992e575d8b4181440b90bdf510cf67ef8c /spec/unit/parser/ast | |
| parent | ef68967f2b72e609a9d69e53771a61fd9f522149 (diff) | |
| download | puppet-3ebf148bf3d82d25e690aec6ec49975e0837e604.tar.gz puppet-3ebf148bf3d82d25e690aec6ec49975e0837e604.tar.xz puppet-3ebf148bf3d82d25e690aec6ec49975e0837e604.zip | |
Enhance selector and case statements to match with regexp
The case and selector statements define ephemeral vars, like 'if'.
Usage:
case statement:
$var = "foobar"
case $var {
"foo": {
notify { "got a foo": }
}
/(.*)bar$/: {
notify{ "hey we got a $1": }
}
}
and for selector:
$val = $test ? {
/^match.*$/ => "matched",
default => "default"
}
Signed-off-by: Brice Figureau <brice-puppet@daysofwonder.com>
Diffstat (limited to 'spec/unit/parser/ast')
| -rwxr-xr-x | spec/unit/parser/ast/casestatement.rb | 143 | ||||
| -rwxr-xr-x | spec/unit/parser/ast/selector.rb | 156 |
2 files changed, 299 insertions, 0 deletions
diff --git a/spec/unit/parser/ast/casestatement.rb b/spec/unit/parser/ast/casestatement.rb new file mode 100755 index 000000000..554e295bc --- /dev/null +++ b/spec/unit/parser/ast/casestatement.rb @@ -0,0 +1,143 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +describe Puppet::Parser::AST::CaseStatement do + before :each do + @scope = Puppet::Parser::Scope.new() + end + + describe "when evaluating" do + + before :each do + @test = stub 'test' + @test.stubs(:safeevaluate).with(@scope).returns("value") + + @option1 = stub 'option1', :eachopt => nil, :default? => false + @option2 = stub 'option2', :eachopt => nil, :default? => false + + @options = stub 'options' + @options.stubs(:each).multiple_yields(@option1, @option2) + + @casestmt = Puppet::Parser::AST::CaseStatement.new :test => @test, :options => @options + end + + it "should evaluate test" do + @test.expects(:safeevaluate).with(@scope) + + @casestmt.evaluate(@scope) + end + + it "should downcase the evaluated test value if allowed" do + Puppet.stubs(:[]).with(:casesensitive).returns(false) + value = stub 'test' + @test.stubs(:safeevaluate).with(@scope).returns(value) + + value.expects(:downcase) + + @casestmt.evaluate(@scope) + end + + it "should scan each option" do + @options.expects(:each).multiple_yields(@option1, @option2) + + @casestmt.evaluate(@scope) + end + + describe "when scanning options" do + before :each do + @opval1 = stub_everything 'opval1' + @option1.stubs(:eachopt).yields(@opval1) + + @opval2 = stub_everything 'opval2' + @option2.stubs(:eachopt).yields(@opval2) + end + + it "should evaluate each sub-option" do + @option1.expects(:eachopt) + @option2.expects(:eachopt) + + @casestmt.evaluate(@scope) + end + + it "should evaluate first matching option" do + @opval2.stubs(:evaluate_match).with { |*arg| arg[0] == "value" }.returns(true) + @option2.expects(:safeevaluate).with(@scope) + + @casestmt.evaluate(@scope) + end + + it "should evaluate_match with sensitive parameter" do + Puppet.stubs(:[]).with(:casesensitive).returns(true) + @opval1.expects(:evaluate_match).with { |*arg| arg[2][:sensitive] == true } + + @casestmt.evaluate(@scope) + end + + it "should return the first matching evaluated option" do + @opval2.stubs(:evaluate_match).with { |*arg| arg[0] == "value" }.returns(true) + @option2.stubs(:safeevaluate).with(@scope).returns(:result) + + @casestmt.evaluate(@scope).should == :result + end + + it "should evaluate the default option if none matched" do + @option1.stubs(:default?).returns(true) + @option1.expects(:safeevaluate).with(@scope) + + @casestmt.evaluate(@scope) + end + + it "should return the default evaluated option if none matched" do + @option1.stubs(:default?).returns(true) + @option1.stubs(:safeevaluate).with(@scope).returns(:result) + + @casestmt.evaluate(@scope).should == :result + end + + it "should return nil if nothing matched" do + @casestmt.evaluate(@scope).should be_nil + end + + it "should match and set scope ephemeral variables" do + @opval1.expects(:evaluate_match).with { |*arg| arg[0] == "value" and arg[1] == @scope } + + @casestmt.evaluate(@scope) + end + + it "should evaluate this regex option if it matches" do + @opval1.stubs(:evaluate_match).with { |*arg| arg[0] == "value" and arg[1] == @scope }.returns(true) + + @option1.expects(:safeevaluate).with(@scope) + + @casestmt.evaluate(@scope) + end + + it "should return this evaluated regex option if it matches" do + @opval1.stubs(:evaluate_match).with { |*arg| arg[0] == "value" and arg[1] == @scope }.returns(true) + @option1.stubs(:safeevaluate).with(@scope).returns(:result) + + @casestmt.evaluate(@scope).should == :result + end + + it "should unset scope ephemeral variables after option evaluation" do + @opval1.stubs(:evaluate_match).with { |*arg| arg[0] == "value" and arg[1] == @scope }.returns(true) + @option1.stubs(:safeevaluate).with(@scope).returns(:result) + + @scope.expects(:unset_ephemeral_var) + + @casestmt.evaluate(@scope) + end + + it "should not leak ephemeral variables even if evaluation fails" do + @opval1.stubs(:evaluate_match).with { |*arg| arg[0] == "value" and arg[1] == @scope }.returns(true) + @option1.stubs(:safeevaluate).with(@scope).raises + + @scope.expects(:unset_ephemeral_var) + + lambda { @casestmt.evaluate(@scope) }.should raise_error + end + end + + end +end diff --git a/spec/unit/parser/ast/selector.rb b/spec/unit/parser/ast/selector.rb new file mode 100755 index 000000000..8b0057784 --- /dev/null +++ b/spec/unit/parser/ast/selector.rb @@ -0,0 +1,156 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +describe Puppet::Parser::AST::Selector do + before :each do + @scope = Puppet::Parser::Scope.new() + end + + describe "when evaluating" do + + before :each do + @param = stub 'param' + @param.stubs(:safeevaluate).with(@scope).returns("value") + + @value1 = stub 'value1' + @param1 = stub_everything 'param1' + @param1.stubs(:safeevaluate).with(@scope).returns(@param1) + @param1.stubs(:respond_to?).with(:downcase).returns(false) + @value1.stubs(:param).returns(@param1) + @value1.stubs(:value).returns(@value1) + + @value2 = stub 'value2' + @param2 = stub_everything 'param2' + @param2.stubs(:safeevaluate).with(@scope).returns(@param2) + @param2.stubs(:respond_to?).with(:downcase).returns(false) + @value2.stubs(:param).returns(@param2) + @value2.stubs(:value).returns(@value2) + + @values = stub 'values', :instance_of? => true + @values.stubs(:each).multiple_yields(@value1, @value2) + + @selector = Puppet::Parser::AST::Selector.new :param => @param, :values => @values + @selector.stubs(:fail) + end + + it "should evaluate param" do + @param.expects(:safeevaluate).with(@scope) + + @selector.evaluate(@scope) + end + + it "should downcase the evaluated param value if allowed" do + Puppet.stubs(:[]).with(:casesensitive).returns(false) + value = stub 'param' + @param.stubs(:safeevaluate).with(@scope).returns(value) + + value.expects(:downcase) + + @selector.evaluate(@scope) + end + + it "should scan each option" do + @values.expects(:each).multiple_yields(@value1, @value2) + + @selector.evaluate(@scope) + end + + describe "when scanning values" do + it "should evaluate first matching option" do + @param2.stubs(:evaluate_match).with { |*arg| arg[0] == "value" }.returns(true) + @value2.expects(:safeevaluate).with(@scope) + + @selector.evaluate(@scope) + end + + it "should return the first matching evaluated option" do + @param2.stubs(:evaluate_match).with { |*arg| arg[0] == "value" }.returns(true) + @value2.stubs(:safeevaluate).with(@scope).returns(:result) + + @selector.evaluate(@scope).should == :result + end + + it "should evaluate the default option if none matched" do + @param1.stubs(:is_a?).with(Puppet::Parser::AST::Default).returns(true) + @value1.expects(:safeevaluate).with(@scope).returns(@param1) + + @selector.evaluate(@scope) + end + + it "should return the default evaluated option if none matched" do + result = stub 'result' + @param1.stubs(:is_a?).with(Puppet::Parser::AST::Default).returns(true) + @value1.stubs(:safeevaluate).returns(result) + + @selector.evaluate(@scope).should == result + end + + it "should return nil if nothing matched" do + @selector.evaluate(@scope).should be_nil + end + + it "should delegate matching to evaluate_match" do + @param1.expects(:evaluate_match).with { |*arg| arg[0] == "value" and arg[1] == @scope } + + @selector.evaluate(@scope) + end + + it "should transmit the sensitive parameter to evaluate_match" do + Puppet.stubs(:[]).with(:casesensitive).returns(:sensitive) + @param1.expects(:evaluate_match).with { |*arg| arg[2][:sensitive] == :sensitive } + + @selector.evaluate(@scope) + end + + it "should transmit the AST file and line to evaluate_match" do + @selector.file = :file + @selector.line = :line + @param1.expects(:evaluate_match).with { |*arg| arg[2][:file] == :file and arg[2][:line] == :line } + + @selector.evaluate(@scope) + end + + + it "should evaluate the matching param" do + @param1.stubs(:evaluate_match).with { |*arg| arg[0] == "value" and arg[1] == @scope }.returns(true) + + @value1.expects(:safeevaluate).with(@scope) + + @selector.evaluate(@scope) + end + + it "should return this evaluated option if it matches" do + @param1.stubs(:evaluate_match).with { |*arg| arg[0] == "value" and arg[1] == @scope }.returns(true) + @value1.stubs(:safeevaluate).with(@scope).returns(:result) + + @selector.evaluate(@scope).should == :result + end + + it "should unset scope ephemeral variables after option evaluation" do + @param1.stubs(:evaluate_match).with { |*arg| arg[0] == "value" and arg[1] == @scope }.returns(true) + @value1.stubs(:safeevaluate).with(@scope).returns(:result) + + @scope.expects(:unset_ephemeral_var) + + @selector.evaluate(@scope) + end + + it "should not leak ephemeral variables even if evaluation fails" do + @param1.stubs(:evaluate_match).with { |*arg| arg[0] == "value" and arg[1] == @scope }.returns(true) + @value1.stubs(:safeevaluate).with(@scope).raises + + @scope.expects(:unset_ephemeral_var) + + lambda { @selector.evaluate(@scope) }.should raise_error + end + + it "should fail if there is no default" do + @selector.expects(:fail) + + @selector.evaluate(@scope) + end + end + + end +end |
