summaryrefslogtreecommitdiffstats
path: root/spec/unit/parser
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2008-02-11 17:24:02 -0600
committerLuke Kanies <luke@madstop.com>2008-02-11 17:24:02 -0600
commit6a4cf6c978e8c8aebba4ed0f16d3de7bb31a0ce0 (patch)
treedf96556dd073aa5d0c23c735a2456da8f144f6b9 /spec/unit/parser
parent3b740ff7a6ab7127ec5e4935782c33245687c429 (diff)
downloadpuppet-6a4cf6c978e8c8aebba4ed0f16d3de7bb31a0ce0.tar.gz
puppet-6a4cf6c978e8c8aebba4ed0f16d3de7bb31a0ce0.tar.xz
puppet-6a4cf6c978e8c8aebba4ed0f16d3de7bb31a0ce0.zip
Fixed #1030 - class and definition evaluation has been significantly
refactored, fixing this problem and making the whole interplay between the classes, definitions, and nodes, and the Compile class much cleaner.
Diffstat (limited to 'spec/unit/parser')
-rwxr-xr-xspec/unit/parser/ast/hostclass.rb131
-rwxr-xr-xspec/unit/parser/compile.rb206
2 files changed, 224 insertions, 113 deletions
diff --git a/spec/unit/parser/ast/hostclass.rb b/spec/unit/parser/ast/hostclass.rb
new file mode 100755
index 000000000..b1e8a48ea
--- /dev/null
+++ b/spec/unit/parser/ast/hostclass.rb
@@ -0,0 +1,131 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../../../spec_helper'
+
+module HostClassTesting
+ def setup
+ @node = Puppet::Node.new "testnode"
+ @parser = Puppet::Parser::Parser.new :environment => "development"
+ @scope_resource = stub 'scope_resource', :builtin? => true
+ @compile = Puppet::Parser::Compile.new(@node, @parser)
+
+ @scope = @compile.topscope
+ end
+end
+
+describe Puppet::Parser::AST::HostClass, "when evaluating" do
+ include HostClassTesting
+
+ before do
+ @top = @parser.newclass "top"
+ @middle = @parser.newclass "middle", :parent => "top"
+ end
+
+ it "should create a resource that references itself" do
+ @top.evaluate(@scope)
+
+ @compile.catalog.resource(:class, "top").should be_instance_of(Puppet::Parser::Resource)
+ end
+
+ it "should evaluate the parent class if one exists" do
+ @middle.evaluate(@scope)
+
+ @compile.catalog.resource(:class, "top").should be_instance_of(Puppet::Parser::Resource)
+ end
+
+ it "should fail to evaluate if a parent class is defined but cannot be found" do
+ othertop = @parser.newclass "something", :parent => "yay"
+ lambda { othertop.evaluate(@scope) }.should raise_error(Puppet::ParseError)
+ end
+
+ it "should not create a new resource if one already exists" do
+ @compile.catalog.expects(:resource).with(:class, "top").returns("something")
+ @compile.catalog.expects(:add_resource).never
+ @top.evaluate(@scope)
+ end
+
+ it "should not create a new parent resource if one already exists and it has a parent class" do
+ @top.evaluate(@scope)
+
+ top_resource = @compile.catalog.resource(:class, "top")
+
+ @middle.evaluate(@scope)
+
+ @compile.catalog.resource(:class, "top").should equal(top_resource)
+ end
+
+ # #795 - tag before evaluation.
+ it "should tag the catalog with the resource tags when it is evaluated" do
+ @middle.evaluate(@scope)
+
+ @compile.catalog.should be_tagged("middle")
+ end
+
+ it "should tag the catalog with the parent class tags when it is evaluated" do
+ @middle.evaluate(@scope)
+
+ @compile.catalog.should be_tagged("top")
+ end
+end
+
+describe Puppet::Parser::AST::HostClass, "when evaluating code" do
+ include HostClassTesting
+
+ before do
+ @top_resource = stub "top_resource"
+ @top = @parser.newclass "top", :code => @top_resource
+
+ @middle_resource = stub "middle_resource"
+ @middle = @parser.newclass "top::middle", :parent => "top", :code => @middle_resource
+ end
+
+ it "should set its namespace to its fully qualified name" do
+ @middle.namespace.should == "top::middle"
+ end
+
+ it "should evaluate the code referred to by the class" do
+ @top_resource.expects(:safeevaluate)
+
+ resource = @top.evaluate(@scope)
+
+ @top.evaluate_code(resource)
+ end
+
+ it "should evaluate the parent class's code if it has a parent" do
+ @top_resource.expects(:safeevaluate)
+ @middle_resource.expects(:safeevaluate)
+
+ resource = @middle.evaluate(@scope)
+
+ @middle.evaluate_code(resource)
+ end
+
+ it "should not evaluate the parent class's code if the parent has already been evaluated" do
+ @top_resource.stubs(:safeevaluate)
+ resource = @top.evaluate(@scope)
+ @top.evaluate_code(resource)
+
+ @top_resource.expects(:safeevaluate).never
+ @middle_resource.stubs(:safeevaluate)
+ resource = @middle.evaluate(@scope)
+ @middle.evaluate_code(resource)
+ end
+
+ it "should use the parent class's scope as its parent scope" do
+ @top_resource.stubs(:safeevaluate)
+ @middle_resource.stubs(:safeevaluate)
+ resource = @middle.evaluate(@scope)
+ @middle.evaluate_code(resource)
+
+ @compile.class_scope(@middle).parent.should equal(@compile.class_scope(@top))
+ end
+
+ it "should add the parent class's namespace to its namespace search path" do
+ @top_resource.stubs(:safeevaluate)
+ @middle_resource.stubs(:safeevaluate)
+ resource = @middle.evaluate(@scope)
+ @middle.evaluate_code(resource)
+
+ @compile.class_scope(@middle).namespaces.should be_include(@top.namespace)
+ end
+end
diff --git a/spec/unit/parser/compile.rb b/spec/unit/parser/compile.rb
index d495ac343..ff205f7a5 100755
--- a/spec/unit/parser/compile.rb
+++ b/spec/unit/parser/compile.rb
@@ -13,6 +13,78 @@ module CompileTesting
end
end
+describe Puppet::Parser::Compile do
+ include CompileTesting
+
+ it "should be able to store references to class scopes" do
+ lambda { @compile.class_set "myname", "myscope" }.should_not raise_error
+ end
+
+ it "should be able to retrieve class scopes by name" do
+ @compile.class_set "myname", "myscope"
+ @compile.class_scope("myname").should == "myscope"
+ end
+
+ it "should be able to retrieve class scopes by object" do
+ klass = mock 'ast_class'
+ klass.expects(:classname).returns("myname")
+ @compile.class_set "myname", "myscope"
+ @compile.class_scope(klass).should == "myscope"
+ end
+
+ it "should be able to return a class list containing all set classes" do
+ @compile.class_set "", "empty"
+ @compile.class_set "one", "yep"
+ @compile.class_set "two", "nope"
+
+ @compile.classlist.sort.should == %w{one two}.sort
+ end
+end
+
+describe Puppet::Parser::Compile, " when initializing" do
+ include CompileTesting
+
+ it "should set its node attribute" do
+ @compile.node.should equal(@node)
+ end
+
+ it "should set its parser attribute" do
+ @compile.parser.should equal(@parser)
+ end
+
+ it "should detect when ast nodes are absent" do
+ @compile.ast_nodes?.should be_false
+ end
+
+ it "should detect when ast nodes are present" do
+ @parser.nodes["testing"] = "yay"
+ @compile.ast_nodes?.should be_true
+ end
+end
+
+describe Puppet::Parser::Compile, "when managing scopes" do
+ include CompileTesting
+
+ it "should create a top scope" do
+ @compile.topscope.should be_instance_of(Puppet::Parser::Scope)
+ end
+
+ it "should be able to create new scopes" do
+ @compile.newscope(@compile.topscope).should be_instance_of(Puppet::Parser::Scope)
+ end
+
+ it "should correctly set the level of newly created scopes" do
+ @compile.newscope(@compile.topscope, :level => 5).level.should == 5
+ end
+
+ it "should set the parent scope of the new scope to be the passed-in parent" do
+ scope = mock 'scope'
+ newscope = @compile.newscope(scope)
+
+ @compile.parent(newscope).should equal(scope)
+ end
+end
+
describe Puppet::Parser::Compile, " when compiling" do
include CompileTesting
@@ -174,21 +246,6 @@ describe Puppet::Parser::Compile, " when compiling" do
end
end
-describe Puppet::Parser::Compile, " when evaluating classes" do
- include CompileTesting
-
- it "should fail if there's no source listed for the scope" do
- scope = stub 'scope', :source => nil
- proc { @compile.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
- @compile.catalog.expects(:tag).with("notfound")
- @scope.expects(:findclass).with("notfound").returns(nil)
- @compile.evaluate_classes(%w{notfound}, @scope)
- end
-end
-
describe Puppet::Parser::Compile, " when evaluating collections" do
include CompileTesting
@@ -235,6 +292,20 @@ describe Puppet::Parser::Compile, " when evaluating collections" do
end
end
+describe Puppet::Parser::Compile, "when told to evaluate missing classes" do
+ include CompileTesting
+
+ it "should fail if there's no source listed for the scope" do
+ scope = stub 'scope', :source => nil
+ proc { @compile.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
+ @compile.catalog.expects(:tag).with("notfound")
+ @scope.expects(:findclass).with("notfound").returns(nil)
+ @compile.evaluate_classes(%w{notfound}, @scope)
+ end
+end
describe Puppet::Parser::Compile, " when evaluating found classes" do
include CompileTesting
@@ -243,53 +314,33 @@ describe Puppet::Parser::Compile, " when evaluating found classes" do
@class = stub 'class', :classname => "my::class"
@scope.stubs(:findclass).with("myclass").returns(@class)
- @resource = stub 'resource', :ref => 'Class[myclass]'
- end
-
- it "should create a resource for each found class" do
- @compile.catalog.stubs(:tag)
-
- @compile.stubs :store_resource
-
- Puppet::Parser::Resource.expects(:new).with(:scope => @scope, :source => @scope.source, :title => "my::class", :type => "class").returns(@resource)
- @compile.evaluate_classes(%w{myclass}, @scope)
+ @resource = stub 'resource', :ref => "Class[myclass]"
end
- it "should store each created resource in the compile" do
+ it "should evaluate each class" do
@compile.catalog.stubs(:tag)
- @compile.expects(:store_resource).with(@scope, @resource)
-
- Puppet::Parser::Resource.stubs(:new).returns(@resource)
- @compile.evaluate_classes(%w{myclass}, @scope)
- end
-
- it "should tag the catalog with the fully-qualified name of each found class" do
- @compile.catalog.expects(:tag).with("my::class")
+ @class.expects(:evaluate).with(@scope)
- @compile.stubs(:store_resource)
-
- Puppet::Parser::Resource.stubs(:new).returns(@resource)
@compile.evaluate_classes(%w{myclass}, @scope)
end
it "should not evaluate the resources created for found classes unless asked" do
@compile.catalog.stubs(:tag)
- @compile.stubs(:store_resource)
@resource.expects(:evaluate).never
- Puppet::Parser::Resource.stubs(:new).returns(@resource)
+ @class.expects(:evaluate).returns(@resource)
+
@compile.evaluate_classes(%w{myclass}, @scope)
end
it "should immediately evaluate the resources created for found classes when asked" do
@compile.catalog.stubs(:tag)
- @compile.stubs(:store_resource)
@resource.expects(:evaluate)
+ @class.expects(:evaluate).returns(@resource)
- Puppet::Parser::Resource.stubs(:new).returns(@resource)
@compile.evaluate_classes(%w{myclass}, @scope, false)
end
@@ -313,6 +364,7 @@ describe Puppet::Parser::Compile, " when evaluating found classes" do
@scope.stubs(:findclass).with("notfound").returns(nil)
Puppet::Parser::Resource.stubs(:new).returns(@resource)
+ @class.stubs :evaluate
@compile.evaluate_classes(%w{myclass notfound}, @scope).should == %w{myclass}
end
end
@@ -411,78 +463,6 @@ describe Puppet::Parser::Compile, " when evaluating AST nodes with AST nodes pre
end
end
-describe Puppet::Parser::Compile, " when initializing" do
- include CompileTesting
-
- it "should set its node attribute" do
- @compile.node.should equal(@node)
- end
-
- it "should set its parser attribute" do
- @compile.parser.should equal(@parser)
- end
-
- it "should detect when ast nodes are absent" do
- @compile.ast_nodes?.should be_false
- end
-
- it "should detect when ast nodes are present" do
- @parser.nodes["testing"] = "yay"
- @compile.ast_nodes?.should be_true
- end
-end
-
-describe Puppet::Parser::Compile do
- include CompileTesting
-
- it "should be able to store references to class scopes" do
- lambda { @compile.class_set "myname", "myscope" }.should_not raise_error
- end
-
- it "should be able to retrieve class scopes by name" do
- @compile.class_set "myname", "myscope"
- @compile.class_scope("myname").should == "myscope"
- end
-
- it "should be able to retrieve class scopes by object" do
- klass = mock 'ast_class'
- klass.expects(:classname).returns("myname")
- @compile.class_set "myname", "myscope"
- @compile.class_scope(klass).should == "myscope"
- end
-
- it "should be able to return a class list containing all set classes" do
- @compile.class_set "", "empty"
- @compile.class_set "one", "yep"
- @compile.class_set "two", "nope"
-
- @compile.classlist.sort.should == %w{one two}.sort
- end
-end
-
-describe Puppet::Parser::Compile, "when managing scopes" do
- include CompileTesting
-
- it "should create a top scope" do
- @compile.topscope.should be_instance_of(Puppet::Parser::Scope)
- end
-
- it "should be able to create new scopes" do
- @compile.newscope(@compile.topscope).should be_instance_of(Puppet::Parser::Scope)
- end
-
- it "should correctly set the level of newly created scopes" do
- @compile.newscope(@compile.topscope, :level => 5).level.should == 5
- end
-
- it "should set the parent scope of the new scope to be the passed-in parent" do
- scope = mock 'scope'
- newscope = @compile.newscope(scope)
-
- @compile.parent(newscope).should equal(scope)
- end
-end
-
describe Puppet::Parser::Compile, "when storing compiled resources" do
include CompileTesting