summaryrefslogtreecommitdiffstats
path: root/spec/unit/parser/compiler_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/unit/parser/compiler_spec.rb')
-rwxr-xr-xspec/unit/parser/compiler_spec.rb1094
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