diff --git a/acceptance/tests/apply/conditionals/should_evaluate_else.rb b/acceptance/tests/apply/conditionals/should_evaluate_else.rb deleted file mode 100755 index 7bdceb1d1..000000000 --- a/acceptance/tests/apply/conditionals/should_evaluate_else.rb +++ /dev/null @@ -1,15 +0,0 @@ -test_name "else clause will be reached if no expressions match" -manifest = %q{ -if( 1 == 2) { - notice('if') -} elsif(2 == 3) { - notice('elsif') -} else { - notice('else') -} -} - -apply_manifest_on(agents, manifest) do - fail_test "the else clause did not evaluate" unless stdout.include? 'else' -end - diff --git a/acceptance/tests/apply/conditionals/should_evaluate_elsif.rb b/acceptance/tests/apply/conditionals/should_evaluate_elsif.rb deleted file mode 100755 index 027e247c9..000000000 --- a/acceptance/tests/apply/conditionals/should_evaluate_elsif.rb +++ /dev/null @@ -1,15 +0,0 @@ -test_name "should evaluate the elsif block in a conditional" -manifest = %q{ -if( 1 == 3) { - notice('if') -} elsif(2 == 2) { - notice('elsif') -} else { - notice('else') -} -} - -apply_manifest_on(agents, manifest) do - fail_test "didn't evaluate elsif" unless stdout.include? 'elsif' -end - diff --git a/acceptance/tests/apply/conditionals/should_evaluate_empty.rb b/acceptance/tests/apply/conditionals/should_evaluate_empty.rb deleted file mode 100644 index 85b0792b4..000000000 --- a/acceptance/tests/apply/conditionals/should_evaluate_empty.rb +++ /dev/null @@ -1,12 +0,0 @@ -test_name "ensure that undefined variables evaluate as false" -manifest = %q{ -if $undef_var { -} else { - notice('undef') -} -} - -apply_manifest_on(agents, manifest) do - fail_test "did not evaluate as expected" unless stdout.include? 'undef' -end - diff --git a/acceptance/tests/apply/conditionals/should_evaluate_false.rb b/acceptance/tests/apply/conditionals/should_evaluate_false.rb deleted file mode 100755 index 9a64e1663..000000000 --- a/acceptance/tests/apply/conditionals/should_evaluate_false.rb +++ /dev/null @@ -1,12 +0,0 @@ -test_name "test that false evaluates to false" -manifest = %q{ -if false { -} else { - notice('false') -} -} - -apply_manifest_on(agents, manifest) do - fail_test "didn't evaluate false correcly" unless stdout.include? 'false' -end - diff --git a/acceptance/tests/apply/conditionals/should_evaluate_if.rb b/acceptance/tests/apply/conditionals/should_evaluate_if.rb deleted file mode 100755 index d0113e518..000000000 --- a/acceptance/tests/apply/conditionals/should_evaluate_if.rb +++ /dev/null @@ -1,15 +0,0 @@ -test_name = "should evaluate an if block correctly" -manifest = %q{ -if( 1 == 1) { - notice('if') -} elsif(2 == 2) { - notice('elsif') -} else { - notice('else') -} -} - -apply_manifest_on(agents, manifest) do - fail_test "didn't evaluate correctly" unless stdout.include? 'if' -end - diff --git a/acceptance/tests/apply/conditionals/should_evaluate_strings_true.rb b/acceptance/tests/apply/conditionals/should_evaluate_strings_true.rb deleted file mode 100755 index 14b753085..000000000 --- a/acceptance/tests/apply/conditionals/should_evaluate_strings_true.rb +++ /dev/null @@ -1,13 +0,0 @@ -test_name "test that the string 'false' evaluates to true" -manifest = %q{ -if 'false' { - notice('true') -} else { - notice('false') -} -} - -apply_manifest_on(agents, manifest) do - fail_test "string 'false' didn't evaluate as true" unless - stdout.include? 'true' -end diff --git a/acceptance/tests/apply/conditionals/should_evaluate_undef.rb b/acceptance/tests/apply/conditionals/should_evaluate_undef.rb deleted file mode 100755 index ba5d6403e..000000000 --- a/acceptance/tests/apply/conditionals/should_evaluate_undef.rb +++ /dev/null @@ -1,11 +0,0 @@ -test_name "empty string should evaluate as false" -manifest = %q{ -if '' { -} else { - notice('empty') -} -} - -apply_manifest_on(agents, manifest) do - fail_test "didn't evaluate as false" unless stdout.include? 'empty' -end diff --git a/spec/integration/parser/compiler_spec.rb b/spec/integration/parser/compiler_spec.rb index 6ce0b7d67..a5ffefcce 100755 --- a/spec/integration/parser/compiler_spec.rb +++ b/spec/integration/parser/compiler_spec.rb @@ -1,541 +1,529 @@ #! /usr/bin/env ruby require 'spec_helper' require 'puppet/parser/parser_factory' require 'puppet_spec/compiler' require 'matchers/resource' describe "Puppet::Parser::Compiler" do include PuppetSpec::Compiler include Matchers::Resource before :each do @node = Puppet::Node.new "testnode" @scope_resource = stub 'scope_resource', :builtin? => true, :finish => nil, :ref => 'Class[main]' @scope = stub 'scope', :resource => @scope_resource, :source => mock("source") end after do Puppet.settings.clear end - # shared because tests are invoked both for classic and future parser - # - shared_examples_for "the compiler" do - it "should be able to determine the configuration version from a local version control repository" do - pending("Bug #14071 about semantics of Puppet::Util::Execute on Windows", :if => Puppet.features.microsoft_windows?) do - # This should always work, because we should always be - # in the puppet repo when we run this. - version = %x{git rev-parse HEAD}.chomp + it "should be able to determine the configuration version from a local version control repository" do + pending("Bug #14071 about semantics of Puppet::Util::Execute on Windows", :if => Puppet.features.microsoft_windows?) do + # This should always work, because we should always be + # in the puppet repo when we run this. + version = %x{git rev-parse HEAD}.chomp - Puppet.settings[:config_version] = 'git rev-parse HEAD' + Puppet.settings[:config_version] = 'git rev-parse HEAD' - @parser = Puppet::Parser::ParserFactory.parser "development" - @compiler = Puppet::Parser::Compiler.new(@node) + @parser = Puppet::Parser::ParserFactory.parser "development" + @compiler = Puppet::Parser::Compiler.new(@node) - @compiler.catalog.version.should == version - end + @compiler.catalog.version.should == version end + end + + it "should not create duplicate resources when a class is referenced both directly and indirectly by the node classifier (4792)" do + Puppet[:code] = <<-PP + class foo + { + notify { foo_notify: } + include bar + } + class bar + { + notify { bar_notify: } + } + PP + + @node.stubs(:classes).returns(['foo', 'bar']) + + catalog = Puppet::Parser::Compiler.compile(@node) + + catalog.resource("Notify[foo_notify]").should_not be_nil + catalog.resource("Notify[bar_notify]").should_not be_nil + end - it "should not create duplicate resources when a class is referenced both directly and indirectly by the node classifier (4792)" do + describe "when resolving class references" do + it "should favor local scope, even if there's an included class in topscope" do Puppet[:code] = <<-PP - class foo - { - notify { foo_notify: } - include bar + class experiment { + class baz { + } + notify {"x" : require => Class[Baz] } } - class bar - { - notify { bar_notify: } + class baz { } + include baz + include experiment + include experiment::baz PP - @node.stubs(:classes).returns(['foo', 'bar']) + catalog = Puppet::Parser::Compiler.compile(Puppet::Node.new("mynode")) - catalog = Puppet::Parser::Compiler.compile(@node) + notify_resource = catalog.resource( "Notify[x]" ) - catalog.resource("Notify[foo_notify]").should_not be_nil - catalog.resource("Notify[bar_notify]").should_not be_nil + notify_resource[:require].title.should == "Experiment::Baz" end - describe "when resolving class references" do - it "should favor local scope, even if there's an included class in topscope" do - Puppet[:code] = <<-PP - class experiment { - class baz { - } - notify {"x" : require => Class[Baz] } - } + it "should favor local scope, even if there's an unincluded class in topscope" do + Puppet[:code] = <<-PP + class experiment { class baz { } - include baz - include experiment - include experiment::baz - PP - - catalog = Puppet::Parser::Compiler.compile(Puppet::Node.new("mynode")) + notify {"x" : require => Class[Baz] } + } + class baz { + } + include experiment + include experiment::baz + PP - notify_resource = catalog.resource( "Notify[x]" ) + catalog = Puppet::Parser::Compiler.compile(Puppet::Node.new("mynode")) - notify_resource[:require].title.should == "Experiment::Baz" - end + notify_resource = catalog.resource( "Notify[x]" ) - it "should favor local scope, even if there's an unincluded class in topscope" do - Puppet[:code] = <<-PP - class experiment { - class baz { + notify_resource[:require].title.should == "Experiment::Baz" + end + end + describe "(ticket #13349) when explicitly specifying top scope" do + ["class {'::bar::baz':}", "include ::bar::baz"].each do |include| + describe "with #{include}" do + it "should find the top level class" do + Puppet[:code] = <<-MANIFEST + class { 'foo::test': } + class foo::test { + #{include} } - notify {"x" : require => Class[Baz] } - } - class baz { - } - include experiment - include experiment::baz - PP - - catalog = Puppet::Parser::Compiler.compile(Puppet::Node.new("mynode")) + class bar::baz { + notify { 'good!': } + } + class foo::bar::baz { + notify { 'bad!': } + } + MANIFEST - notify_resource = catalog.resource( "Notify[x]" ) + catalog = Puppet::Parser::Compiler.compile(Puppet::Node.new("mynode")) - notify_resource[:require].title.should == "Experiment::Baz" - end - end - describe "(ticket #13349) when explicitly specifying top scope" do - ["class {'::bar::baz':}", "include ::bar::baz"].each do |include| - describe "with #{include}" do - it "should find the top level class" do - Puppet[:code] = <<-MANIFEST - class { 'foo::test': } - class foo::test { - #{include} - } - class bar::baz { - notify { 'good!': } - } - class foo::bar::baz { - notify { 'bad!': } - } - MANIFEST - - catalog = Puppet::Parser::Compiler.compile(Puppet::Node.new("mynode")) - - catalog.resource("Class[Bar::Baz]").should_not be_nil - catalog.resource("Notify[good!]").should_not be_nil - catalog.resource("Class[Foo::Bar::Baz]").should be_nil - catalog.resource("Notify[bad!]").should be_nil - end + catalog.resource("Class[Bar::Baz]").should_not be_nil + catalog.resource("Notify[good!]").should_not be_nil + catalog.resource("Class[Foo::Bar::Baz]").should be_nil + catalog.resource("Notify[bad!]").should be_nil end end end + end - it "should recompute the version after input files are re-parsed" do - Puppet[:code] = 'class foo { }' - Time.stubs(:now).returns(1) - node = Puppet::Node.new('mynode') - Puppet::Parser::Compiler.compile(node).version.should == 1 - Time.stubs(:now).returns(2) - Puppet::Parser::Compiler.compile(node).version.should == 1 # no change because files didn't change - Puppet::Resource::TypeCollection.any_instance.stubs(:stale?).returns(true).then.returns(false) # pretend change - Puppet::Parser::Compiler.compile(node).version.should == 2 - end - - ['class', 'define', 'node'].each do |thing| - it "should not allow '#{thing}' inside evaluated conditional constructs" do - Puppet[:code] = <<-PP - if true { - #{thing} foo { - } - notify { decoy: } - } - PP - - begin - Puppet::Parser::Compiler.compile(Puppet::Node.new("mynode")) - raise "compilation should have raised Puppet::Error" - rescue Puppet::Error => e - e.message.should =~ /at line 2/ - end - end - end + it "should recompute the version after input files are re-parsed" do + Puppet[:code] = 'class foo { }' + Time.stubs(:now).returns(1) + node = Puppet::Node.new('mynode') + Puppet::Parser::Compiler.compile(node).version.should == 1 + Time.stubs(:now).returns(2) + Puppet::Parser::Compiler.compile(node).version.should == 1 # no change because files didn't change + Puppet::Resource::TypeCollection.any_instance.stubs(:stale?).returns(true).then.returns(false) # pretend change + Puppet::Parser::Compiler.compile(node).version.should == 2 + end - it "should not allow classes inside unevaluated conditional constructs" do + ['class', 'define', 'node'].each do |thing| + it "should not allow '#{thing}' inside evaluated conditional constructs" do Puppet[:code] = <<-PP - if false { - class foo { + if true { + #{thing} foo { } + notify { decoy: } } PP - lambda { Puppet::Parser::Compiler.compile(Puppet::Node.new("mynode")) }.should raise_error(Puppet::Error) + begin + Puppet::Parser::Compiler.compile(Puppet::Node.new("mynode")) + raise "compilation should have raised Puppet::Error" + rescue Puppet::Error => e + e.message.should =~ /at line 2/ + end end + end - describe "when defining relationships" do - def extract_name(ref) - ref.sub(/File\[(\w+)\]/, '\1') - end + it "should not allow classes inside unevaluated conditional constructs" do + Puppet[:code] = <<-PP + if false { + class foo { + } + } + PP - let(:node) { Puppet::Node.new('mynode') } - let(:code) do - <<-MANIFEST - file { [a,b,c]: - mode => 0644, - } - file { [d,e]: - mode => 0755, - } - MANIFEST - end - let(:expected_relationships) { [] } - let(:expected_subscriptions) { [] } + lambda { Puppet::Parser::Compiler.compile(Puppet::Node.new("mynode")) }.should raise_error(Puppet::Error) + end - before :each do - Puppet[:code] = code - end + describe "when defining relationships" do + def extract_name(ref) + ref.sub(/File\[(\w+)\]/, '\1') + end - after :each do - catalog = Puppet::Parser::Compiler.compile(node) + let(:node) { Puppet::Node.new('mynode') } + let(:code) do + <<-MANIFEST + file { [a,b,c]: + mode => 0644, + } + file { [d,e]: + mode => 0755, + } + MANIFEST + end + let(:expected_relationships) { [] } + let(:expected_subscriptions) { [] } - resources = catalog.resources.select { |res| res.type == 'File' } + before :each do + Puppet[:code] = code + end - actual_relationships, actual_subscriptions = [:before, :notify].map do |relation| - resources.map do |res| - dependents = Array(res[relation]) - dependents.map { |ref| [res.title, extract_name(ref)] } - end.inject(&:concat) - end + after :each do + catalog = Puppet::Parser::Compiler.compile(node) + + resources = catalog.resources.select { |res| res.type == 'File' } - actual_relationships.should =~ expected_relationships - actual_subscriptions.should =~ expected_subscriptions + actual_relationships, actual_subscriptions = [:before, :notify].map do |relation| + resources.map do |res| + dependents = Array(res[relation]) + dependents.map { |ref| [res.title, extract_name(ref)] } + end.inject(&:concat) end - it "should create a relationship" do - code << "File[a] -> File[b]" + actual_relationships.should =~ expected_relationships + actual_subscriptions.should =~ expected_subscriptions + end - expected_relationships << ['a','b'] - end + it "should create a relationship" do + code << "File[a] -> File[b]" - it "should create a subscription" do - code << "File[a] ~> File[b]" + expected_relationships << ['a','b'] + end - expected_subscriptions << ['a', 'b'] - end + it "should create a subscription" do + code << "File[a] ~> File[b]" - it "should create relationships using title arrays" do - code << "File[a,b] -> File[c,d]" + expected_subscriptions << ['a', 'b'] + end - expected_relationships.concat [ - ['a', 'c'], - ['b', 'c'], - ['a', 'd'], - ['b', 'd'], - ] - end + it "should create relationships using title arrays" do + code << "File[a,b] -> File[c,d]" - it "should create relationships using collection expressions" do - code << "File <| mode == 0644 |> -> File <| mode == 0755 |>" - - expected_relationships.concat [ - ['a', 'd'], - ['b', 'd'], - ['c', 'd'], - ['a', 'e'], - ['b', 'e'], - ['c', 'e'], - ] - end + expected_relationships.concat [ + ['a', 'c'], + ['b', 'c'], + ['a', 'd'], + ['b', 'd'], + ] + end - it "should create relationships using resource names" do - code << "'File[a]' -> 'File[b]'" + it "should create relationships using collection expressions" do + code << "File <| mode == 0644 |> -> File <| mode == 0755 |>" + + expected_relationships.concat [ + ['a', 'd'], + ['b', 'd'], + ['c', 'd'], + ['a', 'e'], + ['b', 'e'], + ['c', 'e'], + ] + end - expected_relationships << ['a', 'b'] - end + it "should create relationships using resource names" do + code << "'File[a]' -> 'File[b]'" - it "should create relationships using variables" do - code << <<-MANIFEST - $var = File[a] - $var -> File[b] - MANIFEST + expected_relationships << ['a', 'b'] + end - expected_relationships << ['a', 'b'] - end + it "should create relationships using variables" do + code << <<-MANIFEST + $var = File[a] + $var -> File[b] + MANIFEST - it "should create relationships using case statements" do - code << <<-MANIFEST - $var = 10 - case $var { - 10: { - file { s1: } - } - 12: { - file { s2: } - } + expected_relationships << ['a', 'b'] + end + + it "should create relationships using case statements" do + code << <<-MANIFEST + $var = 10 + case $var { + 10: { + file { s1: } } - -> - case $var + 2 { - 10: { - file { t1: } - } - 12: { - file { t2: } - } + 12: { + file { s2: } } - MANIFEST + } + -> + case $var + 2 { + 10: { + file { t1: } + } + 12: { + file { t2: } + } + } + MANIFEST - expected_relationships << ['s1', 't2'] - end + expected_relationships << ['s1', 't2'] + end - it "should create relationships using array members" do - code << <<-MANIFEST - $var = [ [ [ File[a], File[b] ] ] ] - $var[0][0][0] -> $var[0][0][1] - MANIFEST + it "should create relationships using array members" do + code << <<-MANIFEST + $var = [ [ [ File[a], File[b] ] ] ] + $var[0][0][0] -> $var[0][0][1] + MANIFEST - expected_relationships << ['a', 'b'] - end + expected_relationships << ['a', 'b'] + end - it "should create relationships using hash members" do - code << <<-MANIFEST - $var = {'foo' => {'bar' => {'source' => File[a], 'target' => File[b]}}} - $var[foo][bar][source] -> $var[foo][bar][target] - MANIFEST + it "should create relationships using hash members" do + code << <<-MANIFEST + $var = {'foo' => {'bar' => {'source' => File[a], 'target' => File[b]}}} + $var[foo][bar][source] -> $var[foo][bar][target] + MANIFEST - expected_relationships << ['a', 'b'] - end + expected_relationships << ['a', 'b'] + end - it "should create relationships using resource declarations" do - code << "file { l: } -> file { r: }" + it "should create relationships using resource declarations" do + code << "file { l: } -> file { r: }" - expected_relationships << ['l', 'r'] - end + expected_relationships << ['l', 'r'] + end - it "should chain relationships" do - code << "File[a] -> File[b] ~> File[c] <- File[d] <~ File[e]" + it "should chain relationships" do + code << "File[a] -> File[b] ~> File[c] <- File[d] <~ File[e]" - expected_relationships << ['a', 'b'] << ['d', 'c'] - expected_subscriptions << ['b', 'c'] << ['e', 'd'] - end + expected_relationships << ['a', 'b'] << ['d', 'c'] + expected_subscriptions << ['b', 'c'] << ['e', 'd'] end + end - context 'when working with immutable node data' do - context 'and have opted in to immutable_node_data' do - before :each do - Puppet[:immutable_node_data] = true - end + context 'when working with immutable node data' do + context 'and have opted in to immutable_node_data' do + before :each do + Puppet[:immutable_node_data] = true + end - def node_with_facts(facts) - Puppet[:facts_terminus] = :memory - Puppet::Node::Facts.indirection.save(Puppet::Node::Facts.new("testing", facts)) - node = Puppet::Node.new("testing") - node.fact_merge - node - end + def node_with_facts(facts) + Puppet[:facts_terminus] = :memory + Puppet::Node::Facts.indirection.save(Puppet::Node::Facts.new("testing", facts)) + node = Puppet::Node.new("testing") + node.fact_merge + node + end - matcher :fail_compile_with do |node, message_regex| - match do |manifest| - @error = nil - begin - compile_to_catalog(manifest, node) - false - rescue Puppet::Error => e - @error = e - message_regex.match(e.message) - end + matcher :fail_compile_with do |node, message_regex| + match do |manifest| + @error = nil + begin + compile_to_catalog(manifest, node) + false + rescue Puppet::Error => e + @error = e + message_regex.match(e.message) end + end - failure_message_for_should do - if @error - "failed with #{@error}\n#{@error.backtrace}" - else - "did not fail" - end + failure_message_for_should do + if @error + "failed with #{@error}\n#{@error.backtrace}" + else + "did not fail" end end + end - it 'should make $facts available' do - node = node_with_facts('the_facts' => 'straight') + it 'should make $facts available' do + node = node_with_facts('the_facts' => 'straight') - catalog = compile_to_catalog(<<-MANIFEST, node) - notify { 'test': message => $facts[the_facts] } - MANIFEST + catalog = compile_to_catalog(<<-MANIFEST, node) + notify { 'test': message => $facts[the_facts] } + MANIFEST - catalog.resource("Notify[test]")[:message].should == "straight" - end + catalog.resource("Notify[test]")[:message].should == "straight" + end - it 'should make $facts reserved' do - node = node_with_facts('the_facts' => 'straight') + it 'should make $facts reserved' do + node = node_with_facts('the_facts' => 'straight') - expect('$facts = {}').to fail_compile_with(node, /assign to a reserved variable name: 'facts'/) - expect('class a { $facts = {} } include a').to fail_compile_with(node, /assign to a reserved variable name: 'facts'/) - end + expect('$facts = {}').to fail_compile_with(node, /assign to a reserved variable name: 'facts'/) + expect('class a { $facts = {} } include a').to fail_compile_with(node, /assign to a reserved variable name: 'facts'/) + end - it 'should make $facts immutable' do - node = node_with_facts('string' => 'value', 'array' => ['string'], 'hash' => { 'a' => 'string' }, 'number' => 1, 'boolean' => true) + it 'should make $facts immutable' do + node = node_with_facts('string' => 'value', 'array' => ['string'], 'hash' => { 'a' => 'string' }, 'number' => 1, 'boolean' => true) - expect('$i=inline_template("<% @facts[%q{new}] = 2 %>")').to fail_compile_with(node, /frozen Hash/i) - expect('$i=inline_template("<% @facts[%q{string}].chop! %>")').to fail_compile_with(node, /frozen String/i) + expect('$i=inline_template("<% @facts[%q{new}] = 2 %>")').to fail_compile_with(node, /frozen Hash/i) + expect('$i=inline_template("<% @facts[%q{string}].chop! %>")').to fail_compile_with(node, /frozen String/i) - expect('$i=inline_template("<% @facts[%q{array}][0].chop! %>")').to fail_compile_with(node, /frozen String/i) - expect('$i=inline_template("<% @facts[%q{array}][1] = 2 %>")').to fail_compile_with(node, /frozen Array/i) + expect('$i=inline_template("<% @facts[%q{array}][0].chop! %>")').to fail_compile_with(node, /frozen String/i) + expect('$i=inline_template("<% @facts[%q{array}][1] = 2 %>")').to fail_compile_with(node, /frozen Array/i) - expect('$i=inline_template("<% @facts[%q{hash}][%q{a}].chop! %>")').to fail_compile_with(node, /frozen String/i) - expect('$i=inline_template("<% @facts[%q{hash}][%q{b}] = 2 %>")').to fail_compile_with(node, /frozen Hash/i) - end + expect('$i=inline_template("<% @facts[%q{hash}][%q{a}].chop! %>")').to fail_compile_with(node, /frozen String/i) + expect('$i=inline_template("<% @facts[%q{hash}][%q{b}] = 2 %>")').to fail_compile_with(node, /frozen Hash/i) + end - it 'should make $facts available even if there are no facts' do - Puppet[:facts_terminus] = :memory - node = Puppet::Node.new("testing2") - node.fact_merge + it 'should make $facts available even if there are no facts' do + Puppet[:facts_terminus] = :memory + node = Puppet::Node.new("testing2") + node.fact_merge - catalog = compile_to_catalog(<<-MANIFEST, node) - notify { 'test': message => $facts } - MANIFEST + catalog = compile_to_catalog(<<-MANIFEST, node) + notify { 'test': message => $facts } + MANIFEST - expect(catalog).to have_resource("Notify[test]").with_parameter(:message, {}) - end + expect(catalog).to have_resource("Notify[test]").with_parameter(:message, {}) end + end - context 'and have not opted in to immutable_node_data' do - before :each do - Puppet[:immutable_node_data] = false - end + context 'and have not opted in to immutable_node_data' do + before :each do + Puppet[:immutable_node_data] = false + end - it 'should not make $facts available' do - Puppet[:facts_terminus] = :memory - facts = Puppet::Node::Facts.new("testing", 'the_facts' => 'straight') - Puppet::Node::Facts.indirection.save(facts) - node = Puppet::Node.new("testing") - node.fact_merge + it 'should not make $facts available' do + Puppet[:facts_terminus] = :memory + facts = Puppet::Node::Facts.new("testing", 'the_facts' => 'straight') + Puppet::Node::Facts.indirection.save(facts) + node = Puppet::Node.new("testing") + node.fact_merge - catalog = compile_to_catalog(<<-MANIFEST, node) - notify { 'test': message => "An $facts space" } - MANIFEST + catalog = compile_to_catalog(<<-MANIFEST, node) + notify { 'test': message => "An $facts space" } + MANIFEST - catalog.resource("Notify[test]")[:message].should == "An space" - end + catalog.resource("Notify[test]")[:message].should == "An space" end end + end - context 'when working with the trusted data hash' do - context 'and have opted in to trusted_node_data' do - before :each do - Puppet[:trusted_node_data] = true - end - - it 'should make $trusted available' do - node = Puppet::Node.new("testing") - node.trusted_data = { "data" => "value" } + context 'when working with the trusted data hash' do + context 'and have opted in to trusted_node_data' do + before :each do + Puppet[:trusted_node_data] = true + end - catalog = compile_to_catalog(<<-MANIFEST, node) - notify { 'test': message => $trusted[data] } - MANIFEST + it 'should make $trusted available' do + node = Puppet::Node.new("testing") + node.trusted_data = { "data" => "value" } - catalog.resource("Notify[test]")[:message].should == "value" - end + catalog = compile_to_catalog(<<-MANIFEST, node) + notify { 'test': message => $trusted[data] } + MANIFEST - it 'should not allow assignment to $trusted' do - node = Puppet::Node.new("testing") - node.trusted_data = { "data" => "value" } - - expect do - catalog = compile_to_catalog(<<-MANIFEST, node) - $trusted = 'changed' - notify { 'test': message => $trusted == 'changed' } - MANIFEST - catalog.resource("Notify[test]")[:message].should == true - end.to raise_error(Puppet::Error, /Attempt to assign to a reserved variable name: 'trusted'/) - end + catalog.resource("Notify[test]")[:message].should == "value" + end - it 'should not allow addition to $trusted hash' do - node = Puppet::Node.new("testing") - node.trusted_data = { "data" => "value" } - - expect do - catalog = compile_to_catalog(<<-MANIFEST, node) - $trusted['extra'] = 'added' - notify { 'test': message => $trusted['extra'] == 'added' } - MANIFEST - catalog.resource("Notify[test]")[:message].should == true - # different errors depending on regular or future parser - end.to raise_error(Puppet::Error, /(can't modify frozen [hH]ash)|(Illegal attempt to assign)/) - end + it 'should not allow assignment to $trusted' do + node = Puppet::Node.new("testing") + node.trusted_data = { "data" => "value" } - it 'should not allow addition to $trusted hash via Ruby inline template' do - node = Puppet::Node.new("testing") - node.trusted_data = { "data" => "value" } - - expect do - catalog = compile_to_catalog(<<-MANIFEST, node) - $dummy = inline_template("<% @trusted['extra'] = 'added' %> lol") - notify { 'test': message => $trusted['extra'] == 'added' } - MANIFEST - catalog.resource("Notify[test]")[:message].should == true - end.to raise_error(Puppet::Error, /can't modify frozen [hH]ash/) - end + expect do + catalog = compile_to_catalog(<<-MANIFEST, node) + $trusted = 'changed' + notify { 'test': message => $trusted == 'changed' } + MANIFEST + catalog.resource("Notify[test]")[:message].should == true + end.to raise_error(Puppet::Error, /Attempt to assign to a reserved variable name: 'trusted'/) end - context 'and have not opted in to trusted_node_data' do - before :each do - Puppet[:trusted_node_data] = false - end - - it 'should not make $trusted available' do - node = Puppet::Node.new("testing") - node.trusted_data = { "data" => "value" } + it 'should not allow addition to $trusted hash' do + node = Puppet::Node.new("testing") + node.trusted_data = { "data" => "value" } + expect do catalog = compile_to_catalog(<<-MANIFEST, node) - notify { 'test': message => $trusted == undef } + $trusted['extra'] = 'added' + notify { 'test': message => $trusted['extra'] == 'added' } MANIFEST - catalog.resource("Notify[test]")[:message].should == true - end + # different errors depending on regular or future parser + end.to raise_error(Puppet::Error, /(can't modify frozen [hH]ash)|(Illegal attempt to assign)/) + end - it 'should allow assignment to $trusted' do - node = Puppet::Node.new("testing") + it 'should not allow addition to $trusted hash via Ruby inline template' do + node = Puppet::Node.new("testing") + node.trusted_data = { "data" => "value" } + expect do catalog = compile_to_catalog(<<-MANIFEST, node) - $trusted = 'changed' - notify { 'test': message => $trusted == 'changed' } + $dummy = inline_template("<% @trusted['extra'] = 'added' %> lol") + notify { 'test': message => $trusted['extra'] == 'added' } MANIFEST - catalog.resource("Notify[test]")[:message].should == true - end + end.to raise_error(Puppet::Error, /can't modify frozen [hH]ash/) end end - context 'when evaluating collection' do - it 'matches on container inherited tags' do - Puppet[:code] = <<-MANIFEST - class xport_test { - tag 'foo_bar' - @notify { 'nbr1': - message => 'explicitly tagged', - tag => 'foo_bar' - } + context 'and have not opted in to trusted_node_data' do + before :each do + Puppet[:trusted_node_data] = false + end - @notify { 'nbr2': - message => 'implicitly tagged' - } + it 'should not make $trusted available' do + node = Puppet::Node.new("testing") + node.trusted_data = { "data" => "value" } - Notify <| tag == 'foo_bar' |> { - message => 'overridden' - } - } - include xport_test + catalog = compile_to_catalog(<<-MANIFEST, node) + notify { 'test': message => $trusted == undef } MANIFEST - catalog = Puppet::Parser::Compiler.compile(Puppet::Node.new("mynode")) + catalog.resource("Notify[test]")[:message].should == true + end + + it 'should allow assignment to $trusted' do + node = Puppet::Node.new("testing") + + catalog = compile_to_catalog(<<-MANIFEST, node) + $trusted = 'changed' + notify { 'test': message => $trusted == 'changed' } + MANIFEST - expect(catalog).to have_resource("Notify[nbr1]").with_parameter(:message, 'overridden') - expect(catalog).to have_resource("Notify[nbr2]").with_parameter(:message, 'overridden') + catalog.resource("Notify[test]")[:message].should == true end end end - describe 'using classic parser' do - before :each do - Puppet[:parser] = 'current' - end - it_behaves_like 'the compiler' do + context 'when evaluating collection' do + it 'matches on container inherited tags' do + Puppet[:code] = <<-MANIFEST + class xport_test { + tag 'foo_bar' + @notify { 'nbr1': + message => 'explicitly tagged', + tag => 'foo_bar' + } + + @notify { 'nbr2': + message => 'implicitly tagged' + } + + Notify <| tag == 'foo_bar' |> { + message => 'overridden' + } + } + include xport_test + MANIFEST + + catalog = Puppet::Parser::Compiler.compile(Puppet::Node.new("mynode")) + + expect(catalog).to have_resource("Notify[nbr1]").with_parameter(:message, 'overridden') + expect(catalog).to have_resource("Notify[nbr2]").with_parameter(:message, 'overridden') end end end diff --git a/spec/integration/parser/conditionals_spec.rb b/spec/integration/parser/conditionals_spec.rb new file mode 100644 index 000000000..82d950a06 --- /dev/null +++ b/spec/integration/parser/conditionals_spec.rb @@ -0,0 +1,117 @@ +require 'spec_helper' +require 'puppet_spec/compiler' +require 'matchers/resource' + +describe "Evaluation of Conditionals" do + include PuppetSpec::Compiler + include Matchers::Resource + + shared_examples_for "a catalog built with conditionals" do + it "evaluates an if block correctly" do + catalog = compile_to_catalog(<<-CODE) + if( 1 == 1) { + notify { 'if': } + } elsif(2 == 2) { + notify { 'elsif': } + } else { + notify { 'else': } + } + CODE + expect(catalog).to have_resource("Notify[if]") + end + + it "evaluates elsif block" do + catalog = compile_to_catalog(<<-CODE) + if( 1 == 3) { + notify { 'if': } + } elsif(2 == 2) { + notify { 'elsif': } + } else { + notify { 'else': } + } + CODE + expect(catalog).to have_resource("Notify[elsif]") + end + + it "reaches the else clause if no expressions match" do + catalog = compile_to_catalog(<<-CODE) + if( 1 == 2) { + notify { 'if': } + } elsif(2 == 3) { + notify { 'elsif': } + } else { + notify { 'else': } + } + CODE + expect(catalog).to have_resource("Notify[else]") + end + + it "evalutes false to false" do + catalog = compile_to_catalog(<<-CODE) + if false { + } else { + notify { 'false': } + } + CODE + expect(catalog).to have_resource("Notify[false]") + end + + it "evaluates the string 'false' as true" do + catalog = compile_to_catalog(<<-CODE) + if 'false' { + notify { 'true': } + } else { + notify { 'false': } + } + CODE + expect(catalog).to have_resource("Notify[true]") + end + + it "evaluates undefined variables as false" do + catalog = compile_to_catalog(<<-CODE) + if $undef_var { + } else { + notify { 'undef': } + } + CODE + expect(catalog).to have_resource("Notify[undef]") + end + end + + context "current parser" do + before(:each) do + Puppet[:parser] = 'current' + end + + it_behaves_like "a catalog built with conditionals" + + it "evaluates empty string as false" do + catalog = compile_to_catalog(<<-CODE) + if '' { + notify { 'true': } + } else { + notify { 'empty': } + } + CODE + expect(catalog).to have_resource("Notify[empty]") + end + end + + context "future parser" do + before(:each) do + Puppet[:parser] = 'future' + end + it_behaves_like "a catalog built with conditionals" + + it "evaluates empty string as true" do + catalog = compile_to_catalog(<<-CODE) + if '' { + notify { 'true': } + } else { + notify { 'empty': } + } + CODE + expect(catalog).to have_resource("Notify[true]") + end + end +end