summaryrefslogtreecommitdiff
path: root/spec/unit/parser
diff options
context:
space:
mode:
Diffstat (limited to 'spec/unit/parser')
-rwxr-xr-xspec/unit/parser/ast/arithmetic_operator_spec.rb100
-rwxr-xr-xspec/unit/parser/collector_spec.rb8
-rwxr-xr-xspec/unit/parser/compiler_spec.rb26
-rw-r--r--spec/unit/parser/eparser_adapter_spec.rb407
-rwxr-xr-xspec/unit/parser/functions/extlookup_spec.rb37
-rwxr-xr-xspec/unit/parser/functions/fqdn_rand_spec.rb5
-rw-r--r--spec/unit/parser/functions/hiera_include_spec.rb2
-rwxr-xr-xspec/unit/parser/functions/hiera_spec.rb2
-rwxr-xr-xspec/unit/parser/functions_spec.rb42
-rw-r--r--spec/unit/parser/methods/collect_spec.rb110
-rw-r--r--spec/unit/parser/methods/each_spec.rb91
-rwxr-xr-xspec/unit/parser/methods/foreach_spec.rb91
-rw-r--r--spec/unit/parser/methods/reduce_spec.rb67
-rw-r--r--spec/unit/parser/methods/reject_spec.rb73
-rw-r--r--spec/unit/parser/methods/select_spec.rb79
-rw-r--r--spec/unit/parser/methods/shared.rb61
-rw-r--r--spec/unit/parser/methods/slice_spec.rb97
-rwxr-xr-xspec/unit/parser/parser_spec.rb4
-rwxr-xr-xspec/unit/parser/scope_spec.rb55
-rwxr-xr-xspec/unit/parser/templatewrapper_spec.rb11
-rwxr-xr-xspec/unit/parser/type_loader_spec.rb356
21 files changed, 1481 insertions, 243 deletions
diff --git a/spec/unit/parser/ast/arithmetic_operator_spec.rb b/spec/unit/parser/ast/arithmetic_operator_spec.rb
index de6941fb7..cdd01e375 100755
--- a/spec/unit/parser/ast/arithmetic_operator_spec.rb
+++ b/spec/unit/parser/ast/arithmetic_operator_spec.rb
@@ -24,7 +24,7 @@ describe Puppet::Parser::AST::ArithmeticOperator do
end
it "should fail for an unknown operator" do
- lambda { operator = ast::ArithmeticOperator.new :lval => @one, :operator => "%", :rval => @two }.should raise_error
+ lambda { operator = ast::ArithmeticOperator.new :lval => @one, :operator => "^", :rval => @two }.should raise_error
end
it "should call Puppet::Parser::Scope.number?" do
@@ -35,7 +35,7 @@ describe Puppet::Parser::AST::ArithmeticOperator do
end
- %w{ + - * / << >>}.each do |op|
+ %w{ + - * / % << >>}.each do |op|
it "should call ruby Numeric '#{op}'" do
one = stub 'one'
two = stub 'two'
@@ -61,4 +61,100 @@ describe Puppet::Parser::AST::ArithmeticOperator do
operator.evaluate(@scope).should == 4.33
end
+ context "when applied to array" do
+ before :each do
+ Puppet[:parser] = 'future'
+ end
+
+ it "+ should concatenate an array" do
+ one = stub 'one', :safeevaluate => [1,2,3]
+ two = stub 'two', :safeevaluate => [4,5]
+ operator = ast::ArithmeticOperator.new :lval => one, :operator => "+", :rval => two
+ operator.evaluate(@scope).should == [1,2,3,4,5]
+ end
+
+ it "<< should append array to an array" do
+ one = stub 'one', :safeevaluate => [1,2,3]
+ two = stub 'two', :safeevaluate => [4,5]
+ operator = ast::ArithmeticOperator.new :lval => one, :operator => "<<", :rval => two
+ operator.evaluate(@scope).should == [1,2,3, [4,5]]
+ end
+
+ it "<< should append object to an array" do
+ one = stub 'one', :safeevaluate => [1,2,3]
+ two = stub 'two', :safeevaluate => 'a b c'
+ operator = ast::ArithmeticOperator.new :lval => one, :operator => "<<", :rval => two
+ operator.evaluate(@scope).should == [1,2,3, 'a b c']
+ end
+
+ context "and input is invalid" do
+ it "should raise error for + if left is not an array" do
+ one = stub 'one', :safeevaluate => 4
+ two = stub 'two', :safeevaluate => [4,5]
+ operator = ast::ArithmeticOperator.new :lval => one, :operator => "+", :rval => two
+ lambda { operator.evaluate(@scope).should == [1,2,3,4,5] }.should raise_error(/left/)
+ end
+
+ it "should raise error for << if left is not an array" do
+ one = stub 'one', :safeevaluate => 4
+ two = stub 'two', :safeevaluate => [4,5]
+ operator = ast::ArithmeticOperator.new :lval => one, :operator => "<<", :rval => two
+ lambda { operator.evaluate(@scope).should == [1,2,3,4,5] }.should raise_error(/left/)
+ end
+
+ it "should raise error for + if right is not an array" do
+ one = stub 'one', :safeevaluate => [1,2]
+ two = stub 'two', :safeevaluate => 45
+ operator = ast::ArithmeticOperator.new :lval => one, :operator => "+", :rval => two
+ lambda { operator.evaluate(@scope).should == [1,2,3,4,5] }.should raise_error(/right/)
+ end
+
+ %w{ - * / % >>}.each do |op|
+ it "should raise error for '#{op}'" do
+ one = stub 'one', :safeevaluate => [1,2,3]
+ two = stub 'two', :safeevaluate => [4,5]
+ operator = ast::ArithmeticOperator.new :lval => @one, :operator => op, :rval => @two
+ lambda { operator.evaluate(@scope).should == [1,2,3,4,5] }.should raise_error
+ end
+ end
+ end
+
+ context "when applied to hash" do
+ before :each do
+ Puppet[:parser] = 'future'
+ end
+
+ it "+ should merge two hashes" do
+ one = stub 'one', :safeevaluate => {'a' => 1, 'b' => 2}
+ two = stub 'two', :safeevaluate => {'c' => 3 }
+ operator = ast::ArithmeticOperator.new :lval => one, :operator => "+", :rval => two
+ operator.evaluate(@scope).should == {'a' => 1, 'b' => 2, 'c' => 3}
+ end
+
+ context "and input is invalid" do
+ it "should raise error for + if left is not a hash" do
+ one = stub 'one', :safeevaluate => 4
+ two = stub 'two', :safeevaluate => {'a' => 1}
+ operator = ast::ArithmeticOperator.new :lval => one, :operator => "+", :rval => two
+ lambda { operator.evaluate(@scope).should == [1,2,3,4,5] }.should raise_error(/left/)
+ end
+
+ it "should raise error for + if right is not a hash" do
+ one = stub 'one', :safeevaluate => {'a' => 1}
+ two = stub 'two', :safeevaluate => 1
+ operator = ast::ArithmeticOperator.new :lval => one, :operator => "+", :rval => two
+ lambda { operator.evaluate(@scope).should == {'a'=>1, 1=>nil} }.should raise_error(/right/)
+ end
+
+ %w{ - * / % << >>}.each do |op|
+ it "should raise error for '#{op}'" do
+ one = stub 'one', :safeevaluate => {'a' => 1, 'b' => 2}
+ two = stub 'two', :safeevaluate => {'c' => 3 }
+ operator = ast::ArithmeticOperator.new :lval => @one, :operator => op, :rval => @two
+ lambda { operator.evaluate(@scope).should == [1,2,3,4,5] }.should raise_error
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/unit/parser/collector_spec.rb b/spec/unit/parser/collector_spec.rb
index 132bddbc5..5d4af0c11 100755
--- a/spec/unit/parser/collector_spec.rb
+++ b/spec/unit/parser/collector_spec.rb
@@ -288,6 +288,10 @@ describe Puppet::Parser::Collector, "when collecting exported resources", :if =>
Puppet[:storeconfigs_backend] = "active_record"
end
+ after :each do
+ Puppet::Rails.teardown
+ end
+
it "should return all matching resources from the current compile and mark them non-virtual and non-exported" do
one = Puppet::Parser::Resource.new('notify', 'one',
:virtual => true,
@@ -304,10 +308,6 @@ describe Puppet::Parser::Collector, "when collecting exported resources", :if =>
@collector.evaluate.should == [one, two]
one.should_not be_virtual
two.should_not be_virtual
-
- # REVISIT: Apparently we never actually marked local resources as
- # non-exported. So, this is what the previous test asserted, and checking
- # what it claims to do causes test failures. --daniel 2011-08-23
end
it "should mark all returned resources as not virtual" do
diff --git a/spec/unit/parser/compiler_spec.rb b/spec/unit/parser/compiler_spec.rb
index 2c4b5221b..d64e57e8b 100755
--- a/spec/unit/parser/compiler_spec.rb
+++ b/spec/unit/parser/compiler_spec.rb
@@ -152,7 +152,7 @@ describe Puppet::Parser::Compiler do
it "should transform node class hashes into a class list" do
node = Puppet::Node.new("mynode")
- node.classes = {'foo'=>{'one'=>'1'}, 'bar'=>{'two'=>'2'}}
+ node.classes = {'foo'=>{'one'=>'p1'}, 'bar'=>{'two'=>'p2'}}
compiler = Puppet::Parser::Compiler.new(node)
compiler.classlist.should =~ ['foo', 'bar']
@@ -231,7 +231,7 @@ describe Puppet::Parser::Compiler do
end
it "should evaluate any parameterized classes named in the node" do
- classes = {'foo'=>{'1'=>'one'}, 'bar'=>{'2'=>'two'}}
+ classes = {'foo'=>{'p1'=>'one'}, 'bar'=>{'p2'=>'two'}}
@node.stubs(:classes).returns(classes)
@compiler.expects(:evaluate_classes).with(classes, @compiler.topscope)
@compiler.compile
@@ -609,7 +609,7 @@ describe Puppet::Parser::Compiler do
# Define the given class with default parameters
def define_class(name, parameters)
@node.classes[name] = parameters
- klass = Puppet::Resource::Type.new(:hostclass, name, :arguments => {'1' => @ast_obj, '2' => @ast_obj})
+ klass = Puppet::Resource::Type.new(:hostclass, name, :arguments => {'p1' => @ast_obj, 'p2' => @ast_obj})
@compiler.topscope.known_resource_types.add klass
end
@@ -627,20 +627,20 @@ describe Puppet::Parser::Compiler do
it "should provide default values for parameters that have no values specified" do
define_class('foo', {})
compile()
- @catalog.resource(:class, 'foo')['1'].should == "foo"
+ @catalog.resource(:class, 'foo')['p1'].should == "foo"
end
it "should use any provided values" do
- define_class('foo', {'1' => 'real_value'})
+ define_class('foo', {'p1' => 'real_value'})
compile()
- @catalog.resource(:class, 'foo')['1'].should == "real_value"
+ @catalog.resource(:class, 'foo')['p1'].should == "real_value"
end
it "should support providing some but not all values" do
- define_class('foo', {'1' => 'real_value'})
+ define_class('foo', {'p1' => 'real_value'})
compile()
- @catalog.resource(:class, 'Foo')['1'].should == "real_value"
- @catalog.resource(:class, 'Foo')['2'].should == "foo"
+ @catalog.resource(:class, 'Foo')['p1'].should == "real_value"
+ @catalog.resource(:class, 'Foo')['p2'].should == "foo"
end
it "should ensure each node class is in catalog and has appropriate tags" do
@@ -648,7 +648,7 @@ describe Puppet::Parser::Compiler do
@node.classes = klasses
ast_obj = Puppet::Parser::AST::String.new(:value => 'foo')
klasses.each do |name|
- klass = Puppet::Resource::Type.new(:hostclass, name, :arguments => {'1' => ast_obj, '2' => ast_obj})
+ klass = Puppet::Resource::Type.new(:hostclass, name, :arguments => {'p1' => ast_obj, 'p2' => ast_obj})
@compiler.topscope.known_resource_types.add klass
end
catalog = @compiler.compile
@@ -659,11 +659,11 @@ describe Puppet::Parser::Compiler do
end
it "should fail if required parameters are missing" do
- klass = {'foo'=>{'1'=>'one'}}
+ klass = {'foo'=>{'a'=>'one'}}
@node.classes = klass
- klass = Puppet::Resource::Type.new(:hostclass, 'foo', :arguments => {'1' => nil, '2' => nil})
+ klass = Puppet::Resource::Type.new(:hostclass, 'foo', :arguments => {'a' => nil, 'b' => nil})
@compiler.topscope.known_resource_types.add klass
- lambda { @compiler.compile }.should raise_error(Puppet::ParseError, "Must pass 2 to Class[Foo]")
+ lambda { @compiler.compile }.should raise_error(Puppet::ParseError, "Must pass b to Class[Foo]")
end
it "should fail if invalid parameters are passed" do
diff --git a/spec/unit/parser/eparser_adapter_spec.rb b/spec/unit/parser/eparser_adapter_spec.rb
new file mode 100644
index 000000000..051633434
--- /dev/null
+++ b/spec/unit/parser/eparser_adapter_spec.rb
@@ -0,0 +1,407 @@
+#! /usr/bin/env ruby
+require 'spec_helper'
+require 'puppet/parser/e_parser_adapter'
+
+describe Puppet::Parser do
+
+ Puppet::Parser::AST
+
+ before :each do
+ @known_resource_types = Puppet::Resource::TypeCollection.new("development")
+ @classic_parser = Puppet::Parser::Parser.new "development"
+ @parser = Puppet::Parser::EParserAdapter.new(@classic_parser)
+ @classic_parser.stubs(:known_resource_types).returns @known_resource_types
+ @true_ast = Puppet::Parser::AST::Boolean.new :value => true
+ end
+
+ it "should require an environment at initialization" do
+ expect {
+ Puppet::Parser::EParserAdapter.new
+ }.to raise_error(ArgumentError, /wrong number of arguments/)
+ end
+
+ describe "when parsing append operator" do
+
+ it "should not raise syntax errors" do
+ expect { @parser.parse("$var += something") }.to_not raise_error
+ end
+
+ it "should raise syntax error on incomplete syntax " do
+ expect {
+ @parser.parse("$var += ")
+ }.to raise_error(Puppet::ParseError, /Syntax error at end of file/)
+ end
+
+ it "should create ast::VarDef with append=true" do
+ vardef = @parser.parse("$var += 2").code[0]
+ vardef.should be_a(Puppet::Parser::AST::VarDef)
+ vardef.append.should == true
+ end
+
+ it "should work with arrays too" do
+ vardef = @parser.parse("$var += ['test']").code[0]
+ vardef.should be_a(Puppet::Parser::AST::VarDef)
+ vardef.append.should == true
+ end
+
+ end
+
+ describe "when parsing selector" do
+ it "should support hash access on the left hand side" do
+ expect { @parser.parse("$h = { 'a' => 'b' } $a = $h['a'] ? { 'b' => 'd', default => undef }") }.to_not raise_error
+ end
+ end
+
+ describe "parsing 'unless'" do
+ it "should create the correct ast objects" do
+ Puppet::Parser::AST::Not.expects(:new).with { |h| h[:value].is_a?(Puppet::Parser::AST::Boolean) }
+ @parser.parse("unless false { $var = 1 }")
+ end
+
+ it "should not raise an error with empty statements" do
+ expect { @parser.parse("unless false { }") }.to_not raise_error
+ end
+
+ #test for bug #13296
+ it "should not override 'unless' as a parameter inside resources" do
+ lambda { @parser.parse("exec {'/bin/echo foo': unless => '/usr/bin/false',}") }.should_not raise_error
+ end
+ end
+
+ describe "when parsing parameter names" do
+ Puppet::Parser::Lexer::KEYWORDS.sort_tokens.each do |keyword|
+ it "should allow #{keyword} as a keyword" do
+ lambda { @parser.parse("exec {'/bin/echo foo': #{keyword} => '/usr/bin/false',}") }.should_not raise_error
+ end
+ end
+ end
+
+ describe "when parsing 'if'" do
+ it "not, it should create the correct ast objects" do
+ Puppet::Parser::AST::Not.expects(:new).with { |h| h[:value].is_a?(Puppet::Parser::AST::Boolean) }
+ @parser.parse("if ! true { $var = 1 }")
+ end
+
+ it "boolean operation, it should create the correct ast objects" do
+ Puppet::Parser::AST::BooleanOperator.expects(:new).with {
+ |h| h[:rval].is_a?(Puppet::Parser::AST::Boolean) and h[:lval].is_a?(Puppet::Parser::AST::Boolean) and h[:operator]=="or"
+ }
+ @parser.parse("if true or true { $var = 1 }")
+
+ end
+
+ it "comparison operation, it should create the correct ast objects" do
+ Puppet::Parser::AST::ComparisonOperator.expects(:new).with {
+ |h| h[:lval].is_a?(Puppet::Parser::AST::Name) and h[:rval].is_a?(Puppet::Parser::AST::Name) and h[:operator]=="<"
+ }
+ @parser.parse("if 1 < 2 { $var = 1 }")
+
+ end
+
+ end
+
+ describe "when parsing if complex expressions" do
+ it "should create a correct ast tree" do
+ aststub = stub_everything 'ast'
+ Puppet::Parser::AST::ComparisonOperator.expects(:new).with {
+ |h| h[:rval].is_a?(Puppet::Parser::AST::Name) and h[:lval].is_a?(Puppet::Parser::AST::Name) and h[:operator]==">"
+ }.returns(aststub)
+ Puppet::Parser::AST::ComparisonOperator.expects(:new).with {
+ |h| h[:rval].is_a?(Puppet::Parser::AST::Name) and h[:lval].is_a?(Puppet::Parser::AST::Name) and h[:operator]=="=="
+ }.returns(aststub)
+ Puppet::Parser::AST::BooleanOperator.expects(:new).with {
+ |h| h[:rval]==aststub and h[:lval]==aststub and h[:operator]=="and"
+ }
+ @parser.parse("if (1 > 2) and (1 == 2) { $var = 1 }")
+ end
+
+ it "should raise an error on incorrect expression" do
+ expect {
+ @parser.parse("if (1 > 2 > ) or (1 == 2) { $var = 1 }")
+ }.to raise_error(Puppet::ParseError, /Syntax error at '\)'/)
+ end
+
+ end
+
+ describe "when parsing resource references" do
+
+ it "should not raise syntax errors" do
+ expect { @parser.parse('exec { test: param => File["a"] }') }.to_not raise_error
+ end
+
+ it "should not raise syntax errors with multiple references" do
+ expect { @parser.parse('exec { test: param => File["a","b"] }') }.to_not raise_error
+ end
+
+ it "should create an ast::ResourceReference" do
+ # NOTE: In egrammar, type and name are unified immediately to lower case whereas the regular grammar
+ # keeps the UC name in some contexts - it gets downcased later as the name of the type is in lower case.
+ #
+ Puppet::Parser::AST::ResourceReference.expects(:new).with { |arg|
+ arg[:line]==1 and arg[:pos] ==25 and arg[:type]=="file" and arg[:title].is_a?(Puppet::Parser::AST::ASTArray)
+ }
+ @parser.parse('exec { test: command => File["a","b"] }')
+ end
+ end
+
+ describe "when parsing resource overrides" do
+
+ it "should not raise syntax errors" do
+ expect { @parser.parse('Resource["title"] { param => value }') }.to_not raise_error
+ end
+
+ it "should not raise syntax errors with multiple overrides" do
+ expect { @parser.parse('Resource["title1","title2"] { param => value }') }.to_not raise_error
+ end
+
+ it "should create an ast::ResourceOverride" do
+ ro = @parser.parse('Resource["title1","title2"] { param => value }').code[0]
+ ro.should be_a(Puppet::Parser::AST::ResourceOverride)
+ ro.line.should == 1
+ ro.object.should be_a(Puppet::Parser::AST::ResourceReference)
+ ro.parameters[0].should be_a(Puppet::Parser::AST::ResourceParam)
+ end
+
+ end
+
+ describe "when parsing if statements" do
+
+ it "should not raise errors with empty if" do
+ expect { @parser.parse("if true { }") }.to_not raise_error
+ end
+
+ it "should not raise errors with empty else" do
+ expect { @parser.parse("if false { notice('if') } else { }") }.to_not raise_error
+ end
+
+ it "should not raise errors with empty if and else" do
+ expect { @parser.parse("if false { } else { }") }.to_not raise_error
+ end
+
+ it "should create a nop node for empty branch" do
+ Puppet::Parser::AST::Nop.expects(:new).twice
+ @parser.parse("if true { }")
+ end
+
+ it "should create a nop node for empty else branch" do
+ Puppet::Parser::AST::Nop.expects(:new)
+ @parser.parse("if true { notice('test') } else { }")
+ end
+
+ it "should build a chain of 'ifs' if there's an 'elsif'" do
+ expect { @parser.parse(<<-PP) }.to_not raise_error
+ if true { notice('test') } elsif true {} else { }
+ PP
+ end
+
+ end
+
+ describe "when parsing function calls" do
+ it "should not raise errors with no arguments" do
+ expect { @parser.parse("tag()") }.to_not raise_error
+ end
+
+ it "should not raise errors with rvalue function with no args" do
+ expect { @parser.parse("$a = template()") }.to_not raise_error
+ end
+
+ it "should not raise errors with arguments" do
+ expect { @parser.parse("notice(1)") }.to_not raise_error
+ end
+
+ it "should not raise errors with multiple arguments" do
+ expect { @parser.parse("notice(1,2)") }.to_not raise_error
+ end
+
+ it "should not raise errors with multiple arguments and a trailing comma" do
+ expect { @parser.parse("notice(1,2,)") }.to_not raise_error
+ end
+
+ end
+
+ describe "when parsing arrays" do
+ it "should parse an array" do
+ expect { @parser.parse("$a = [1,2]") }.to_not raise_error
+ end
+
+ it "should not raise errors with a trailing comma" do
+ expect { @parser.parse("$a = [1,2,]") }.to_not raise_error
+ end
+
+ it "should accept an empty array" do
+ expect { @parser.parse("$var = []\n") }.to_not raise_error
+ end
+ end
+
+ describe "when parsing classes" do
+ before :each do
+ @krt = Puppet::Resource::TypeCollection.new("development")
+ @classic_parser = Puppet::Parser::Parser.new "development"
+ @parser = Puppet::Parser::EParserAdapter.new(@classic_parser)
+ @classic_parser.stubs(:known_resource_types).returns @krt
+ end
+
+ it "should not create new classes" do
+ @parser.parse("class foobar {}").code[0].should be_a(Puppet::Parser::AST::Hostclass)
+ @krt.hostclass("foobar").should be_nil
+ end
+
+ it "should correctly set the parent class when one is provided" do
+ @parser.parse("class foobar inherits yayness {}").code[0].instantiate('')[0].parent.should == "yayness"
+ end
+
+ it "should correctly set the parent class for multiple classes at a time" do
+ statements = @parser.parse("class foobar inherits yayness {}\nclass boo inherits bar {}").code
+ statements[0].instantiate('')[0].parent.should == "yayness"
+ statements[1].instantiate('')[0].parent.should == "bar"
+ end
+
+ it "should define the code when some is provided" do
+ @parser.parse("class foobar { $var = val }").code[0].code.should_not be_nil
+ end
+
+ it "should accept parameters with trailing comma" do
+ @parser.parse("file { '/example': ensure => file, }").should be
+ end
+
+ it "should accept parametrized classes with trailing comma" do
+ @parser.parse("class foobar ($var1 = 0,) { $var = val }").code[0].code.should_not be_nil
+ end
+
+ it "should define parameters when provided" do
+ foobar = @parser.parse("class foobar($biz,$baz) {}").code[0].instantiate('')[0]
+ foobar.arguments.should == {"biz" => nil, "baz" => nil}
+ end
+ end
+
+ describe "when parsing resources" do
+ before :each do
+ @krt = Puppet::Resource::TypeCollection.new("development")
+ @classic_parser = Puppet::Parser::Parser.new "development"
+ @parser = Puppet::Parser::EParserAdapter.new(@classic_parser)
+ @classic_parser.stubs(:known_resource_types).returns @krt
+ end
+
+ it "should be able to parse class resources" do
+ @krt.add(Puppet::Resource::Type.new(:hostclass, "foobar", :arguments => {"biz" => nil}))
+ expect { @parser.parse("class { foobar: biz => stuff }") }.to_not raise_error
+ end
+
+ it "should correctly mark exported resources as exported" do
+ @parser.parse("@@file { '/file': }").code[0].exported.should be_true
+ end
+
+ it "should correctly mark virtual resources as virtual" do
+ @parser.parse("@file { '/file': }").code[0].virtual.should be_true
+ end
+ end
+
+ describe "when parsing nodes" do
+ it "should be able to parse a node with a single name" do
+ node = @parser.parse("node foo { }").code[0]
+ node.should be_a Puppet::Parser::AST::Node
+ node.names.length.should == 1
+ node.names[0].value.should == "foo"
+ end
+
+ it "should be able to parse a node with two names" do
+ node = @parser.parse("node foo, bar { }").code[0]
+ node.should be_a Puppet::Parser::AST::Node
+ node.names.length.should == 2
+ node.names[0].value.should == "foo"
+ node.names[1].value.should == "bar"
+ end
+
+ it "should be able to parse a node with three names" do
+ node = @parser.parse("node foo, bar, baz { }").code[0]
+ node.should be_a Puppet::Parser::AST::Node
+ node.names.length.should == 3
+ node.names[0].value.should == "foo"
+ node.names[1].value.should == "bar"
+ node.names[2].value.should == "baz"
+ end
+ end
+
+ it "should fail if trying to collect defaults" do
+ expect {
+ @parser.parse("@Port { protocols => tcp }")
+ }.to raise_error(Puppet::ParseError, /Defaults are not virtualizable/)
+ end
+
+ context "when parsing collections" do
+ it "should parse basic collections" do
+ @parser.parse("Port <| |>").code.
+ should be_all {|x| x.is_a? Puppet::Parser::AST::Collection }
+ end
+
+ it "should parse fully qualified collections" do
+ @parser.parse("Port::Range <| |>").code.
+ should be_all {|x| x.is_a? Puppet::Parser::AST::Collection }
+ end
+ end
+
+ it "should not assign to a fully qualified variable" do
+ expect {
+ @parser.parse("$one::two = yay")
+ }.to raise_error(Puppet::ParseError, /Cannot assign to variables in other namespaces/)
+ end
+
+ it "should parse assignment of undef" do
+ tree = @parser.parse("$var = undef")
+ tree.code.children[0].should be_an_instance_of Puppet::Parser::AST::VarDef
+ tree.code.children[0].value.should be_an_instance_of Puppet::Parser::AST::Undef
+ end
+
+ it "should treat classes as case insensitive" do
+ @classic_parser.known_resource_types.import_ast(@parser.parse("class yayness {}"), '')
+ @classic_parser.known_resource_types.hostclass('yayness').
+ should == @classic_parser.find_hostclass("", "YayNess")
+ end
+
+ it "should treat defines as case insensitive" do
+ @classic_parser.known_resource_types.import_ast(@parser.parse("define funtest {}"), '')
+ @classic_parser.known_resource_types.hostclass('funtest').
+ should == @classic_parser.find_hostclass("", "fUntEst")
+ end
+ context "when parsing method calls" do
+ it "should parse method call with one param lambda" do
+ expect { @parser.parse("$a.foreach {|$a| debug $a }") }.to_not raise_error
+ end
+ it "should parse method call with two param lambda" do
+ expect { @parser.parse("$a.foreach {|$a,$b| debug $a }") }.to_not raise_error
+ end
+ it "should parse method call with two param lambda and default value" do
+ expect { @parser.parse("$a.foreach {|$a,$b=1| debug $a }") }.to_not raise_error
+ end
+ it "should parse method call without lambda (statement)" do
+ expect { @parser.parse("$a.foreach") }.to_not raise_error
+ end
+ it "should parse method call without lambda (expression)" do
+ expect { @parser.parse("$x = $a.foreach + 1") }.to_not raise_error
+ end
+ context "a receiver expression of type" do
+ it "variable should be allowed" do
+ expect { @parser.parse("$a.foreach") }.to_not raise_error
+ end
+ it "hasharrayaccess should be allowed" do
+ expect { @parser.parse("$a[0][1].foreach") }.to_not raise_error
+ end
+ it "quoted text should be allowed" do
+ expect { @parser.parse("\"monkey\".foreach") }.to_not raise_error
+ expect { @parser.parse("'monkey'.foreach") }.to_not raise_error
+ end
+ it "selector text should be allowed" do
+ expect { @parser.parse("$a ? { 'banana'=>[1,2,3]}.foreach") }.to_not raise_error
+ end
+ it "function call should be allowed" do
+ expect { @parser.parse("duh(1,2,3).foreach") }.to_not raise_error
+ end
+ it "method call should be allowed" do
+ expect { @parser.parse("$a.foo.bar") }.to_not raise_error
+ end
+ it "chained method calls with lambda should be allowed" do
+ expect { @parser.parse("$a.foo{||}.bar{||}") }.to_not raise_error
+ end
+ end
+ end
+end
diff --git a/spec/unit/parser/functions/extlookup_spec.rb b/spec/unit/parser/functions/extlookup_spec.rb
index fae32fa97..ecd7a817a 100755
--- a/spec/unit/parser/functions/extlookup_spec.rb
+++ b/spec/unit/parser/functions/extlookup_spec.rb
@@ -1,6 +1,5 @@
#! /usr/bin/env ruby
require 'spec_helper'
-require 'tempfile'
describe "the extlookup function" do
include PuppetSpec::Files
@@ -33,36 +32,40 @@ describe "the extlookup function" do
end
it "should lookup the key in a supplied datafile" do
- t = Tempfile.new('extlookup.csv') do
+ dir = tmpdir("extlookup_spec")
+ File.open("#{dir}/extlookup.csv", "w") do |t|
t.puts 'key,value'
t.puts 'nonkey,nonvalue'
- t.close
-
- result = @scope.function_extlookup([ "key", "default", t.path])
- result.should == "value"
end
+
+ @scope.stubs(:[]).with('::extlookup_datadir').returns(dir)
+ @scope.stubs(:[]).with('::extlookup_precedence').returns(nil)
+ result = @scope.function_extlookup([ "key", "default", "extlookup"])
+ result.should == "value"
end
it "should return an array if the datafile contains more than two columns" do
- t = Tempfile.new('extlookup.csv') do
+ dir = tmpdir("extlookup_spec")
+ File.open("#{dir}/extlookup.csv", "w") do |t|
t.puts 'key,value1,value2'
t.puts 'nonkey,nonvalue,nonvalue'
- t.close
-
- result = @scope.function_extlookup([ "key", "default", t.path])
- result.should == ["value1", "value2"]
end
+
+ @scope.stubs(:[]).with('::extlookup_datadir').returns(dir)
+ @scope.stubs(:[]).with('::extlookup_precedence').returns(nil)
+ result = @scope.function_extlookup([ "key", "default", "extlookup"])
+ result.should == ["value1", "value2"]
end
it "should raise an error if there's no matching key and no default" do
- t = Tempfile.new('extlookup.csv') do
- t.puts 'key,value'
+ dir = tmpdir("extlookup_spec")
+ File.open("#{dir}/extlookup.csv", "w") do |t|
t.puts 'nonkey,nonvalue'
- t.close
-
- result = @scope.function_extlookup([ "key", nil, t.path])
- result.should == "value"
end
+
+ @scope.stubs(:[]).with('::extlookup_datadir').returns(dir)
+ @scope.stubs(:[]).with('::extlookup_precedence').returns(nil)
+ lambda { @scope.function_extlookup([ "key", nil, "extlookup"]) }.should raise_error(Puppet::ParseError, /No match found.*key/)
end
describe "should look in $extlookup_datadir for data files listed by $extlookup_precedence" do
diff --git a/spec/unit/parser/functions/fqdn_rand_spec.rb b/spec/unit/parser/functions/fqdn_rand_spec.rb
index 1facda6e8..e28dbff26 100755
--- a/spec/unit/parser/functions/fqdn_rand_spec.rb
+++ b/spec/unit/parser/functions/fqdn_rand_spec.rb
@@ -55,4 +55,9 @@ describe "the fqdn_rand function" do
val2 = @scope.function_fqdn_rand([10000000,42])
val1.should_not eql(val2)
end
+
+ it "should use the Puppet::Util function" do
+ Puppet::Util.expects(:deterministic_rand).with(177093203648075535190027737376590689559,4)
+ @scope.function_fqdn_rand([4])
+ end
end
diff --git a/spec/unit/parser/functions/hiera_include_spec.rb b/spec/unit/parser/functions/hiera_include_spec.rb
index f06d8c69c..a71bdb6c5 100644
--- a/spec/unit/parser/functions/hiera_include_spec.rb
+++ b/spec/unit/parser/functions/hiera_include_spec.rb
@@ -1,6 +1,4 @@
require 'spec_helper'
-require 'hiera_puppet'
-require 'puppet/parser/functions/hiera_include'
describe 'Puppet::Parser::Functions#hiera_include' do
let :scope do Puppet::Parser::Scope.new_for_test_harness('foo') end
diff --git a/spec/unit/parser/functions/hiera_spec.rb b/spec/unit/parser/functions/hiera_spec.rb
index 0abcb1b28..f22eee9d4 100755
--- a/spec/unit/parser/functions/hiera_spec.rb
+++ b/spec/unit/parser/functions/hiera_spec.rb
@@ -1,5 +1,3 @@
-#! /usr/bin/env ruby
-
require 'spec_helper'
describe 'Puppet::Parser::Functions#hiera' do
diff --git a/spec/unit/parser/functions_spec.rb b/spec/unit/parser/functions_spec.rb
index 1430ff26f..41ef54436 100755
--- a/spec/unit/parser/functions_spec.rb
+++ b/spec/unit/parser/functions_spec.rb
@@ -2,6 +2,9 @@
require 'spec_helper'
describe Puppet::Parser::Functions do
+ def callable_functions_from(mod)
+ Class.new { include mod }.new
+ end
it "should have a method for returning an environment-specific module" do
Puppet::Parser::Functions.environment_module(Puppet::Node::Environment.new("myenv")).should be_instance_of(Module)
@@ -16,15 +19,15 @@ describe Puppet::Parser::Functions do
end
describe "when calling newfunction" do
+ let(:function_module) { Module.new }
before do
- @module = Module.new
- Puppet::Parser::Functions.stubs(:environment_module).returns @module
+ Puppet::Parser::Functions.stubs(:environment_module).returns(function_module)
end
it "should create the function in the environment module" do
Puppet::Parser::Functions.newfunction("name", :type => :rvalue) { |args| }
- @module.should be_method_defined :function_name
+ function_module.should be_method_defined :function_name
end
it "should warn if the function already exists" do
@@ -37,12 +40,22 @@ describe Puppet::Parser::Functions do
it "should raise an error if the function type is not correct" do
lambda { Puppet::Parser::Functions.newfunction("name", :type => :unknown) { |args| } }.should raise_error Puppet::DevError, "Invalid statement type :unknown"
end
+
+ it "instruments the function to profiles the execution" do
+ messages = []
+ Puppet::Util::Profiler.current = Puppet::Util::Profiler::WallClock.new(proc { |msg| messages << msg }, "id")
+
+ Puppet::Parser::Functions.newfunction("name", :type => :rvalue) { |args| }
+ callable_functions_from(function_module).function_name([])
+
+ messages.first.should =~ /Called name/
+ end
end
describe "when calling function to test function existence" do
+ let(:function_module) { Module.new }
before do
- @module = Module.new
- Puppet::Parser::Functions.stubs(:environment_module).returns @module
+ Puppet::Parser::Functions.stubs(:environment_module).returns(function_module)
end
it "should return false if the function doesn't exist" do
@@ -65,40 +78,39 @@ describe Puppet::Parser::Functions do
end
describe "when calling function to test arity" do
- before :each do
- Puppet::Node::Environment.stubs(:current).returns(nil)
- @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new("foo"))
- @scope = Puppet::Parser::Scope.new(@compiler)
+ let(:function_module) { Module.new }
+ before do
+ Puppet::Parser::Functions.stubs(:environment_module).returns(function_module)
end
it "should raise an error if the function is called with too many arguments" do
Puppet::Parser::Functions.newfunction("name", :arity => 2) { |args| }
- lambda { @scope.function_name([1,2,3]) }.should raise_error ArgumentError
+ lambda { callable_functions_from(function_module).function_name([1,2,3]) }.should raise_error ArgumentError
end
it "should raise an error if the function is called with too few arguments" do
Puppet::Parser::Functions.newfunction("name", :arity => 2) { |args| }
- lambda { @scope.function_name([1]) }.should raise_error ArgumentError
+ lambda { callable_functions_from(function_module).function_name([1]) }.should raise_error ArgumentError
end
it "should not raise an error if the function is called with correct number of arguments" do
Puppet::Parser::Functions.newfunction("name", :arity => 2) { |args| }
- lambda { @scope.function_name([1,2]) }.should_not raise_error ArgumentError
+ lambda { callable_functions_from(function_module).function_name([1,2]) }.should_not raise_error ArgumentError
end
it "should raise an error if the variable arg function is called with too few arguments" do
Puppet::Parser::Functions.newfunction("name", :arity => -3) { |args| }
- lambda { @scope.function_name([1]) }.should raise_error ArgumentError
+ lambda { callable_functions_from(function_module).function_name([1]) }.should raise_error ArgumentError
end
it "should not raise an error if the variable arg function is called with correct number of arguments" do
Puppet::Parser::Functions.newfunction("name", :arity => -3) { |args| }
- lambda { @scope.function_name([1,2]) }.should_not raise_error ArgumentError
+ lambda { callable_functions_from(function_module).function_name([1,2]) }.should_not raise_error ArgumentError
end
it "should not raise an error if the variable arg function is called with more number of arguments" do
Puppet::Parser::Functions.newfunction("name", :arity => -3) { |args| }
- lambda { @scope.function_name([1,2,3]) }.should_not raise_error ArgumentError
+ lambda { callable_functions_from(function_module).function_name([1,2,3]) }.should_not raise_error ArgumentError
end
end
diff --git a/spec/unit/parser/methods/collect_spec.rb b/spec/unit/parser/methods/collect_spec.rb
new file mode 100644
index 000000000..13cd9eda6
--- /dev/null
+++ b/spec/unit/parser/methods/collect_spec.rb
@@ -0,0 +1,110 @@
+require 'puppet'
+require 'spec_helper'
+require 'puppet_spec/compiler'
+
+require 'unit/parser/methods/shared'
+
+describe 'the collect method' do
+ include PuppetSpec::Compiler
+
+ before :each do
+ Puppet[:parser] = "future"
+ end
+
+ context "using future parser" do
+ context "in Ruby style should be callable as" do
+ it 'collect on an array (multiplying each value by 2)' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = [1,2,3]
+ $a.collect {|$x| $x*2}.foreach {|$v|
+ file { "/file_$v": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_2")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_4")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_6")['ensure'].should == 'present'
+ end
+
+ it 'collect on a hash selecting keys' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = {'a'=>1,'b'=>2,'c'=>3}
+ $a.collect {|$x| $x[0]}.foreach {|$k|
+ file { "/file_$k": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_a")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_b")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_c")['ensure'].should == 'present'
+ end
+ it 'foreach on a hash selecting value' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = {'a'=>1,'b'=>2,'c'=>3}
+ $a.collect {|$x| $x[1]}.foreach {|$k|
+ file { "/file_$k": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_1")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_2")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_3")['ensure'].should == 'present'
+ end
+ end
+ context "in Java style should be callable as" do
+ shared_examples_for 'java style' do
+ it 'collect on an array (multiplying each value by 2)' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = [1,2,3]
+ $a.collect |$x| #{farr}{ $x*2}.foreach |$v| #{farr}{
+ file { "/file_$v": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_2")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_4")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_6")['ensure'].should == 'present'
+ end
+
+ it 'collect on a hash selecting keys' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = {'a'=>1,'b'=>2,'c'=>3}
+ $a.collect |$x| #{farr}{ $x[0]}.foreach |$k| #{farr}{
+ file { "/file_$k": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_a")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_b")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_c")['ensure'].should == 'present'
+ end
+
+ it 'foreach on a hash selecting value' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = {'a'=>1,'b'=>2,'c'=>3}
+ $a.collect |$x| #{farr} {$x[1]}.foreach |$k|#{farr}{
+ file { "/file_$k": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_1")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_2")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_3")['ensure'].should == 'present'
+ end
+ end
+ describe 'without fat arrow' do
+ it_should_behave_like 'java style' do
+ let(:farr) { '' }
+ end
+ end
+ describe 'with fat arrow' do
+ it_should_behave_like 'java style' do
+ let(:farr) { '=>' }
+ end
+ end
+ end
+ end
+
+ it_should_behave_like 'all iterative functions argument checks', 'collect'
+ it_should_behave_like 'all iterative functions hash handling', 'collect'
+end
diff --git a/spec/unit/parser/methods/each_spec.rb b/spec/unit/parser/methods/each_spec.rb
new file mode 100644
index 000000000..4d276e95d
--- /dev/null
+++ b/spec/unit/parser/methods/each_spec.rb
@@ -0,0 +1,91 @@
+require 'puppet'
+require 'spec_helper'
+require 'puppet_spec/compiler'
+require 'rubygems'
+
+describe 'the each method' do
+ include PuppetSpec::Compiler
+
+ before :each do
+ Puppet[:parser] = 'future'
+ end
+
+ context "should be callable as" do
+ it 'each on an array selecting each value' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = [1,2,3]
+ $a.each |$v| {
+ file { "/file_$v": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_1")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_2")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_3")['ensure'].should == 'present'
+ end
+ it 'each on an array selecting each value - function call style' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = [1,2,3]
+ each ($a) |$index, $v| => {
+ file { "/file_$v": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_1")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_2")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_3")['ensure'].should == 'present'
+ end
+
+ it 'each on an array with index' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = [present, absent, present]
+ $a.each |$k,$v| {
+ file { "/file_${$k+1}": ensure => $v }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_1")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_2")['ensure'].should == 'absent'
+ catalog.resource(:file, "/file_3")['ensure'].should == 'present'
+ end
+
+ it 'each on a hash selecting entries' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = {'a'=>'present','b'=>'absent','c'=>'present'}
+ $a.each |$e| {
+ file { "/file_${e[0]}": ensure => $e[1] }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_a")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_b")['ensure'].should == 'absent'
+ catalog.resource(:file, "/file_c")['ensure'].should == 'present'
+ end
+ it 'each on a hash selecting key and value' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = {'a'=>present,'b'=>absent,'c'=>present}
+ $a.each |$k, $v| {
+ file { "/file_$k": ensure => $v }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_a")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_b")['ensure'].should == 'absent'
+ catalog.resource(:file, "/file_c")['ensure'].should == 'present'
+ end
+ end
+ context "should produce receiver" do
+ it 'each checking produced value using single expression' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = [1, 3, 2]
+ $b = $a.each |$x| { "unwanted" }
+ file { "/file_${b[1]}":
+ ensure => present
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_3")['ensure'].should == 'present'
+ end
+
+ end
+end
diff --git a/spec/unit/parser/methods/foreach_spec.rb b/spec/unit/parser/methods/foreach_spec.rb
new file mode 100755
index 000000000..72a9379a4
--- /dev/null
+++ b/spec/unit/parser/methods/foreach_spec.rb
@@ -0,0 +1,91 @@
+require 'puppet'
+require 'spec_helper'
+require 'puppet_spec/compiler'
+require 'rubygems'
+
+describe 'the foreach method' do
+ include PuppetSpec::Compiler
+
+ before :each do
+ Puppet[:parser] = 'future'
+ end
+
+ context "should be callable as" do
+ it 'foreach on an array selecting each value' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = [1,2,3]
+ $a.foreach {|$v|
+ file { "/file_$v": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_1")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_2")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_3")['ensure'].should == 'present'
+ end
+ it 'foreach on an array selecting each value - function call style' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = [1,2,3]
+ foreach ($a) {|$v|
+ file { "/file_$v": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_1")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_2")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_3")['ensure'].should == 'present'
+ end
+
+ it 'foreach on an array with index' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = [present, absent, present]
+ $a.foreach {|$k,$v|
+ file { "/file_${$k+1}": ensure => $v }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_1")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_2")['ensure'].should == 'absent'
+ catalog.resource(:file, "/file_3")['ensure'].should == 'present'
+ end
+
+ it 'foreach on a hash selecting entries' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = {'a'=>'present','b'=>'absent','c'=>'present'}
+ $a.foreach {|$e|
+ file { "/file_${e[0]}": ensure => $e[1] }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_a")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_b")['ensure'].should == 'absent'
+ catalog.resource(:file, "/file_c")['ensure'].should == 'present'
+ end
+ it 'foreach on a hash selecting key and value' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = {'a'=>present,'b'=>absent,'c'=>present}
+ $a.foreach {|$k, $v|
+ file { "/file_$k": ensure => $v }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_a")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_b")['ensure'].should == 'absent'
+ catalog.resource(:file, "/file_c")['ensure'].should == 'present'
+ end
+ end
+ context "should produce receiver" do
+ it 'each checking produced value using single expression' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = [1, 3, 2]
+ $b = $a.each |$x| { $x }
+ file { "/file_${b[1]}":
+ ensure => present
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_3")['ensure'].should == 'present'
+ end
+
+ end
+end
diff --git a/spec/unit/parser/methods/reduce_spec.rb b/spec/unit/parser/methods/reduce_spec.rb
new file mode 100644
index 000000000..99ecfd18d
--- /dev/null
+++ b/spec/unit/parser/methods/reduce_spec.rb
@@ -0,0 +1,67 @@
+require 'puppet'
+require 'spec_helper'
+require 'puppet_spec/compiler'
+
+describe 'the reduce method' do
+ include PuppetSpec::Compiler
+
+ before :all do
+ # enable switching back
+ @saved_parser = Puppet[:parser]
+ # These tests only work with future parser
+ end
+ after :all do
+ # switch back to original
+ Puppet[:parser] = @saved_parser
+ end
+
+ before :each do
+ node = Puppet::Node.new("floppy", :environment => 'production')
+ @compiler = Puppet::Parser::Compiler.new(node)
+ @scope = Puppet::Parser::Scope.new(@compiler)
+ @topscope = @scope.compiler.topscope
+ @scope.parent = @topscope
+ Puppet[:parser] = 'future'
+ end
+
+ context "should be callable as" do
+ it 'reduce on an array' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = [1,2,3]
+ $b = $a.reduce {|$memo, $x| $memo + $x }
+ file { "/file_$b": ensure => present }
+ MANIFEST
+
+ catalog.resource(:file, "/file_6")['ensure'].should == 'present'
+ end
+ it 'reduce on an array with start value' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = [1,2,3]
+ $b = $a.reduce(4) {|$memo, $x| $memo + $x }
+ file { "/file_$b": ensure => present }
+ MANIFEST
+
+ catalog.resource(:file, "/file_10")['ensure'].should == 'present'
+ end
+ it 'reduce on a hash' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = {a=>1, b=>2, c=>3}
+ $start = [ignored, 4]
+ $b = $a.reduce {|$memo, $x| ['sum', $memo[1] + $x[1]] }
+ file { "/file_${$b[0]}_${$b[1]}": ensure => present }
+ MANIFEST
+
+ catalog.resource(:file, "/file_sum_6")['ensure'].should == 'present'
+ end
+ it 'reduce on a hash with start value' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = {a=>1, b=>2, c=>3}
+ $start = ['ignored', 4]
+ $b = $a.reduce($start) {|$memo, $x| ['sum', $memo[1] + $x[1]] }
+ file { "/file_${$b[0]}_${$b[1]}": ensure => present }
+ MANIFEST
+
+ catalog.resource(:file, "/file_sum_10")['ensure'].should == 'present'
+ end
+ end
+end
diff --git a/spec/unit/parser/methods/reject_spec.rb b/spec/unit/parser/methods/reject_spec.rb
new file mode 100644
index 000000000..e37eaebc5
--- /dev/null
+++ b/spec/unit/parser/methods/reject_spec.rb
@@ -0,0 +1,73 @@
+require 'puppet'
+require 'spec_helper'
+require 'puppet_spec/compiler'
+
+require 'unit/parser/methods/shared'
+
+describe 'the reject method' do
+ include PuppetSpec::Compiler
+
+ before :each do
+ Puppet[:parser] = 'future'
+ end
+
+ it 'rejects on an array (no berries)' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = ['strawberry','blueberry','orange']
+ $a.reject {|$x| $x =~ /berry$/}.foreach {|$v|
+ file { "/file_$v": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_orange")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_strawberry").should == nil
+ end
+
+ it 'produces an array when acting on an array' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = ['strawberry','blueberry','orange']
+ $b = $a.reject {|$x| $x =~ /berry$/}
+ file { "/file_${b[0]}": ensure => present }
+
+ MANIFEST
+
+ catalog.resource(:file, "/file_orange")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_strawberry").should == nil
+ end
+
+ it 'rejects on a hash (all berries) by key' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = {'strawberry'=>'red','blueberry'=>'blue','orange'=>'orange'}
+ $a.reject {|$x| $x[0] =~ /berry$/}.foreach {|$v|
+ file { "/file_${v[0]}": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_orange")['ensure'].should == 'present'
+ end
+
+ it 'produces a hash when acting on a hash' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = {'strawberry'=>'red','blueberry'=>'blue','grape'=>'purple'}
+ $b = $a.reject {|$x| $x[0] =~ /berry$/}
+ file { "/file_${b[grape]}": ensure => present }
+
+ MANIFEST
+
+ catalog.resource(:file, "/file_purple")['ensure'].should == 'present'
+ end
+
+ it 'rejects on a hash (all berries) by value' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = {'strawb'=>'red berry','blueb'=>'blue berry','orange'=>'orange fruit'}
+ $a.reject {|$x| $x[1] =~ /berry$/}.foreach {|$v|
+ file { "/file_${v[0]}": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_orange")['ensure'].should == 'present'
+ end
+
+ it_should_behave_like 'all iterative functions argument checks', 'reject'
+ it_should_behave_like 'all iterative functions hash handling', 'reject'
+end
diff --git a/spec/unit/parser/methods/select_spec.rb b/spec/unit/parser/methods/select_spec.rb
new file mode 100644
index 000000000..e61ee3a31
--- /dev/null
+++ b/spec/unit/parser/methods/select_spec.rb
@@ -0,0 +1,79 @@
+require 'puppet'
+require 'spec_helper'
+require 'puppet_spec/compiler'
+
+require 'unit/parser/methods/shared'
+
+describe 'the select method' do
+ include PuppetSpec::Compiler
+
+ before :each do
+ Puppet[:parser] = 'future'
+ end
+
+ it 'should select on an array (all berries)' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = ['strawberry','blueberry','orange']
+ $a.select {|$x| $x =~ /berry$/}.foreach {|$v|
+ file { "/file_$v": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_strawberry")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_blueberry")['ensure'].should == 'present'
+ end
+
+ it 'should produce an array when acting on an array' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = ['strawberry','blueberry','orange']
+ $b = $a.select {|$x| $x =~ /berry$/}
+ file { "/file_${b[0]}": ensure => present }
+ file { "/file_${b[1]}": ensure => present }
+ MANIFEST
+
+ catalog.resource(:file, "/file_strawberry")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_blueberry")['ensure'].should == 'present'
+ end
+
+ it 'selects on a hash (all berries) by key' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = {'strawberry'=>'red','blueberry'=>'blue','orange'=>'orange'}
+ $a.select {|$x| $x[0] =~ /berry$/}.foreach {|$v|
+ file { "/file_${v[0]}": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_strawberry")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_blueberry")['ensure'].should == 'present'
+ end
+
+ it 'should produce a hash when acting on a hash' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = {'strawberry'=>'red','blueberry'=>'blue','orange'=>'orange'}
+ $b = $a.select {|$x| $x[0] =~ /berry$/}
+ file { "/file_${b['strawberry']}": ensure => present }
+ file { "/file_${b['blueberry']}": ensure => present }
+ file { "/file_${b['orange']}": ensure => present }
+
+ MANIFEST
+
+ catalog.resource(:file, "/file_red")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_blue")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_")['ensure'].should == 'present'
+ end
+
+ it 'selects on a hash (all berries) by value' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = {'strawb'=>'red berry','blueb'=>'blue berry','orange'=>'orange fruit'}
+ $a.select {|$x| $x[1] =~ /berry$/}.foreach {|$v|
+ file { "/file_${v[0]}": ensure => present }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_strawb")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_blueb")['ensure'].should == 'present'
+ end
+
+ it_should_behave_like 'all iterative functions argument checks', 'select'
+ it_should_behave_like 'all iterative functions hash handling', 'select'
+end
diff --git a/spec/unit/parser/methods/shared.rb b/spec/unit/parser/methods/shared.rb
new file mode 100644
index 000000000..bf9c9f05f
--- /dev/null
+++ b/spec/unit/parser/methods/shared.rb
@@ -0,0 +1,61 @@
+
+shared_examples_for 'all iterative functions hash handling' do |func|
+ it 'passes a hash entry as an array of the key and value' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ {a=>1}.#{func} { |$v| notify { "${v[0]} ${v[1]}": } }
+ MANIFEST
+
+ catalog.resource(:notify, "a 1").should_not be_nil
+ end
+end
+
+shared_examples_for 'all iterative functions argument checks' do |func|
+
+ it 'raises an error when defined with more than 1 argument' do
+ expect do
+ compile_to_catalog(<<-MANIFEST)
+ [1].#{func} { |$x, $yikes| }
+ MANIFEST
+ end.to raise_error(Puppet::Error, /Too few arguments/)
+ end
+
+ it 'raises an error when defined with fewer than 1 argument' do
+ expect do
+ compile_to_catalog(<<-MANIFEST)
+ [1].#{func} { || }
+ MANIFEST
+ end.to raise_error(Puppet::Error, /Too many arguments/)
+ end
+
+ it 'raises an error when used against an unsupported type' do
+ expect do
+ compile_to_catalog(<<-MANIFEST)
+ "not correct".#{func} { |$v| }
+ MANIFEST
+ end.to raise_error(Puppet::Error, /must be an Array or a Hash/)
+ end
+
+ it 'raises an error when called with any parameters besides a block' do
+ expect do
+ compile_to_catalog(<<-MANIFEST)
+ [1].#{func}(1) { |$v| }
+ MANIFEST
+ end.to raise_error(Puppet::Error, /Wrong number of arguments/)
+ end
+
+ it 'raises an error when called without a block' do
+ expect do
+ compile_to_catalog(<<-MANIFEST)
+ [1].#{func}()
+ MANIFEST
+ end.to raise_error(Puppet::Error, /Wrong number of arguments/)
+ end
+
+ it 'raises an error when called without a block' do
+ expect do
+ compile_to_catalog(<<-MANIFEST)
+ [1].#{func}(1)
+ MANIFEST
+ end.to raise_error(Puppet::Error, /must be a parameterized block/)
+ end
+end
diff --git a/spec/unit/parser/methods/slice_spec.rb b/spec/unit/parser/methods/slice_spec.rb
new file mode 100644
index 000000000..b213415a1
--- /dev/null
+++ b/spec/unit/parser/methods/slice_spec.rb
@@ -0,0 +1,97 @@
+require 'puppet'
+require 'spec_helper'
+require 'puppet_spec/compiler'
+require 'rubygems'
+
+describe 'methods' do
+ include PuppetSpec::Compiler
+
+ before :all do
+ # enable switching back
+ @saved_parser = Puppet[:parser]
+ # These tests only work with future parser
+ Puppet[:parser] = 'future'
+ end
+ after :all do
+ # switch back to original
+ Puppet[:parser] = @saved_parser
+ end
+
+ before :each do
+ node = Puppet::Node.new("floppy", :environment => 'production')
+ @compiler = Puppet::Parser::Compiler.new(node)
+ @scope = Puppet::Parser::Scope.new(@compiler)
+ @topscope = @scope.compiler.topscope
+ @scope.parent = @topscope
+ Puppet[:parser] = 'future'
+ end
+
+ context "should be callable on array as" do
+
+ it 'slice with explicit parameters' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = [1, present, 2, absent, 3, present]
+ $a.slice(2) |$k,$v| {
+ file { "/file_${$k}": ensure => $v }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_1")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_2")['ensure'].should == 'absent'
+ catalog.resource(:file, "/file_3")['ensure'].should == 'present'
+ end
+ it 'slice with one parameter' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = [1, present, 2, absent, 3, present]
+ $a.slice(2) |$k| {
+ file { "/file_${$k[0]}": ensure => $k[1] }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_1")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_2")['ensure'].should == 'absent'
+ catalog.resource(:file, "/file_3")['ensure'].should == 'present'
+ end
+ it 'slice with shorter last slice' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = [1, present, 2, present, 3, absent]
+ $a.slice(4) |$a, $b, $c, $d| {
+ file { "/file_$a.$c": ensure => $b }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_1.2")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_3.")['ensure'].should == 'absent'
+ end
+ end
+ context "should be callable on hash as" do
+
+ it 'slice with explicit parameters, missing are empty' do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = {1=>present, 2=>present, 3=>absent}
+ $a.slice(2) |$a,$b| {
+ file { "/file_${a[0]}.${b[0]}": ensure => $a[1] }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_1.2")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_3.")['ensure'].should == 'absent'
+ end
+
+ end
+ context "when called without a block" do
+ it "should produce an array with the result" do
+ catalog = compile_to_catalog(<<-MANIFEST)
+ $a = [1, present, 2, absent, 3, present]
+ $a.slice(2).each |$k| {
+ file { "/file_${$k[0]}": ensure => $k[1] }
+ }
+ MANIFEST
+
+ catalog.resource(:file, "/file_1")['ensure'].should == 'present'
+ catalog.resource(:file, "/file_2")['ensure'].should == 'absent'
+ catalog.resource(:file, "/file_3")['ensure'].should == 'present'
+
+ end
+ end
+end
diff --git a/spec/unit/parser/parser_spec.rb b/spec/unit/parser/parser_spec.rb
index 7ff0c17b2..07ab6780c 100755
--- a/spec/unit/parser/parser_spec.rb
+++ b/spec/unit/parser/parser_spec.rb
@@ -100,11 +100,11 @@ describe Puppet::Parser do
Puppet::Parser::AST::Not.expects(:new).with { |h| h[:value].is_a?(Puppet::Parser::AST::Boolean) }
@parser.parse("unless false { $var = 1 }")
end
-
+
it "should not raise an error with empty statements" do
expect { @parser.parse("unless false { }") }.to_not raise_error
end
-
+
#test for bug #13296
it "should not override 'unless' as a parameter inside resources" do
lambda { @parser.parse("exec {'/bin/echo foo': unless => '/usr/bin/false',}") }.should_not raise_error
diff --git a/spec/unit/parser/scope_spec.rb b/spec/unit/parser/scope_spec.rb
index 86e9a8b10..8540ad20d 100755
--- a/spec/unit/parser/scope_spec.rb
+++ b/spec/unit/parser/scope_spec.rb
@@ -84,32 +84,34 @@ describe Puppet::Parser::Scope do
end
describe "when custom functions are called" do
- before :each do
- @env = Puppet::Node::Environment.new('testing')
- @compiler = Puppet::Parser::Compiler.new(Puppet::Node.new('foo', :environment => @env))
- @scope = Puppet::Parser::Scope.new(@compiler)
- end
+ let(:env) { Puppet::Node::Environment.new('testing') }
+ let(:compiler) { Puppet::Parser::Compiler.new(Puppet::Node.new('foo', :environment => env)) }
+ let(:scope) { Puppet::Parser::Scope.new(compiler) }
- it "should load and call the method if it looks like a function and it exists" do
- @scope.function_sprintf(["%b", 123]).should == "1111011"
+ it "calls methods prefixed with function_ as custom functions" do
+ scope.function_sprintf(["%b", 123]).should == "1111011"
end
- it "should raise and error when called without an Array" do
- expect { @scope.function_sprintf("%b", 123) }.to raise_error ArgumentError, /custom functions must be called with a single array that contains the arguments/
+ it "raises an error when arguments are not passed in an Array" do
+ expect do
+ scope.function_sprintf("%b", 123)
+ end.to raise_error ArgumentError, /custom functions must be called with a single array that contains the arguments/
end
- it "should raise and error when subsequent calls are without an Array" do
- @scope.function_sprintf(["first call"])
+ it "raises an error on subsequent calls when arguments are not passed in an Array" do
+ scope.function_sprintf(["first call"])
- expect { @scope.function_sprintf("%b", 123) }.to raise_error ArgumentError, /custom functions must be called with a single array that contains the arguments/
+ expect do
+ scope.function_sprintf("%b", 123)
+ end.to raise_error ArgumentError, /custom functions must be called with a single array that contains the arguments/
end
- it "should raise NoMethodError if the method doesn't look like a function" do
- expect { @scope.sprintf(["%b", 123]) }.to raise_error(NoMethodError)
+ it "raises NoMethodError when the not prefixed" do
+ expect { scope.sprintf(["%b", 123]) }.to raise_error(NoMethodError)
end
- it "should raise NoMethodError if the method looks like a function but doesn't exist" do
- expect { @scope.function_fake_bs(['cows']) }.to raise_error(NoMethodError)
+ it "raises NoMethodError when prefixed with function_ but it doesn't exist" do
+ expect { scope.function_fake_bs(['cows']) }.to raise_error(NoMethodError)
end
end
@@ -493,6 +495,27 @@ describe Puppet::Parser::Scope do
end
end
+ context "when using ephemeral as local scope" do
+ it "should store all variables in local scope" do
+ @scope.new_ephemeral true
+ @scope.setvar("apple", :fruit)
+ @scope["apple"].should == :fruit
+ end
+
+ it "should remove all local scope variables on unset" do
+ @scope.new_ephemeral true
+ @scope.setvar("apple", :fruit)
+ @scope["apple"].should == :fruit
+ @scope.unset_ephemeral_var
+ @scope["apple"].should == nil
+ end
+ it "should be created from a hash" do
+ @scope.ephemeral_from({ "apple" => :fruit, "strawberry" => :berry})
+ @scope["apple"].should == :fruit
+ @scope["strawberry"].should == :berry
+ end
+ end
+
describe "when setting ephemeral vars from matches" do
before :each do
@match = stub 'match', :is_a? => true
diff --git a/spec/unit/parser/templatewrapper_spec.rb b/spec/unit/parser/templatewrapper_spec.rb
index 1b95b0a73..81e0d846d 100755
--- a/spec/unit/parser/templatewrapper_spec.rb
+++ b/spec/unit/parser/templatewrapper_spec.rb
@@ -70,6 +70,12 @@ describe Puppet::Parser::TemplateWrapper do
tw.tags.should == ["tag1","tag2"]
end
+ it "warns about deprecated access to in-scope variables via method calls" do
+ Puppet.expects(:deprecation_warning).with("Variable access via 'in_scope_variable' is deprecated. Use '@in_scope_variable' instead. template[inline]:1")
+ scope["in_scope_variable"] = "is good"
+ tw.result("<%= in_scope_variable %>")
+ end
+
it "provides access to in-scope variables via method calls" do
scope["in_scope_variable"] = "is good"
tw.result("<%= in_scope_variable %>").should == "is good"
@@ -93,11 +99,6 @@ describe Puppet::Parser::TemplateWrapper do
tw.result("<%= @one %>").should == "foo"
end
- it "should not error out if one of the variables is a symbol" do
- scope.expects(:to_hash).returns(:_timestamp => "1234")
- tw.result("<%= @_timestamp %>").should == "1234"
- end
-
%w{! . ; :}.each do |badchar|
it "translates #{badchar} to _ in instance variables" do
scope["one#{badchar}"] = "foo"
diff --git a/spec/unit/parser/type_loader_spec.rb b/spec/unit/parser/type_loader_spec.rb
index e15c05fea..2938d4563 100755
--- a/spec/unit/parser/type_loader_spec.rb
+++ b/spec/unit/parser/type_loader_spec.rb
@@ -2,6 +2,8 @@
require 'spec_helper'
require 'puppet/parser/type_loader'
+require 'puppet/parser/parser_factory'
+require 'puppet/parser/e_parser_adapter'
require 'puppet_spec/modules'
require 'puppet_spec/files'
@@ -9,222 +11,246 @@ describe Puppet::Parser::TypeLoader do
include PuppetSpec::Modules
include PuppetSpec::Files
- before do
- @loader = Puppet::Parser::TypeLoader.new(:myenv)
- Puppet.expects(:deprecation_warning).never
- end
-
- it "should support an environment" do
- loader = Puppet::Parser::TypeLoader.new(:myenv)
- loader.environment.name.should == :myenv
- end
-
- it "should include the Environment Helper" do
- @loader.class.ancestors.should be_include(Puppet::Node::Environment::Helper)
- end
-
- it "should delegate its known resource types to its environment" do
- @loader.known_resource_types.should be_instance_of(Puppet::Resource::TypeCollection)
- end
-
- describe "when loading names from namespaces" do
- it "should do nothing if the name to import is an empty string" do
- @loader.expects(:name2files).never
- @loader.try_load_fqname(:hostclass, "") { |filename, modname| raise :should_not_occur }.should be_nil
+ shared_examples_for 'the typeloader' do
+ before do
+ @loader = Puppet::Parser::TypeLoader.new(:myenv)
+ Puppet.expects(:deprecation_warning).never
end
- it "should attempt to import each generated name" do
- @loader.expects(:import).with("foo/bar",nil).returns([])
- @loader.expects(:import).with("foo",nil).returns([])
- @loader.try_load_fqname(:hostclass, "foo::bar") { |f| false }
+ it "should support an environment" do
+ loader = Puppet::Parser::TypeLoader.new(:myenv)
+ loader.environment.name.should == :myenv
end
- end
- describe "when importing" do
- before do
- Puppet::Parser::Files.stubs(:find_manifests).returns ["modname", %w{file}]
- Puppet::Parser::Parser.any_instance.stubs(:parse).returns(Puppet::Parser::AST::Hostclass.new(''))
- Puppet::Parser::Parser.any_instance.stubs(:file=)
+ it "should include the Environment Helper" do
+ @loader.class.ancestors.should be_include(Puppet::Node::Environment::Helper)
end
- it "should return immediately when imports are being ignored" do
- Puppet::Parser::Files.expects(:find_manifests).never
- Puppet[:ignoreimport] = true
- @loader.import("foo").should be_nil
+ it "should delegate its known resource types to its environment" do
+ @loader.known_resource_types.should be_instance_of(Puppet::Resource::TypeCollection)
end
- it "should find all manifests matching the file or pattern" do
- Puppet::Parser::Files.expects(:find_manifests).with { |pat, opts| pat == "myfile" }.returns ["modname", %w{one}]
- @loader.import("myfile")
- end
+ describe "when loading names from namespaces" do
+ it "should do nothing if the name to import is an empty string" do
+ @loader.expects(:name2files).never
+ @loader.try_load_fqname(:hostclass, "") { |filename, modname| raise :should_not_occur }.should be_nil
+ end
- it "should use the directory of the current file if one is set" do
- Puppet::Parser::Files.expects(:find_manifests).with { |pat, opts| opts[:cwd] == make_absolute("/current") }.returns ["modname", %w{one}]
- @loader.import("myfile", make_absolute("/current/file"))
+ it "should attempt to import each generated name" do
+ @loader.expects(:import).with("foo/bar",nil).returns([])
+ @loader.expects(:import).with("foo",nil).returns([])
+ @loader.try_load_fqname(:hostclass, "foo::bar") { |f| false }
+ end
end
- it "should pass the environment when looking for files" do
- Puppet::Parser::Files.expects(:find_manifests).with { |pat, opts| opts[:environment] == @loader.environment }.returns ["modname", %w{one}]
- @loader.import("myfile")
- end
+ describe "when importing" do
+ before do
+ Puppet::Parser::Files.stubs(:find_manifests).returns ["modname", %w{file}]
+ parser_class.any_instance.stubs(:parse).returns(Puppet::Parser::AST::Hostclass.new(''))
+ parser_class.any_instance.stubs(:file=)
+ end
- it "should fail if no files are found" do
- Puppet::Parser::Files.expects(:find_manifests).returns [nil, []]
- lambda { @loader.import("myfile") }.should raise_error(Puppet::ImportError)
- end
+ it "should return immediately when imports are being ignored" do
+ Puppet::Parser::Files.expects(:find_manifests).never
+ Puppet[:ignoreimport] = true
+ @loader.import("foo").should be_nil
+ end
- it "should parse each found file" do
- Puppet::Parser::Files.expects(:find_manifests).returns ["modname", [make_absolute("/one")]]
- @loader.expects(:parse_file).with(make_absolute("/one")).returns(Puppet::Parser::AST::Hostclass.new(''))
- @loader.import("myfile")
- end
+ it "should find all manifests matching the file or pattern" do
+ Puppet::Parser::Files.expects(:find_manifests).with { |pat, opts| pat == "myfile" }.returns ["modname", %w{one}]
+ @loader.import("myfile")
+ end
- it "should make each file qualified before attempting to parse it" do
- Puppet::Parser::Files.expects(:find_manifests).returns ["modname", %w{one}]
- @loader.expects(:parse_file).with(make_absolute("/current/one")).returns(Puppet::Parser::AST::Hostclass.new(''))
- @loader.import("myfile", make_absolute("/current/file"))
- end
+ it "should use the directory of the current file if one is set" do
+ Puppet::Parser::Files.expects(:find_manifests).with { |pat, opts| opts[:cwd] == make_absolute("/current") }.returns ["modname", %w{one}]
+ @loader.import("myfile", make_absolute("/current/file"))
+ end
- it "should not attempt to import files that have already been imported" do
- Puppet::Parser::Files.expects(:find_manifests).returns ["modname", %w{/one}]
- Puppet::Parser::Parser.any_instance.expects(:parse).once.returns(Puppet::Parser::AST::Hostclass.new(''))
- @loader.import("myfile")
+ it "should pass the environment when looking for files" do
+ Puppet::Parser::Files.expects(:find_manifests).with { |pat, opts| opts[:environment] == @loader.environment }.returns ["modname", %w{one}]
+ @loader.import("myfile")
+ end
- # This will fail if it tries to reimport the file.
- @loader.import("myfile")
- end
- end
+ it "should fail if no files are found" do
+ Puppet::Parser::Files.expects(:find_manifests).returns [nil, []]
+ lambda { @loader.import("myfile") }.should raise_error(Puppet::ImportError)
+ end
- describe "when importing all" do
- before do
- @base = tmpdir("base")
+ it "should parse each found file" do
+ Puppet::Parser::Files.expects(:find_manifests).returns ["modname", [make_absolute("/one")]]
+ @loader.expects(:parse_file).with(make_absolute("/one")).returns(Puppet::Parser::AST::Hostclass.new(''))
+ @loader.import("myfile")
+ end
- # Create two module path directories
- @modulebase1 = File.join(@base, "first")
- FileUtils.mkdir_p(@modulebase1)
- @modulebase2 = File.join(@base, "second")
- FileUtils.mkdir_p(@modulebase2)
+ it "should make each file qualified before attempting to parse it" do
+ Puppet::Parser::Files.expects(:find_manifests).returns ["modname", %w{one}]
+ @loader.expects(:parse_file).with(make_absolute("/current/one")).returns(Puppet::Parser::AST::Hostclass.new(''))
+ @loader.import("myfile", make_absolute("/current/file"))
+ end
- Puppet[:modulepath] = "#{@modulebase1}#{File::PATH_SEPARATOR}#{@modulebase2}"
- end
+ it "should not attempt to import files that have already been imported" do
+ @loader = Puppet::Parser::TypeLoader.new(:myenv)
- def mk_module(basedir, name)
- PuppetSpec::Modules.create(name, basedir)
+ Puppet::Parser::Files.expects(:find_manifests).returns ["modname", %w{/one}]
+ parser_class.any_instance.expects(:parse).once.returns(Puppet::Parser::AST::Hostclass.new(''))
+ other_parser_class.any_instance.expects(:parse).never.returns(Puppet::Parser::AST::Hostclass.new(''))
+ @loader.import("myfile")
+
+ # This will fail if it tries to reimport the file.
+ @loader.import("myfile")
+ end
end
- # We have to pass the base path so that we can
- # write to modules that are in the second search path
- def mk_manifests(base, mod, type, files)
- exts = {"ruby" => ".rb", "puppet" => ".pp"}
- files.collect do |file|
- name = mod.name + "::" + file.gsub("/", "::")
- path = File.join(base, mod.name, "manifests", file + exts[type])
- FileUtils.mkdir_p(File.split(path)[0])
-
- # write out the class
- if type == "ruby"
- File.open(path, "w") { |f| f.print "hostclass '#{name}' do\nend" }
- else
- File.open(path, "w") { |f| f.print "class #{name} {}" }
+ describe "when importing all" do
+ before do
+ @base = tmpdir("base")
+
+ # Create two module path directories
+ @modulebase1 = File.join(@base, "first")
+ FileUtils.mkdir_p(@modulebase1)
+ @modulebase2 = File.join(@base, "second")
+ FileUtils.mkdir_p(@modulebase2)
+
+ Puppet[:modulepath] = "#{@modulebase1}#{File::PATH_SEPARATOR}#{@modulebase2}"
+ end
+
+ def mk_module(basedir, name)
+ PuppetSpec::Modules.create(name, basedir)
+ end
+
+ # We have to pass the base path so that we can
+ # write to modules that are in the second search path
+ def mk_manifests(base, mod, type, files)
+ exts = {"ruby" => ".rb", "puppet" => ".pp"}
+ files.collect do |file|
+ name = mod.name + "::" + file.gsub("/", "::")
+ path = File.join(base, mod.name, "manifests", file + exts[type])
+ FileUtils.mkdir_p(File.split(path)[0])
+
+ # write out the class
+ if type == "ruby"
+ File.open(path, "w") { |f| f.print "hostclass '#{name}' do\nend" }
+ else
+ File.open(path, "w") { |f| f.print "class #{name} {}" }
+ end
+ name
end
- name
end
- end
- it "should load all puppet manifests from all modules in the specified environment" do
- @module1 = mk_module(@modulebase1, "one")
- @module2 = mk_module(@modulebase2, "two")
+ it "should load all puppet manifests from all modules in the specified environment" do
+ @module1 = mk_module(@modulebase1, "one")
+ @module2 = mk_module(@modulebase2, "two")
- mk_manifests(@modulebase1, @module1, "puppet", %w{a b})
- mk_manifests(@modulebase2, @module2, "puppet", %w{c d})
+ mk_manifests(@modulebase1, @module1, "puppet", %w{a b})
+ mk_manifests(@modulebase2, @module2, "puppet", %w{c d})
- @loader.import_all
+ @loader.import_all
- @loader.environment.known_resource_types.hostclass("one::a").should be_instance_of(Puppet::Resource::Type)
- @loader.environment.known_resource_types.hostclass("one::b").should be_instance_of(Puppet::Resource::Type)
- @loader.environment.known_resource_types.hostclass("two::c").should be_instance_of(Puppet::Resource::Type)
- @loader.environment.known_resource_types.hostclass("two::d").should be_instance_of(Puppet::Resource::Type)
- end
+ @loader.environment.known_resource_types.hostclass("one::a").should be_instance_of(Puppet::Resource::Type)
+ @loader.environment.known_resource_types.hostclass("one::b").should be_instance_of(Puppet::Resource::Type)
+ @loader.environment.known_resource_types.hostclass("two::c").should be_instance_of(Puppet::Resource::Type)
+ @loader.environment.known_resource_types.hostclass("two::d").should be_instance_of(Puppet::Resource::Type)
+ end
- it "should load all ruby manifests from all modules in the specified environment" do
- Puppet.expects(:deprecation_warning).at_least(1)
+ it "should load all ruby manifests from all modules in the specified environment" do
+ Puppet.expects(:deprecation_warning).at_least(1)
- @module1 = mk_module(@modulebase1, "one")
- @module2 = mk_module(@modulebase2, "two")
+ @module1 = mk_module(@modulebase1, "one")
+ @module2 = mk_module(@modulebase2, "two")
- mk_manifests(@modulebase1, @module1, "ruby", %w{a b})
- mk_manifests(@modulebase2, @module2, "ruby", %w{c d})
+ mk_manifests(@modulebase1, @module1, "ruby", %w{a b})
+ mk_manifests(@modulebase2, @module2, "ruby", %w{c d})
- @loader.import_all
+ @loader.import_all
- @loader.environment.known_resource_types.hostclass("one::a").should be_instance_of(Puppet::Resource::Type)
- @loader.environment.known_resource_types.hostclass("one::b").should be_instance_of(Puppet::Resource::Type)
- @loader.environment.known_resource_types.hostclass("two::c").should be_instance_of(Puppet::Resource::Type)
- @loader.environment.known_resource_types.hostclass("two::d").should be_instance_of(Puppet::Resource::Type)
- end
+ @loader.environment.known_resource_types.hostclass("one::a").should be_instance_of(Puppet::Resource::Type)
+ @loader.environment.known_resource_types.hostclass("one::b").should be_instance_of(Puppet::Resource::Type)
+ @loader.environment.known_resource_types.hostclass("two::c").should be_instance_of(Puppet::Resource::Type)
+ @loader.environment.known_resource_types.hostclass("two::d").should be_instance_of(Puppet::Resource::Type)
+ end
- it "should not load manifests from duplicate modules later in the module path" do
- @module1 = mk_module(@modulebase1, "one")
+ it "should not load manifests from duplicate modules later in the module path" do
+ @module1 = mk_module(@modulebase1, "one")
- # duplicate
- @module2 = mk_module(@modulebase2, "one")
+ # duplicate
+ @module2 = mk_module(@modulebase2, "one")
- mk_manifests(@modulebase1, @module1, "puppet", %w{a})
- mk_manifests(@modulebase2, @module2, "puppet", %w{c})
+ mk_manifests(@modulebase1, @module1, "puppet", %w{a})
+ mk_manifests(@modulebase2, @module2, "puppet", %w{c})
- @loader.import_all
+ @loader.import_all
- @loader.environment.known_resource_types.hostclass("one::c").should be_nil
- end
+ @loader.environment.known_resource_types.hostclass("one::c").should be_nil
+ end
- it "should load manifests from subdirectories" do
- @module1 = mk_module(@modulebase1, "one")
+ it "should load manifests from subdirectories" do
+ @module1 = mk_module(@modulebase1, "one")
- mk_manifests(@modulebase1, @module1, "puppet", %w{a a/b a/b/c})
+ mk_manifests(@modulebase1, @module1, "puppet", %w{a a/b a/b/c})
- @loader.import_all
+ @loader.import_all
- @loader.environment.known_resource_types.hostclass("one::a::b").should be_instance_of(Puppet::Resource::Type)
- @loader.environment.known_resource_types.hostclass("one::a::b::c").should be_instance_of(Puppet::Resource::Type)
+ @loader.environment.known_resource_types.hostclass("one::a::b").should be_instance_of(Puppet::Resource::Type)
+ @loader.environment.known_resource_types.hostclass("one::a::b::c").should be_instance_of(Puppet::Resource::Type)
+ end
end
- end
- describe "when parsing a file" do
- before do
- @parser = Puppet::Parser::Parser.new(@loader.environment)
- @parser.stubs(:parse).returns(Puppet::Parser::AST::Hostclass.new(''))
- @parser.stubs(:file=)
- Puppet::Parser::Parser.stubs(:new).with(@loader.environment).returns @parser
- end
+ describe "when parsing a file" do
+ before do
+ @parser = Puppet::Parser::ParserFactory.parser(@loader.environment)
+ @parser.class.should == parser_class
+ @parser.stubs(:parse).returns(Puppet::Parser::AST::Hostclass.new(''))
+ @parser.stubs(:file=)
+ Puppet::Parser::ParserFactory.stubs(:parser).with(@loader.environment).returns @parser
+ end
- it "should create a new parser instance for each file using the current environment" do
- Puppet::Parser::Parser.expects(:new).with(@loader.environment).returns @parser
- @loader.parse_file("/my/file")
- end
+ it "should create a new parser instance for each file using the current environment" do
+ Puppet::Parser::ParserFactory.expects(:parser).with(@loader.environment).returns @parser
+ @loader.parse_file("/my/file")
+ end
- it "should assign the parser its file and parse" do
- @parser.expects(:file=).with("/my/file")
- @parser.expects(:parse).returns(Puppet::Parser::AST::Hostclass.new(''))
- @loader.parse_file("/my/file")
+ it "should assign the parser its file and parse" do
+ @parser.expects(:file=).with("/my/file")
+ @parser.expects(:parse).returns(Puppet::Parser::AST::Hostclass.new(''))
+ @loader.parse_file("/my/file")
+ end
end
- end
- it "should be able to add classes to the current resource type collection" do
- file = tmpfile("simple_file.pp")
- File.open(file, "w") { |f| f.puts "class foo {}" }
- @loader.import(file)
+ it "should be able to add classes to the current resource type collection" do
+ file = tmpfile("simple_file.pp")
+ File.open(file, "w") { |f| f.puts "class foo {}" }
+ @loader.import(file)
- @loader.known_resource_types.hostclass("foo").should be_instance_of(Puppet::Resource::Type)
- end
+ @loader.known_resource_types.hostclass("foo").should be_instance_of(Puppet::Resource::Type)
+ end
- describe "when deciding where to look for files" do
- { 'foo' => ['foo'],
- 'foo::bar' => ['foo/bar', 'foo'],
- 'foo::bar::baz' => ['foo/bar/baz', 'foo/bar', 'foo']
- }.each do |fqname, expected_paths|
- it "should look for #{fqname.inspect} in #{expected_paths.inspect}" do
- @loader.instance_eval { name2files(fqname) }.should == expected_paths
+ describe "when deciding where to look for files" do
+ { 'foo' => ['foo'],
+ 'foo::bar' => ['foo/bar', 'foo'],
+ 'foo::bar::baz' => ['foo/bar/baz', 'foo/bar', 'foo']
+ }.each do |fqname, expected_paths|
+ it "should look for #{fqname.inspect} in #{expected_paths.inspect}" do
+ @loader.instance_eval { name2files(fqname) }.should == expected_paths
+ end
end
end
end
+ describe 'when using the classic parser' do
+ before :each do
+ Puppet[:parser] = 'current'
+ end
+ it_should_behave_like 'the typeloader' do
+ let(:parser_class) { Puppet::Parser::Parser}
+ let(:other_parser_class) { Puppet::Parser::EParserAdapter}
+ end
+ end
+ describe 'when using the future parser' do
+ before :each do
+ Puppet[:parser] = 'future'
+ end
+ it_should_behave_like 'the typeloader' do
+ let(:parser_class) { Puppet::Parser::EParserAdapter}
+ let(:other_parser_class) { Puppet::Parser::Parser}
+ end
+ end
end