diff options
Diffstat (limited to 'spec/unit/parser/compiler_spec.rb')
-rwxr-xr-x | spec/unit/parser/compiler_spec.rb | 1094 |
1 files changed, 547 insertions, 547 deletions
diff --git a/spec/unit/parser/compiler_spec.rb b/spec/unit/parser/compiler_spec.rb index 872cd7961..a3fe56c0e 100755 --- a/spec/unit/parser/compiler_spec.rb +++ b/spec/unit/parser/compiler_spec.rb @@ -3,752 +3,752 @@ require File.dirname(__FILE__) + '/../../spec_helper' class CompilerTestResource - attr_accessor :builtin, :virtual, :evaluated, :type, :title + attr_accessor :builtin, :virtual, :evaluated, :type, :title - def initialize(type, title) - @type = type - @title = title - end + def initialize(type, title) + @type = type + @title = title + end - def [](attr) - return nil if attr == :stage - :main - end + def [](attr) + return nil if attr == :stage + :main + end - def ref - "#{type.to_s.capitalize}[#{title}]" - end + def ref + "#{type.to_s.capitalize}[#{title}]" + end - def evaluated? - @evaluated - end + def evaluated? + @evaluated + end - def builtin? - @builtin - end + def builtin? + @builtin + end - def virtual? - @virtual - end + def virtual? + @virtual + end - def evaluate - end + def evaluate + end end describe Puppet::Parser::Compiler do - def resource(type, title) - Puppet::Parser::Resource.new(type, title, :scope => @scope) + def resource(type, title) + Puppet::Parser::Resource.new(type, title, :scope => @scope) + end + + before :each do + @node = Puppet::Node.new "testnode" + @known_resource_types = Puppet::Resource::TypeCollection.new "development" + @compiler = Puppet::Parser::Compiler.new(@node) + @scope = Puppet::Parser::Scope.new(:compiler => @compiler, :source => stub('source')) + @scope_resource = Puppet::Parser::Resource.new(:file, "/my/file", :scope => @scope) + @scope.resource = @scope_resource + @compiler.environment.stubs(:known_resource_types).returns @known_resource_types + end + + it "should have a class method that compiles, converts, and returns a catalog" do + compiler = stub 'compiler' + Puppet::Parser::Compiler.expects(:new).with(@node).returns compiler + catalog = stub 'catalog' + compiler.expects(:compile).returns catalog + converted_catalog = stub 'converted_catalog' + catalog.expects(:to_resource).returns converted_catalog + + Puppet::Parser::Compiler.compile(@node).should equal(converted_catalog) + end + + it "should fail intelligently when a class-level compile fails" do + Puppet::Parser::Compiler.expects(:new).raises ArgumentError + lambda { Puppet::Parser::Compiler.compile(@node) }.should raise_error(Puppet::Error) + end + + it "should use the node's environment as its environment" do + @compiler.environment.should equal(@node.environment) + end + + it "should include the resource type collection helper" do + Puppet::Parser::Compiler.ancestors.should be_include(Puppet::Resource::TypeCollectionHelper) + end + + it "should be able to return a class list containing all added classes" do + @compiler.add_class "" + @compiler.add_class "one" + @compiler.add_class "two" + + @compiler.classlist.sort.should == %w{one two}.sort + end + + describe "when initializing" do + + it "should set its node attribute" do + @compiler.node.should equal(@node) end - - before :each do - @node = Puppet::Node.new "testnode" - @known_resource_types = Puppet::Resource::TypeCollection.new "development" - @compiler = Puppet::Parser::Compiler.new(@node) - @scope = Puppet::Parser::Scope.new(:compiler => @compiler, :source => stub('source')) - @scope_resource = Puppet::Parser::Resource.new(:file, "/my/file", :scope => @scope) - @scope.resource = @scope_resource - @compiler.environment.stubs(:known_resource_types).returns @known_resource_types + it "should detect when ast nodes are absent" do + @compiler.ast_nodes?.should be_false end - it "should have a class method that compiles, converts, and returns a catalog" do - compiler = stub 'compiler' - Puppet::Parser::Compiler.expects(:new).with(@node).returns compiler - catalog = stub 'catalog' - compiler.expects(:compile).returns catalog - converted_catalog = stub 'converted_catalog' - catalog.expects(:to_resource).returns converted_catalog - - Puppet::Parser::Compiler.compile(@node).should equal(converted_catalog) + it "should detect when ast nodes are present" do + @known_resource_types.expects(:nodes?).returns true + @compiler.ast_nodes?.should be_true end - it "should fail intelligently when a class-level compile fails" do - Puppet::Parser::Compiler.expects(:new).raises ArgumentError - lambda { Puppet::Parser::Compiler.compile(@node) }.should raise_error(Puppet::Error) + it "should copy the known_resource_types version to the catalog" do + @compiler.catalog.version.should == @known_resource_types.version end - it "should use the node's environment as its environment" do - @compiler.environment.should equal(@node.environment) + it "should copy any node classes into the class list" do + node = Puppet::Node.new("mynode") + node.classes = %w{foo bar} + compiler = Puppet::Parser::Compiler.new(node) + + compiler.classlist.should include("foo") + compiler.classlist.should include("bar") end - it "should include the resource type collection helper" do - Puppet::Parser::Compiler.ancestors.should be_include(Puppet::Resource::TypeCollectionHelper) + it "should add a 'main' stage to the catalog" do + @compiler.catalog.resource(:stage, :main).should be_instance_of(Puppet::Parser::Resource) end + end - it "should be able to return a class list containing all added classes" do - @compiler.add_class "" - @compiler.add_class "one" - @compiler.add_class "two" + describe "when managing scopes" do - @compiler.classlist.sort.should == %w{one two}.sort + it "should create a top scope" do + @compiler.topscope.should be_instance_of(Puppet::Parser::Scope) end - describe "when initializing" do - - it "should set its node attribute" do - @compiler.node.should equal(@node) - end - it "should detect when ast nodes are absent" do - @compiler.ast_nodes?.should be_false - end + it "should be able to create new scopes" do + @compiler.newscope(@compiler.topscope).should be_instance_of(Puppet::Parser::Scope) + end - it "should detect when ast nodes are present" do - @known_resource_types.expects(:nodes?).returns true - @compiler.ast_nodes?.should be_true - end + it "should correctly set the level of newly created scopes" do + @compiler.newscope(@compiler.topscope, :level => 5).level.should == 5 + end - it "should copy the known_resource_types version to the catalog" do - @compiler.catalog.version.should == @known_resource_types.version - end + it "should set the parent scope of the new scope to be the passed-in parent" do + scope = mock 'scope' + newscope = @compiler.newscope(scope) - it "should copy any node classes into the class list" do - node = Puppet::Node.new("mynode") - node.classes = %w{foo bar} - compiler = Puppet::Parser::Compiler.new(node) + newscope.parent.should equal(scope) + end - compiler.classlist.should include("foo") - compiler.classlist.should include("bar") - end + it "should set the parent scope of the new scope to its topscope if the parent passed in is nil" do + scope = mock 'scope' + newscope = @compiler.newscope(nil) - it "should add a 'main' stage to the catalog" do - @compiler.catalog.resource(:stage, :main).should be_instance_of(Puppet::Parser::Resource) - end + newscope.parent.should equal(@compiler.topscope) end + end - describe "when managing scopes" do - - it "should create a top scope" do - @compiler.topscope.should be_instance_of(Puppet::Parser::Scope) - end + describe "when compiling" do - it "should be able to create new scopes" do - @compiler.newscope(@compiler.topscope).should be_instance_of(Puppet::Parser::Scope) - end + def compile_methods + [:set_node_parameters, :evaluate_main, :evaluate_ast_node, :evaluate_node_classes, :evaluate_generators, :fail_on_unevaluated, + :finish, :store, :extract, :evaluate_relationships] + end - it "should correctly set the level of newly created scopes" do - @compiler.newscope(@compiler.topscope, :level => 5).level.should == 5 - end + # Stub all of the main compile methods except the ones we're specifically interested in. + def compile_stub(*except) + (compile_methods - except).each { |m| @compiler.stubs(m) } + end - it "should set the parent scope of the new scope to be the passed-in parent" do - scope = mock 'scope' - newscope = @compiler.newscope(scope) + it "should set node parameters as variables in the top scope" do + params = {"a" => "b", "c" => "d"} + @node.stubs(:parameters).returns(params) + compile_stub(:set_node_parameters) + @compiler.compile + @compiler.topscope.lookupvar("a").should == "b" + @compiler.topscope.lookupvar("c").should == "d" + end - newscope.parent.should equal(scope) - end + it "should set the client and server versions on the catalog" do + params = {"clientversion" => "2", "serverversion" => "3"} + @node.stubs(:parameters).returns(params) + compile_stub(:set_node_parameters) + @compiler.compile + @compiler.catalog.client_version.should == "2" + @compiler.catalog.server_version.should == "3" + end - it "should set the parent scope of the new scope to its topscope if the parent passed in is nil" do - scope = mock 'scope' - newscope = @compiler.newscope(nil) + it "should evaluate any existing classes named in the node" do + classes = %w{one two three four} + main = stub 'main' + one = stub 'one', :name => "one" + three = stub 'three', :name => "three" + @node.stubs(:name).returns("whatever") + @node.stubs(:classes).returns(classes) - newscope.parent.should equal(@compiler.topscope) - end + @compiler.expects(:evaluate_classes).with(classes, @compiler.topscope) + @compiler.class.publicize_methods(:evaluate_node_classes) { @compiler.evaluate_node_classes } end - describe "when compiling" do + it "should evaluate the main class if it exists" do + compile_stub(:evaluate_main) + main_class = @known_resource_types.add Puppet::Resource::Type.new(:hostclass, "") + main_class.expects(:evaluate_code).with { |r| r.is_a?(Puppet::Parser::Resource) } + @compiler.topscope.expects(:source=).with(main_class) - def compile_methods - [:set_node_parameters, :evaluate_main, :evaluate_ast_node, :evaluate_node_classes, :evaluate_generators, :fail_on_unevaluated, - :finish, :store, :extract, :evaluate_relationships] - end - - # Stub all of the main compile methods except the ones we're specifically interested in. - def compile_stub(*except) - (compile_methods - except).each { |m| @compiler.stubs(m) } - end + @compiler.compile + end - it "should set node parameters as variables in the top scope" do - params = {"a" => "b", "c" => "d"} - @node.stubs(:parameters).returns(params) - compile_stub(:set_node_parameters) - @compiler.compile - @compiler.topscope.lookupvar("a").should == "b" - @compiler.topscope.lookupvar("c").should == "d" - end + it "should create a new, empty 'main' if no main class exists" do + compile_stub(:evaluate_main) + @compiler.compile + @known_resource_types.find_hostclass([""], "").should be_instance_of(Puppet::Resource::Type) + end - it "should set the client and server versions on the catalog" do - params = {"clientversion" => "2", "serverversion" => "3"} - @node.stubs(:parameters).returns(params) - compile_stub(:set_node_parameters) - @compiler.compile - @compiler.catalog.client_version.should == "2" - @compiler.catalog.server_version.should == "3" - end + it "should add an edge between the main stage and main class" do + @compiler.compile + (stage = @compiler.catalog.resource(:stage, "main")).should be_instance_of(Puppet::Parser::Resource) + (klass = @compiler.catalog.resource(:class, "")).should be_instance_of(Puppet::Parser::Resource) - it "should evaluate any existing classes named in the node" do - classes = %w{one two three four} - main = stub 'main' - one = stub 'one', :name => "one" - three = stub 'three', :name => "three" - @node.stubs(:name).returns("whatever") - @node.stubs(:classes).returns(classes) + @compiler.catalog.edge?(stage, klass).should be_true + end - @compiler.expects(:evaluate_classes).with(classes, @compiler.topscope) - @compiler.class.publicize_methods(:evaluate_node_classes) { @compiler.evaluate_node_classes } - end + it "should evaluate any node classes" do + @node.stubs(:classes).returns(%w{one two three four}) + @compiler.expects(:evaluate_classes).with(%w{one two three four}, @compiler.topscope) + @compiler.send(:evaluate_node_classes) + end - it "should evaluate the main class if it exists" do - compile_stub(:evaluate_main) - main_class = @known_resource_types.add Puppet::Resource::Type.new(:hostclass, "") - main_class.expects(:evaluate_code).with { |r| r.is_a?(Puppet::Parser::Resource) } - @compiler.topscope.expects(:source=).with(main_class) + it "should evaluate all added collections" do + colls = [] + # And when the collections fail to evaluate. + colls << mock("coll1-false") + colls << mock("coll2-false") + colls.each { |c| c.expects(:evaluate).returns(false) } - @compiler.compile - end + @compiler.add_collection(colls[0]) + @compiler.add_collection(colls[1]) - it "should create a new, empty 'main' if no main class exists" do - compile_stub(:evaluate_main) - @compiler.compile - @known_resource_types.find_hostclass([""], "").should be_instance_of(Puppet::Resource::Type) - end + compile_stub(:evaluate_generators) + @compiler.compile + end - it "should add an edge between the main stage and main class" do - @compiler.compile - (stage = @compiler.catalog.resource(:stage, "main")).should be_instance_of(Puppet::Parser::Resource) - (klass = @compiler.catalog.resource(:class, "")).should be_instance_of(Puppet::Parser::Resource) + it "should ignore builtin resources" do + resource = resource(:file, "testing") - @compiler.catalog.edge?(stage, klass).should be_true - end + @compiler.add_resource(@scope, resource) + resource.expects(:evaluate).never - it "should evaluate any node classes" do - @node.stubs(:classes).returns(%w{one two three four}) - @compiler.expects(:evaluate_classes).with(%w{one two three four}, @compiler.topscope) - @compiler.send(:evaluate_node_classes) - end + @compiler.compile + end - it "should evaluate all added collections" do - colls = [] - # And when the collections fail to evaluate. - colls << mock("coll1-false") - colls << mock("coll2-false") - colls.each { |c| c.expects(:evaluate).returns(false) } + it "should evaluate unevaluated resources" do + resource = CompilerTestResource.new(:file, "testing") - @compiler.add_collection(colls[0]) - @compiler.add_collection(colls[1]) + @compiler.add_resource(@scope, resource) - compile_stub(:evaluate_generators) - @compiler.compile - end + # We have to now mark the resource as evaluated + resource.expects(:evaluate).with { |*whatever| resource.evaluated = true } - it "should ignore builtin resources" do - resource = resource(:file, "testing") + @compiler.compile + end - @compiler.add_resource(@scope, resource) - resource.expects(:evaluate).never + it "should not evaluate already-evaluated resources" do + resource = resource(:file, "testing") + resource.stubs(:evaluated?).returns true - @compiler.compile - end + @compiler.add_resource(@scope, resource) + resource.expects(:evaluate).never - it "should evaluate unevaluated resources" do - resource = CompilerTestResource.new(:file, "testing") + @compiler.compile + end - @compiler.add_resource(@scope, resource) + it "should evaluate unevaluated resources created by evaluating other resources" do + resource = CompilerTestResource.new(:file, "testing") + @compiler.add_resource(@scope, resource) - # We have to now mark the resource as evaluated - resource.expects(:evaluate).with { |*whatever| resource.evaluated = true } + resource2 = CompilerTestResource.new(:file, "other") - @compiler.compile - end + # We have to now mark the resource as evaluated + resource.expects(:evaluate).with { |*whatever| resource.evaluated = true; @compiler.add_resource(@scope, resource2) } + resource2.expects(:evaluate).with { |*whatever| resource2.evaluated = true } - it "should not evaluate already-evaluated resources" do - resource = resource(:file, "testing") - resource.stubs(:evaluated?).returns true - @compiler.add_resource(@scope, resource) - resource.expects(:evaluate).never + @compiler.compile + end - @compiler.compile - end + describe "when finishing" do + before do + @compiler.send(:evaluate_main) + @catalog = @compiler.catalog + end - it "should evaluate unevaluated resources created by evaluating other resources" do - resource = CompilerTestResource.new(:file, "testing") - @compiler.add_resource(@scope, resource) + def add_resource(name, parent = nil) + resource = Puppet::Parser::Resource.new "file", name, :scope => @scope + @compiler.add_resource(@scope, resource) + @catalog.add_edge(parent, resource) if parent + resource + end - resource2 = CompilerTestResource.new(:file, "other") + it "should call finish() on all resources" do + # Add a resource that does respond to :finish + resource = Puppet::Parser::Resource.new "file", "finish", :scope => @scope + resource.expects(:finish) - # We have to now mark the resource as evaluated - resource.expects(:evaluate).with { |*whatever| resource.evaluated = true; @compiler.add_resource(@scope, resource2) } - resource2.expects(:evaluate).with { |*whatever| resource2.evaluated = true } + @compiler.add_resource(@scope, resource) + # And one that does not + dnf_resource = stub_everything "dnf", :ref => "File[dnf]", :type => "file" - @compiler.compile - end + @compiler.add_resource(@scope, dnf_resource) - describe "when finishing" do - before do - @compiler.send(:evaluate_main) - @catalog = @compiler.catalog - end + @compiler.send(:finish) + end - def add_resource(name, parent = nil) - resource = Puppet::Parser::Resource.new "file", name, :scope => @scope - @compiler.add_resource(@scope, resource) - @catalog.add_edge(parent, resource) if parent - resource - end + it "should call finish() in add_resource order" do + resources = sequence('resources') - it "should call finish() on all resources" do - # Add a resource that does respond to :finish - resource = Puppet::Parser::Resource.new "file", "finish", :scope => @scope - resource.expects(:finish) + resource1 = add_resource("finish1") + resource1.expects(:finish).in_sequence(resources) - @compiler.add_resource(@scope, resource) + resource2 = add_resource("finish2") + resource2.expects(:finish).in_sequence(resources) - # And one that does not - dnf_resource = stub_everything "dnf", :ref => "File[dnf]", :type => "file" + @compiler.send(:finish) + end - @compiler.add_resource(@scope, dnf_resource) + it "should add each container's metaparams to its contained resources" do + main = @catalog.resource(:class, :main) + main[:noop] = true - @compiler.send(:finish) - end + resource1 = add_resource("meh", main) - it "should call finish() in add_resource order" do - resources = sequence('resources') + @compiler.send(:finish) + resource1[:noop].should be_true + end - resource1 = add_resource("finish1") - resource1.expects(:finish).in_sequence(resources) + it "should add metaparams recursively" do + main = @catalog.resource(:class, :main) + main[:noop] = true - resource2 = add_resource("finish2") - resource2.expects(:finish).in_sequence(resources) + resource1 = add_resource("meh", main) + resource2 = add_resource("foo", resource1) - @compiler.send(:finish) - end + @compiler.send(:finish) + resource2[:noop].should be_true + end - it "should add each container's metaparams to its contained resources" do - main = @catalog.resource(:class, :main) - main[:noop] = true + it "should prefer metaparams from immediate parents" do + main = @catalog.resource(:class, :main) + main[:noop] = true - resource1 = add_resource("meh", main) + resource1 = add_resource("meh", main) + resource2 = add_resource("foo", resource1) - @compiler.send(:finish) - resource1[:noop].should be_true - end + resource1[:noop] = false - it "should add metaparams recursively" do - main = @catalog.resource(:class, :main) - main[:noop] = true + @compiler.send(:finish) + resource2[:noop].should be_false + end - resource1 = add_resource("meh", main) - resource2 = add_resource("foo", resource1) + it "should merge tags downward" do + main = @catalog.resource(:class, :main) + main.tag("one") - @compiler.send(:finish) - resource2[:noop].should be_true - end + resource1 = add_resource("meh", main) + resource1.tag "two" + resource2 = add_resource("foo", resource1) - it "should prefer metaparams from immediate parents" do - main = @catalog.resource(:class, :main) - main[:noop] = true + @compiler.send(:finish) + resource2.tags.should be_include("one") + resource2.tags.should be_include("two") + end - resource1 = add_resource("meh", main) - resource2 = add_resource("foo", resource1) + it "should work if only middle resources have metaparams set" do + main = @catalog.resource(:class, :main) - resource1[:noop] = false + resource1 = add_resource("meh", main) + resource1[:noop] = true + resource2 = add_resource("foo", resource1) - @compiler.send(:finish) - resource2[:noop].should be_false - end + @compiler.send(:finish) + resource2[:noop].should be_true + end + end - it "should merge tags downward" do - main = @catalog.resource(:class, :main) - main.tag("one") + it "should return added resources in add order" do + resource1 = resource(:file, "yay") + @compiler.add_resource(@scope, resource1) + resource2 = resource(:file, "youpi") + @compiler.add_resource(@scope, resource2) - resource1 = add_resource("meh", main) - resource1.tag "two" - resource2 = add_resource("foo", resource1) + @compiler.resources.should == [resource1, resource2] + end - @compiler.send(:finish) - resource2.tags.should be_include("one") - resource2.tags.should be_include("two") - end + it "should add resources that do not conflict with existing resources" do + resource = resource(:file, "yay") + @compiler.add_resource(@scope, resource) - it "should work if only middle resources have metaparams set" do - main = @catalog.resource(:class, :main) + @compiler.catalog.should be_vertex(resource) + end - resource1 = add_resource("meh", main) - resource1[:noop] = true - resource2 = add_resource("foo", resource1) + it "should fail to add resources that conflict with existing resources" do + path = Puppet.features.posix? ? "/foo" : "C:/foo" + file1 = Puppet::Type.type(:file).new :path => path + file2 = Puppet::Type.type(:file).new :path => path - @compiler.send(:finish) - resource2[:noop].should be_true - end - end + @compiler.add_resource(@scope, file1) + lambda { @compiler.add_resource(@scope, file2) }.should raise_error(Puppet::Resource::Catalog::DuplicateResourceError) + end - it "should return added resources in add order" do - resource1 = resource(:file, "yay") - @compiler.add_resource(@scope, resource1) - resource2 = resource(:file, "youpi") - @compiler.add_resource(@scope, resource2) + it "should add an edge from the scope resource to the added resource" do + resource = resource(:file, "yay") + @compiler.add_resource(@scope, resource) - @compiler.resources.should == [resource1, resource2] - end + @compiler.catalog.should be_edge(@scope.resource, resource) + end - it "should add resources that do not conflict with existing resources" do - resource = resource(:file, "yay") - @compiler.add_resource(@scope, resource) + it "should add an edge to any specified stage for class resources" do + other_stage = resource(:stage, "other") + @compiler.add_resource(@scope, other_stage) + resource = resource(:class, "foo") + resource[:stage] = 'other' - @compiler.catalog.should be_vertex(resource) - end + @compiler.add_resource(@scope, resource) - it "should fail to add resources that conflict with existing resources" do - path = Puppet.features.posix? ? "/foo" : "C:/foo" - file1 = Puppet::Type.type(:file).new :path => path - file2 = Puppet::Type.type(:file).new :path => path + @compiler.catalog.edge?(other_stage, resource).should be_true + end - @compiler.add_resource(@scope, file1) - lambda { @compiler.add_resource(@scope, file2) }.should raise_error(Puppet::Resource::Catalog::DuplicateResourceError) - end + it "should fail if a non-class resource attempts to set a stage" do + other_stage = resource(:stage, "other") + @compiler.add_resource(@scope, other_stage) + resource = resource(:file, "foo") + resource[:stage] = 'other' - it "should add an edge from the scope resource to the added resource" do - resource = resource(:file, "yay") - @compiler.add_resource(@scope, resource) + lambda { @compiler.add_resource(@scope, resource) }.should raise_error(ArgumentError) + end - @compiler.catalog.should be_edge(@scope.resource, resource) - end + it "should fail if an unknown stage is specified" do + resource = resource(:class, "foo") + resource[:stage] = 'other' - it "should add an edge to any specified stage for class resources" do - other_stage = resource(:stage, "other") - @compiler.add_resource(@scope, other_stage) - resource = resource(:class, "foo") - resource[:stage] = 'other' + lambda { @compiler.add_resource(@scope, resource) }.should raise_error(ArgumentError) + end - @compiler.add_resource(@scope, resource) + it "should add edges from the class resources to the main stage if no stage is specified" do + main = @compiler.catalog.resource(:stage, :main) + resource = resource(:class, "foo") + @compiler.add_resource(@scope, resource) - @compiler.catalog.edge?(other_stage, resource).should be_true - end + @compiler.catalog.should be_edge(main, resource) + end - it "should fail if a non-class resource attempts to set a stage" do - other_stage = resource(:stage, "other") - @compiler.add_resource(@scope, other_stage) - resource = resource(:file, "foo") - resource[:stage] = 'other' + it "should not add non-class resources that don't specify a stage to the 'main' stage" do + main = @compiler.catalog.resource(:stage, :main) + resource = resource(:file, "foo") + @compiler.add_resource(@scope, resource) - lambda { @compiler.add_resource(@scope, resource) }.should raise_error(ArgumentError) - end + @compiler.catalog.should_not be_edge(main, resource) + end - it "should fail if an unknown stage is specified" do - resource = resource(:class, "foo") - resource[:stage] = 'other' + it "should not add any parent-edges to stages" do + stage = resource(:stage, "other") + @compiler.add_resource(@scope, stage) - lambda { @compiler.add_resource(@scope, resource) }.should raise_error(ArgumentError) - end + @scope.resource = resource(:class, "foo") - it "should add edges from the class resources to the main stage if no stage is specified" do - main = @compiler.catalog.resource(:stage, :main) - resource = resource(:class, "foo") - @compiler.add_resource(@scope, resource) + @compiler.catalog.edge?(@scope.resource, stage).should be_false + end - @compiler.catalog.should be_edge(main, resource) - end + it "should not attempt to add stages to other stages" do + other_stage = resource(:stage, "other") + second_stage = resource(:stage, "second") + @compiler.add_resource(@scope, other_stage) + @compiler.add_resource(@scope, second_stage) - it "should not add non-class resources that don't specify a stage to the 'main' stage" do - main = @compiler.catalog.resource(:stage, :main) - resource = resource(:file, "foo") - @compiler.add_resource(@scope, resource) + second_stage[:stage] = "other" - @compiler.catalog.should_not be_edge(main, resource) - end + @compiler.catalog.edge?(other_stage, second_stage).should be_false + end - it "should not add any parent-edges to stages" do - stage = resource(:stage, "other") - @compiler.add_resource(@scope, stage) + it "should have a method for looking up resources" do + resource = resource(:yay, "foo") + @compiler.add_resource(@scope, resource) + @compiler.findresource("Yay[foo]").should equal(resource) + end - @scope.resource = resource(:class, "foo") + it "should be able to look resources up by type and title" do + resource = resource(:yay, "foo") + @compiler.add_resource(@scope, resource) + @compiler.findresource("Yay", "foo").should equal(resource) + end - @compiler.catalog.edge?(@scope.resource, stage).should be_false - end + it "should not evaluate virtual defined resources" do + resource = resource(:file, "testing") + resource.virtual = true + @compiler.add_resource(@scope, resource) - it "should not attempt to add stages to other stages" do - other_stage = resource(:stage, "other") - second_stage = resource(:stage, "second") - @compiler.add_resource(@scope, other_stage) - @compiler.add_resource(@scope, second_stage) + resource.expects(:evaluate).never - second_stage[:stage] = "other" + @compiler.compile + end + end - @compiler.catalog.edge?(other_stage, second_stage).should be_false - end + describe "when evaluating collections" do - it "should have a method for looking up resources" do - resource = resource(:yay, "foo") - @compiler.add_resource(@scope, resource) - @compiler.findresource("Yay[foo]").should equal(resource) - end + it "should evaluate each collection" do + 2.times { |i| + coll = mock 'coll%s' % i + @compiler.add_collection(coll) - it "should be able to look resources up by type and title" do - resource = resource(:yay, "foo") - @compiler.add_resource(@scope, resource) - @compiler.findresource("Yay", "foo").should equal(resource) + # This is the hard part -- we have to emulate the fact that + # collections delete themselves if they are done evaluating. + coll.expects(:evaluate).with do + @compiler.delete_collection(coll) end + } - it "should not evaluate virtual defined resources" do - resource = resource(:file, "testing") - resource.virtual = true - @compiler.add_resource(@scope, resource) - - resource.expects(:evaluate).never - - @compiler.compile - end + @compiler.class.publicize_methods(:evaluate_collections) { @compiler.evaluate_collections } end - describe "when evaluating collections" do - - it "should evaluate each collection" do - 2.times { |i| - coll = mock 'coll%s' % i - @compiler.add_collection(coll) - - # This is the hard part -- we have to emulate the fact that - # collections delete themselves if they are done evaluating. - coll.expects(:evaluate).with do - @compiler.delete_collection(coll) - end - } - - @compiler.class.publicize_methods(:evaluate_collections) { @compiler.evaluate_collections } - end + it "should not fail when there are unevaluated resource collections that do not refer to specific resources" do + coll = stub 'coll', :evaluate => false + coll.expects(:resources).returns(nil) - it "should not fail when there are unevaluated resource collections that do not refer to specific resources" do - coll = stub 'coll', :evaluate => false - coll.expects(:resources).returns(nil) + @compiler.add_collection(coll) - @compiler.add_collection(coll) - - lambda { @compiler.compile }.should_not raise_error - end + lambda { @compiler.compile }.should_not raise_error + end - it "should fail when there are unevaluated resource collections that refer to a specific resource" do - coll = stub 'coll', :evaluate => false - coll.expects(:resources).returns(:something) + it "should fail when there are unevaluated resource collections that refer to a specific resource" do + coll = stub 'coll', :evaluate => false + coll.expects(:resources).returns(:something) - @compiler.add_collection(coll) + @compiler.add_collection(coll) - lambda { @compiler.compile }.should raise_error(Puppet::ParseError) - end + lambda { @compiler.compile }.should raise_error(Puppet::ParseError) + end - it "should fail when there are unevaluated resource collections that refer to multiple specific resources" do - coll = stub 'coll', :evaluate => false - coll.expects(:resources).returns([:one, :two]) + it "should fail when there are unevaluated resource collections that refer to multiple specific resources" do + coll = stub 'coll', :evaluate => false + coll.expects(:resources).returns([:one, :two]) - @compiler.add_collection(coll) + @compiler.add_collection(coll) - lambda { @compiler.compile }.should raise_error(Puppet::ParseError) - end + lambda { @compiler.compile }.should raise_error(Puppet::ParseError) end - - describe "when evaluating relationships" do - it "should evaluate each relationship with its catalog" do - dep = stub 'dep' - dep.expects(:evaluate).with(@compiler.catalog) - @compiler.add_relationship dep - @compiler.evaluate_relationships - end + end + + describe "when evaluating relationships" do + it "should evaluate each relationship with its catalog" do + dep = stub 'dep' + dep.expects(:evaluate).with(@compiler.catalog) + @compiler.add_relationship dep + @compiler.evaluate_relationships end + end - describe "when told to evaluate missing classes" do + describe "when told to evaluate missing classes" do - it "should fail if there's no source listed for the scope" do - scope = stub 'scope', :source => nil - proc { @compiler.evaluate_classes(%w{one two}, scope) }.should raise_error(Puppet::DevError) - end + it "should fail if there's no source listed for the scope" do + scope = stub 'scope', :source => nil + proc { @compiler.evaluate_classes(%w{one two}, scope) }.should raise_error(Puppet::DevError) + end - it "should tag the catalog with the name of each not-found class" do - @compiler.catalog.expects(:tag).with("notfound") - @scope.expects(:find_hostclass).with("notfound").returns(nil) - @compiler.evaluate_classes(%w{notfound}, @scope) - end + it "should tag the catalog with the name of each not-found class" do + @compiler.catalog.expects(:tag).with("notfound") + @scope.expects(:find_hostclass).with("notfound").returns(nil) + @compiler.evaluate_classes(%w{notfound}, @scope) end + end - describe "when evaluating found classes" do + describe "when evaluating found classes" do - before do - @class = stub 'class', :name => "my::class" - @scope.stubs(:find_hostclass).with("myclass").returns(@class) + before do + @class = stub 'class', :name => "my::class" + @scope.stubs(:find_hostclass).with("myclass").returns(@class) - @resource = stub 'resource', :ref => "Class[myclass]", :type => "file" - end + @resource = stub 'resource', :ref => "Class[myclass]", :type => "file" + end - it "should evaluate each class" do - @compiler.catalog.stubs(:tag) + it "should evaluate each class" do + @compiler.catalog.stubs(:tag) - @class.expects(:mk_plain_resource).with(@scope) - @scope.stubs(:class_scope).with(@class) + @class.expects(:mk_plain_resource).with(@scope) + @scope.stubs(:class_scope).with(@class) - @compiler.evaluate_classes(%w{myclass}, @scope) - end + @compiler.evaluate_classes(%w{myclass}, @scope) + end - it "should not evaluate the resources created for found classes unless asked" do - @compiler.catalog.stubs(:tag) + it "should not evaluate the resources created for found classes unless asked" do + @compiler.catalog.stubs(:tag) - @resource.expects(:evaluate).never + @resource.expects(:evaluate).never - @class.expects(:mk_plain_resource).returns(@resource) - @scope.stubs(:class_scope).with(@class) + @class.expects(:mk_plain_resource).returns(@resource) + @scope.stubs(:class_scope).with(@class) - @compiler.evaluate_classes(%w{myclass}, @scope) - end + @compiler.evaluate_classes(%w{myclass}, @scope) + end - it "should immediately evaluate the resources created for found classes when asked" do - @compiler.catalog.stubs(:tag) + it "should immediately evaluate the resources created for found classes when asked" do + @compiler.catalog.stubs(:tag) - @resource.expects(:evaluate) - @class.expects(:mk_plain_resource).returns(@resource) - @scope.stubs(:class_scope).with(@class) + @resource.expects(:evaluate) + @class.expects(:mk_plain_resource).returns(@resource) + @scope.stubs(:class_scope).with(@class) - @compiler.evaluate_classes(%w{myclass}, @scope, false) - end + @compiler.evaluate_classes(%w{myclass}, @scope, false) + end - it "should skip classes that have already been evaluated" do - @compiler.catalog.stubs(:tag) + it "should skip classes that have already been evaluated" do + @compiler.catalog.stubs(:tag) - @scope.stubs(:class_scope).with(@class).returns("something") + @scope.stubs(:class_scope).with(@class).returns("something") - @compiler.expects(:add_resource).never + @compiler.expects(:add_resource).never - @resource.expects(:evaluate).never + @resource.expects(:evaluate).never - Puppet::Parser::Resource.expects(:new).never - @compiler.evaluate_classes(%w{myclass}, @scope, false) - end + Puppet::Parser::Resource.expects(:new).never + @compiler.evaluate_classes(%w{myclass}, @scope, false) + end - it "should skip classes previously evaluated with different capitalization" do - @compiler.catalog.stubs(:tag) - @scope.stubs(:find_hostclass).with("MyClass").returns(@class) - @scope.stubs(:class_scope).with(@class).returns("something") - @compiler.expects(:add_resource).never - @resource.expects(:evaluate).never - Puppet::Parser::Resource.expects(:new).never - @compiler.evaluate_classes(%w{MyClass}, @scope, false) - end + it "should skip classes previously evaluated with different capitalization" do + @compiler.catalog.stubs(:tag) + @scope.stubs(:find_hostclass).with("MyClass").returns(@class) + @scope.stubs(:class_scope).with(@class).returns("something") + @compiler.expects(:add_resource).never + @resource.expects(:evaluate).never + Puppet::Parser::Resource.expects(:new).never + @compiler.evaluate_classes(%w{MyClass}, @scope, false) + end - it "should return the list of found classes" do - @compiler.catalog.stubs(:tag) + it "should return the list of found classes" do + @compiler.catalog.stubs(:tag) - @compiler.stubs(:add_resource) - @scope.stubs(:find_hostclass).with("notfound").returns(nil) - @scope.stubs(:class_scope).with(@class) + @compiler.stubs(:add_resource) + @scope.stubs(:find_hostclass).with("notfound").returns(nil) + @scope.stubs(:class_scope).with(@class) - Puppet::Parser::Resource.stubs(:new).returns(@resource) - @class.stubs :mk_plain_resource - @compiler.evaluate_classes(%w{myclass notfound}, @scope).should == %w{myclass} - end + Puppet::Parser::Resource.stubs(:new).returns(@resource) + @class.stubs :mk_plain_resource + @compiler.evaluate_classes(%w{myclass notfound}, @scope).should == %w{myclass} end + end - describe "when evaluating AST nodes with no AST nodes present" do + describe "when evaluating AST nodes with no AST nodes present" do - it "should do nothing" do - @compiler.expects(:ast_nodes?).returns(false) - @compiler.known_resource_types.expects(:nodes).never - Puppet::Parser::Resource.expects(:new).never + it "should do nothing" do + @compiler.expects(:ast_nodes?).returns(false) + @compiler.known_resource_types.expects(:nodes).never + Puppet::Parser::Resource.expects(:new).never - @compiler.send(:evaluate_ast_node) - end + @compiler.send(:evaluate_ast_node) end + end - describe "when evaluating AST nodes with AST nodes present" do + describe "when evaluating AST nodes with AST nodes present" do - before do - @compiler.known_resource_types.stubs(:nodes?).returns true + before do + @compiler.known_resource_types.stubs(:nodes?).returns true - # Set some names for our test - @node.stubs(:names).returns(%w{a b c}) - @compiler.known_resource_types.stubs(:node).with("a").returns(nil) - @compiler.known_resource_types.stubs(:node).with("b").returns(nil) - @compiler.known_resource_types.stubs(:node).with("c").returns(nil) + # Set some names for our test + @node.stubs(:names).returns(%w{a b c}) + @compiler.known_resource_types.stubs(:node).with("a").returns(nil) + @compiler.known_resource_types.stubs(:node).with("b").returns(nil) + @compiler.known_resource_types.stubs(:node).with("c").returns(nil) - # It should check this last, of course. - @compiler.known_resource_types.stubs(:node).with("default").returns(nil) - end + # It should check this last, of course. + @compiler.known_resource_types.stubs(:node).with("default").returns(nil) + end - it "should fail if the named node cannot be found" do - proc { @compiler.send(:evaluate_ast_node) }.should raise_error(Puppet::ParseError) - end + it "should fail if the named node cannot be found" do + proc { @compiler.send(:evaluate_ast_node) }.should raise_error(Puppet::ParseError) + end - it "should evaluate the first node class matching the node name" do - node_class = stub 'node', :name => "c", :evaluate_code => nil - @compiler.known_resource_types.stubs(:node).with("c").returns(node_class) + it "should evaluate the first node class matching the node name" do + node_class = stub 'node', :name => "c", :evaluate_code => nil + @compiler.known_resource_types.stubs(:node).with("c").returns(node_class) - node_resource = stub 'node resource', :ref => "Node[c]", :evaluate => nil, :type => "node" - node_class.expects(:mk_plain_resource).returns(node_resource) + node_resource = stub 'node resource', :ref => "Node[c]", :evaluate => nil, :type => "node" + node_class.expects(:mk_plain_resource).returns(node_resource) - @compiler.compile - end + @compiler.compile + end - it "should match the default node if no matching node can be found" do - node_class = stub 'node', :name => "default", :evaluate_code => nil - @compiler.known_resource_types.stubs(:node).with("default").returns(node_class) + it "should match the default node if no matching node can be found" do + node_class = stub 'node', :name => "default", :evaluate_code => nil + @compiler.known_resource_types.stubs(:node).with("default").returns(node_class) - node_resource = stub 'node resource', :ref => "Node[default]", :evaluate => nil, :type => "node" - node_class.expects(:mk_plain_resource).returns(node_resource) + node_resource = stub 'node resource', :ref => "Node[default]", :evaluate => nil, :type => "node" + node_class.expects(:mk_plain_resource).returns(node_resource) - @compiler.compile - end + @compiler.compile + end - it "should evaluate the node resource immediately rather than using lazy evaluation" do - node_class = stub 'node', :name => "c" - @compiler.known_resource_types.stubs(:node).with("c").returns(node_class) + it "should evaluate the node resource immediately rather than using lazy evaluation" do + node_class = stub 'node', :name => "c" + @compiler.known_resource_types.stubs(:node).with("c").returns(node_class) - node_resource = stub 'node resource', :ref => "Node[c]", :type => "node" - node_class.expects(:mk_plain_resource).returns(node_resource) + node_resource = stub 'node resource', :ref => "Node[c]", :type => "node" + node_class.expects(:mk_plain_resource).returns(node_resource) - node_resource.expects(:evaluate) + node_resource.expects(:evaluate) - @compiler.send(:evaluate_ast_node) - end + @compiler.send(:evaluate_ast_node) + end - it "should set the node's scope as the top scope" do - node_resource = stub 'node resource', :ref => "Node[c]", :evaluate => nil, :type => "node" - node_class = stub 'node', :name => "c", :mk_plain_resource => node_resource + it "should set the node's scope as the top scope" do + node_resource = stub 'node resource', :ref => "Node[c]", :evaluate => nil, :type => "node" + node_class = stub 'node', :name => "c", :mk_plain_resource => node_resource - @compiler.known_resource_types.stubs(:node).with("c").returns(node_class) + @compiler.known_resource_types.stubs(:node).with("c").returns(node_class) - # The #evaluate method normally does this. - scope = stub 'scope', :source => "mysource" - @compiler.topscope.expects(:class_scope).with(node_class).returns(scope) - node_resource.stubs(:evaluate) - @compiler.stubs :create_settings_scope + # The #evaluate method normally does this. + scope = stub 'scope', :source => "mysource" + @compiler.topscope.expects(:class_scope).with(node_class).returns(scope) + node_resource.stubs(:evaluate) + @compiler.stubs :create_settings_scope - @compiler.compile + @compiler.compile - @compiler.topscope.should equal(scope) - end + @compiler.topscope.should equal(scope) end + end - describe "when managing resource overrides" do + describe "when managing resource overrides" do - before do - @override = stub 'override', :ref => "File[/foo]", :type => "my" - @resource = resource(:file, "/foo") - end + before do + @override = stub 'override', :ref => "File[/foo]", :type => "my" + @resource = resource(:file, "/foo") + end - it "should be able to store overrides" do - lambda { @compiler.add_override(@override) }.should_not raise_error - end + it "should be able to store overrides" do + lambda { @compiler.add_override(@override) }.should_not raise_error + end - it "should apply overrides to the appropriate resources" do - @compiler.add_resource(@scope, @resource) - @resource.expects(:merge).with(@override) + it "should apply overrides to the appropriate resources" do + @compiler.add_resource(@scope, @resource) + @resource.expects(:merge).with(@override) - @compiler.add_override(@override) + @compiler.add_override(@override) - @compiler.compile - end + @compiler.compile + end - it "should accept overrides before the related resource has been created" do - @resource.expects(:merge).with(@override) + it "should accept overrides before the related resource has been created" do + @resource.expects(:merge).with(@override) - # First store the override - @compiler.add_override(@override) + # First store the override + @compiler.add_override(@override) - # Then the resource - @compiler.add_resource(@scope, @resource) + # Then the resource + @compiler.add_resource(@scope, @resource) - # And compile, so they get resolved - @compiler.compile - end + # And compile, so they get resolved + @compiler.compile + end - it "should fail if the compile is finished and resource overrides have not been applied" do - @compiler.add_override(@override) + it "should fail if the compile is finished and resource overrides have not been applied" do + @compiler.add_override(@override) - lambda { @compiler.compile }.should raise_error(Puppet::ParseError) - end + lambda { @compiler.compile }.should raise_error(Puppet::ParseError) end + end end |