summaryrefslogtreecommitdiffstats
path: root/spec/unit/parser/ast
diff options
context:
space:
mode:
authorLuke Kanies <luke@madstop.com>2008-02-12 14:19:19 -0600
committerLuke Kanies <luke@madstop.com>2008-02-12 14:19:19 -0600
commitc8da318a2a4445e0ce10c76a7fbb64635b291ccd (patch)
tree3e9f1495f1779f18a8282f9a62a4c4ad97ecd6e4 /spec/unit/parser/ast
parent8b2fae019b31513becd002eb474e1b4803abde24 (diff)
downloadpuppet-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-xspec/unit/parser/ast/definition.rb148
-rwxr-xr-xspec/unit/parser/ast/node.rb127
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