diff options
| author | Luke Kanies <luke@madstop.com> | 2008-02-12 14:19:19 -0600 |
|---|---|---|
| committer | Luke Kanies <luke@madstop.com> | 2008-02-12 14:19:19 -0600 |
| commit | c8da318a2a4445e0ce10c76a7fbb64635b291ccd (patch) | |
| tree | 3e9f1495f1779f18a8282f9a62a4c4ad97ecd6e4 /spec/unit/parser/ast | |
| parent | 8b2fae019b31513becd002eb474e1b4803abde24 (diff) | |
| download | puppet-c8da318a2a4445e0ce10c76a7fbb64635b291ccd.tar.gz puppet-c8da318a2a4445e0ce10c76a7fbb64635b291ccd.tar.xz puppet-c8da318a2a4445e0ce10c76a7fbb64635b291ccd.zip | |
Moving the ast node tests to rspec (which I could have
*sworn* I did this weekend). In the process, I fixed
a couple of bugs related to differentiating between
nodes and classes, and then cleaned up quite a few
error messages.
Diffstat (limited to 'spec/unit/parser/ast')
| -rwxr-xr-x | spec/unit/parser/ast/definition.rb | 148 | ||||
| -rwxr-xr-x | spec/unit/parser/ast/node.rb | 127 |
2 files changed, 275 insertions, 0 deletions
diff --git a/spec/unit/parser/ast/definition.rb b/spec/unit/parser/ast/definition.rb index ba80894e8..f236e23b7 100755 --- a/spec/unit/parser/ast/definition.rb +++ b/spec/unit/parser/ast/definition.rb @@ -44,4 +44,152 @@ describe Puppet::Parser::AST::Definition, "when evaluating" do # it "should not copy the resource's title as the name if 'name' is one of the resource parameters" # # it "should evaluate the associated code with the new scope" + + def test_initialize + parser = mkparser + + # Create a new definition + klass = parser.newdefine "yayness", + :arguments => [["owner", stringobj("nobody")], %w{mode}], + :code => AST::ASTArray.new( + :children => [resourcedef("file", "/tmp/$name", + "owner" => varref("owner"), "mode" => varref("mode"))] + ) + + # Test validattr? a couple different ways + [:owner, "owner", :schedule, "schedule"].each do |var| + assert(klass.validattr?(var), "%s was not considered valid" % var.inspect) + end + + [:random, "random"].each do |var| + assert(! klass.validattr?(var), "%s was considered valid" % var.inspect) + end + + end + + def test_evaluate + parser = mkparser + config = mkcompiler + config.send(:evaluate_main) + scope = config.topscope + klass = parser.newdefine "yayness", + :arguments => [["owner", stringobj("nobody")], %w{mode}], + :code => AST::ASTArray.new( + :children => [resourcedef("file", "/tmp/$name", + "owner" => varref("owner"), "mode" => varref("mode"))] + ) + + resource = Puppet::Parser::Resource.new( + :title => "first", + :type => "yayness", + :exported => false, + :virtual => false, + :scope => scope, + :source => scope.source + ) + resource.send(:set_parameter, "name", "first") + resource.send(:set_parameter, "mode", "755") + + resource.stubs(:title) + assert_nothing_raised do + klass.evaluate_code(resource) + end + + firstobj = config.findresource("File[/tmp/first]") + assert(firstobj, "Did not create /tmp/first obj") + + assert_equal("File", firstobj.type) + assert_equal("/tmp/first", firstobj.title) + assert_equal("nobody", firstobj[:owner]) + assert_equal("755", firstobj[:mode]) + + # Make sure we can't evaluate it with the same args + assert_raise(Puppet::ParseError) do + klass.evaluate_code(resource) + end + + # Now create another with different args + resource2 = Puppet::Parser::Resource.new( + :title => "second", + :type => "yayness", + :exported => false, + :virtual => false, + :scope => scope, + :source => scope.source + ) + resource2.send(:set_parameter, "name", "second") + resource2.send(:set_parameter, "mode", "755") + resource2.send(:set_parameter, "owner", "daemon") + + assert_nothing_raised do + klass.evaluate_code(resource2) + end + + secondobj = config.findresource("File[/tmp/second]") + assert(secondobj, "Did not create /tmp/second obj") + + assert_equal("File", secondobj.type) + assert_equal("/tmp/second", secondobj.title) + assert_equal("daemon", secondobj[:owner]) + assert_equal("755", secondobj[:mode]) + end + + # #539 - definitions should support both names and titles + def test_names_and_titles + parser = mkparser + scope = mkscope :parser => parser + + [ + {:name => "one", :title => "two"}, + {:title => "mytitle"} + ].each_with_index do |hash, i| + # Create a definition that uses both name and title. Put this + # inside the loop so the subscope expectations work. + klass = parser.newdefine "yayness%s" % i + + resource = Puppet::Parser::Resource.new( + :title => hash[:title], + :type => "yayness%s" % i, + :exported => false, + :virtual => false, + :scope => scope, + :source => scope.source + ) + + subscope = klass.subscope(scope, resource) + + klass.expects(:subscope).returns(subscope) + + if hash[:name] + resource.stubs(:to_hash).returns({:name => hash[:name]}) + end + + assert_nothing_raised("Could not evaluate definition with %s" % hash.inspect) do + klass.evaluate_code(resource) + end + + name = hash[:name] || hash[:title] + title = hash[:title] + + assert_equal(name, subscope.lookupvar("name"), + "Name did not get set correctly") + assert_equal(title, subscope.lookupvar("title"), + "title did not get set correctly") + + [:name, :title].each do |param| + val = resource.send(param) + assert(subscope.tags.include?(val), + "Scope was not tagged with %s '%s'" % [param, val]) + end + end + end + + # Testing the root cause of #615. We should be using the fqname for the type, instead + # of just the short name. + def test_fully_qualified_types + parser = mkparser + klass = parser.newclass("one::two") + + assert_equal("one::two", klass.classname, "Class did not get fully qualified class name") + end end diff --git a/spec/unit/parser/ast/node.rb b/spec/unit/parser/ast/node.rb new file mode 100755 index 000000000..340630194 --- /dev/null +++ b/spec/unit/parser/ast/node.rb @@ -0,0 +1,127 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +module ASTNodeTesting + def setup + @node = Puppet::Node.new "testnode" + @parser = Puppet::Parser::Parser.new :environment => "development" + @scope_resource = stub 'scope_resource', :builtin? => true + @compiler = Puppet::Parser::Compiler.new(@node, @parser) + + @scope = @compiler.topscope + end +end + +describe Puppet::Parser::AST::Node, "when evaluating" do + include ASTNodeTesting + + before do + @top = @parser.newnode("top").shift + @middle = @parser.newnode("middle", :parent => "top").shift + end + + it "should create a resource that references itself" do + @top.evaluate(@scope) + + @compiler.catalog.resource(:node, "top").should be_an_instance_of(Puppet::Parser::Resource) + end + + it "should evaluate the parent class if one exists" do + @middle.evaluate(@scope) + + @compiler.catalog.resource(:node, "top").should be_an_instance_of(Puppet::Parser::Resource) + end + + it "should fail to evaluate if a parent class is defined but cannot be found" do + othertop = @parser.newnode("something", :parent => "yay").shift + lambda { othertop.evaluate(@scope) }.should raise_error(Puppet::ParseError) + end + + it "should not create a new resource if one already exists" do + @compiler.catalog.expects(:resource).with(:node, "top").returns("something") + @compiler.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 = @compiler.catalog.resource(:node, "top") + + @middle.evaluate(@scope) + + @compiler.catalog.resource(:node, "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) + + @compiler.catalog.should be_tagged("middle") + end + + it "should tag the catalog with the parent class tags when it is evaluated" do + @middle.evaluate(@scope) + + @compiler.catalog.should be_tagged("top") + end +end + +describe Puppet::Parser::AST::Node, "when evaluating code" do + include ASTNodeTesting + + before do + @top_resource = stub "top_resource" + @top = @parser.newnode("top", :code => @top_resource).shift + + @middle_resource = stub "middle_resource" + @middle = @parser.newnode("middle", :parent => "top", :code => @middle_resource).shift + 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) + + @compiler.class_scope(@middle).parent.should equal(@compiler.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) + + @compiler.class_scope(@middle).namespaces.should be_include(@top.namespace) + end +end |
