From aab419b8c1ad84e51c6f58839290bbe5d1e7b28b Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Tue, 14 Aug 2007 00:09:49 -0500 Subject: An intermediate commit in the work towards adding multi-environment support. This has required splitting the interpreter up considerably, which is much cleaner but is a large project. There is now a 'nodes' handler, but it is currently non-functional, although all the support structure is there. It just needs to have the individual methods fleshed out, and it needs to be connected to the 'facts' handler. --- test/language/configuration.rb | 131 ++++++++++++++++ test/language/interpreter.rb | 279 --------------------------------- test/language/node.rb | 207 +++++++++++++------------ test/network/handler/node.rb | 341 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 578 insertions(+), 380 deletions(-) create mode 100755 test/language/configuration.rb create mode 100755 test/network/handler/node.rb (limited to 'test') diff --git a/test/language/configuration.rb b/test/language/configuration.rb new file mode 100755 index 000000000..4cbba8063 --- /dev/null +++ b/test/language/configuration.rb @@ -0,0 +1,131 @@ +#!/usr/bin/env ruby + +$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'mocha' +require 'puppettest' +require 'puppettest/parsertesting' +require 'puppet/parser/configuration' + +# Test our configuration object. +class TestConfiguration < Test::Unit::TestCase + include PuppetTest + include PuppetTest::ParserTesting + + Config = Puppet::Parser::Configuration + Scope = Puppet::Parser::Scope + + def mkconfig + Config.new(:host => "foo", :interpreter => "interp") + end + + def test_initialize + # Make sure we get an error if we don't send an interpreter + assert_raise(ArgumentError, "Did not fail when missing host") do + Config.new(:interpreter => "yay" ) + end + assert_raise(ArgumentError, "Did not fail when missing interp") do + Config.new(:host => "foo") + end + + # Now check the defaults + config = nil + assert_nothing_raised("Could not init config with all required options") do + config = Config.new(:host => "foo", :interpreter => "interp") + end + + assert_equal("foo", config.host, "Did not set host correctly") + assert_equal("interp", config.interpreter, "Did not set interpreter correctly") + assert_equal({}, config.facts, "Did not set default facts") + + # Now make a new one with facts, to make sure the facts get set appropriately + assert_nothing_raised("Could not init config with all required options") do + config = Config.new(:host => "foo", :interpreter => "interp", :facts => {"a" => "b"}) + end + assert_equal({"a" => "b"}, config.facts, "Did not set facts") + end + + def test_initvars + config = mkconfig + [:class_scopes, :resource_table, :exported_resources, :resource_overrides].each do |table| + assert_instance_of(Hash, config.send(:instance_variable_get, "@#{table}"), "Did not set %s table correctly" % table) + end + end + + # Make sure we store and can retrieve references to classes and their scopes. + def test_class_set_and_class_scope + klass = Object.new + klass.expects(:classname).returns("myname") + + config = mkconfig + + assert_nothing_raised("Could not set class") do + config.class_set "myname", "myscope" + end + # First try to retrieve it by name. + assert_equal("myscope", config.class_scope("myname"), "Could not retrieve class scope by name") + + # Then by object + assert_equal("myscope", config.class_scope(klass), "Could not retrieve class scope by object") + end + + def test_classlist + config = mkconfig + + config.class_set "", "empty" + config.class_set "one", "yep" + config.class_set "two", "nope" + + # Make sure our class list is correct + assert_equal(%w{one two}.sort, config.classlist.sort, "Did not get correct class list") + end + + # Make sure collections get added to our internal array + def test_add_collection + config = mkconfig + assert_nothing_raised("Could not add collection") do + config.add_collection "nope" + end + assert_equal(%w{nope}, config.instance_variable_get("@collections"), "Did not add collection") + end + + # Make sure we create a graph of scopes. + def test_newscope + config = mkconfig + graph = config.instance_variable_get("@graph") + assert_instance_of(Scope, config.topscope, "Did not create top scope") + assert_instance_of(GRATR::Digraph, graph, "Did not create graph") + + assert(graph.vertex?(config.topscope), "The top scope is not a vertex in the graph") + + # Now that we've got the top scope, create a new, subscope + subscope = nil + assert_nothing_raised("Could not create subscope") do + subscope = config.newscope + end + assert_instance_of(Scope, subscope, "Did not create subscope") + assert(graph.edge?(config.topscope, subscope), "An edge between top scope and subscope was not added") + + # Make sure a scope can find its parent. + assert(config.parent(subscope), "Could not look up parent scope on configuration") + assert_equal(config.topscope.object_id, config.parent(subscope).object_id, "Did not get correct parent scope from configuration") + assert_equal(config.topscope.object_id, subscope.parent.object_id, "Scope did not correctly retrieve its parent scope") + + # Now create another, this time specifying the parent scope + another = nil + assert_nothing_raised("Could not create subscope") do + another = config.newscope(subscope) + end + assert_instance_of(Scope, another, "Did not create second subscope") + assert(graph.edge?(subscope, another), "An edge between parent scope and second subscope was not added") + + # Make sure it can find its parent. + assert(config.parent(another), "Could not look up parent scope of second subscope on configuration") + assert_equal(subscope.object_id, config.parent(another).object_id, "Did not get correct parent scope of second subscope from configuration") + assert_equal(subscope.object_id, another.parent.object_id, "Second subscope did not correctly retrieve its parent scope") + + # And make sure both scopes show up in the right order in the search path + assert_equal([another.object_id, subscope.object_id, config.topscope.object_id], another.scope_path.collect { |p| p.object_id }, + "Did not get correct scope path") + end +end diff --git a/test/language/interpreter.rb b/test/language/interpreter.rb index 75800cc41..070e2e77e 100755 --- a/test/language/interpreter.rb +++ b/test/language/interpreter.rb @@ -431,96 +431,6 @@ class TestInterpreter < PuppetTest::TestCase assert(found.include?("/tmp/klass1"), "Did not evaluate klass1") assert(found.include?("/tmp/klass2"), "Did not evaluate klass2") end - - def mk_node_mapper - # First, make sure our nodesearch command works as we expect - # Make a nodemapper - mapper = tempfile() - ruby = %x{which ruby}.chomp - File.open(mapper, "w") { |f| - f.puts "#!#{ruby} - require 'yaml' - name = ARGV.last.chomp - result = {} - - if name =~ /a/ - result[:parameters] = {'one' => ARGV.last + '1', 'two' => ARGV.last + '2'} - end - - if name =~ /p/ - result['classes'] = [1,2,3].collect { |n| ARGV.last + n.to_s } - end - - puts YAML.dump(result) - " - } - File.chmod(0755, mapper) - mapper - end - - def test_nodesearch_external - interp = mkinterp - - mapper = mk_node_mapper - # Make sure it gives the right response - assert_equal({'classes' => %w{apple1 apple2 apple3}, :parameters => {"one" => "apple1", "two" => "apple2"}}, - YAML.load(%x{#{mapper} apple})) - - # First make sure we get nil back by default - assert_nothing_raised { - assert_nil(interp.nodesearch_external("apple"), - "Interp#nodesearch_external defaulted to a non-nil response") - } - assert_nothing_raised { Puppet[:external_nodes] = mapper } - - node = nil - # Both 'a' and 'p', so we get classes and parameters - assert_nothing_raised { node = interp.nodesearch_external("apple") } - assert_equal("apple", node.name, "node name was not set correctly for apple") - assert_equal(%w{apple1 apple2 apple3}, node.classes, "node classes were not set correctly for apple") - assert_equal( {"one" => "apple1", "two" => "apple2"}, node.parameters, "node parameters were not set correctly for apple") - - # A 'p' but no 'a', so we only get classes - assert_nothing_raised { node = interp.nodesearch_external("plum") } - assert_equal("plum", node.name, "node name was not set correctly for plum") - assert_equal(%w{plum1 plum2 plum3}, node.classes, "node classes were not set correctly for plum") - assert_equal({}, node.parameters, "node parameters were not set correctly for plum") - - # An 'a' but no 'p', so we only get parameters. - assert_nothing_raised { node = interp.nodesearch_external("guava")} # no p's, thus no classes - assert_equal("guava", node.name, "node name was not set correctly for guava") - assert_equal([], node.classes, "node classes were not set correctly for guava") - assert_equal({"one" => "guava1", "two" => "guava2"}, node.parameters, "node parameters were not set correctly for guava") - - assert_nothing_raised { node = interp.nodesearch_external("honeydew")} # neither, thus nil - assert_nil(node) - end - - # Make sure a nodesearch with arguments works - def test_nodesearch_external_arguments - mapper = mk_node_mapper - Puppet[:external_nodes] = "#{mapper} -s something -p somethingelse" - interp = mkinterp - node = nil - assert_nothing_raised do - node = interp.nodesearch("apple") - end - assert_instance_of(NodeDef, node, "did not create node") - end - - # A wrapper test, to make sure we're correctly calling the external search method. - def test_nodesearch_external_functional - mapper = mk_node_mapper - - Puppet[:external_nodes] = mapper - interp = mkinterp - - node = nil - assert_nothing_raised do - node = interp.nodesearch("apple") - end - assert_instance_of(NodeDef, node, "did not create node") - end def test_check_resource_collections interp = mkinterp @@ -598,64 +508,6 @@ class TestInterpreter < PuppetTest::TestCase assert(scope.classlist.include?("base"), "NodeDef did not evaluate class") end - # This can stay in the main test suite because it doesn't actually use ldapsearch, - # it just overrides the method so it behaves as though it were hitting ldap. - def test_ldapnodes - interp = mkinterp - - nodetable = {} - - # Override the ldapsearch definition, so we don't have to actually set it up. - interp.meta_def(:ldapsearch) do |name| - nodetable[name] - end - - # Make sure we get nothing for nonexistent hosts - node = nil - assert_nothing_raised do - node = interp.nodesearch_ldap("nosuchhost") - end - - assert_nil(node, "Got a node for a non-existent host") - - # Now add a base node with some classes and parameters - nodetable["base"] = [nil, %w{one two}, {"base" => "true"}] - - assert_nothing_raised do - node = interp.nodesearch_ldap("base") - end - - assert_instance_of(NodeDef, node, "Did not get node from ldap nodesearch") - assert_equal("base", node.name, "node name was not set") - - assert_equal(%w{one two}, node.classes, "node classes were not set") - assert_equal({"base" => "true"}, node.parameters, "node parameters were not set") - - # Now use a different with this as the base - nodetable["middle"] = ["base", %w{three}, {"center" => "boo"}] - assert_nothing_raised do - node = interp.nodesearch_ldap("middle") - end - - assert_instance_of(NodeDef, node, "Did not get node from ldap nodesearch") - assert_equal("middle", node.name, "node name was not set") - - assert_equal(%w{one two three}.sort, node.classes.sort, "node classes were not set correctly with a parent node") - assert_equal({"base" => "true", "center" => "boo"}, node.parameters, "node parameters were not set correctly with a parent node") - - # And one further, to make sure we fully recurse - nodetable["top"] = ["middle", %w{four five}, {"master" => "far"}] - assert_nothing_raised do - node = interp.nodesearch_ldap("top") - end - - assert_instance_of(NodeDef, node, "Did not get node from ldap nodesearch") - assert_equal("top", node.name, "node name was not set") - - assert_equal(%w{one two three four five}.sort, node.classes.sort, "node classes were not set correctly with the top node") - assert_equal({"base" => "true", "center" => "boo", "master" => "far"}, node.parameters, "node parameters were not set correctly with the top node") - end - # Make sure that reparsing is atomic -- failures don't cause a broken state, and we aren't subject # to race conditions if someone contacts us while we're reparsing. def test_atomic_reparsing @@ -682,135 +534,4 @@ class TestInterpreter < PuppetTest::TestCase end end -class LdapNodeTest < PuppetTest::TestCase - include PuppetTest - include PuppetTest::ServerTest - include PuppetTest::ParserTesting - include PuppetTest::ResourceTesting - AST = Puppet::Parser::AST - NodeDef = Puppet::Parser::Interpreter::NodeDef - confine "LDAP is not available" => Puppet.features.ldap? - confine "No LDAP test data for networks other than Luke's" => Facter.value(:domain) == "madstop.com" - def ldapconnect - - @ldap = LDAP::Conn.new("ldap", 389) - @ldap.set_option( LDAP::LDAP_OPT_PROTOCOL_VERSION, 3 ) - @ldap.simple_bind("", "") - - return @ldap - end - - def ldaphost(name) - node = NodeDef.new(:name => name) - parent = nil - found = false - @ldap.search( "ou=hosts, dc=madstop, dc=com", 2, - "(&(objectclass=puppetclient)(cn=%s))" % name - ) do |entry| - node.classes = entry.vals("puppetclass") || [] - node.parameters = entry.to_hash.inject({}) do |hash, ary| - if ary[1].length == 1 - hash[ary[0]] = ary[1].shift - else - hash[ary[0]] = ary[1] - end - hash - end - parent = node.parameters["parentnode"] - found = true - end - raise "Could not find node %s" % name unless found - - return node, parent - end - - def test_ldapsearch - Puppet[:ldapbase] = "ou=hosts, dc=madstop, dc=com" - Puppet[:ldapnodes] = true - - ldapconnect() - - interp = mkinterp :NodeSources => [:ldap, :code] - - # Make sure we get nil and nil back when we search for something missing - parent, classes, parameters = nil - assert_nothing_raised do - parent, classes, parameters = interp.ldapsearch("nosuchhost") - end - - assert_nil(parent, "Got a parent for a non-existent host") - assert_nil(classes, "Got classes for a non-existent host") - - # Make sure we can find 'culain' in ldap - assert_nothing_raised do - parent, classes, parameters = interp.ldapsearch("culain") - end - - node, realparent = ldaphost("culain") - assert_equal(realparent, parent, "did not get correct parent node from ldap") - assert_equal(node.classes, classes, "did not get correct ldap classes from ldap") - assert_equal(node.parameters, parameters, "did not get correct ldap parameters from ldap") - - # Now compare when we specify the attributes to get. - Puppet[:ldapattrs] = "cn" - assert_nothing_raised do - parent, classes, parameters = interp.ldapsearch("culain") - end - assert_equal(realparent, parent, "did not get correct parent node from ldap") - assert_equal(node.classes, classes, "did not get correct ldap classes from ldap") - - list = %w{cn puppetclass parentnode dn} - should = node.parameters.inject({}) { |h, a| h[a[0]] = a[1] if list.include?(a[0]); h } - assert_equal(should, parameters, "did not get correct ldap parameters from ldap") - end -end - -class LdapReconnectTests < PuppetTest::TestCase - include PuppetTest - include PuppetTest::ServerTest - include PuppetTest::ParserTesting - include PuppetTest::ResourceTesting - AST = Puppet::Parser::AST - NodeDef = Puppet::Parser::Interpreter::NodeDef - confine "Not running on culain as root" => (Puppet::Util::SUIDManager.uid == 0 and Facter.value("hostname") == "culain") - - def test_ldapreconnect - Puppet[:ldapbase] = "ou=hosts, dc=madstop, dc=com" - Puppet[:ldapnodes] = true - - interp = nil - assert_nothing_raised { - interp = Puppet::Parser::Interpreter.new( - :Manifest => mktestmanifest() - ) - } - hostname = "culain.madstop.com" - - # look for our host - assert_nothing_raised { - parent, classes = interp.nodesearch_ldap(hostname) - } - - # Now restart ldap - system("/etc/init.d/slapd restart 2>/dev/null >/dev/null") - sleep(1) - - # and look again - assert_nothing_raised { - parent, classes = interp.nodesearch_ldap(hostname) - } - - # Now stop ldap - system("/etc/init.d/slapd stop 2>/dev/null >/dev/null") - cleanup do - system("/etc/init.d/slapd start 2>/dev/null >/dev/null") - end - - # And make sure we actually fail here - assert_raise(Puppet::Error) { - parent, classes = interp.nodesearch_ldap(hostname) - } - end -end - # $Id$ diff --git a/test/language/node.rb b/test/language/node.rb index 61983df92..4cbba8063 100755 --- a/test/language/node.rb +++ b/test/language/node.rb @@ -2,125 +2,130 @@ $:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ -require 'puppet' -require 'puppet/parser/parser' +require 'mocha' require 'puppettest' +require 'puppettest/parsertesting' +require 'puppet/parser/configuration' -class TestParser < Test::Unit::TestCase +# Test our configuration object. +class TestConfiguration < Test::Unit::TestCase + include PuppetTest include PuppetTest::ParserTesting - def setup - super - Puppet[:parseonly] = true + Config = Puppet::Parser::Configuration + Scope = Puppet::Parser::Scope + + def mkconfig + Config.new(:host => "foo", :interpreter => "interp") + end + + def test_initialize + # Make sure we get an error if we don't send an interpreter + assert_raise(ArgumentError, "Did not fail when missing host") do + Config.new(:interpreter => "yay" ) + end + assert_raise(ArgumentError, "Did not fail when missing interp") do + Config.new(:host => "foo") + end + + # Now check the defaults + config = nil + assert_nothing_raised("Could not init config with all required options") do + config = Config.new(:host => "foo", :interpreter => "interp") + end + + assert_equal("foo", config.host, "Did not set host correctly") + assert_equal("interp", config.interpreter, "Did not set interpreter correctly") + assert_equal({}, config.facts, "Did not set default facts") + + # Now make a new one with facts, to make sure the facts get set appropriately + assert_nothing_raised("Could not init config with all required options") do + config = Config.new(:host => "foo", :interpreter => "interp", :facts => {"a" => "b"}) + end + assert_equal({"a" => "b"}, config.facts, "Did not set facts") end - def test_simple_hostname - check_parseable "host1" - check_parseable "'host2'" - check_parseable "\"host3\"" - check_parseable [ "'host1'", "host2" ] - check_parseable [ "'host1'", "'host2'" ] - check_parseable [ "'host1'", "\"host2\"" ] - check_parseable [ "\"host1\"", "host2" ] - check_parseable [ "\"host1\"", "'host2'" ] - check_parseable [ "\"host1\"", "\"host2\"" ] + def test_initvars + config = mkconfig + [:class_scopes, :resource_table, :exported_resources, :resource_overrides].each do |table| + assert_instance_of(Hash, config.send(:instance_variable_get, "@#{table}"), "Did not set %s table correctly" % table) + end end - def test_qualified_hostname - check_parseable "'host.example.com'" - check_parseable "\"host.example.com\"" - check_parseable [ "'host.example.com'", "host1" ] - check_parseable [ "\"host.example.com\"", "host1" ] - check_parseable "'host-1.37examples.example.com'" - check_parseable "\"host-1.37examples.example.com\"" - check_parseable "'svn.23.nu'" - check_parseable "\"svn.23.nu\"" - check_parseable "'HOST'" - check_parseable "\"HOST\"" + # Make sure we store and can retrieve references to classes and their scopes. + def test_class_set_and_class_scope + klass = Object.new + klass.expects(:classname).returns("myname") + + config = mkconfig + + assert_nothing_raised("Could not set class") do + config.class_set "myname", "myscope" + end + # First try to retrieve it by name. + assert_equal("myscope", config.class_scope("myname"), "Could not retrieve class scope by name") + + # Then by object + assert_equal("myscope", config.class_scope(klass), "Could not retrieve class scope by object") end - def test_inherits_from_default - check_parseable(["default", "host1"], "node default {}\nnode host1 inherits default {}") + def test_classlist + config = mkconfig + + config.class_set "", "empty" + config.class_set "one", "yep" + config.class_set "two", "nope" + + # Make sure our class list is correct + assert_equal(%w{one two}.sort, config.classlist.sort, "Did not get correct class list") end - def test_reject_hostname - check_nonparseable "host.example.com" - check_nonparseable "host@example.com" - check_nonparseable "'$foo.example.com'" - check_nonparseable "\"$foo.example.com\"" - check_nonparseable "'host1 host2'" - check_nonparseable "\"host1 host2\"" - check_nonparseable "HOST" + # Make sure collections get added to our internal array + def test_add_collection + config = mkconfig + assert_nothing_raised("Could not add collection") do + config.add_collection "nope" + end + assert_equal(%w{nope}, config.instance_variable_get("@collections"), "Did not add collection") end - AST = Puppet::Parser::AST + # Make sure we create a graph of scopes. + def test_newscope + config = mkconfig + graph = config.instance_variable_get("@graph") + assert_instance_of(Scope, config.topscope, "Did not create top scope") + assert_instance_of(GRATR::Digraph, graph, "Did not create graph") + + assert(graph.vertex?(config.topscope), "The top scope is not a vertex in the graph") - def check_parseable(hostnames, code = nil) - unless hostnames.is_a?(Array) - hostnames = [ hostnames ] + # Now that we've got the top scope, create a new, subscope + subscope = nil + assert_nothing_raised("Could not create subscope") do + subscope = config.newscope end - interp = nil - code ||= "node #{hostnames.join(", ")} { }" - parser = mkparser - parser.string = code - # Strip quotes - hostnames.map! { |s| s.sub(/^['"](.*)['"]$/, "\\1") } - - # parse - assert_nothing_raised("Could not parse '%s'" % code) { - parser.parse - } - - # Now make sure we can look up each of the names - hostnames.each do |name| - assert(parser.findnode(name), - "Could not find node %s" % name.inspect) + assert_instance_of(Scope, subscope, "Did not create subscope") + assert(graph.edge?(config.topscope, subscope), "An edge between top scope and subscope was not added") + + # Make sure a scope can find its parent. + assert(config.parent(subscope), "Could not look up parent scope on configuration") + assert_equal(config.topscope.object_id, config.parent(subscope).object_id, "Did not get correct parent scope from configuration") + assert_equal(config.topscope.object_id, subscope.parent.object_id, "Scope did not correctly retrieve its parent scope") + + # Now create another, this time specifying the parent scope + another = nil + assert_nothing_raised("Could not create subscope") do + another = config.newscope(subscope) end - end + assert_instance_of(Scope, another, "Did not create second subscope") + assert(graph.edge?(subscope, another), "An edge between parent scope and second subscope was not added") - def check_nonparseable(hostname) - interp = nil - parser = mkparser - parser.string = "node #{hostname} { }" - assert_raise(Puppet::DevError, Puppet::ParseError, "#{hostname} passed") { - parser.parse - } - end + # Make sure it can find its parent. + assert(config.parent(another), "Could not look up parent scope of second subscope on configuration") + assert_equal(subscope.object_id, config.parent(another).object_id, "Did not get correct parent scope of second subscope from configuration") + assert_equal(subscope.object_id, another.parent.object_id, "Second subscope did not correctly retrieve its parent scope") - # Make sure we can find default nodes if there's no other entry - def test_default_node - Puppet[:parseonly] = false - - fileA = tempfile() - fileB = tempfile() - code = %{ -node mynode { - file { "#{fileA}": ensure => file } -} - -node default { - file { "#{fileB}": ensure => file } -} -} - interp = nil - assert_nothing_raised { - interp = mkinterp :Code => code - } - - # First make sure it parses - assert_nothing_raised { - interp.send(:parsefiles) - } - - # Make sure we find our normal node - assert(interp.nodesearch("mynode"), - "Did not find normal node") - - # Now look for the default node - default = interp.nodesearch("someother") - assert(default, - "Did not find default node") - - assert_equal("default", default.classname) + # And make sure both scopes show up in the right order in the search path + assert_equal([another.object_id, subscope.object_id, config.topscope.object_id], another.scope_path.collect { |p| p.object_id }, + "Did not get correct scope path") end end diff --git a/test/network/handler/node.rb b/test/network/handler/node.rb new file mode 100755 index 000000000..c682929d9 --- /dev/null +++ b/test/network/handler/node.rb @@ -0,0 +1,341 @@ +#!/usr/bin/env ruby + +$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'mocha' +require 'puppettest' +require 'puppettest/resourcetesting' +require 'puppettest/parsertesting' +require 'puppettest/servertest' +require 'puppet/network/handler/node' + +module NodeTesting + include PuppetTest + Node = Puppet::Network::Handler::Node + SimpleNode = Puppet::Network::Handler::Node::SimpleNode + + def mk_node_mapper + # First, make sure our nodesearch command works as we expect + # Make a nodemapper + mapper = tempfile() + ruby = %x{which ruby}.chomp + File.open(mapper, "w") { |f| + f.puts "#!#{ruby} + require 'yaml' + name = ARGV.last.chomp + result = {} + + if name =~ /a/ + result[:parameters] = {'one' => ARGV.last + '1', 'two' => ARGV.last + '2'} + end + + if name =~ /p/ + result['classes'] = [1,2,3].collect { |n| ARGV.last + n.to_s } + end + + puts YAML.dump(result) + " + } + File.chmod(0755, mapper) + mapper + end + + def mk_searcher(name) + searcher = Object.new + searcher.extend(Node.node_source(name)) + end +end + +class TestNodeInterface < Test::Unit::TestCase + def setup + super + end + + def teardown + end + + def test_node + raise "Failing, yo" + end + + def test_environment + raise "still failing" + end + + def test_parameters + raise "still failing" + end + + def test_classes + raise "still failing" + end +end + +# Test our configuration object. +class TestNodeSources < Test::Unit::TestCase + include NodeTesting + + def test_node_sources + mod = nil + assert_nothing_raised("Could not add new search type") do + mod = Node.newnode_source(:testing) do + def nodesearch(name) + end + end + end + assert_equal(mod, Node.node_source(:testing), "Did not get node_source back") + + cleanup do + Node.rm_node_source(:testing) + end + end + + def test_external_node_source + mapper = mk_node_mapper + searcher = mk_searcher(:external) + + # Make sure it gives the right response + assert_equal({'classes' => %w{apple1 apple2 apple3}, :parameters => {"one" => "apple1", "two" => "apple2"}}, + YAML.load(%x{#{mapper} apple})) + + # First make sure we get nil back by default + assert_nothing_raised { + assert_nil(searcher.nodesearch("apple"), + "Interp#nodesearch_external defaulted to a non-nil response") + } + assert_nothing_raised { Puppet[:external_nodes] = mapper } + + node = nil + # Both 'a' and 'p', so we get classes and parameters + assert_nothing_raised { node = searcher.nodesearch("apple") } + assert_equal("apple", node.name, "node name was not set correctly for apple") + assert_equal(%w{apple1 apple2 apple3}, node.classes, "node classes were not set correctly for apple") + assert_equal( {"one" => "apple1", "two" => "apple2"}, node.parameters, "node parameters were not set correctly for apple") + + # A 'p' but no 'a', so we only get classes + assert_nothing_raised { node = searcher.nodesearch("plum") } + assert_equal("plum", node.name, "node name was not set correctly for plum") + assert_equal(%w{plum1 plum2 plum3}, node.classes, "node classes were not set correctly for plum") + assert_equal({}, node.parameters, "node parameters were not set correctly for plum") + + # An 'a' but no 'p', so we only get parameters. + assert_nothing_raised { node = searcher.nodesearch("guava")} # no p's, thus no classes + assert_equal("guava", node.name, "node name was not set correctly for guava") + assert_equal([], node.classes, "node classes were not set correctly for guava") + assert_equal({"one" => "guava1", "two" => "guava2"}, node.parameters, "node parameters were not set correctly for guava") + + assert_nothing_raised { node = searcher.nodesearch("honeydew")} # neither, thus nil + assert_nil(node) + end + + # Make sure a nodesearch with arguments works + def test_nodesearch_external_arguments + mapper = mk_node_mapper + Puppet[:external_nodes] = "#{mapper} -s something -p somethingelse" + searcher = mk_searcher(:external) + node = nil + assert_nothing_raised do + node = searcher.nodesearch("apple") + end + assert_instance_of(SimpleNode, node, "did not create node") + end + + # A wrapper test, to make sure we're correctly calling the external search method. + def test_nodesearch_external_functional + mapper = mk_node_mapper + searcher = mk_searcher(:external) + + Puppet[:external_nodes] = mapper + + node = nil + assert_nothing_raised do + node = searcher.nodesearch("apple") + end + assert_instance_of(SimpleNode, node, "did not create node") + end + + # This can stay in the main test suite because it doesn't actually use ldapsearch, + # it just overrides the method so it behaves as though it were hitting ldap. + def test_ldap_nodesearch + searcher = mk_searcher(:ldap) + + nodetable = {} + + # Override the ldapsearch definition, so we don't have to actually set it up. + searcher.meta_def(:ldapsearch) do |name| + nodetable[name] + end + + # Make sure we get nothing for nonexistent hosts + node = nil + assert_nothing_raised do + node = searcher.nodesearch("nosuchhost") + end + + assert_nil(node, "Got a node for a non-existent host") + + # Now add a base node with some classes and parameters + nodetable["base"] = [nil, %w{one two}, {"base" => "true"}] + + assert_nothing_raised do + node = searcher.nodesearch("base") + end + + assert_instance_of(SimpleNode, node, "Did not get node from ldap nodesearch") + assert_equal("base", node.name, "node name was not set") + + assert_equal(%w{one two}, node.classes, "node classes were not set") + assert_equal({"base" => "true"}, node.parameters, "node parameters were not set") + + # Now use a different with this as the base + nodetable["middle"] = ["base", %w{three}, {"center" => "boo"}] + assert_nothing_raised do + node = searcher.nodesearch("middle") + end + + assert_instance_of(SimpleNode, node, "Did not get node from ldap nodesearch") + assert_equal("middle", node.name, "node name was not set") + + assert_equal(%w{one two three}.sort, node.classes.sort, "node classes were not set correctly with a parent node") + assert_equal({"base" => "true", "center" => "boo"}, node.parameters, "node parameters were not set correctly with a parent node") + + # And one further, to make sure we fully recurse + nodetable["top"] = ["middle", %w{four five}, {"master" => "far"}] + assert_nothing_raised do + node = searcher.nodesearch("top") + end + + assert_instance_of(SimpleNode, node, "Did not get node from ldap nodesearch") + assert_equal("top", node.name, "node name was not set") + + assert_equal(%w{one two three four five}.sort, node.classes.sort, "node classes were not set correctly with the top node") + assert_equal({"base" => "true", "center" => "boo", "master" => "far"}, node.parameters, "node parameters were not set correctly with the top node") + end +end + +class LdapNodeTest < PuppetTest::TestCase + include NodeTesting + include PuppetTest::ServerTest + include PuppetTest::ParserTesting + include PuppetTest::ResourceTesting + AST = Puppet::Parser::AST + confine "LDAP is not available" => Puppet.features.ldap? + confine "No LDAP test data for networks other than Luke's" => Facter.value(:domain) == "madstop.com" + + def ldapconnect + + @ldap = LDAP::Conn.new("ldap", 389) + @ldap.set_option( LDAP::LDAP_OPT_PROTOCOL_VERSION, 3 ) + @ldap.simple_bind("", "") + + return @ldap + end + + def ldaphost(name) + node = NodeDef.new(:name => name) + parent = nil + found = false + @ldap.search( "ou=hosts, dc=madstop, dc=com", 2, + "(&(objectclass=puppetclient)(cn=%s))" % name + ) do |entry| + node.classes = entry.vals("puppetclass") || [] + node.parameters = entry.to_hash.inject({}) do |hash, ary| + if ary[1].length == 1 + hash[ary[0]] = ary[1].shift + else + hash[ary[0]] = ary[1] + end + hash + end + parent = node.parameters["parentnode"] + found = true + end + raise "Could not find node %s" % name unless found + + return node, parent + end + + def test_ldapsearch + Puppet[:ldapbase] = "ou=hosts, dc=madstop, dc=com" + Puppet[:ldapnodes] = true + + searcher = Object.new + searcher.extend(Node.node_source(:ldap)) + + ldapconnect() + + # Make sure we get nil and nil back when we search for something missing + parent, classes, parameters = nil + assert_nothing_raised do + parent, classes, parameters = searcher.ldapsearch("nosuchhost") + end + + assert_nil(parent, "Got a parent for a non-existent host") + assert_nil(classes, "Got classes for a non-existent host") + + # Make sure we can find 'culain' in ldap + assert_nothing_raised do + parent, classes, parameters = searcher.ldapsearch("culain") + end + + node, realparent = ldaphost("culain") + assert_equal(realparent, parent, "did not get correct parent node from ldap") + assert_equal(node.classes, classes, "did not get correct ldap classes from ldap") + assert_equal(node.parameters, parameters, "did not get correct ldap parameters from ldap") + + # Now compare when we specify the attributes to get. + Puppet[:ldapattrs] = "cn" + assert_nothing_raised do + parent, classes, parameters = searcher.ldapsearch("culain") + end + assert_equal(realparent, parent, "did not get correct parent node from ldap") + assert_equal(node.classes, classes, "did not get correct ldap classes from ldap") + + list = %w{cn puppetclass parentnode dn} + should = node.parameters.inject({}) { |h, a| h[a[0]] = a[1] if list.include?(a[0]); h } + assert_equal(should, parameters, "did not get correct ldap parameters from ldap") + end +end + +class LdapReconnectTests < PuppetTest::TestCase + include NodeTesting + include PuppetTest::ServerTest + include PuppetTest::ParserTesting + include PuppetTest::ResourceTesting + AST = Puppet::Parser::AST + confine "Not running on culain as root" => (Puppet::Util::SUIDManager.uid == 0 and Facter.value("hostname") == "culain") + + def test_ldapreconnect + Puppet[:ldapbase] = "ou=hosts, dc=madstop, dc=com" + Puppet[:ldapnodes] = true + + searcher = Object.new + searcher.extend(Node.node_source(:ldap)) + hostname = "culain.madstop.com" + + # look for our host + assert_nothing_raised { + parent, classes = searcher.nodesearch(hostname) + } + + # Now restart ldap + system("/etc/init.d/slapd restart 2>/dev/null >/dev/null") + sleep(1) + + # and look again + assert_nothing_raised { + parent, classes = searcher.nodesearch(hostname) + } + + # Now stop ldap + system("/etc/init.d/slapd stop 2>/dev/null >/dev/null") + cleanup do + system("/etc/init.d/slapd start 2>/dev/null >/dev/null") + end + + # And make sure we actually fail here + assert_raise(Puppet::Error) { + parent, classes = searcher.nodesearch(hostname) + } + end +end -- cgit From 90a9d09cd08ec072530e2f000e9f7b65f1c41095 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Tue, 14 Aug 2007 18:25:08 -0500 Subject: Finalizing the node handler. It now correctly uses the different node sources and knows how to retrieve data from those sources. Now I just need to fix the language stuff to use this handler instead of the existing node stuff. --- test/language/node.rb | 131 ----------------- test/network/handler/node.rb | 330 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 324 insertions(+), 137 deletions(-) delete mode 100755 test/language/node.rb (limited to 'test') diff --git a/test/language/node.rb b/test/language/node.rb deleted file mode 100755 index 4cbba8063..000000000 --- a/test/language/node.rb +++ /dev/null @@ -1,131 +0,0 @@ -#!/usr/bin/env ruby - -$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ - -require 'mocha' -require 'puppettest' -require 'puppettest/parsertesting' -require 'puppet/parser/configuration' - -# Test our configuration object. -class TestConfiguration < Test::Unit::TestCase - include PuppetTest - include PuppetTest::ParserTesting - - Config = Puppet::Parser::Configuration - Scope = Puppet::Parser::Scope - - def mkconfig - Config.new(:host => "foo", :interpreter => "interp") - end - - def test_initialize - # Make sure we get an error if we don't send an interpreter - assert_raise(ArgumentError, "Did not fail when missing host") do - Config.new(:interpreter => "yay" ) - end - assert_raise(ArgumentError, "Did not fail when missing interp") do - Config.new(:host => "foo") - end - - # Now check the defaults - config = nil - assert_nothing_raised("Could not init config with all required options") do - config = Config.new(:host => "foo", :interpreter => "interp") - end - - assert_equal("foo", config.host, "Did not set host correctly") - assert_equal("interp", config.interpreter, "Did not set interpreter correctly") - assert_equal({}, config.facts, "Did not set default facts") - - # Now make a new one with facts, to make sure the facts get set appropriately - assert_nothing_raised("Could not init config with all required options") do - config = Config.new(:host => "foo", :interpreter => "interp", :facts => {"a" => "b"}) - end - assert_equal({"a" => "b"}, config.facts, "Did not set facts") - end - - def test_initvars - config = mkconfig - [:class_scopes, :resource_table, :exported_resources, :resource_overrides].each do |table| - assert_instance_of(Hash, config.send(:instance_variable_get, "@#{table}"), "Did not set %s table correctly" % table) - end - end - - # Make sure we store and can retrieve references to classes and their scopes. - def test_class_set_and_class_scope - klass = Object.new - klass.expects(:classname).returns("myname") - - config = mkconfig - - assert_nothing_raised("Could not set class") do - config.class_set "myname", "myscope" - end - # First try to retrieve it by name. - assert_equal("myscope", config.class_scope("myname"), "Could not retrieve class scope by name") - - # Then by object - assert_equal("myscope", config.class_scope(klass), "Could not retrieve class scope by object") - end - - def test_classlist - config = mkconfig - - config.class_set "", "empty" - config.class_set "one", "yep" - config.class_set "two", "nope" - - # Make sure our class list is correct - assert_equal(%w{one two}.sort, config.classlist.sort, "Did not get correct class list") - end - - # Make sure collections get added to our internal array - def test_add_collection - config = mkconfig - assert_nothing_raised("Could not add collection") do - config.add_collection "nope" - end - assert_equal(%w{nope}, config.instance_variable_get("@collections"), "Did not add collection") - end - - # Make sure we create a graph of scopes. - def test_newscope - config = mkconfig - graph = config.instance_variable_get("@graph") - assert_instance_of(Scope, config.topscope, "Did not create top scope") - assert_instance_of(GRATR::Digraph, graph, "Did not create graph") - - assert(graph.vertex?(config.topscope), "The top scope is not a vertex in the graph") - - # Now that we've got the top scope, create a new, subscope - subscope = nil - assert_nothing_raised("Could not create subscope") do - subscope = config.newscope - end - assert_instance_of(Scope, subscope, "Did not create subscope") - assert(graph.edge?(config.topscope, subscope), "An edge between top scope and subscope was not added") - - # Make sure a scope can find its parent. - assert(config.parent(subscope), "Could not look up parent scope on configuration") - assert_equal(config.topscope.object_id, config.parent(subscope).object_id, "Did not get correct parent scope from configuration") - assert_equal(config.topscope.object_id, subscope.parent.object_id, "Scope did not correctly retrieve its parent scope") - - # Now create another, this time specifying the parent scope - another = nil - assert_nothing_raised("Could not create subscope") do - another = config.newscope(subscope) - end - assert_instance_of(Scope, another, "Did not create second subscope") - assert(graph.edge?(subscope, another), "An edge between parent scope and second subscope was not added") - - # Make sure it can find its parent. - assert(config.parent(another), "Could not look up parent scope of second subscope on configuration") - assert_equal(subscope.object_id, config.parent(another).object_id, "Did not get correct parent scope of second subscope from configuration") - assert_equal(subscope.object_id, another.parent.object_id, "Second subscope did not correctly retrieve its parent scope") - - # And make sure both scopes show up in the right order in the search path - assert_equal([another.object_id, subscope.object_id, config.topscope.object_id], another.scope_path.collect { |p| p.object_id }, - "Did not get correct scope path") - end -end diff --git a/test/network/handler/node.rb b/test/network/handler/node.rb index c682929d9..02da9eef0 100755 --- a/test/network/handler/node.rb +++ b/test/network/handler/node.rb @@ -43,31 +43,342 @@ module NodeTesting def mk_searcher(name) searcher = Object.new searcher.extend(Node.node_source(name)) + searcher.meta_def(:newnode) do |name, *args| + SimpleNode.new(name, *args) + end + searcher + end + + def mk_node_source + @node_info = {} + @node_source = Node.newnode_source(:testing, :fact_merge => true) do + def nodesearch(key) + if info = @node_info[key] + SimpleNode.new(info) + else + nil + end + end + end + Puppet[:node_source] = "testing" + + cleanup { Node.rm_node_source(:testing) } end end class TestNodeInterface < Test::Unit::TestCase + include NodeTesting + def setup super + mk_node_source + end + + # Make sure that the handler includes the appropriate + # node source. + def test_initialize + # First try it when passing in the node source + handler = nil + assert_nothing_raised("Could not specify a node source") do + handler = Node.new(:Source => :testing) + end + assert(handler.metaclass.included_modules.include?(@node_source), "Handler did not include node source") + + # Now use the Puppet[:node_source] + Puppet[:node_source] = "testing" + assert_nothing_raised("Could not specify a node source") do + handler = Node.new() + end + assert(handler.metaclass.included_modules.include?(@node_source), "Handler did not include node source") + + # And make sure we throw an exception when an invalid node source is used + assert_raise(ArgumentError, "Accepted an invalid node source") do + handler = Node.new(:Source => "invalid") + end end - def teardown + # Make sure we can find and we cache a fact handler. + def test_fact_handler + handler = Node.new + fhandler = nil + assert_nothing_raised("Could not retrieve the fact handler") do + fhandler = handler.send(:fact_handler) + end + assert_instance_of(Puppet::Network::Handler::Facts, fhandler, "Did not get a fact handler back") + + # Now call it again, making sure we're caching the value. + fhandler2 = nil + assert_nothing_raised("Could not retrieve the fact handler") do + fhandler2 = handler.send(:fact_handler) + end + assert_instance_of(Puppet::Network::Handler::Facts, fhandler2, "Did not get a fact handler on the second run") + assert_equal(fhandler.object_id, fhandler2.object_id, "Did not cache fact handler") end - def test_node - raise "Failing, yo" + # Make sure we can get node facts from the fact handler. + def test_node_facts + # Check the case where we find the node. + handler = Node.new + fhandler = handler.send(:fact_handler) + fhandler.expects(:get).with("present").returns("a" => "b") + + result = nil + assert_nothing_raised("Could not get facts from fact handler") do + result = handler.send(:node_facts, "present") + end + assert_equal({"a" => "b"}, result, "Did not get correct facts back") + + # Now try the case where the fact handler knows nothing about our host + fhandler.expects(:get).with('missing').returns(nil) + result = nil + assert_nothing_raised("Could not get facts from fact handler when host is missing") do + result = handler.send(:node_facts, "missing") + end + assert_equal({}, result, "Did not get empty hash when no facts are known") end + # Test our simple shorthand + def test_newnode + SimpleNode.expects(:new).with("stuff") + handler = Node.new + handler.newnode("stuff") + end + + # Make sure we can build up the correct node names to search for + def test_node_names + handler = Node.new + + # Verify that the handler asks for the facts if we don't pass them in + handler.expects(:node_facts).with("testing").returns({}) + handler.send(:node_names, "testing") + + handler = Node.new + # Test it first with no parameters + assert_equal(%w{testing}, handler.send(:node_names, "testing"), "Node names did not default to an array including just the node name") + + # Now test it with a fully qualified name + assert_equal(%w{testing.domain.com testing}, handler.send(:node_names, "testing.domain.com"), + "Fully qualified names did not get turned into multiple names, longest first") + + # And try it with a short name + domain fact + assert_equal(%w{testing host.domain.com host}, handler.send(:node_names, "testing", "domain" => "domain.com", "hostname" => "host"), + "The domain fact was not used to build up an fqdn") + + # And with an fqdn + assert_equal(%w{testing host.domain.com host}, handler.send(:node_names, "testing", "fqdn" => "host.domain.com"), + "The fqdn was not used") + + # And make sure the fqdn beats the domain + assert_equal(%w{testing host.other.com host}, handler.send(:node_names, "testing", "domain" => "domain.com", "fqdn" => "host.other.com"), + "The domain was used in preference to the fqdn") + end + + # Make sure we can retrieve a whole node by name. + def test_details_when_we_find_nodes + handler = Node.new + + # Make sure we get the facts first + handler.expects(:node_facts).with("host").returns(:facts) + + # Find the node names + handler.expects(:node_names).with("host", :facts).returns(%w{a b c}) + + # Iterate across them + handler.expects(:nodesearch).with("a").returns(nil) + handler.expects(:nodesearch).with("b").returns(nil) + + # Create an example node to return + node = SimpleNode.new("host") + + # Make sure its source is set + node.expects(:source=).with(handler.source) + + # And make sure we actually get it back + handler.expects(:nodesearch).with("c").returns(node) + + handler.expects(:fact_merge?).returns(true) + + # Make sure we merge the facts with the node's parameters. + node.expects(:fact_merge).with(:facts) + + # Now call the method + result = nil + assert_nothing_raised("could not call 'details'") do + result = handler.details("host") + end + assert_equal(node, result, "Did not get correct node back") + end + + # But make sure we pass through to creating default nodes when appropriate. + def test_details_using_default_node + handler = Node.new + + # Make sure we get the facts first + handler.expects(:node_facts).with("host").returns(:facts) + + # Find the node names + handler.expects(:node_names).with("host", :facts).returns([]) + + # Create an example node to return + node = SimpleNode.new("host") + + # Make sure its source is set + node.expects(:source=).with(handler.source) + + # And make sure we actually get it back + handler.expects(:nodesearch).with("default").returns(node) + + # This time, have it return false + handler.expects(:fact_merge?).returns(false) + + # And because fact_merge was false, we don't merge them. + node.expects(:fact_merge).never + + # Now call the method + result = nil + assert_nothing_raised("could not call 'details'") do + result = handler.details("host") + end + assert_equal(node, result, "Did not get correct node back") + end + + # Make sure our handler behaves rationally when it comes to getting environment data. def test_environment - raise "still failing" + # What happens when we can't find the node + handler = Node.new + handler.expects(:details).with("fake").returns(nil) + + result = nil + assert_nothing_raised("Could not call 'Node.environment'") do + result = handler.environment("fake") + end + assert_nil(result, "Got an environment for a node we could not find") + + # Now for nodes we can find + handler = Node.new + node = SimpleNode.new("fake") + handler.expects(:details).with("fake").returns(node) + node.expects(:environment).returns("dev") + + result = nil + assert_nothing_raised("Could not call 'Node.environment'") do + result = handler.environment("fake") + end + assert_equal("dev", result, "Did not get environment back") end + # Make sure our handler behaves rationally when it comes to getting parameter data. def test_parameters - raise "still failing" + # What happens when we can't find the node + handler = Node.new + handler.expects(:details).with("fake").returns(nil) + + result = nil + assert_nothing_raised("Could not call 'Node.parameters'") do + result = handler.parameters("fake") + end + assert_nil(result, "Got parameters for a node we could not find") + + # Now for nodes we can find + handler = Node.new + node = SimpleNode.new("fake") + handler.expects(:details).with("fake").returns(node) + node.expects(:parameters).returns({"a" => "b"}) + + result = nil + assert_nothing_raised("Could not call 'Node.parameters'") do + result = handler.parameters("fake") + end + assert_equal({"a" => "b"}, result, "Did not get parameters back") end def test_classes - raise "still failing" + # What happens when we can't find the node + handler = Node.new + handler.expects(:details).with("fake").returns(nil) + + result = nil + assert_nothing_raised("Could not call 'Node.classes'") do + result = handler.classes("fake") + end + assert_nil(result, "Got classes for a node we could not find") + + # Now for nodes we can find + handler = Node.new + node = SimpleNode.new("fake") + handler.expects(:details).with("fake").returns(node) + node.expects(:classes).returns(%w{yay foo}) + + result = nil + assert_nothing_raised("Could not call 'Node.classes'") do + result = handler.classes("fake") + end + assert_equal(%w{yay foo}, result, "Did not get classes back") + end +end + +class TestSimpleNode < Test::Unit::TestCase + include NodeTesting + + # Make sure we get all the defaults correctly. + def test_simplenode_initialize + node = nil + assert_nothing_raised("could not create a node without classes or parameters") do + node = SimpleNode.new("testing") + end + assert_equal("testing", node.name, "Did not set name correctly") + assert_equal({}, node.parameters, "Node parameters did not default correctly") + assert_equal([], node.classes, "Node classes did not default correctly") + + # Now test it with values for both + params = {"a" => "b"} + classes = %w{one two} + assert_nothing_raised("could not create a node with classes and parameters") do + node = SimpleNode.new("testing", :parameters => params, :classes => classes) + end + assert_equal("testing", node.name, "Did not set name correctly") + assert_equal(params, node.parameters, "Node parameters did not get set correctly") + assert_equal(classes, node.classes, "Node classes did not get set correctly") + + # And make sure a single class gets turned into an array + assert_nothing_raised("could not create a node with a class as a string") do + node = SimpleNode.new("testing", :classes => "test") + end + assert_equal(%w{test}, node.classes, "A node class string was not converted to an array") + + # Make sure we get environments + assert_nothing_raised("could not create a node with an environment") do + node = SimpleNode.new("testing", :environment => "test") + end + assert_equal("test", node.environment, "Environment was not set") + + # Now make sure we get the default env + Puppet[:environment] = "prod" + assert_nothing_raised("could not create a node with no environment") do + node = SimpleNode.new("testing") + end + assert_equal("prod", node.environment, "Did not get default environment") + + # But that it stays nil if there's no default env set + Puppet[:environment] = "" + assert_nothing_raised("could not create a node with no environment and no default env") do + node = SimpleNode.new("testing") + end + assert_nil(node.environment, "Got a default env when none was set") + + end + + # Verify that the node source wins over facter. + def test_fact_merge + node = SimpleNode.new("yay", :parameters => {"a" => "one", "b" => "two"}) + + assert_nothing_raised("Could not merge parameters") do + node.fact_merge("b" => "three", "c" => "yay") + end + params = node.parameters + assert_equal("one", params["a"], "Lost nodesource parameters in parameter merge") + assert_equal("two", params["b"], "Overrode nodesource parameters in parameter merge") + assert_equal("yay", params["c"], "Did not get facts in parameter merge") end end @@ -87,12 +398,16 @@ class TestNodeSources < Test::Unit::TestCase cleanup do Node.rm_node_source(:testing) + assert(! Node.const_defined?("Testing"), "Did not remove constant") end end def test_external_node_source + source = Node.node_source(:external) + assert(source, "Could not find external node source") mapper = mk_node_mapper searcher = mk_searcher(:external) + assert(searcher.fact_merge?, "External node source does not merge facts") # Make sure it gives the right response assert_equal({'classes' => %w{apple1 apple2 apple3}, :parameters => {"one" => "apple1", "two" => "apple2"}}, @@ -157,7 +472,10 @@ class TestNodeSources < Test::Unit::TestCase # This can stay in the main test suite because it doesn't actually use ldapsearch, # it just overrides the method so it behaves as though it were hitting ldap. def test_ldap_nodesearch + source = Node.node_source(:ldap) + assert(source, "Could not find ldap node source") searcher = mk_searcher(:ldap) + assert(searcher.fact_merge?, "LDAP node source does not merge facts") nodetable = {} -- cgit From 65559af75e3da6522f4c3e952a73d80e0040609c Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Wed, 15 Aug 2007 13:55:55 -0500 Subject: Adding a "none" node source, which will be the default node source and will just return an empty node. --- test/network/handler/node.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'test') diff --git a/test/network/handler/node.rb b/test/network/handler/node.rb index 02da9eef0..37b63db69 100755 --- a/test/network/handler/node.rb +++ b/test/network/handler/node.rb @@ -529,6 +529,24 @@ class TestNodeSources < Test::Unit::TestCase assert_equal(%w{one two three four five}.sort, node.classes.sort, "node classes were not set correctly with the top node") assert_equal({"base" => "true", "center" => "boo", "master" => "far"}, node.parameters, "node parameters were not set correctly with the top node") end + + # Make sure we always get a node back from the 'none' nodesource. + def test_nodesource_none + source = Node.node_source(:none) + assert(source, "Could not find 'none' node source") + searcher = mk_searcher(:none) + assert(searcher.fact_merge?, "'none' node source does not merge facts") + + # Run a couple of node names through it + node = nil + %w{192.168.0.1 0:0:0:3:a:f host host.domain.com}.each do |name| + assert_nothing_raised("Could not create an empty node with name '%s'" % name) do + node = searcher.nodesearch(name) + end + assert_instance_of(SimpleNode, node, "Did not get a simple node back for %s" % name) + assert_equal(name, node.name, "Name was not set correctly") + end + end end class LdapNodeTest < PuppetTest::TestCase -- cgit From aabad8e1e262fb2f63fa4eef0f0e6fc00cc4b01f Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Wed, 15 Aug 2007 14:21:59 -0500 Subject: Adding the necessary name/ip fields to the node methods --- test/network/handler/node.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/network/handler/node.rb b/test/network/handler/node.rb index 37b63db69..9fad3f765 100755 --- a/test/network/handler/node.rb +++ b/test/network/handler/node.rb @@ -141,7 +141,7 @@ class TestNodeInterface < Test::Unit::TestCase def test_newnode SimpleNode.expects(:new).with("stuff") handler = Node.new - handler.newnode("stuff") + handler.send(:newnode, "stuff") end # Make sure we can build up the correct node names to search for -- cgit From 70dffdde70b60ae9e84b6ab2889f6b50fe6bed70 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Wed, 15 Aug 2007 16:31:44 -0500 Subject: The new configuration handler looks to be ready for usage. Now I just need to convert the interpreter to use SimpleNode objects, then continue with the Configuration object. --- test/network/handler/configuration.rb | 167 ++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100755 test/network/handler/configuration.rb (limited to 'test') diff --git a/test/network/handler/configuration.rb b/test/network/handler/configuration.rb new file mode 100755 index 000000000..7a505f5eb --- /dev/null +++ b/test/network/handler/configuration.rb @@ -0,0 +1,167 @@ +#!/usr/bin/env ruby + +$:.unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' +require 'puppet/network/handler/configuration' + +class TestHandlerConfiguration < Test::Unit::TestCase + include PuppetTest + + Config = Puppet::Network::Handler.handler(:configuration) + + # Check all of the setup stuff. + def test_initialize + config = nil + assert_nothing_raised("Could not create local config") do + config = Config.new(:Local => true) + end + + assert(config.local?, "Config is not considered local after being started that way") + end + + # Make sure we create the node handler when necessary. + def test_node_handler + config = Config.new + handler = nil + assert_nothing_raised("Could not create node handler") do + handler = config.send(:node_handler) + end + assert_instance_of(Puppet::Network::Handler.handler(:node), handler, "Did not create node handler") + + # Now make sure we get the same object back again + assert_equal(handler.object_id, config.send(:node_handler).object_id, "Did not cache node handler") + end + + # Test creation/returning of the interpreter + def test_interpreter + config = Config.new + + # First test the defaults + args = {} + config.instance_variable_set("@options", args) + config.expects(:create_interpreter).with(args).returns(:interp) + assert_equal(:interp, config.send(:interpreter), "Did not return the interpreter") + + # Now run it again and make sure we get the same thing + assert_equal(:interp, config.send(:interpreter), "Did not cache the interpreter") + end + + def test_create_interpreter + config = Config.new(:Local => false) + args = {} + + # Try it first with defaults. + Puppet::Parser::Interpreter.expects(:new).with(:Local => config.local?, :Manifest => Puppet[:manifest]).returns(:interp) + assert_equal(:interp, config.send(:create_interpreter, args), "Did not return the interpreter") + + # Now reset it and make sure a specified manifest passes through + file = tempfile + args[:Manifest] = file + Puppet::Parser::Interpreter.expects(:new).with(:Local => config.local?, :Manifest => file).returns(:interp) + assert_equal(:interp, config.send(:create_interpreter, args), "Did not return the interpreter") + + # And make sure the code does, too + args.delete(:Manifest) + args[:Code] = "yay" + Puppet::Parser::Interpreter.expects(:new).with(:Local => config.local?, :Code => "yay").returns(:interp) + assert_equal(:interp, config.send(:create_interpreter, args), "Did not return the interpreter") + end + + # Make sure node objects get appropriate data added to them. + def test_add_node_data + # First with no classes + config = Config.new + + fakenode = Object.new + # Set the server facts to something + config.instance_variable_set("@server_facts", :facts) + fakenode.expects(:fact_merge).with(:facts) + config.send(:add_node_data, fakenode) + + # Now try it with classes. + config.instance_variable_set("@options", {:Classes => %w{a b}}) + list = [] + fakenode = Object.new + fakenode.expects(:fact_merge).with(:facts) + fakenode.expects(:classes).returns(list).times(2) + config.send(:add_node_data, fakenode) + assert_equal(%w{a b}, list, "Did not add classes to node") + end + + def test_compile + config = Config.new + + # First do a local + node = Object.new + node.expects(:name).returns(:mynode) + + interp = Object.new + interp.expects(:compile).with(node).returns(:config) + config.expects(:interpreter).returns(interp) + + Puppet.expects(:notice) # The log message from benchmarking + + assert_equal(:config, config.send(:compile, node), "Did not return config") + + # Now try it non-local + config = Config.new(:Local => true) + + node = Object.new + node.expects(:name).returns(:mynode) + + interp = Object.new + interp.expects(:compile).with(node).returns(:config) + config.expects(:interpreter).returns(interp) + + assert_equal(:config, config.send(:compile, node), "Did not return config") + end + + def test_set_server_facts + config = Config.new + assert_nothing_raised("Could not call :set_server_facts") do + config.send(:set_server_facts) + end + facts = config.instance_variable_get("@server_facts") + %w{servername serverversion serverip}.each do |fact| + assert(facts.include?(fact), "Config did not set %s fact" % fact) + end + end + + def test_translate + # First do a local config + config = Config.new(:Local => true) + assert_equal(:plain, config.send(:translate, :plain), "Attempted to translate local config") + + # Now a non-local + config = Config.new(:Local => false) + obj = Object.new + yamld = Object.new + obj.expects(:to_yaml).with(:UseBlock => true).returns(yamld) + CGI.expects(:escape).with(yamld).returns(:translated) + assert_equal(:translated, config.send(:translate, obj), "Did not return translated config") + end + + # Check that we're storing the node freshness into the rails db. Hackilicious. + def test_update_node_freshness + # This is stupid. + config = Config.new + node = Object.new + node.expects(:name).returns(:hostname) + now = Object.new + Time.expects(:now).returns(now) + host = Object.new + host.expects(:last_freshcheck=).with(now) + host.expects(:save) + + # Only test the case where rails is there + Puppet[:storeconfigs] = true + Puppet.features.expects(:rails?).returns(true) + Puppet::Rails.expects(:connect) + Puppet::Rails::Host.expects(:find_or_create_by_name).with(:hostname).returns(host) + + config.send(:update_node_freshness, node) + + + end +end -- cgit From 901ae687eb75885c5b717b03f2d6667f5ed8ffb5 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Wed, 15 Aug 2007 16:32:06 -0500 Subject: Requiring mocha in all cases in the test tree --- test/lib/puppettest.rb | 1 + 1 file changed, 1 insertion(+) (limited to 'test') diff --git a/test/lib/puppettest.rb b/test/lib/puppettest.rb index 8b85966f5..5c385afb1 100755 --- a/test/lib/puppettest.rb +++ b/test/lib/puppettest.rb @@ -4,6 +4,7 @@ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) $LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '../../lib'))) require 'puppet' +require 'mocha' require 'test/unit' # Yay; hackish but it works -- cgit From 297dabb63744f8ad468ee4bf5caa54a75754ceee Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Wed, 15 Aug 2007 16:56:05 -0500 Subject: Refactoring a small part of the interface between the configuration handler and the interpreter. --- test/network/handler/configuration.rb | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/network/handler/configuration.rb b/test/network/handler/configuration.rb index 7a505f5eb..525db5e6a 100755 --- a/test/network/handler/configuration.rb +++ b/test/network/handler/configuration.rb @@ -143,7 +143,7 @@ class TestHandlerConfiguration < Test::Unit::TestCase end # Check that we're storing the node freshness into the rails db. Hackilicious. - def test_update_node_freshness + def test_update_node_check # This is stupid. config = Config.new node = Object.new @@ -160,8 +160,30 @@ class TestHandlerConfiguration < Test::Unit::TestCase Puppet::Rails.expects(:connect) Puppet::Rails::Host.expects(:find_or_create_by_name).with(:hostname).returns(host) - config.send(:update_node_freshness, node) + config.send(:update_node_check, node) + end + def test_version + # First try the case where we can't look up the node + config = Config.new + handler = Object.new + handler.expects(:details).with(:client).returns(false) + config.expects(:node_handler).returns(handler) + interp = Object.new + interp.expects(:configuration_version).returns(:version) + config.expects(:interpreter).returns(interp) + assert_equal(:version, config.version(:client), "Did not return configuration version") + # And then when we find the node. + config = Config.new + node = Object.new + handler = Object.new + handler.expects(:details).with(:client).returns(node) + config.expects(:update_node_check).with(node) + config.expects(:node_handler).returns(handler) + interp = Object.new + interp.expects(:configuration_version).returns(:version) + config.expects(:interpreter).returns(interp) + assert_equal(:version, config.version(:client), "Did not return configuration version") end end -- cgit From a9539548d957304a03aa8bdc61c06793228f57c0 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Wed, 15 Aug 2007 17:05:49 -0500 Subject: Keeping the node names in the node object, so that they are available to the interpreter --- test/network/handler/node.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'test') diff --git a/test/network/handler/node.rb b/test/network/handler/node.rb index 9fad3f765..9902c2dd1 100755 --- a/test/network/handler/node.rb +++ b/test/network/handler/node.rb @@ -193,6 +193,9 @@ class TestNodeInterface < Test::Unit::TestCase # Make sure its source is set node.expects(:source=).with(handler.source) + # And that the names are retained + node.expects(:names=).with(%w{a b c}) + # And make sure we actually get it back handler.expects(:nodesearch).with("c").returns(node) -- cgit From 1527f4a615f9c429e90becd90f9ed1e8c1e83249 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Wed, 15 Aug 2007 17:18:43 -0500 Subject: Adding node caching, so that node sources are not spammed during file serving and such --- test/network/handler/node.rb | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/test/network/handler/node.rb b/test/network/handler/node.rb index 9902c2dd1..745c7470e 100755 --- a/test/network/handler/node.rb +++ b/test/network/handler/node.rb @@ -66,7 +66,7 @@ module NodeTesting end end -class TestNodeInterface < Test::Unit::TestCase +class TestNodeHandler < Test::Unit::TestCase include NodeTesting def setup @@ -318,6 +318,28 @@ class TestNodeInterface < Test::Unit::TestCase end assert_equal(%w{yay foo}, result, "Did not get classes back") end + + # We reuse the filetimeout for the node caching timeout. + def test_node_caching + handler = Node.new + + node = Object.new + node.metaclass.instance_eval do + attr_accessor :time, :name + end + node.time = Time.now + node.name = "yay" + + # Make sure caching works normally + assert_nothing_raised("Could not cache node") do + handler.send(:cache, node) + end + assert_equal(node.object_id, handler.send(:cached?, "yay").object_id, "Did not get node back from the cache") + + # Now set the node's time to be a long time ago + node.time = Time.now - 50000 + assert(! handler.send(:cached?, "yay"), "Timed-out node was returned from cache") + end end class TestSimpleNode < Test::Unit::TestCase @@ -332,6 +354,7 @@ class TestSimpleNode < Test::Unit::TestCase assert_equal("testing", node.name, "Did not set name correctly") assert_equal({}, node.parameters, "Node parameters did not default correctly") assert_equal([], node.classes, "Node classes did not default correctly") + assert_instance_of(Time, node.time, "Did not set the creation time") # Now test it with values for both params = {"a" => "b"} -- cgit From a846ea900f9fa7a2baaa4fbd0742f080e7fd7a04 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Thu, 16 Aug 2007 21:21:40 -0500 Subject: The new parser configuration object works now, but the rest of the compiling process is hosed (although the parser itself should still be fine). The configuration object is unifying a lot of work that was scattered around either the interpreter or the scopes, and it simplifies the whole system. However, its new simplicity has made the complexity of the rest of the system that much more apparent, and I am resolved to fixing the system rather than hacking it sufficiently to just make it work. --- test/language/configuration.rb | 627 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 606 insertions(+), 21 deletions(-) (limited to 'test') diff --git a/test/language/configuration.rb b/test/language/configuration.rb index 4cbba8063..aafdf8356 100755 --- a/test/language/configuration.rb +++ b/test/language/configuration.rb @@ -14,35 +14,40 @@ class TestConfiguration < Test::Unit::TestCase Config = Puppet::Parser::Configuration Scope = Puppet::Parser::Scope + Node = Puppet::Network::Handler.handler(:node) + SimpleNode = Node::SimpleNode - def mkconfig - Config.new(:host => "foo", :interpreter => "interp") + def mknode(name = "foo") + @node = SimpleNode.new(name) end - def test_initialize - # Make sure we get an error if we don't send an interpreter - assert_raise(ArgumentError, "Did not fail when missing host") do - Config.new(:interpreter => "yay" ) - end - assert_raise(ArgumentError, "Did not fail when missing interp") do - Config.new(:host => "foo") - end + def mkparser + # This should mock an interpreter + @parser = mock 'parser' + end + + def mkconfig(options = {}) + @config = Config.new(mknode, mkparser, options) + end - # Now check the defaults + def test_initialize config = nil assert_nothing_raised("Could not init config with all required options") do - config = Config.new(:host => "foo", :interpreter => "interp") + config = Config.new("foo", "parser") end - assert_equal("foo", config.host, "Did not set host correctly") - assert_equal("interp", config.interpreter, "Did not set interpreter correctly") - assert_equal({}, config.facts, "Did not set default facts") + assert_equal("foo", config.node, "Did not set node correctly") + assert_equal("parser", config.parser, "Did not set parser correctly") - # Now make a new one with facts, to make sure the facts get set appropriately - assert_nothing_raised("Could not init config with all required options") do - config = Config.new(:host => "foo", :interpreter => "interp", :facts => {"a" => "b"}) + # We're not testing here whether we call initvars, because it's too difficult to + # mock. + + # Now try it with some options + assert_nothing_raised("Could not init config with extra options") do + config = Config.new("foo", "parser", :ast_nodes => false) end - assert_equal({"a" => "b"}, config.facts, "Did not set facts") + + assert_equal(false, config.ast_nodes?, "Did not set ast_nodes? correctly") end def test_initvars @@ -50,14 +55,19 @@ class TestConfiguration < Test::Unit::TestCase [:class_scopes, :resource_table, :exported_resources, :resource_overrides].each do |table| assert_instance_of(Hash, config.send(:instance_variable_get, "@#{table}"), "Did not set %s table correctly" % table) end + assert_instance_of(Scope, config.topscope, "Did not create a topscope") + graph = config.instance_variable_get("@scope_graph") + assert_instance_of(GRATR::Digraph, graph, "Did not create scope graph") + assert(graph.vertex?(config.topscope), "Did not add top scope as a vertex in the graph") end # Make sure we store and can retrieve references to classes and their scopes. def test_class_set_and_class_scope - klass = Object.new + klass = mock 'ast_class' klass.expects(:classname).returns("myname") config = mkconfig + config.expects(:tag).with("myname") assert_nothing_raised("Could not set class") do config.class_set "myname", "myscope" @@ -92,7 +102,7 @@ class TestConfiguration < Test::Unit::TestCase # Make sure we create a graph of scopes. def test_newscope config = mkconfig - graph = config.instance_variable_get("@graph") + graph = config.instance_variable_get("@scope_graph") assert_instance_of(Scope, config.topscope, "Did not create top scope") assert_instance_of(GRATR::Digraph, graph, "Did not create graph") @@ -128,4 +138,579 @@ class TestConfiguration < Test::Unit::TestCase assert_equal([another.object_id, subscope.object_id, config.topscope.object_id], another.scope_path.collect { |p| p.object_id }, "Did not get correct scope path") end + + # The heart of the action. + def test_compile + config = mkconfig + [:set_node_parameters, :evaluate_main, :evaluate_ast_nodes, :evaluate_classes, :evaluate_generators, :fail_on_unevaluated, :finish].each do |method| + config.expects(method) + end + config.expects(:extract).returns(:config) + assert_equal(:config, config.compile, "Did not return the results of the extraction") + end + + # Test setting the node's parameters into the top scope. + def test_set_node_parameters + config = mkconfig + @node.parameters = {"a" => "b", "c" => "d"} + scope = config.topscope + @node.parameters.each do |param, value| + scope.expects(:setvar).with(param, value) + end + + assert_nothing_raised("Could not call 'set_node_parameters'") do + config.send(:set_node_parameters) + end + end + + # Test that we can evaluate the main class, which is the one named "" in namespace + # "". + def test_evaluate_main + config = mkconfig + main = mock 'main_class' + config.topscope.expects(:source=).with(main) + main.expects(:safeevaluate).with(:scope => config.topscope, :nosubscope => true) + @parser.expects(:findclass).with("", "").returns(main) + + assert_nothing_raised("Could not call evaluate_main") do + config.send(:evaluate_main) + end + end + + # Make sure we either don't look for nodes, or that we find and evaluate the right object. + def test_evaluate_ast_node + # First try it with ast_nodes disabled + config = mkconfig :ast_nodes => false + config.expects(:ast_nodes?).returns(false) + config.parser.expects(:nodes).never + + assert_nothing_raised("Could not call evaluate_ast_node when ast nodes are disabled") do + config.send(:evaluate_ast_node) + end + + # Now try it with them enabled, but no node found. + nodes = mock 'node_hash' + config = mkconfig :ast_nodes => true + config.expects(:ast_nodes?).returns(true) + config.parser.expects(:nodes).returns(nodes).times(4) + + # Set some names for our test + @node.names = %w{a b c} + nodes.expects(:[]).with("a").returns(nil) + nodes.expects(:[]).with("b").returns(nil) + nodes.expects(:[]).with("c").returns(nil) + + # It should check this last, of course. + nodes.expects(:[]).with("default").returns(nil) + + # And make sure the lack of a node throws an exception + assert_raise(Puppet::ParseError, "Did not fail when we couldn't find an ast node") do + config.send(:evaluate_ast_node) + end + + # Finally, make sure it works dandily when we have a node + nodes = mock 'hash' + config = mkconfig :ast_nodes => true + config.expects(:ast_nodes?).returns(true) + config.parser.expects(:nodes).returns(nodes).times(3) + + node = mock 'node' + node.expects(:safeevaluate).with(:scope => config.topscope) + # Set some names for our test + @node.names = %w{a b c} + nodes.expects(:[]).with("a").returns(nil) + nodes.expects(:[]).with("b").returns(nil) + nodes.expects(:[]).with("c").returns(node) + nodes.expects(:[]).with("default").never + + # And make sure the lack of a node throws an exception + assert_nothing_raised("Failed when a node was found") do + config.send(:evaluate_ast_node) + end + + # Lastly, check when we actually find the default. + nodes = mock 'hash' + config = mkconfig :ast_nodes => true + config.expects(:ast_nodes?).returns(true) + config.parser.expects(:nodes).returns(nodes).times(4) + + node = mock 'node' + node.expects(:safeevaluate).with(:scope => config.topscope) + # Set some names for our test + @node.names = %w{a b c} + nodes.expects(:[]).with("a").returns(nil) + nodes.expects(:[]).with("b").returns(nil) + nodes.expects(:[]).with("c").returns(nil) + nodes.expects(:[]).with("default").returns(node) + + # And make sure the lack of a node throws an exception + assert_nothing_raised("Failed when a node was found") do + config.send(:evaluate_ast_node) + end + end + + # Make sure our config object handles tags appropriately. + def test_tags + config = mkconfig + config.send(:tag, "one") + assert_equal(%w{one}, config.send(:tags), "Did not add tag") + + config.send(:tag, "two", "three") + assert_equal(%w{one two three}, config.send(:tags), "Did not add new tags") + + config.send(:tag, "two") + assert_equal(%w{one two three}, config.send(:tags), "Allowed duplicate tag") + end + + def test_evaluate_classes + config = mkconfig + classes = { + "one" => mock('class one'), + "three" => mock('class three') + } + + classes.each do |name, obj| + config.parser.expects(:findclass).with("", name).returns(obj) + obj.expects(:safeevaluate).with(:scope => config.topscope) + end + %w{two four}.each do |name| + config.parser.expects(:findclass).with("", name).returns(nil) + end + + config.expects(:tag).with("two") + config.expects(:tag).with("four") + + @node.classes = %w{one two three four} + assert_nothing_raised("could not call evaluate_classes") do + config.send(:evaluate_classes) + end + end + + def test_evaluate_collections + config = mkconfig + + colls = [] + + # Make sure we return false when there's nothing there. + assert(! config.send(:evaluate_collections), "Returned true when there were no collections") + + # And when the collections fail to evaluate. + colls << mock("coll1-false") + colls << mock("coll2-false") + colls.each { |c| c.expects(:evaluate).returns(false) } + + config.instance_variable_set("@collections", colls) + assert(! config.send(:evaluate_collections), "Returned true when collections both evaluated nothing") + + # Now have one of the colls evaluate + colls.clear + colls << mock("coll1-one-true") + colls << mock("coll2-one-true") + colls[0].expects(:evaluate).returns(true) + colls[1].expects(:evaluate).returns(false) + assert(config.send(:evaluate_collections), "Did not return true when one collection evaluated true") + + # And have them both eval true + colls.clear + colls << mock("coll1-both-true") + colls << mock("coll2-both-true") + colls[0].expects(:evaluate).returns(true) + colls[1].expects(:evaluate).returns(true) + assert(config.send(:evaluate_collections), "Did not return true when both collections evaluated true") + end + + def test_unevaluated_resources + config = mkconfig + resources = {} + config.instance_variable_set("@resource_table", resources) + + # First test it when the table is empty + assert_nil(config.send(:unevaluated_resources), "Somehow found unevaluated resources in an empty table") + + # Then add a builtin resources + resources["one"] = mock("builtin only") + resources["one"].expects(:builtin?).returns(true) + assert_nil(config.send(:unevaluated_resources), "Considered a builtin resource unevaluated") + + # And do both builtin and non-builtin but already evaluated + resources.clear + resources["one"] = mock("builtin (with eval)") + resources["one"].expects(:builtin?).returns(true) + resources["two"] = mock("evaled (with builtin)") + resources["two"].expects(:builtin?).returns(false) + resources["two"].expects(:evaluated?).returns(true) + assert_nil(config.send(:unevaluated_resources), "Considered either a builtin or evaluated resource unevaluated") + + # Now a single unevaluated resource. + resources.clear + resources["one"] = mock("unevaluated") + resources["one"].expects(:builtin?).returns(false) + resources["one"].expects(:evaluated?).returns(false) + assert_equal([resources["one"]], config.send(:unevaluated_resources), "Did not find unevaluated resource") + + # With two uneval'ed resources, and an eval'ed one thrown in + resources.clear + resources["one"] = mock("unevaluated one") + resources["one"].expects(:builtin?).returns(false) + resources["one"].expects(:evaluated?).returns(false) + resources["two"] = mock("unevaluated two") + resources["two"].expects(:builtin?).returns(false) + resources["two"].expects(:evaluated?).returns(false) + resources["three"] = mock("evaluated") + resources["three"].expects(:builtin?).returns(false) + resources["three"].expects(:evaluated?).returns(true) + + result = config.send(:unevaluated_resources) + %w{one two}.each do |name| + assert(result.include?(resources[name]), "Did not find %s in the unevaluated list" % name) + end + end + + def test_evaluate_definitions + # First try the case where there's nothing to return + config = mkconfig + config.expects(:unevaluated_resources).returns(nil) + + assert_nothing_raised("Could not test for unevaluated resources") do + assert(! config.send(:evaluate_definitions), "evaluate_definitions returned true when no resources were evaluated") + end + + # Now try it with resources left to evaluate + resources = [] + res1 = mock("resource1") + res1.expects(:evaluate) + res2 = mock("resource2") + res2.expects(:evaluate) + resources << res1 << res2 + config = mkconfig + config.expects(:unevaluated_resources).returns(resources) + + assert_nothing_raised("Could not test for unevaluated resources") do + assert(config.send(:evaluate_definitions), "evaluate_definitions returned false when resources were evaluated") + end + end + + def test_evaluate_generators + # First try the case where we have nothing to do + config = mkconfig + config.expects(:evaluate_definitions).returns(false) + config.expects(:evaluate_collections).returns(false) + + assert_nothing_raised("Could not call :eval_iterate") do + config.send(:evaluate_generators) + end + + # FIXME I could not get this test to work, but the code is short + # enough that I'm ok with it. + # It's important that collections are evaluated before definitions, + # so make sure that's the case by verifying that collections get tested + # twice but definitions only once. + #config = mkconfig + #config.expects(:evaluate_collections).returns(true).returns(false) + #config.expects(:evaluate_definitions).returns(false) + #config.send(:eval_iterate) + end + + def test_store + config = mkconfig + Puppet.features.expects(:rails?).returns(true) + Puppet::Rails.expects(:connect) + + args = {:name => "yay"} + config.expects(:store_to_active_record).with(args) + config.send(:store, args) + end + + def test_store_to_active_record + config = mkconfig + args = {:name => "yay"} + Puppet::Rails::Host.stubs(:transaction).yields + Puppet::Rails::Host.expects(:store).with(args) + config.send(:store_to_active_record, args) + end + + # Make sure that 'finish' gets called on all of our resources. + def test_finish + config = mkconfig + table = config.instance_variable_get("@resource_table") + + # Add a resource that does respond to :finish + yep = mock("finisher") + yep.expects(:respond_to?).with(:finish).returns(true) + yep.expects(:finish) + table["yep"] = yep + + # And one that does not + dnf = mock("dnf") + dnf.expects(:respond_to?).with(:finish).returns(false) + table["dnf"] = dnf + + config.send(:finish) + end + + def test_extract + config = mkconfig + config.expects(:extraction_format).returns(:whatever) + config.expects(:extract_to_whatever).returns(:result) + assert_equal(:result, config.send(:extract), "Did not return extraction result as the method result") + end + + # We want to make sure that the scope and resource graphs translate correctly + def test_extract_to_transportable_simple + # Start with a really simple graph -- one scope, one resource. + config = mkconfig + resources = config.instance_variable_get("@resource_graph") + scopes = config.instance_variable_get("@scope_graph") + + # Get rid of the topscope + scopes.vertices.each { |v| scopes.remove_vertex!(v) } + + scope = mock("scope") + scope.expects(:to_trans).returns([]) + scopes.add_vertex! scope + + # The topscope is the key to picking out the top of the graph. + config.instance_variable_set("@topscope", scope) + + resource = mock "resource" + resource.expects(:to_trans).returns(:resource) + resources.add_edge! scope, resource + + result = nil + assert_nothing_raised("Could not extract transportable configuration") do + result = config.send :extract_to_transportable + end + assert_equal([:resource], result, "Did not translate simple configuration correctly") + end + + def test_extract_to_transportable_complex + # Now try it with a more complicated graph -- a three tier graph, each tier + # having a scope and a resource. + config = mkconfig + resources = config.instance_variable_get("@resource_graph") + scopes = config.instance_variable_get("@scope_graph") + + # Get rid of the topscope + scopes.vertices.each { |v| scopes.remove_vertex!(v) } + + fakebucket = Class.new(Array) do + attr_accessor :name + def initialize(n) + @name = n + end + end + + # Create our scopes. + top = mock("top") + top.expects(:to_trans).returns(fakebucket.new("top")) + # The topscope is the key to picking out the top of the graph. + config.instance_variable_set("@topscope", top) + middle = mock("middle") + middle.expects(:to_trans).returns(fakebucket.new("middle")) + scopes.add_edge! top, middle + bottom = mock("bottom") + bottom.expects(:to_trans).returns(fakebucket.new("bottom")) + scopes.add_edge! middle, bottom + + topres = mock "topres" + topres.expects(:to_trans).returns(:topres) + resources.add_edge! top, topres + + midres = mock "midres" + midres.expects(:to_trans).returns(:midres) + resources.add_edge! middle, midres + + botres = mock "botres" + botres.expects(:to_trans).returns(:botres) + resources.add_edge! bottom, botres + + result = nil + assert_nothing_raised("Could not extract transportable configuration") do + result = config.send :extract_to_transportable + end + assert_equal([[[:botres], :midres], :topres], result, "Did not translate medium configuration correctly") + end + + def test_verify_uniqueness + config = mkconfig + + resources = config.instance_variable_get("@resource_table") + resource = mock("noconflict") + resource.expects(:ref).returns("File[yay]") + assert_nothing_raised("Raised an exception when there should have been no conflict") do + config.send(:verify_uniqueness, resource) + end + + # Now try the case where our type is isomorphic + resources["thing"] = true + + isoconflict = mock("isoconflict") + isoconflict.expects(:ref).returns("thing") + isoconflict.expects(:type).returns("testtype") + faketype = mock("faketype") + faketype.expects(:isomorphic?).returns(false) + faketype.expects(:name).returns("whatever") + Puppet::Type.expects(:type).with("testtype").returns(faketype) + assert_nothing_raised("Raised an exception when was a conflict in non-isomorphic types") do + config.send(:verify_uniqueness, isoconflict) + end + + # Now test for when we actually have an exception + initial = mock("initial") + resources["thing"] = initial + initial.expects(:file).returns(false) + + conflict = mock("conflict") + conflict.expects(:ref).returns("thing").times(2) + conflict.expects(:type).returns("conflict") + conflict.expects(:file).returns(false) + conflict.expects(:line).returns(false) + + faketype = mock("faketype") + faketype.expects(:isomorphic?).returns(true) + Puppet::Type.expects(:type).with("conflict").returns(faketype) + assert_raise(Puppet::ParseError, "Did not fail when two isomorphic resources conflicted") do + config.send(:verify_uniqueness, conflict) + end + end + + def test_store_resource + # Run once when there's no conflict + config = mkconfig + table = config.instance_variable_get("@resource_table") + resource = mock("resource") + resource.expects(:ref).returns("yay") + config.expects(:verify_uniqueness).with(resource) + scope = mock("scope") + + graph = config.instance_variable_get("@resource_graph") + graph.expects(:add_edge!).with(scope, resource) + + assert_nothing_raised("Could not store resource") do + config.store_resource(scope, resource) + end + assert_equal(resource, table["yay"], "Did not store resource in table") + + # Now for conflicts + config = mkconfig + table = config.instance_variable_get("@resource_table") + resource = mock("resource") + config.expects(:verify_uniqueness).with(resource).raises(ArgumentError) + + assert_raise(ArgumentError, "Did not raise uniqueness exception") do + config.store_resource(scope, resource) + end + assert(table.empty?, "Conflicting resource was stored in table") + end + + def test_fail_on_unevaluated + config = mkconfig + config.expects(:fail_on_unevaluated_overrides) + config.expects(:fail_on_unevaluated_resource_collections) + config.send :fail_on_unevaluated + end + + def test_store_override + # First test the case when the resource is not present. + config = mkconfig + overrides = config.instance_variable_get("@resource_overrides") + override = Object.new + override.expects(:ref).returns(:myref).times(2) + override.expects(:override=).with(true) + + assert_nothing_raised("Could not call store_override") do + config.store_override(override) + end + assert_instance_of(Array, overrides[:myref], "Overrides table is not a hash of arrays") + assert_equal(override, overrides[:myref][0], "Did not store override in appropriately named array") + + # And when the resource already exists. + resource = mock 'resource' + resources = config.instance_variable_get("@resource_table") + resources[:resref] = resource + + override = mock 'override' + resource.expects(:merge).with(override) + override.expects(:override=).with(true) + override.expects(:ref).returns(:resref) + assert_nothing_raised("Could not call store_override when the resource already exists.") do + config.store_override(override) + end + end + + def test_resource_overrides + config = mkconfig + overrides = config.instance_variable_get("@resource_overrides") + overrides[:test] = :yay + resource = mock 'resource' + resource.expects(:ref).returns(:test) + + assert_equal(:yay, config.resource_overrides(resource), "Did not return overrides from table") + end + + def test_fail_on_unevaluated_resource_collections + config = mkconfig + collections = config.instance_variable_get("@collections") + + # Make sure we're fine when the list is empty + assert_nothing_raised("Failed when no collections were present") do + config.send :fail_on_unevaluated_resource_collections + end + + # And that we're fine when we've got collections but with no resources + collections << mock('coll') + collections[0].expects(:resources).returns(nil) + assert_nothing_raised("Failed when no resource collections were present") do + config.send :fail_on_unevaluated_resource_collections + end + + # But that we do fail when we've got resource collections left. + collections.clear + + # return both an array and a string, because that's tested internally + collections << mock('coll returns one') + collections[0].expects(:resources).returns(:something) + + collections << mock('coll returns many') + collections[1].expects(:resources).returns([:one, :two]) + + assert_raise(Puppet::ParseError, "Did not fail on unevaluated resource collections") do + config.send :fail_on_unevaluated_resource_collections + end + end + + def test_fail_on_unevaluated_overrides + config = mkconfig + overrides = config.instance_variable_get("@resource_overrides") + + # Make sure we're fine when the list is empty + assert_nothing_raised("Failed when no collections were present") do + config.send :fail_on_unevaluated_overrides + end + + # But that we fail if there are any overrides left in the table. + overrides[:yay] = [] + overrides[:foo] = [] + overrides[:bar] = [mock("override")] + overrides[:bar][0].expects(:ref).returns("yay") + assert_raise(Puppet::ParseError, "Failed to fail when overrides remain") do + config.send :fail_on_unevaluated_overrides + end + end + + def test_find_resource + config = mkconfig + resources = config.instance_variable_get("@resource_table") + + assert_nothing_raised("Could not call findresource when the resource table was empty") do + assert_nil(config.findresource("yay", "foo"), "Returned a non-existent resource") + assert_nil(config.findresource("yay[foo]"), "Returned a non-existent resource") + end + + resources["Foo[bar]"] = :yay + assert_nothing_raised("Could not call findresource when the resource table was not empty") do + assert_equal(:yay, config.findresource("foo", "bar"), "Returned a non-existent resource") + assert_equal(:yay, config.findresource("Foo[bar]"), "Returned a non-existent resource") + end + end end -- cgit From 6467c21e15b8a28e627d1395f76fe8f42ee77d70 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Mon, 20 Aug 2007 13:28:40 -0500 Subject: The first pass where at least all of the snippet tests pass. I have unfortunately had to stop being so assiduous in my rewriting of tests, but I am in too much of a time crunch to do this "right". The basic structure is definitely in place, though, and from here it is a question of making the rest of the tests work and hopefully writing some sufficient new tests, rather than making the code itself work. --- test/language/ast/component.rb | 12 +- test/language/configuration.rb | 16 +- test/language/interpreter.rb | 156 +----------- test/language/parser.rb | 17 ++ test/language/resource.rb | 425 ++++++++++++++++----------------- test/language/scope.rb | 250 ++++++++----------- test/lib/puppettest/parsertesting.rb | 21 +- test/lib/puppettest/resourcetesting.rb | 46 ++-- test/network/handler/master.rb | 74 ------ 9 files changed, 382 insertions(+), 635 deletions(-) (limited to 'test') diff --git a/test/language/ast/component.rb b/test/language/ast/component.rb index 40543e9ab..13cf60857 100755 --- a/test/language/ast/component.rb +++ b/test/language/ast/component.rb @@ -17,10 +17,10 @@ class TestASTComponent < Test::Unit::TestCase AST = Puppet::Parser::AST def test_component - interp, scope, source = mkclassframing + parser, scope, source = mkclassframing # Create a new definition - klass = interp.newdefine "yayness", + klass = parser.newdefine "yayness", :arguments => [["owner", stringobj("nobody")], %w{mode}], :code => AST::ASTArray.new( :children => [resourcedef("file", "/tmp/$name", @@ -90,7 +90,7 @@ class TestASTComponent < Test::Unit::TestCase # #539 - definitions should support both names and titles def test_names_and_titles - interp, scope, source = mkclassframing + parser, scope, source = mkclassframing [ {:name => "one", :title => "two"}, @@ -98,7 +98,7 @@ class TestASTComponent < Test::Unit::TestCase ].each_with_index do |hash, i| # Create a definition that uses both name and title - klass = interp.newdefine "yayness%s" % i + klass = parser.newdefine "yayness%s" % i subscope = klass.subscope(scope, "yayness%s" % i) @@ -133,8 +133,8 @@ class TestASTComponent < Test::Unit::TestCase # 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 - interp = mkinterp - klass = interp.newclass("one::two") + parser = mkparser + klass = parser.newclass("one::two") assert_equal("one::two", klass.classname, "Class did not get fully qualified class name") end diff --git a/test/language/configuration.rb b/test/language/configuration.rb index aafdf8356..688782f7b 100755 --- a/test/language/configuration.rb +++ b/test/language/configuration.rb @@ -27,7 +27,12 @@ class TestConfiguration < Test::Unit::TestCase end def mkconfig(options = {}) - @config = Config.new(mknode, mkparser, options) + if node = options[:node] + options.delete(:node) + else + node = mknode + end + @config = Config.new(node, mkparser, options) end def test_initialize @@ -111,7 +116,7 @@ class TestConfiguration < Test::Unit::TestCase # Now that we've got the top scope, create a new, subscope subscope = nil assert_nothing_raised("Could not create subscope") do - subscope = config.newscope + subscope = config.newscope(config.topscope) end assert_instance_of(Scope, subscope, "Did not create subscope") assert(graph.edge?(config.topscope, subscope), "An edge between top scope and subscope was not added") @@ -121,11 +126,12 @@ class TestConfiguration < Test::Unit::TestCase assert_equal(config.topscope.object_id, config.parent(subscope).object_id, "Did not get correct parent scope from configuration") assert_equal(config.topscope.object_id, subscope.parent.object_id, "Scope did not correctly retrieve its parent scope") - # Now create another, this time specifying the parent scope + # Now create another, this time specifying options another = nil assert_nothing_raised("Could not create subscope") do - another = config.newscope(subscope) + another = config.newscope(subscope, :name => "testing") end + assert_equal("testing", another.name, "did not set scope option correctly") assert_instance_of(Scope, another, "Did not create second subscope") assert(graph.edge?(subscope, another), "An edge between parent scope and second subscope was not added") @@ -142,7 +148,7 @@ class TestConfiguration < Test::Unit::TestCase # The heart of the action. def test_compile config = mkconfig - [:set_node_parameters, :evaluate_main, :evaluate_ast_nodes, :evaluate_classes, :evaluate_generators, :fail_on_unevaluated, :finish].each do |method| + [:set_node_parameters, :evaluate_main, :evaluate_ast_node, :evaluate_classes, :evaluate_generators, :fail_on_unevaluated, :finish].each do |method| config.expects(method) end config.expects(:extract).returns(:config) diff --git a/test/language/interpreter.rb b/test/language/interpreter.rb index 070e2e77e..6b9aa7258 100755 --- a/test/language/interpreter.rb +++ b/test/language/interpreter.rb @@ -20,7 +20,6 @@ class TestInterpreter < PuppetTest::TestCase include PuppetTest::ParserTesting include PuppetTest::ResourceTesting AST = Puppet::Parser::AST - NodeDef = Puppet::Parser::Interpreter::NodeDef # create a simple manifest that uses nodes to create a file def mknodemanifest(node, file) @@ -34,23 +33,13 @@ class TestInterpreter < PuppetTest::TestCase return [file, createdfile] end - def test_simple - file = tempfile() - File.open(file, "w") { |f| - f.puts "file { \"/etc\": owner => root }" - } - assert_nothing_raised { - Puppet::Parser::Interpreter.new(:Manifest => file) - } - end - def test_reloadfiles - hostname = Facter["hostname"].value + node = mknode(Facter["hostname"].value) file = tempfile() # Create a first version - createdfile = mknodemanifest(hostname, file) + createdfile = mknodemanifest(node.name, file) interp = nil assert_nothing_raised { @@ -59,61 +48,21 @@ class TestInterpreter < PuppetTest::TestCase config = nil assert_nothing_raised { - config = interp.run(hostname, {}) + config = interp.compile(node) } - sleep(1) + Puppet[:filetimeout] = -5 # Now create a new file - createdfile = mknodemanifest(hostname, file) + createdfile = mknodemanifest(node.name, file) newconfig = nil assert_nothing_raised { - newconfig = interp.run(hostname, {}) + newconfig = interp.compile(node) } assert(config != newconfig, "Configs are somehow the same") end - # Make sure searchnode behaves as we expect. - def test_nodesearch - # We use two sources here to catch a weird bug where the default - # node is used if the host isn't in the first source. - interp = mkinterp - - # Make some nodes - names = %w{node1 node2 node2.domain.com} - interp.newnode names - interp.newnode %w{default} - - nodes = {} - # Make sure we can find them all, using the direct method - names.each do |name| - nodes[name] = interp.nodesearch_code(name) - assert(nodes[name], "Could not find %s" % name) - nodes[name].file = __FILE__ - end - - # Now let's try it with the nodesearch method - names.each do |name| - node = interp.nodesearch(name) - assert(node, "Could not find #{name} via nodesearch") - end - - # Make sure we find the default node when we search for nonexistent nodes - assert_nothing_raised do - default = interp.nodesearch("nosuchnode") - assert(default, "Did not find default node") - assert_equal("default", default.classname) - end - - # Now make sure the longest match always wins - node = interp.nodesearch(*%w{node2 node2.domain.com}) - - assert(node, "Did not find node2") - assert_equal("node2.domain.com", node.classname, - "Did not get longest match") - end - def test_parsedate Puppet[:filetimeout] = 0 main = tempfile() @@ -160,35 +109,6 @@ class TestInterpreter < PuppetTest::TestCase newdate = interp.parsedate assert(date != newdate, "Parsedate was not updated") end - - # Make sure class, node, and define methods are case-insensitive - def test_structure_case_insensitivity - interp = mkinterp - - result = nil - assert_nothing_raised do - result = interp.newclass "Yayness" - end - assert_equal(result, interp.findclass("", "yayNess")) - - assert_nothing_raised do - result = interp.newdefine "FunTest" - end - assert_equal(result, interp.finddefine("", "fUntEst"), - "%s was not matched" % "fUntEst") - - assert_nothing_raised do - result = interp.newnode("MyNode").shift - end - assert_equal(result, interp.nodesearch("mYnOde"), - "mYnOde was not matched") - - assert_nothing_raised do - result = interp.newnode("YayTest.Domain.Com").shift - end - assert_equal(result, interp.nodesearch("yaYtEst.domAin.cOm"), - "yaYtEst.domAin.cOm was not matched") - end # Make sure our whole chain works. def test_evaluate @@ -444,70 +364,6 @@ class TestInterpreter < PuppetTest::TestCase end end - def test_nodedef - interp = mkinterp - interp.newclass("base") - interp.newclass("sub", :parent => "base") - interp.newclass("other") - - node = nil - assert_nothing_raised("Could not create a node definition") do - node = NodeDef.new :name => "yay", :classes => "sub", :parameters => {"one" => "two", "three" => "four"} - end - - scope = mkscope :interp => interp - assert_nothing_raised("Could not evaluate the node definition") do - node.evaluate(:scope => scope) - end - - assert_equal("two", scope.lookupvar("one"), "NodeDef did not set variable") - assert_equal("four", scope.lookupvar("three"), "NodeDef did not set variable") - - assert(scope.classlist.include?("sub"), "NodeDef did not evaluate class") - assert(scope.classlist.include?("base"), "NodeDef did not evaluate base class") - - # Now try a node def with multiple classes - assert_nothing_raised("Could not create a node definition") do - node = NodeDef.new :name => "yay", :classes => %w{sub other base}, :parameters => {"one" => "two", "three" => "four"} - end - - scope = mkscope :interp => interp - assert_nothing_raised("Could not evaluate the node definition") do - node.evaluate(:scope => scope) - end - - assert_equal("two", scope.lookupvar("one"), "NodeDef did not set variable") - assert_equal("four", scope.lookupvar("three"), "NodeDef did not set variable") - - assert(scope.classlist.include?("sub"), "NodeDef did not evaluate class") - assert(scope.classlist.include?("other"), "NodeDef did not evaluate other class") - - # And a node def with no params - assert_nothing_raised("Could not create a node definition with no params") do - node = NodeDef.new :name => "yay", :classes => %w{sub other base} - end - - scope = mkscope :interp => interp - assert_nothing_raised("Could not evaluate the node definition") do - node.evaluate(:scope => scope) - end - - assert(scope.classlist.include?("sub"), "NodeDef did not evaluate class") - assert(scope.classlist.include?("other"), "NodeDef did not evaluate other class") - - # Now make sure nodedef doesn't fail when some classes are not defined (#687). - assert_nothing_raised("Could not create a node definition with some invalid classes") do - node = NodeDef.new :name => "yay", :classes => %w{base unknown} - end - - scope = mkscope :interp => interp - assert_nothing_raised("Could not evaluate the node definition with some invalid classes") do - node.evaluate(:scope => scope) - end - - assert(scope.classlist.include?("base"), "NodeDef did not evaluate class") - end - # Make sure that reparsing is atomic -- failures don't cause a broken state, and we aren't subject # to race conditions if someone contacts us while we're reparsing. def test_atomic_reparsing diff --git a/test/language/parser.rb b/test/language/parser.rb index afffa9293..77595b155 100755 --- a/test/language/parser.rb +++ b/test/language/parser.rb @@ -1175,6 +1175,23 @@ file { "/tmp/yayness": assert_instance_of(AST::HostClass, klass, "Did not autoload sub class from alone file with no namespace") assert_equal("alone::sub", klass.classname, "Incorrect class was returned") end + + # Make sure class, node, and define methods are case-insensitive + def test_structure_case_insensitivity + parser = mkparser + + result = nil + assert_nothing_raised do + result = parser.newclass "Yayness" + end + assert_equal(result, parser.findclass("", "yayNess")) + + assert_nothing_raised do + result = parser.newdefine "FunTest" + end + assert_equal(result, parser.finddefine("", "fUntEst"), + "%s was not matched" % "fUntEst") + end end # $Id$ diff --git a/test/language/resource.rb b/test/language/resource.rb index 039c67216..73d516f51 100755 --- a/test/language/resource.rb +++ b/test/language/resource.rb @@ -11,149 +11,198 @@ class TestResource < PuppetTest::TestCase include PuppetTest::ResourceTesting Parser = Puppet::Parser AST = Parser::AST + Resource = Puppet::Parser::Resource Reference = Puppet::Parser::Resource::Reference def setup super Puppet[:trace] = false - @interp, @scope, @source = mkclassframing end def test_initialize args = {:type => "resource", :title => "testing", - :source => @source, :scope => @scope} + :source => "source", :scope => "scope"} # Check our arg requirements args.each do |name, value| try = args.dup try.delete(name) - assert_raise(Puppet::DevError) do + assert_raise(ArgumentError, "Did not fail when %s was missing" % name) do Parser::Resource.new(try) end end - args[:params] = paramify @source, :one => "yay", :three => "rah" + Reference.expects(:new).with(:type => "resource", :title => "testing", :scope => "scope").returns(:ref) res = nil assert_nothing_raised do res = Parser::Resource.new(args) end - - # Make sure it got the parameters correctly. - assert_equal("yay", res[:one]) - assert_equal("rah", res[:three]) - - assert_equal({:one => "yay", :three => "rah"}, res.to_hash) end - def test_override + def test_merge res = mkresource + other = mkresource - # Now verify we can't override with any random class - assert_raise(Puppet::ParseError) do - res.set paramify(@scope.findclass("other"), "one" => "boo").shift + # First try the case where the resource is not allowed to override + res.source = "source1" + other.source = "source2" + other.source.expects(:child_of?).with("source1").returns(false) + assert_raise(Puppet::ParseError, "Allowed unrelated resources to override") do + res.merge(other) end - # And that we can with a subclass - assert_nothing_raised do - res.set paramify(@scope.findclass("sub1"), "one" => "boo").shift - end + # Next try it when the sources are equal. + res.source = "source3" + other.source = res.source + other.source.expects(:child_of?).with("source3").never + params = {:a => :b, :c => :d} + other.expects(:params).returns(params) + res.expects(:override_parameter).with(:b) + res.expects(:override_parameter).with(:d) + res.merge(other) + + # And then parentage is involved + other = mkresource + res.source = "source3" + other.source = "source4" + other.source.expects(:child_of?).with("source3").returns(true) + params = {:a => :b, :c => :d} + other.expects(:params).returns(params) + res.expects(:override_parameter).with(:b) + res.expects(:override_parameter).with(:d) + res.merge(other) + end - # And that a different subclass can override a different parameter - assert_nothing_raised do - res.set paramify(@scope.findclass("sub2"), "three" => "boo").shift - end + # the [] method + def test_array_accessors + res = mkresource + params = res.instance_variable_get("@params") + assert_nil(res[:missing], "Found a missing parameter somehow") + params[:something] = stub(:value => "yay") + assert_equal("yay", res[:something], "Did not correctly call value on the parameter") - # But not the same one - assert_raise(Puppet::ParseError) do - res.set paramify(@scope.findclass("sub2"), "one" => "something").shift - end + res.expects(:title).returns(:mytitle) + assert_equal(:mytitle, res[:title], "Did not call title when asked for it as a param") end - def check_paramadd(val1, val2, merged_val) - res = mkresource :params => {"one" => val1} - assert_nothing_raised do - res.set Parser::Resource::Param.new( - :name => "one", :value => val2, - :add => true, :source => @scope.findclass("sub1")) - end - assert_equal(merged_val, res[:one]) + # Make sure any defaults stored in the scope get added to our resource. + def test_add_defaults + res = mkresource + params = res.instance_variable_get("@params") + params[:a] = :b + res.scope.expects(:lookupdefaults).with(res.type).returns(:a => :replaced, :c => :d) + res.expects(:debug) + + res.send(:add_defaults) + assert_equal(:d, params[:c], "Did not set default") + assert_equal(:b, params[:a], "Replaced parameter with default") end - def test_paramadd - check_paramadd([], [], []) - check_paramadd([], "rah", ["rah"]) - check_paramadd([], ["rah", "bah"], ["rah", "bah"]) - - check_paramadd("yay", [], ["yay"]) - check_paramadd("yay", "rah", ["yay", "rah"]) - check_paramadd("yay", ["rah", "bah"], ["yay", "rah", "bah"]) - - check_paramadd(["yay", "boo"], [], ["yay", "boo"]) - check_paramadd(["yay", "boo"], "rah", ["yay", "boo", "rah"]) - check_paramadd(["yay", "boo"], ["rah", "bah"], - ["yay", "boo", "rah", "bah"]) + def test_finish + res = mkresource + res.expects(:add_overrides) + res.expects(:add_defaults) + res.expects(:add_metaparams) + res.expects(:validate) + res.finish end - def test_merge - # Start with the normal one + # Make sure we paramcheck our params + def test_validate res = mkresource + params = res.instance_variable_get("@params") + params[:one] = :two + params[:three] = :four + res.expects(:paramcheck).with(:one) + res.expects(:paramcheck).with(:three) + res.send(:validate) + end - # Now create a resource from a different scope - other = mkresource :source => other, :params => {"one" => "boo"} - - # Make sure we can't merge it - assert_raise(Puppet::ParseError) do - res.merge(other) - end - - # Make one from a subscope - other = mkresource :source => "sub1", :params => {"one" => "boo"} - - # Make sure it merges - assert_nothing_raised do - res.merge(other) - end + def test_override_parameter + res = mkresource + params = res.instance_variable_get("@params") + + # There are three cases, with the second having two options: + + # No existing parameter. + param = stub(:name => "myparam") + res.send(:override_parameter, param) + assert_equal(param, params["myparam"], "Override was not added to param list") + + # An existing parameter that we can override. + source = stub(:child_of? => true) + # Start out without addition + params["param2"] = stub(:source => :whatever) + param = stub(:name => "param2", :source => source, :add => false) + res.send(:override_parameter, param) + assert_equal(param, params["param2"], "Override was not added to param list") + + # Try with addition. + params["param2"] = stub(:value => :a, :source => :whatever) + param = stub(:name => "param2", :source => source, :add => true, :value => :b) + param.expects(:value=).with([:a, :b]) + res.send(:override_parameter, param) + assert_equal(param, params["param2"], "Override was not added to param list") + + # And finally, make sure we throw an exception when the sources aren't related + source = stub(:child_of? => false) + params["param2"] = stub(:source => :whatever, :file => :f, :line => :l) + old = params["param2"] + param = stub(:name => "param2", :source => source, :file => :f, :line => :l) + assert_raise(Puppet::ParseError, "Did not fail when params conflicted") do + res.send(:override_parameter, param) + end + assert_equal(old, params["param2"], "Param was replaced irrespective of conflict") + end - assert_equal("boo", res["one"]) + def test_set_parameter + res = mkresource + params = res.instance_variable_get("@params") + + # First test the simple case: It's already a parameter + param = mock('param') + param.expects(:is_a?).with(Resource::Param).returns(true) + param.expects(:name).returns("pname") + res.send(:set_parameter, param) + assert_equal(param, params["pname"], "Parameter was not added to hash") + + # Now the case where there's no value but it's not a param + param = mock('param') + param.expects(:is_a?).with(Resource::Param).returns(false) + assert_raise(ArgumentError, "Did not fail when a non-param was passed") do + res.send(:set_parameter, param) + end + + # and the case where a value is passed in + param = stub :name => "pname", :value => "whatever" + Resource::Param.expects(:new).with(:name => "pname", :value => "myvalue", :source => res.source).returns(param) + res.send(:set_parameter, "pname", "myvalue") + assert_equal(param, params["pname"], "Did not put param in hash") end def test_paramcheck - # First make a builtin resource - res = nil - assert_nothing_raised do - res = Parser::Resource.new :type => "file", :title => tempfile(), - :source => @source, :scope => @scope - end - - %w{path group source schedule subscribe}.each do |param| - assert_nothing_raised("Param %s was considered invalid" % param) do - res.paramcheck(param) - end - end - - %w{this bad noness}.each do |param| - assert_raise(Puppet::ParseError, "%s was considered valid" % param) do - res.paramcheck(param) - end - end + # There are three cases here: - # Now create a defined resource - assert_nothing_raised do - res = Parser::Resource.new :type => "resource", :title => "yay", - :source => @source, :scope => @scope - end - - %w{one two three schedule subscribe}.each do |param| - assert_nothing_raised("Param %s was considered invalid" % param) do - res.paramcheck(param) - end - end - - %w{this bad noness}.each do |param| - assert_raise(Puppet::ParseError, "%s was considered valid" % param) do - res.paramcheck(param) - end - end + # It's a valid parameter + res = mkresource + ref = mock('ref') + res.instance_variable_set("@ref", ref) + klass = mock("class") + ref.expects(:typeclass).returns(klass).times(4) + klass.expects(:validattr?).with("good").returns(true) + assert(res.send(:paramcheck, :good), "Did not allow valid param") + + # It's name or title + klass.expects(:validattr?).with("name").returns(false) + assert(res.send(:paramcheck, :name), "Did not allow name") + klass.expects(:validattr?).with("title").returns(false) + assert(res.send(:paramcheck, :title), "Did not allow title") + + # It's not actually allowed + klass.expects(:validattr?).with("other").returns(false) + res.expects(:fail) + ref.expects(:type) + res.send(:paramcheck, :other) end def test_to_trans @@ -186,62 +235,10 @@ class TestResource < PuppetTest::TestCase assert_equal(["file", refs[3].title], obj["notify"], "Array with single resource reference was not turned into single value") end - def test_adddefaults - # Set some defaults at the top level - top = {:one => "fun", :two => "shoe"} - - @scope.setdefaults("resource", paramify(@source, top)) - - # Make a resource at that level - res = Parser::Resource.new :type => "resource", :title => "yay", - :source => @source, :scope => @scope - - # Add the defaults - assert_nothing_raised do - res.adddefaults - end - - # And make sure we got them - top.each do |p, v| - assert_equal(v, res[p]) - end - - # Now got a bit lower - other = @scope.newscope - - # And create a resource - lowerres = Parser::Resource.new :type => "resource", :title => "funtest", - :source => @source, :scope => other - - assert_nothing_raised do - lowerres.adddefaults - end - - # And check - top.each do |p, v| - assert_equal(v, lowerres[p]) - end - - # Now add some of our own defaults - lower = {:one => "shun", :three => "free"} - other.setdefaults("resource", paramify(@source, lower)) - otherres = Parser::Resource.new :type => "resource", :title => "yaytest", - :source => @source, :scope => other - - should = top.dup - # Make sure the lower defaults beat the higher ones. - lower.each do |p, v| should[p] = v end - - otherres.adddefaults - - should.each do |p,v| - assert_equal(v, otherres[p]) - end - end - def test_evaluate + @parser = mkparser # Make a definition that we know will, um, do something - @interp.newdefine "evaltest", + @parser.newdefine "evaltest", :arguments => [%w{one}, ["two", stringobj("755")]], :code => resourcedef("file", "/tmp", "owner" => varref("one"), "mode" => varref("two")) @@ -272,49 +269,36 @@ class TestResource < PuppetTest::TestCase "Evaluated resource was not deleted") end - def test_addoverrides - # First create an override for an object that doesn't yet exist - over1 = mkresource :source => "sub1", :params => {:one => "yay"} - - assert_nothing_raised do - @scope.setoverride(over1) - end - - assert(over1.override, "Override was not marked so") - - # Now make the resource - res = mkresource :source => "base", :params => {:one => "rah", - :three => "foo"} - - # And add it to our scope - @scope.setresource(res) - - # And make sure over1 has not yet taken affect - assert_equal("foo", res[:three], "Lost value") - - # Now add an immediately binding override - over2 = mkresource :source => "sub1", :params => {:three => "yay"} - - assert_nothing_raised do - @scope.setoverride(over2) - end - - # And make sure it worked - assert_equal("yay", res[:three], "Override 2 was ignored") - - # Now add our late-binding override - assert_nothing_raised do - res.addoverrides - end - - # And make sure they're still around - assert_equal("yay", res[:one], "Override 1 lost") - assert_equal("yay", res[:three], "Override 2 lost") - - # And finally, make sure that there are no remaining overrides - assert_nothing_raised do - res.addoverrides - end + def test_add_overrides + # Try it with nil + res = mkresource + res.scope = mock('scope') + config = mock("config") + res.scope.expects(:configuration).returns(config) + config.expects(:resource_overrides).with(res).returns(nil) + res.expects(:merge).never + res.send(:add_overrides) + + # And an empty array + res = mkresource + res.scope = mock('scope') + config = mock("config") + res.scope.expects(:configuration).returns(config) + config.expects(:resource_overrides).with(res).returns([]) + res.expects(:merge).never + res.send(:add_overrides) + + # And with some overrides + res = mkresource + res.scope = mock('scope') + config = mock("config") + res.scope.expects(:configuration).returns(config) + returns = %w{a b} + config.expects(:resource_overrides).with(res).returns(returns) + res.expects(:merge).with("a") + res.expects(:merge).with("b") + res.send(:add_overrides) + assert(returns.empty?, "Did not clear overrides") end def test_proxymethods @@ -326,28 +310,18 @@ class TestResource < PuppetTest::TestCase assert_equal(false, res.builtin?) end - def test_addmetaparams - mkevaltest @interp - res = Parser::Resource.new :type => "evaltest", :title => "yay", - :source => @source, :scope => @scope, - :params => paramify(@source, :tag => "yay") - - assert_nil(res[:schedule], "Got schedule already") - assert_nothing_raised do - res.addmetaparams - end - @scope.setvar("schedule", "daily") - - # This is so we can test that it won't override already-set metaparams - @scope.setvar("tag", "funtest") + def test_add_metaparams + res = mkresource + params = res.instance_variable_get("@params") + params[:a] = :b + Puppet::Type.expects(:eachmetaparam).multiple_yields(:a, :b, :c) + res.scope.expects(:lookupvar).with("b", false).returns(:something) + res.scope.expects(:lookupvar).with("c", false).returns(:undefined) + res.expects(:set_parameter).with(:b, :something) - assert_nothing_raised do - res.addmetaparams - end + res.send(:add_metaparams) - assert_equal("daily", res[:schedule], "Did not get metaparam") - assert_equal("yay", res[:tag], "Overrode explicitly-set metaparam") - assert_nil(res[:noop], "Got invalid metaparam") + assert_nil(params[:c], "A value was created somehow for an unset metaparam") end def test_reference_conversion @@ -397,18 +371,19 @@ class TestResource < PuppetTest::TestCase # #472. Really, this still isn't the best behaviour, but at least # it's consistent with what we have elsewhere. def test_defaults_from_parent_classes + @parser = mkparser # Make a parent class with some defaults in it - @interp.newclass("base", + @parser.newclass("base", :code => defaultobj("file", :owner => "root", :group => "root") ) # Now a mid-level class with some different values - @interp.newclass("middle", :parent => "base", + @parser.newclass("middle", :parent => "base", :code => defaultobj("file", :owner => "bin", :mode => "755") ) # Now a lower class with its own defaults plus a resource - @interp.newclass("bottom", :parent => "middle", + @parser.newclass("bottom", :parent => "middle", :code => AST::ASTArray.new(:children => [ defaultobj("file", :owner => "adm", :recurse => "true"), resourcedef("file", "/tmp/yayness", {}) @@ -435,17 +410,18 @@ class TestResource < PuppetTest::TestCase # The second part of #539 - make sure resources pass the arguments # correctly. def test_title_with_definitions - define = @interp.newdefine "yayness", + @parser = mkparser + define = @parser.newdefine "yayness", :code => resourcedef("file", "/tmp", "owner" => varref("name"), "mode" => varref("title")) - klass = @interp.findclass("", "") + klass = @parser.findclass("", "") should = {:name => :owner, :title => :mode} [ {:name => "one", :title => "two"}, {:title => "three"}, ].each do |hash| - scope = mkscope :interp => @interp + scope = mkscope :parser => @parser args = {:type => "yayness", :title => hash[:title], :source => klass, :scope => scope} if hash[:name] @@ -487,7 +463,8 @@ class TestResource < PuppetTest::TestCase # #643 - Make sure virtual defines result in virtual resources def test_virtual_defines - define = @interp.newdefine("yayness", + @parser = mkparser + define = @parser.newdefine("yayness", :code => resourcedef("file", varref("name"), "mode" => "644")) diff --git a/test/language/scope.rb b/test/language/scope.rb index f0feee156..bd90caa53 100755 --- a/test/language/scope.rb +++ b/test/language/scope.rb @@ -98,8 +98,8 @@ class TestScope < Test::Unit::TestCase end def test_lookupvar - interp = mkinterp - scope = mkscope :interp => interp + parser = mkparser + scope = mkscope :parser => parser # first do the plain lookups assert_equal("", scope.lookupvar("var"), "scope did not default to string") @@ -111,7 +111,7 @@ class TestScope < Test::Unit::TestCase assert_equal("yep", scope.lookupvar("var"), "did not retrieve value correctly") # Now test the parent lookups - subscope = mkscope :interp => interp + subscope = mkscope :parser => parser subscope.parent = scope assert_equal("", subscope.lookupvar("nope"), "scope did not default to string with parent") assert_equal("", subscope.lookupvar("nope", true), "scope ignored usestring setting with parent") @@ -129,12 +129,12 @@ class TestScope < Test::Unit::TestCase end def test_lookup_qualified_var - interp = mkinterp - scope = mkscope :interp => interp + parser = mkparser + scope = mkscope :parser => parser scopes = {} classes = ["", "one", "one::two", "one::two::three"].each do |name| - klass = interp.newclass(name) + klass = parser.newclass(name) klass.evaluate(:scope => scope) scopes[name] = scope.class_scope(klass) end @@ -149,7 +149,7 @@ class TestScope < Test::Unit::TestCase def test_declarative # set to declarative - top = mkscope(:declarative => true) + top = mkscope sub = mkscope(:parent => top) assert_nothing_raised { @@ -166,93 +166,89 @@ class TestScope < Test::Unit::TestCase } end - def test_notdeclarative - # set to not declarative - top = mkscope(:declarative => false) - sub = mkscope(:parent => top) + def test_setdefaults + config = mkconfig - assert_nothing_raised { - top.setvar("test","value") - } - assert_nothing_raised { - top.setvar("test","other") - } - assert_nothing_raised { - sub.setvar("test","later") - } - assert_nothing_raised { - sub.setvar("test","yayness") - } - end + scope = config.topscope - def test_setdefaults - interp, scope, source = mkclassframing + defaults = scope.instance_variable_get("@defaults") - # The setdefaults method doesn't really check what we're doing, - # so we're just going to use fake defaults here. + # First the case where there are no defaults and we pass a single param + param = stub :name => "myparam" + scope.setdefaults(:mytype, param) + assert_equal({"myparam" => param}, defaults[:mytype], "Did not set default correctly") - # First do a simple local lookup - params = paramify(source, :one => "fun", :two => "shoe") - origshould = {} - params.each do |p| origshould[p.name] = p end - assert_nothing_raised do - scope.setdefaults(:file, params) - end + # Now the case where we pass in multiple parameters + param1 = stub :name => "one" + param2 = stub :name => "two" + scope.setdefaults(:newtype, [param1, param2]) + assert_equal({"one" => param1, "two" => param2}, defaults[:newtype], "Did not set multiple defaults correctly") - ret = nil - assert_nothing_raised do - ret = scope.lookupdefaults(:file) + # And the case where there's actually a conflict. Use the first default for this. + newparam = stub :name => "myparam" + assert_raise(Puppet::ParseError, "Allowed resetting of defaults") do + scope.setdefaults(:mytype, param) end + assert_equal({"myparam" => param}, defaults[:mytype], "Replaced default even though there was a failure") + end - assert_equal(origshould, ret) + def test_lookupdefaults + config = mkconfig + top = config.topscope - # Now create a subscope and add some more params. - newscope = scope.newscope + # Make a subscope + sub = config.newscope(top) - newparams = paramify(source, :one => "shun", :three => "free") - assert_nothing_raised { - newscope.setdefaults(:file, newparams) - } + topdefs = top.instance_variable_get("@defaults") + subdefs = sub.instance_variable_get("@defaults") - # And make sure we get the appropriate ones back - should = {} - params.each do |p| should[p.name] = p end - newparams.each do |p| should[p.name] = p end + # First add some defaults to our top scope + topdefs[:t1] = {:p1 => :p2, :p3 => :p4} + topdefs[:t2] = {:p5 => :p6} - assert_nothing_raised do - ret = newscope.lookupdefaults(:file) - end - - assert_equal(should, ret) + # Then the sub scope + subdefs[:t1] = {:p1 => :p7, :p8 => :p9} + subdefs[:t2] = {:p5 => :p10, :p11 => :p12} - # Make sure we still only get the originals from the top scope - assert_nothing_raised do - ret = scope.lookupdefaults(:file) + # Now make sure we get the correct list back + result = nil + assert_nothing_raised("Could not get defaults") do + result = sub.lookupdefaults(:t1) end + assert_equal(:p9, result[:p8], "Did not get child defaults") + assert_equal(:p4, result[:p3], "Did not override parent defaults with child default") + assert_equal(:p7, result[:p1], "Did not get parent defaults") + end - assert_equal(origshould, ret) + def test_parent + config = mkconfig + top = config.topscope - # Now create another scope and make sure we only get the top defaults - otherscope = scope.newscope - assert_equal(origshould, otherscope.lookupdefaults(:file)) + # Make a subscope + sub = config.newscope(top) - # And make sure none of the scopes has defaults for other types - [scope, newscope, otherscope].each do |sc| - assert_equal({}, sc.lookupdefaults(:exec)) - end + assert_equal(top, sub.parent, "Did not find parent scope correctly") + assert_equal(top, sub.parent, "Did not find parent scope on second call") + end + + def test_class_scope + config = mkconfig + scope = config.topscope + config.expects(:class_scope).with(:testing).returns(:myscope) + assert_equal(:myscope, scope.class_scope(:testing), "Did not pass back the results of config.class_scope") end - def test_strinterp + def test_strparser # Make and evaluate our classes so the qualified lookups work - interp = mkinterp - klass = interp.newclass("") - scope = mkscope(:interp => interp) + parser = mkparser + klass = parser.newclass("") + scope = mkscope(:parser => parser) klass.evaluate(:scope => scope) - klass = interp.newclass("one") + klass = parser.newclass("one") klass.evaluate(:scope => scope) - klass = interp.newclass("one::two") + klass = parser.newclass("one::two") klass.evaluate(:scope => scope) @@ -264,7 +260,7 @@ class TestScope < Test::Unit::TestCase scopes = {"" => scope} %w{one one::two one::two::three}.each do |name| - klass = interp.newclass(name) + klass = parser.newclass(name) klass.evaluate(:scope => scope) scopes[name] = scope.class_scope(klass) scopes[name].setvar("test", "value-%s" % name.sub(/.+::/,'')) @@ -297,8 +293,8 @@ class TestScope < Test::Unit::TestCase tests.each do |input, output| assert_nothing_raised("Failed to scan %s" % input.inspect) do - assert_equal(output, scope.strinterp(input), - 'did not interpret %s correctly' % input.inspect) + assert_equal(output, scope.strparser(input), + 'did not parserret %s correctly' % input.inspect) end end @@ -310,8 +306,8 @@ class TestScope < Test::Unit::TestCase %w{d f h l w z}.each do |l| string = "\\" + l assert_nothing_raised do - assert_equal(string, scope.strinterp(string), - 'did not interpret %s correctly' % string) + assert_equal(string, scope.strparser(string), + 'did not parserret %s correctly' % string) end assert(logs.detect { |m| m.message =~ /Unrecognised escape/ }, @@ -321,7 +317,7 @@ class TestScope < Test::Unit::TestCase end def test_setclass - interp, scope, source = mkclassframing + parser, scope, source = mkclassframing base = scope.findclass("base") assert(base, "Could not find base class") @@ -392,11 +388,11 @@ class TestScope < Test::Unit::TestCase end def test_includefunction - interp = mkinterp - scope = mkscope :interp => interp + parser = mkparser + scope = mkscope :parser => parser - myclass = interp.newclass "myclass" - otherclass = interp.newclass "otherclass" + myclass = parser.newclass "myclass" + otherclass = parser.newclass "otherclass" function = Puppet::Parser::AST::Function.new( :name => "include", @@ -417,12 +413,12 @@ class TestScope < Test::Unit::TestCase end def test_definedfunction - interp = mkinterp + parser = mkparser %w{one two}.each do |name| - interp.newdefine name + parser.newdefine name end - scope = mkscope :interp => interp + scope = mkscope :parser => parser assert_nothing_raised { %w{one two file user}.each do |type| @@ -503,7 +499,7 @@ class TestScope < Test::Unit::TestCase # Verify that we recursively mark as exported the results of collectable # components. def test_exportedcomponents - interp, scope, source = mkclassframing + parser, scope, source = mkclassframing children = [] args = AST::ASTArray.new( @@ -513,7 +509,7 @@ class TestScope < Test::Unit::TestCase ) # Create a top-level component - interp.newdefine "one", :arguments => [%w{arg}], + parser.newdefine "one", :arguments => [%w{arg}], :code => AST::ASTArray.new( :children => [ resourcedef("file", "/tmp", {"owner" => varref("arg")}) @@ -521,7 +517,7 @@ class TestScope < Test::Unit::TestCase ) # And a component that calls it - interp.newdefine "two", :arguments => [%w{arg}], + parser.newdefine "two", :arguments => [%w{arg}], :code => AST::ASTArray.new( :children => [ resourcedef("one", "ptest", {"arg" => varref("arg")}) @@ -529,7 +525,7 @@ class TestScope < Test::Unit::TestCase ) # And then a third component that calls the second - interp.newdefine "three", :arguments => [%w{arg}], + parser.newdefine "three", :arguments => [%w{arg}], :code => AST::ASTArray.new( :children => [ resourcedef("two", "yay", {"arg" => varref("arg")}) @@ -545,7 +541,7 @@ class TestScope < Test::Unit::TestCase obj.evaluate :scope => scope # And then evaluate it - interp.evaliterate(scope) + parser.evaliterate(scope) %w{file}.each do |type| objects = scope.lookupexported(type) @@ -585,9 +581,11 @@ Host <<||>>" objects = nil # We run it twice because we want to make sure there's no conflict # if we pull it up from the database. + node = mknode + node.parameters = {"hostname" => node.name} 2.times { |i| assert_nothing_raised { - objects = interp.run("localhost", {"hostname" => "localhost"}) + objects = interp.compile(node) } flat = objects.flatten @@ -603,7 +601,7 @@ Host <<||>>" # Make sure tags behave appropriately. def test_tags - interp, scope, source = mkclassframing + parser, scope, source = mkclassframing # First make sure we can only set legal tags ["an invalid tag", "-anotherinvalid", "bad*tag"].each do |tag| @@ -637,58 +635,22 @@ Host <<||>>" assert_equal((ptags + %w{onemore subscope}).sort, newscope.tags.sort) end - # Make sure we successfully translate objects - def test_translate - interp, scope, source = mkclassframing - - # Create a define that we'll be using - interp.newdefine("wrapper", :code => AST::ASTArray.new(:children => [ - resourcedef("file", varref("name"), "owner" => "root") - ])) - - # Now create a resource that uses that define - define = mkresource(:type => "wrapper", :title => "/tmp/testing", - :scope => scope, :source => source, :params => :none) - - scope.setresource define - - # And a normal resource - scope.setresource mkresource(:type => "file", :title => "/tmp/rahness", - :scope => scope, :source => source, - :params => {:owner => "root"}) - - # Evaluate the the define thing. - define.evaluate - - # Now the scope should have a resource and a subscope. Translate the - # whole thing. - ret = nil - assert_nothing_raised do - ret = scope.translate - end - - assert_instance_of(Puppet::TransBucket, ret) - - ret.each do |obj| - assert(obj.is_a?(Puppet::TransBucket) || obj.is_a?(Puppet::TransObject), - "Got a non-transportable object %s" % obj.class) - end - - rahness = ret.find { |c| c.type == "file" and c.name == "/tmp/rahness" } - assert(rahness, "Could not find top-level file") - assert_equal("root", rahness["owner"]) - - bucket = ret.find { |c| c.class == Puppet::TransBucket and c.name == "/tmp/testing" } - assert(bucket, "Could not find define bucket") + # FIXME This isn't a great test, but I need to move on. + def test_to_trans + bucket = mock("transbucket") + Puppet::TransBucket.expects(:new).with([]).returns(bucket) + scope = mkscope + scope.type = "mytype" + scope.name = "myname" - testing = bucket.find { |c| c.type == "file" and c.name == "/tmp/testing" } - assert(testing, "Could not find define file") - assert_equal("root", testing["owner"]) + bucket.expects(:name=).with("myname") + bucket.expects(:type=).with("mytype") + scope.to_trans end def test_namespaces - interp, scope, source = mkclassframing + parser, scope, source = mkclassframing assert_equal([""], scope.namespaces, "Started out with incorrect namespaces") @@ -701,17 +663,17 @@ Host <<||>>" end def test_findclass_and_finddefine - interp = mkinterp + parser = mkparser - # Make sure our scope calls the interp findclass method with + # Make sure our scope calls the parser findclass method with # the right namespaces - scope = mkscope :interp => interp + scope = mkscope :parser => parser - interp.metaclass.send(:attr_accessor, :last) + parser.metaclass.send(:attr_accessor, :last) methods = [:findclass, :finddefine] methods.each do |m| - interp.meta_def(m) do |namespace, name| + parser.meta_def(m) do |namespace, name| @checked ||= [] @checked << [namespace, name] @@ -727,7 +689,7 @@ Host <<||>>" end test = proc do |should| - interp.last = scope.namespaces[-1] + parser.last = scope.namespaces[-1] methods.each do |method| result = scope.send(method, "testing") assert_equal(should, result, diff --git a/test/lib/puppettest/parsertesting.rb b/test/lib/puppettest/parsertesting.rb index d66367ada..368e112f9 100644 --- a/test/lib/puppettest/parsertesting.rb +++ b/test/lib/puppettest/parsertesting.rb @@ -5,6 +5,8 @@ module PuppetTest::ParserTesting include PuppetTest AST = Puppet::Parser::AST + Config = Puppet::Parser::Configuration + # A fake class that we can use for testing evaluation. class FakeAST attr_writer :evaluate @@ -39,6 +41,19 @@ module PuppetTest::ParserTesting ) end + def mkconfig(parser = nil) + require 'puppet/network/handler/node' + parser ||= mkparser + node = mknode + return Config.new(parser, node) + end + + def mknode(name = nil) + name ||= "nodename" + Puppet::Network::Handler.handler(:node) + Puppet::Network::Handler::Node::SimpleNode.new("nodename") + end + def mkinterp(args = {}) args[:Code] ||= "" unless args.include?(:Manifest) args[:Local] ||= true @@ -50,9 +65,9 @@ module PuppetTest::ParserTesting end def mkscope(hash = {}) - hash[:interp] ||= mkinterp - hash[:source] ||= (hash[:interp].findclass("", "") || - hash[:interp].newclass("")) + hash[:configuration] ||= mkconfig + hash[:parser] ||= mkparser + hash[:source] ||= (hash[:parser].findclass("", "") || hash[:parser].newclass("")) unless hash[:source] raise "Could not find source for scope" diff --git a/test/lib/puppettest/resourcetesting.rb b/test/lib/puppettest/resourcetesting.rb index 8cb59b83d..cbcfb0baf 100644 --- a/test/lib/puppettest/resourcetesting.rb +++ b/test/lib/puppettest/resourcetesting.rb @@ -1,25 +1,25 @@ module PuppetTest::ResourceTesting Parser = Puppet::Parser AST = Puppet::Parser::AST - def mkclassframing(interp = nil) - interp ||= mkinterp + def mkclassframing(parser = nil) + parser ||= mkparser - interp.newdefine("resource", :arguments => [%w{one}, %w{two value}, %w{three}]) - interp.newclass("") - source = interp.newclass("base") - interp.newclass("sub1", :parent => "base") - interp.newclass("sub2", :parent => "base") - interp.newclass("other") + parser.newdefine("resource", :arguments => [%w{one}, %w{two value}, %w{three}]) + parser.newclass("") + source = parser.newclass("base") + parser.newclass("sub1", :parent => "base") + parser.newclass("sub2", :parent => "base") + parser.newclass("other") - scope = Parser::Scope.new(:interp => interp) - scope.source = source + config = mkconfig(:parser => parser) + config.topscope.source = source - return interp, scope, source + return parser, config.topscope, source end - def mkevaltest(interp = nil) - interp ||= mkinterp - @interp.newdefine("evaltest", + def mkevaltest(parser = nil) + parser ||= mkparser + @parser.newdefine("evaltest", :arguments => [%w{one}, ["two", stringobj("755")]], :code => resourcedef("file", "/tmp", "owner" => varref("one"), "mode" => varref("two")) @@ -27,26 +27,14 @@ module PuppetTest::ResourceTesting end def mkresource(args = {}) - - if args[:scope] and ! args[:source] - args[:source] = args[:scope].source - end - - unless args[:scope] - unless defined? @scope - raise "Must set @scope to mkresource" - end - end + args[:source] ||= "source" + args[:scope] ||= "scope" {:type => "resource", :title => "testing", - :source => @source, :scope => @scope}.each do |param, value| + :source => "source", :scope => "scope"}.each do |param, value| args[param] ||= value end - unless args[:source].is_a?(Puppet::Parser::AST::HostClass) - args[:source] = args[:scope].findclass(args[:source]) - end - params = args[:params] || {:one => "yay", :three => "rah"} if args[:params] == :none args.delete(:params) diff --git a/test/network/handler/master.rb b/test/network/handler/master.rb index 08e17373b..9cf52b1cd 100755 --- a/test/network/handler/master.rb +++ b/test/network/handler/master.rb @@ -8,56 +8,6 @@ require 'puppet/network/handler/master' class TestMaster < Test::Unit::TestCase include PuppetTest::ServerTest - # run through all of the existing test files and make sure everything - # works - def test_files - count = 0 - textfiles { |file| - Puppet.debug("parsing %s" % file) - client = nil - master = nil - - # create our master - assert_nothing_raised() { - # this is the default server setup - master = Puppet::Network::Handler.master.new( - :Manifest => file, - :UseNodes => false, - :Local => true - ) - } - - # and our client - assert_nothing_raised() { - client = Puppet::Network::Client.master.new( - :Master => master - ) - } - - # pull our configuration a few times - assert_nothing_raised() { - client.getconfig - stopservices - Puppet::Type.allclear - } - assert_nothing_raised() { - client.getconfig - stopservices - Puppet::Type.allclear - } - assert_nothing_raised() { - client.getconfig - stopservices - Puppet::Type.allclear - } - # only test three files; that's plenty - if count > 3 - break - end - count += 1 - } - end - def test_defaultmanifest textfiles { |file| Puppet[:manifest] = file @@ -166,30 +116,6 @@ class TestMaster < Test::Unit::TestCase assert(FileTest.exists?(file2), "Second file %s does not exist" % file2) end - def test_addfacts - master = nil - file = mktestmanifest() - # create our master - assert_nothing_raised() { - # this is the default server setup - master = Puppet::Network::Handler.master.new( - :Manifest => file, - :UseNodes => false, - :Local => true - ) - } - - facts = {} - - assert_nothing_raised { - master.addfacts(facts) - } - - %w{serverversion servername serverip}.each do |fact| - assert(facts.include?(fact), "Fact %s was not set" % fact) - end - end - # Make sure we're using the hostname as configured with :node_name def test_hostname_in_getconfig master = nil -- cgit From 2a4e1011dbc244754f434f7eb97f3d41463e5cd4 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Mon, 20 Aug 2007 19:09:26 -0500 Subject: All language tests now pass. I expect there are other failures elsewhere, but I want to commit this before delving into them. My method for fixing the tests was to do as little as possible, keeping the tests as bad or as good as they were before I started. Mostly this was about changing references to the interpreter into references to the parser (since that is where the new* methods are now for ast containers) and then dealing with the new config object and its relationship to scopes. --- test/language/ast.rb | 35 +++-- test/language/ast/component.rb | 36 +++-- test/language/ast/hostclass.rb | 33 +++-- test/language/ast/resourceref.rb | 18 +-- test/language/collector.rb | 19 +-- test/language/configuration.rb | 25 +++- test/language/functions.rb | 77 +++++----- test/language/interpreter.rb | 263 ++--------------------------------- test/language/parser.rb | 14 +- test/language/resource.rb | 123 ++++++---------- test/language/scope.rb | 246 +++++++++----------------------- test/lib/puppettest.rb | 1 + test/lib/puppettest/parsertesting.rb | 12 +- 13 files changed, 276 insertions(+), 626 deletions(-) (limited to 'test') diff --git a/test/language/ast.rb b/test/language/ast.rb index 9e00c610d..38e658edb 100755 --- a/test/language/ast.rb +++ b/test/language/ast.rb @@ -49,24 +49,21 @@ class TestAST < Test::Unit::TestCase # Make sure our override object behaves "correctly" def test_override - interp, scope, source = mkclassframing + scope = mkscope ref = nil assert_nothing_raised do - ref = resourceoverride("resource", "yaytest", "one" => "yay", "two" => "boo") + ref = resourceoverride("file", "/yayness", "owner" => "blah", "group" => "boo") end + Puppet::Parser::Resource.expects(:new).with { |o| o.is_a?(Hash) }.returns(:override) + scope.expects(:setoverride).with(:override) ret = nil assert_nothing_raised do ret = ref.evaluate :scope => scope end - assert_instance_of(Puppet::Parser::Resource, ret) - - assert(ret.override?, "Resource was not an override resource") - - assert(scope.overridetable[ret.ref].include?(ret), - "Was not stored in the override table") + assert_equal(:override, ret, "Did not return override") end # make sure our resourcedefaults ast object works correctly. @@ -97,16 +94,16 @@ class TestAST < Test::Unit::TestCase end def test_node - interp = mkinterp - scope = mkscope(:interp => interp) + scope = mkscope + parser = scope.configuration.parser # Define a base node - basenode = interp.newnode "basenode", :code => AST::ASTArray.new(:children => [ + basenode = parser.newnode "basenode", :code => AST::ASTArray.new(:children => [ resourcedef("file", "/tmp/base", "owner" => "root") ]) # Now define a subnode - nodes = interp.newnode ["mynode", "othernode"], + nodes = parser.newnode ["mynode", "othernode"], :code => AST::ASTArray.new(:children => [ resourcedef("file", "/tmp/mynode", "owner" => "root"), resourcedef("file", "/tmp/basenode", "owner" => "daemon") @@ -116,9 +113,9 @@ class TestAST < Test::Unit::TestCase # Make sure we can find them all. %w{mynode othernode}.each do |node| - assert(interp.nodesearch_code(node), "Could not find %s" % node) + assert(parser.nodes[node], "Could not find %s" % node) end - mynode = interp.nodesearch_code("mynode") + mynode = parser.nodes["mynode"] # Now try evaluating the node assert_nothing_raised do @@ -135,9 +132,9 @@ class TestAST < Test::Unit::TestCase assert_equal("daemon", basefile[:owner]) # Now make sure we can evaluate nodes with parents - child = interp.newnode(%w{child}, :parent => "basenode").shift + child = parser.newnode(%w{child}, :parent => "basenode").shift - newscope = mkscope :interp => interp + newscope = mkscope :parser => parser assert_nothing_raised do child.evaluate :scope => newscope end @@ -147,8 +144,7 @@ class TestAST < Test::Unit::TestCase end def test_collection - interp = mkinterp - scope = mkscope(:interp => interp) + scope = mkscope coll = nil assert_nothing_raised do @@ -165,7 +161,8 @@ class TestAST < Test::Unit::TestCase assert_instance_of(Puppet::Parser::Collector, ret) # Now make sure we get it back from the scope - assert_equal([ret], scope.collections) + colls = scope.configuration.instance_variable_get("@collections") + assert_equal([ret], colls, "Did not store collector in config's collection list") end def test_virtual_collexp diff --git a/test/language/ast/component.rb b/test/language/ast/component.rb index 13cf60857..cf0cce976 100755 --- a/test/language/ast/component.rb +++ b/test/language/ast/component.rb @@ -16,8 +16,8 @@ class TestASTComponent < Test::Unit::TestCase include PuppetTest::ResourceTesting AST = Puppet::Parser::AST - def test_component - parser, scope, source = mkclassframing + def test_initialize + parser = mkparser # Create a new definition klass = parser.newdefine "yayness", @@ -35,27 +35,41 @@ class TestASTComponent < Test::Unit::TestCase [:random, "random"].each do |var| assert(! klass.validattr?(var), "%s was considered valid" % var.inspect) end + + end + + def test_evaluate + parser = mkparser + config = mkconfig + 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"))] + ) + # Now call it a couple of times # First try it without a required param - assert_raise(Puppet::ParseError) do - klass.evaluate(:scope => scope, + assert_raise(Puppet::ParseError, "Did not fail when a required parameter was not provided") do + klass.evaluate_resource(:scope => scope, :name => "bad", :arguments => {"owner" => "nobody"} ) end # And make sure it didn't create the file - assert_nil(scope.findresource("File[/tmp/bad]"), + assert_nil(config.findresource("File[/tmp/bad]"), "Made file with invalid params") assert_nothing_raised do - klass.evaluate(:scope => scope, + klass.evaluate_resource(:scope => scope, :title => "first", :arguments => {"mode" => "755"} ) end - firstobj = scope.findresource("File[/tmp/first]") + firstobj = config.findresource("File[/tmp/first]") assert(firstobj, "Did not create /tmp/first obj") assert_equal("file", firstobj.type) @@ -65,7 +79,7 @@ class TestASTComponent < Test::Unit::TestCase # Make sure we can't evaluate it with the same args assert_raise(Puppet::ParseError) do - klass.evaluate(:scope => scope, + klass.evaluate_resource(:scope => scope, :title => "first", :arguments => {"mode" => "755"} ) @@ -73,13 +87,13 @@ class TestASTComponent < Test::Unit::TestCase # Now create another with different args assert_nothing_raised do - klass.evaluate(:scope => scope, + klass.evaluate_resource(:scope => scope, :title => "second", :arguments => {"mode" => "755", "owner" => "daemon"} ) end - secondobj = scope.findresource("File[/tmp/second]") + secondobj = config.findresource("File[/tmp/second]") assert(secondobj, "Did not create /tmp/second obj") assert_equal("file", secondobj.type) @@ -110,7 +124,7 @@ class TestASTComponent < Test::Unit::TestCase end args[:scope] = scope assert_nothing_raised("Could not evaluate definition with %s" % hash.inspect) do - klass.evaluate(args) + klass.evaluate_resource(args) end name = hash[:name] || hash[:title] diff --git a/test/language/ast/hostclass.rb b/test/language/ast/hostclass.rb index 051bee36c..f093504ec 100755 --- a/test/language/ast/hostclass.rb +++ b/test/language/ast/hostclass.rb @@ -17,10 +17,11 @@ class TestASTHostClass < Test::Unit::TestCase AST = Puppet::Parser::AST def test_hostclass - interp, scope, source = mkclassframing + scope = mkscope + parser = scope.configuration.parser # Create the class we're testing, first with no parent - klass = interp.newclass "first", + klass = parser.newclass "first", :code => AST::ASTArray.new( :children => [resourcedef("file", "/tmp", "owner" => "nobody", "mode" => "755")] @@ -43,13 +44,13 @@ class TestASTHostClass < Test::Unit::TestCase assert_equal("755", tmp[:mode]) # Now create a couple more classes. - newbase = interp.newclass "newbase", + newbase = parser.newclass "newbase", :code => AST::ASTArray.new( :children => [resourcedef("file", "/tmp/other", "owner" => "nobody", "mode" => "644")] ) - newsub = interp.newclass "newsub", + newsub = parser.newclass "newsub", :parent => "newbase", :code => AST::ASTArray.new( :children => [resourcedef("file", "/tmp/yay", @@ -60,7 +61,7 @@ class TestASTHostClass < Test::Unit::TestCase ) # Override a different variable in the top scope. - moresub = interp.newclass "moresub", + moresub = parser.newclass "moresub", :parent => "newbase", :code => AST::ASTArray.new( :children => [resourceoverride("file", "/tmp/other", @@ -92,19 +93,20 @@ class TestASTHostClass < Test::Unit::TestCase # Make sure that classes set their namespaces to themselves. This # way they start looking for definitions in their own namespace. def test_hostclass_namespace - interp, scope, source = mkclassframing + scope = mkscope + parser = scope.configuration.parser # Create a new class klass = nil assert_nothing_raised do - klass = interp.newclass "funtest" + klass = parser.newclass "funtest" end # Now define a definition in that namespace define = nil assert_nothing_raised do - define = interp.newdefine "funtest::mydefine" + define = parser.newdefine "funtest::mydefine" end assert_equal("funtest", klass.namespace, @@ -127,17 +129,18 @@ class TestASTHostClass < Test::Unit::TestCase # At the same time, make sure definitions in the parent class can be # found within the subclass (#517). def test_parent_scope_from_parentclass - interp = mkinterp + scope = mkscope + parser = scope.configuration.parser - interp.newclass("base") - fun = interp.newdefine("base::fun") - interp.newclass("middle", :parent => "base") - interp.newclass("sub", :parent => "middle") - scope = mkscope :interp => interp + parser.newclass("base") + fun = parser.newdefine("base::fun") + parser.newclass("middle", :parent => "base") + parser.newclass("sub", :parent => "middle") + scope = mkscope :parser => parser ret = nil assert_nothing_raised do - ret = scope.evalclasses("sub") + ret = scope.configuration.evaluate_classes(["sub"]) end subscope = scope.class_scope(scope.findclass("sub")) diff --git a/test/language/ast/resourceref.rb b/test/language/ast/resourceref.rb index 7b7889dc1..a3d6775a2 100755 --- a/test/language/ast/resourceref.rb +++ b/test/language/ast/resourceref.rb @@ -19,13 +19,13 @@ class TestASTResourceRef < Test::Unit::TestCase def setup super - @interp = mkinterp - @scope = mkscope :interp => @interp + @scope = mkscope + @parser = @scope.configuration.parser end def test_evaluate - @interp.newdefine "one::two" - @interp.newdefine "one-two" + @parser.newdefine "one::two" + @parser.newdefine "one-two" [%w{file /tmp/yay}, %w{one::two three}, %w{one-two three}].each do |type, title| ref = newref(type, title) @@ -41,9 +41,9 @@ class TestASTResourceRef < Test::Unit::TestCase # Related to #706, make sure resource references correctly translate to qualified types. def test_scoped_references - @interp.newdefine "one" - @interp.newdefine "one::two" - @interp.newdefine "three" + @parser.newdefine "one" + @parser.newdefine "one::two" + @parser.newdefine "three" twoscope = @scope.newscope(:type => "one", :namespace => "one") assert(twoscope.finddefine("two"), "Could not find 'two' definition") title = "title" @@ -70,8 +70,8 @@ class TestASTResourceRef < Test::Unit::TestCase end # Now run the same tests, but with the classes - @interp.newclass "four" - @interp.newclass "one::five" + @parser.newclass "four" + @parser.newclass "one::five" # First try an unqualified type assert_equal("four", newref("class", "four").evaluate(:scope => twoscope).title, diff --git a/test/language/collector.rb b/test/language/collector.rb index bdcaf4aec..a4119929f 100755 --- a/test/language/collector.rb +++ b/test/language/collector.rb @@ -16,7 +16,8 @@ class TestCollector < Test::Unit::TestCase def setup super Puppet[:trace] = false - @interp, @scope, @source = mkclassframing + @scope = mkscope + @config = @scope.configuration end # Test just collecting a specific resource. This is used by the 'realize' @@ -32,7 +33,7 @@ class TestCollector < Test::Unit::TestCase assert_nothing_raised do coll.resources = ["File[/tmp/virtual1]", "File[/tmp/virtual3]"] end - @scope.newcollection(coll) + @config.add_collection(coll) # Evaluate the collector and make sure it doesn't fail with no resources # found yet @@ -62,7 +63,7 @@ class TestCollector < Test::Unit::TestCase "Resource got realized") # Make sure that the collection is still there - assert(@scope.collections.include?(coll), "collection was deleted too soon") + assert(@config.collections.include?(coll), "collection was deleted too soon") # Now add our third resource three = mkresource(:type => "file", :title => "/tmp/virtual3", @@ -76,7 +77,7 @@ class TestCollector < Test::Unit::TestCase assert(! three.virtual?, "three is still virtual") # And make sure that the collection got deleted from the scope's list - assert(@scope.collections.empty?, "collection was not deleted") + assert(@config.collections.empty?, "collection was not deleted") end def test_virtual @@ -102,10 +103,10 @@ class TestCollector < Test::Unit::TestCase end # Set it in our scope - @scope.newcollection(coll) + @config.add_collection(coll) # Make sure it's in the collections - assert(@scope.collections.include?(coll), "collection was not added") + assert(@config.collections.include?(coll), "collection was not added") # And try to collect the virtual resources. ret = nil @@ -148,7 +149,7 @@ class TestCollector < Test::Unit::TestCase coll = Puppet::Parser::Collector.new(@scope, "file", nil, nil, :virtual) end - @scope.newcollection(coll) + @config.add_collection(coll) # run the collection and make sure it doesn't get deleted, since it # didn't return anything @@ -157,7 +158,7 @@ class TestCollector < Test::Unit::TestCase "Evaluate returned incorrect value") end - assert_equal([coll], @scope.collections, "Collection was deleted") + assert_equal([coll], @config.collections, "Collection was deleted") # Make a resource one = mkresource(:type => "file", :title => "/tmp/virtual1", @@ -170,7 +171,7 @@ class TestCollector < Test::Unit::TestCase "Evaluate returned incorrect value") end - assert_equal([coll], @scope.collections, "Collection was deleted") + assert_equal([coll], @config.collections, "Collection was deleted") assert_equal(false, one.virtual?, "One was not realized") end diff --git a/test/language/configuration.rb b/test/language/configuration.rb index 688782f7b..fbdf68e73 100755 --- a/test/language/configuration.rb +++ b/test/language/configuration.rb @@ -287,9 +287,11 @@ class TestConfiguration < Test::Unit::TestCase config.expects(:tag).with("four") @node.classes = %w{one two three four} + result = nil assert_nothing_raised("could not call evaluate_classes") do - config.send(:evaluate_classes) + result = config.send(:evaluate_classes) end + assert_equal(%w{one three}, result, "Did not return the list of evaluated classes") end def test_evaluate_collections @@ -719,4 +721,25 @@ class TestConfiguration < Test::Unit::TestCase assert_equal(:yay, config.findresource("Foo[bar]"), "Returned a non-existent resource") end end + + # #620 - Nodes and classes should conflict, else classes don't get evaluated + def test_nodes_and_classes_name_conflict + # Test node then class + config = mkconfig + node = stub :nodescope? => true + klass = stub :nodescope? => false + config.class_set("one", node) + assert_raise(Puppet::ParseError, "Did not fail when replacing node with class") do + config.class_set("one", klass) + end + + # and class then node + config = mkconfig + node = stub :nodescope? => true + klass = stub :nodescope? => false + config.class_set("two", klass) + assert_raise(Puppet::ParseError, "Did not fail when replacing node with class") do + config.class_set("two", node) + end + end end diff --git a/test/language/functions.rb b/test/language/functions.rb index 34207de17..42d8d7585 100755 --- a/test/language/functions.rb +++ b/test/language/functions.rb @@ -3,7 +3,6 @@ $:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ require 'puppet' -require 'puppet/parser/interpreter' require 'puppet/parser/parser' require 'puppet/network/client' require 'puppettest' @@ -204,16 +203,17 @@ class TestLangFunctions < Test::Unit::TestCase f.puts %{file { "#{file}": content => template("#{template}") }} end - interpreter = Puppet::Parser::Interpreter.new( + interp = Puppet::Parser::Interpreter.new( :Manifest => manifest, :UseNodes => false ) + node = mknode - parsedate = interpreter.parsedate() + parsedate = interp.parsedate() objects = nil assert_nothing_raised { - objects = interpreter.run("myhost", {}) + objects = interp.compile(node) } fileobj = objects[0] @@ -221,7 +221,7 @@ class TestLangFunctions < Test::Unit::TestCase assert_equal("original text\n", fileobj["content"], "Template did not work") - Puppet[:filetimeout] = 0 + Puppet[:filetimeout] = -5 # Have to sleep because one second is the fs's time granularity. sleep(1) @@ -231,9 +231,9 @@ class TestLangFunctions < Test::Unit::TestCase end assert_nothing_raised { - objects = interpreter.run("myhost", {}) + objects = interp.compile(node) } - newdate = interpreter.parsedate() + newdate = interp.parsedate() assert(parsedate != newdate, "Parse date did not change") end @@ -306,35 +306,36 @@ class TestLangFunctions < Test::Unit::TestCase end def test_realize - @interp, @scope, @source = mkclassframing + scope = mkscope + parser = scope.configuration.parser # Make a definition - @interp.newdefine("mytype") + parser.newdefine("mytype") [%w{file /tmp/virtual}, %w{mytype yay}].each do |type, title| # Make a virtual resource virtual = mkresource(:type => type, :title => title, :virtual => true, :params => {}) - @scope.setresource virtual + scope.setresource virtual ref = Puppet::Parser::Resource::Reference.new( :type => type, :title => title, - :scope => @scope + :scope => scope ) # Now call the realize function assert_nothing_raised do - @scope.function_realize(ref) + scope.function_realize(ref) end # Make sure it created a collection - assert_equal(1, @scope.collections.length, + assert_equal(1, scope.configuration.collections.length, "Did not set collection") assert_nothing_raised do - @scope.collections.each do |coll| coll.evaluate end + scope.configuration.collections.each do |coll| coll.evaluate end end - @scope.collections.clear + scope.configuration.collections.clear # Now make sure the virtual resource is no longer virtual assert(! virtual.virtual?, "Did not make virtual resource real") @@ -343,29 +344,29 @@ class TestLangFunctions < Test::Unit::TestCase # Make sure we puke on any resource that doesn't exist none = Puppet::Parser::Resource::Reference.new( :type => "file", :title => "/tmp/nosuchfile", - :scope => @scope + :scope => scope ) # The function works assert_nothing_raised do - @scope.function_realize(none.to_s) + scope.function_realize(none.to_s) end # Make sure it created a collection - assert_equal(1, @scope.collections.length, + assert_equal(1, scope.configuration.collections.length, "Did not set collection") # And the collection has our resource in it - assert_equal([none.to_s], @scope.collections[0].resources, + assert_equal([none.to_s], scope.configuration.collections[0].resources, "Did not set resources in collection") end def test_defined - interp = mkinterp - scope = mkscope(:interp => interp) + scope = mkscope + parser = scope.configuration.parser - interp.newclass("yayness") - interp.newdefine("rahness") + parser.newclass("yayness") + parser.newdefine("rahness") assert_nothing_raised do assert(scope.function_defined("yayness"), "yayness class was not considered defined") @@ -395,11 +396,11 @@ class TestLangFunctions < Test::Unit::TestCase end def test_search - interp = mkinterp - scope = mkscope(:interp => interp) + parser = mkparser + scope = mkscope(:parser => parser) - fun = interp.newdefine("yay::ness") - foo = interp.newdefine("foo::bar") + fun = parser.newdefine("yay::ness") + foo = parser.newdefine("foo::bar") search = Puppet::Parser::Functions.function(:search) assert_nothing_raised do @@ -417,36 +418,36 @@ class TestLangFunctions < Test::Unit::TestCase end def test_include - interp = mkinterp - scope = mkscope(:interp => interp) + scope = mkscope + parser = scope.configuration.parser assert_raise(Puppet::ParseError, "did not throw error on missing class") do scope.function_include("nosuchclass") end - interp.newclass("myclass") + parser.newclass("myclass") assert_nothing_raised do scope.function_include "myclass" end - assert(scope.classlist.include?("myclass"), + assert(scope.configuration.classlist.include?("myclass"), "class was not evaluated") # Now try multiple classes at once - classes = %w{one two three}.each { |c| interp.newclass(c) } + classes = %w{one two three}.each { |c| parser.newclass(c) } assert_nothing_raised do scope.function_include classes end classes.each do |c| - assert(scope.classlist.include?(c), + assert(scope.configuration.classlist.include?(c), "class %s was not evaluated" % c) end # Now try a scoped class - interp.newclass("os::redhat") + parser.newclass("os::redhat") assert_nothing_raised("Could not include qualified class name") do scope.function_include("os::redhat") @@ -454,8 +455,8 @@ class TestLangFunctions < Test::Unit::TestCase end def test_file - interp = mkinterp - scope = mkscope(:interp => interp) + parser = mkparser + scope = mkscope(:parser => parser) file1 = tempfile file2 = tempfile @@ -497,8 +498,8 @@ class TestLangFunctions < Test::Unit::TestCase assert_equal("yay\n", %x{#{command}}, "command did not work") assert_equal("yay-foo\n", %x{#{command} foo}, "command did not work") - interp = mkinterp - scope = mkscope(:interp => interp) + scope = mkscope + parser = scope.configuration.parser val = nil assert_nothing_raised("Could not call generator with no args") do diff --git a/test/language/interpreter.rb b/test/language/interpreter.rb index 6b9aa7258..ebbc3f87f 100755 --- a/test/language/interpreter.rb +++ b/test/language/interpreter.rb @@ -111,257 +111,16 @@ class TestInterpreter < PuppetTest::TestCase end # Make sure our whole chain works. - def test_evaluate - interp, scope, source = mkclassframing - - # Create a define that we'll be using - interp.newdefine("wrapper", :code => AST::ASTArray.new(:children => [ - resourcedef("file", varref("name"), "owner" => "root") - ])) - - # Now create a resource that uses that define - define = mkresource(:type => "wrapper", :title => "/tmp/testing", - :scope => scope, :source => source, :params => :none) - - scope.setresource define - - # And a normal resource - scope.setresource mkresource(:type => "file", :title => "/tmp/rahness", - :scope => scope, :source => source, - :params => {:owner => "root"}) - - # Now evaluate everything - objects = nil - interp.usenodes = false - assert_nothing_raised do - objects = interp.evaluate(nil, {}) - end - - assert_instance_of(Puppet::TransBucket, objects) - end - - # Test evaliterate. It's a very simple method, but it's pretty tough - # to test. It iterates over collections and instances of defined types - # until there's no more work to do. - def test_evaliterate - interp, scope, source = mkclassframing - - # Create a top-level definition that creates a builtin object - interp.newdefine("one", :arguments => [%w{owner}], - :code => AST::ASTArray.new(:children => [ - resourcedef("file", varref("name"), - "owner" => varref("owner") - ) - ]) - ) - - # Create another definition to call that one - interp.newdefine("two", :arguments => [%w{owner}], - :code => AST::ASTArray.new(:children => [ - resourcedef("one", varref("name"), - "owner" => varref("owner") - ) - ]) - ) - - # And then a third - interp.newdefine("three", :arguments => [%w{owner}], - :code => AST::ASTArray.new(:children => [ - resourcedef("two", varref("name"), - "owner" => varref("owner") - ) - ]) - ) - - # And create a definition that creates a virtual resource - interp.newdefine("virtualizer", :arguments => [%w{owner}], - :code => AST::ASTArray.new(:children => [ - virt_resourcedef("one", varref("name"), - "owner" => varref("owner") - ) - ]) - ) - - # Now create an instance of three - three = Puppet::Parser::Resource.new( - :type => "three", :title => "one", - :scope => scope, :source => source, - :params => paramify(source, :owner => "root") - ) - scope.setresource(three) - - # An instance of the virtualizer - virt = Puppet::Parser::Resource.new( - :type => "virtualizer", :title => "two", - :scope => scope, :source => source, - :params => paramify(source, :owner => "root") - ) - scope.setresource(virt) - - # And a virtual instance of three - virt_three = Puppet::Parser::Resource.new( - :type => "three", :title => "three", - :scope => scope, :source => source, - :params => paramify(source, :owner => "root") - ) - virt_three.virtual = true - scope.setresource(virt_three) - - # Create a normal, virtual resource - plainvirt = Puppet::Parser::Resource.new( - :type => "user", :title => "five", - :scope => scope, :source => source, - :params => paramify(source, :uid => "root") - ) - plainvirt.virtual = true - scope.setresource(plainvirt) - - # Now create some collections for our virtual resources - %w{Three[three] One[two]}.each do |ref| - coll = Puppet::Parser::Collector.new(scope, "file", nil, nil, :virtual) - coll.resources = [ref] - scope.newcollection(coll) - end - - # And create a generic user collector for our plain resource - coll = Puppet::Parser::Collector.new(scope, "user", nil, nil, :virtual) - scope.newcollection(coll) - - ret = nil - assert_nothing_raised do - ret = scope.unevaluated - end - - - assert_instance_of(Array, ret) - assert_equal(3, ret.length, - "did not get the correct number of unevaled resources") - - # Now translate the whole tree - assert_nothing_raised do - Timeout::timeout(2) do - interp.evaliterate(scope) - end - end - - # Now make sure we've got all of our files - %w{one two three}.each do |name| - file = scope.findresource("File[%s]" % name) - assert(file, "Could not find file %s" % name) - - assert_equal("root", file[:owner]) - assert(! file.virtual?, "file %s is still virtual" % name) - end - - # Now make sure we found the user - assert(! plainvirt.virtual?, "user was not realized") - end - - # Make sure we fail if there are any leftover overrides to perform. - # This would normally mean that someone is trying to override an object - # that does not exist. - def test_failonleftovers - interp, scope, source = mkclassframing - - # Make sure we don't fail, since there are no overrides - assert_nothing_raised do - interp.failonleftovers(scope) - end - - # Add an override, and make sure it causes a failure - over1 = mkresource :scope => scope, :source => source, - :params => {:one => "yay"} - - scope.setoverride(over1) - - assert_raise(Puppet::ParseError) do - interp.failonleftovers(scope) - end - - # Make a new scope to test leftover collections - scope = mkscope :interp => interp - interp.meta_def(:check_resource_collections) do - raise ArgumentError, "yep" - end - - assert_raise(ArgumentError, "did not call check_resource_colls") do - interp.failonleftovers(scope) - end - end - - def test_evalnode + def test_compile interp = mkinterp - interp.usenodes = false - scope = Parser::Scope.new(:interp => interp) - facts = Facter.to_hash - - # First make sure we get no failures when client is nil - assert_nothing_raised do - interp.evalnode(nil, scope, facts) - end - - # Now define a node - interp.newnode "mynode", :code => AST::ASTArray.new(:children => [ - resourcedef("file", "/tmp/testing", "owner" => "root") - ]) - - # Eval again, and make sure it does nothing - assert_nothing_raised do - interp.evalnode("mynode", scope, facts) - end - - assert_nil(scope.findresource("File[/tmp/testing]"), - "Eval'ed node with nodes off") - - # Now enable usenodes and make sure it works. - interp.usenodes = true - assert_nothing_raised do - interp.evalnode("mynode", scope, facts) - end - file = scope.findresource("File[/tmp/testing]") - - assert_instance_of(Puppet::Parser::Resource, file, - "Could not find file") - end - - # This is mostly used for the cfengine module - def test_specificclasses - interp = mkinterp :Classes => %w{klass1 klass2}, :UseNodes => false - - # Make sure it's not a failure to be missing classes, since - # we're using the cfengine class list, which is huge. - assert_nothing_raised do - interp.evaluate(nil, {}) - end - - interp.newclass("klass1", :code => AST::ASTArray.new(:children => [ - resourcedef("file", "/tmp/klass1", "owner" => "root") - ])) - interp.newclass("klass2", :code => AST::ASTArray.new(:children => [ - resourcedef("file", "/tmp/klass2", "owner" => "root") - ])) - - ret = nil - assert_nothing_raised do - ret = interp.evaluate(nil, {}) - end - - found = ret.flatten.collect do |res| res.name end - - assert(found.include?("/tmp/klass1"), "Did not evaluate klass1") - assert(found.include?("/tmp/klass2"), "Did not evaluate klass2") - end - - def test_check_resource_collections - interp = mkinterp - scope = mkscope :interp => interp - coll = Puppet::Parser::Collector.new(scope, "file", nil, nil, :virtual) - coll.resources = ["File[/tmp/virtual1]", "File[/tmp/virtual2]"] - scope.newcollection(coll) - - assert_raise(Puppet::ParseError, "Did not fail on remaining resource colls") do - interp.check_resource_collections(scope) - end + interp.expects(:parsefiles) + parser = interp.instance_variable_get("@parser") + + node = mock('node') + config = mock('config') + config.expects(:compile).returns(:config) + Puppet::Parser::Configuration.expects(:new).with(node, parser).returns(config) + assert_equal(:config, interp.compile(node), "Did not return the results of config.compile") end # Make sure that reparsing is atomic -- failures don't cause a broken state, and we aren't subject @@ -373,7 +132,7 @@ class TestInterpreter < PuppetTest::TestCase interp = mkinterp :Manifest => file, :UseNodes => false assert_nothing_raised("Could not compile the first time") do - interp.run("yay", {}) + interp.compile(mknode("yay")) end oldparser = interp.send(:instance_variable_get, "@parser") @@ -381,7 +140,7 @@ class TestInterpreter < PuppetTest::TestCase # Now add a syntax failure File.open(file, "w") { |f| f.puts %{file { /tmp: ensure => directory }} } assert_nothing_raised("Could not compile the first time") do - interp.run("yay", {}) + interp.compile(mknode("yay")) end # And make sure the old parser is still there diff --git a/test/language/parser.rb b/test/language/parser.rb index 77595b155..c172aafca 100755 --- a/test/language/parser.rb +++ b/test/language/parser.rb @@ -38,13 +38,13 @@ class TestParser < Test::Unit::TestCase def test_failers failers { |file| parser = mkparser - interp = mkinterp Puppet.debug("parsing failer %s" % file) if __FILE__ == $0 - assert_raise(Puppet::ParseError) { + assert_raise(Puppet::ParseError, "Did not fail while parsing %s" % file) { parser.file = file ast = parser.parse - scope = mkscope :interp => interp - ast.classes[""].evaluate :scope => scope + config = mkconfig(parser) + config.compile + #ast.classes[""].evaluate :scope => config.topscope } Puppet::Type.allclear } @@ -622,7 +622,7 @@ file { "/tmp/yayness": code = nil assert_nothing_raised do - code = interp.run("hostname.domain.com", {}).flatten + code = interp.compile(mknode).flatten end assert(code.length == 1, "Did not get the file") assert_instance_of(Puppet::TransObject, code[0]) @@ -871,7 +871,8 @@ file { "/tmp/yayness": end def test_newclass - parser = mkparser + scope = mkscope + parser = scope.configuration.parser mkcode = proc do |ary| classes = ary.collect do |string| @@ -880,7 +881,6 @@ file { "/tmp/yayness": AST::ASTArray.new(:children => classes) end - scope = Puppet::Parser::Scope.new(:interp => mkinterp) # First make sure that code is being appended code = mkcode.call(%w{original code}) diff --git a/test/language/resource.rb b/test/language/resource.rb index 73d516f51..50d58cf32 100755 --- a/test/language/resource.rb +++ b/test/language/resource.rb @@ -19,6 +19,10 @@ class TestResource < PuppetTest::TestCase Puppet[:trace] = false end + def teardown + mocha_verify + end + def test_initialize args = {:type => "resource", :title => "testing", :source => "source", :scope => "scope"} @@ -208,11 +212,14 @@ class TestResource < PuppetTest::TestCase def test_to_trans # First try translating a builtin resource. Make sure we use some references # and arrays, to make sure they translate correctly. + source = mock("source") + scope = mock("scope") + scope.expects(:tags).returns([]) refs = [] 4.times { |i| refs << Puppet::Parser::Resource::Reference.new(:title => "file%s" % i, :type => "file") } res = Parser::Resource.new :type => "file", :title => "/tmp", - :source => @source, :scope => @scope, - :params => paramify(@source, :owner => "nobody", :group => %w{you me}, + :source => source, :scope => scope, + :params => paramify(source, :owner => "nobody", :group => %w{you me}, :require => refs[0], :ignore => %w{svn}, :subscribe => [refs[1], refs[2]], :notify => [refs[3]]) @@ -236,37 +243,25 @@ class TestResource < PuppetTest::TestCase end def test_evaluate - @parser = mkparser - # Make a definition that we know will, um, do something - @parser.newdefine "evaltest", - :arguments => [%w{one}, ["two", stringobj("755")]], - :code => resourcedef("file", "/tmp", - "owner" => varref("one"), "mode" => varref("two")) - - res = Parser::Resource.new :type => "evaltest", :title => "yay", - :source => @source, :scope => @scope, - :params => paramify(@source, :one => "nobody") + # First try the most common case, we're not a builtin type. + res = mkresource + ref = res.instance_variable_get("@ref") + type = mock("type") + ref.expects(:definedtype).returns(type) + res.expects(:finish) + res.scope = mock("scope") + config = mock("config") + res.scope.expects(:configuration).returns(config) + config.expects(:delete_resource).with(res) - # Now try evaluating - ret = nil - assert_nothing_raised do - ret = res.evaluate + args = {:scope => res.scope, :arguments => res.to_hash} + # This is insane; FIXME we need to redesign how classes and components are evaluated. + [:type, :title, :virtual, :exported].each do |param| + args[param] = res.send(param) end + type.expects(:evaluate_resource).with(args) - # Make sure we can find our object now - result = @scope.findresource("File[/tmp]") - - # Now make sure we got the code we expected. - assert_instance_of(Puppet::Parser::Resource, result) - - assert_equal("file", result.type) - assert_equal("/tmp", result.title) - assert_equal("nobody", result["owner"]) - assert_equal("755", result["mode"]) - - # And that we cannot find the old resource - assert_nil(@scope.findresource("Evaltest[yay]"), - "Evaluated resource was not deleted") + res.evaluate end def test_add_overrides @@ -303,7 +298,7 @@ class TestResource < PuppetTest::TestCase def test_proxymethods res = Parser::Resource.new :type => "evaltest", :title => "yay", - :source => @source, :scope => @scope + :source => mock("source"), :scope => mock('scope') assert_equal("evaltest", res.type) assert_equal("yay", res.title) @@ -331,6 +326,7 @@ class TestResource < PuppetTest::TestCase # Now create an obj that uses it res = mkresource :type => "file", :title => "/tmp/resource", :params => {:require => ref} + res.scope = stub(:tags => []) trans = nil assert_nothing_raised do @@ -344,6 +340,7 @@ class TestResource < PuppetTest::TestCase two = Parser::Resource::Reference.new(:type => "file", :title => "/tmp/ref2") res = mkresource :type => "file", :title => "/tmp/resource2", :params => {:require => [ref, two]} + res.scope = stub(:tags => []) trans = nil assert_nothing_raised do @@ -368,62 +365,24 @@ class TestResource < PuppetTest::TestCase assert_nil(ref.builtintype, "Component was considered builtin") end - # #472. Really, this still isn't the best behaviour, but at least - # it's consistent with what we have elsewhere. - def test_defaults_from_parent_classes - @parser = mkparser - # Make a parent class with some defaults in it - @parser.newclass("base", - :code => defaultobj("file", :owner => "root", :group => "root") - ) - - # Now a mid-level class with some different values - @parser.newclass("middle", :parent => "base", - :code => defaultobj("file", :owner => "bin", :mode => "755") - ) - - # Now a lower class with its own defaults plus a resource - @parser.newclass("bottom", :parent => "middle", - :code => AST::ASTArray.new(:children => [ - defaultobj("file", :owner => "adm", :recurse => "true"), - resourcedef("file", "/tmp/yayness", {}) - ]) - ) - - # Now evaluate the class. - assert_nothing_raised("Failed to evaluate class tree") do - @scope.evalclasses("bottom") - end - - # Make sure our resource got created. - res = @scope.findresource("File[/tmp/yayness]") - assert_nothing_raised("Could not add defaults") do - res.adddefaults - end - assert(res, "could not find resource") - {:owner => "adm", :recurse => "true", :group => "root", :mode => "755"}.each do |param, value| - assert_equal(value, res[param], "%s => %s did not inherit correctly" % - [param, value]) - end - end - # The second part of #539 - make sure resources pass the arguments # correctly. def test_title_with_definitions - @parser = mkparser - define = @parser.newdefine "yayness", + parser = mkparser + define = parser.newdefine "yayness", :code => resourcedef("file", "/tmp", "owner" => varref("name"), "mode" => varref("title")) - klass = @parser.findclass("", "") + + klass = parser.findclass("", "") should = {:name => :owner, :title => :mode} [ {:name => "one", :title => "two"}, {:title => "three"}, ].each do |hash| - scope = mkscope :parser => @parser + config = mkconfig parser args = {:type => "yayness", :title => hash[:title], - :source => klass, :scope => scope} + :source => klass, :scope => config.topscope} if hash[:name] args[:params] = {:name => hash[:name]} else @@ -438,7 +397,7 @@ class TestResource < PuppetTest::TestCase res.evaluate end - made = scope.findresource("File[/tmp]") + made = config.topscope.findresource("File[/tmp]") assert(made, "Did not create resource with %s" % hash.inspect) should.each do |orig, param| assert_equal(hash[orig] || hash[:title], made[param], @@ -450,7 +409,7 @@ class TestResource < PuppetTest::TestCase # part of #629 -- the undef keyword. Make sure 'undef' params get skipped. def test_undef_and_to_hash res = mkresource :type => "file", :title => "/tmp/testing", - :source => @source, :scope => @scope, + :source => mock("source"), :scope => mock("scope"), :params => {:owner => :undef, :mode => "755"} hash = nil @@ -463,12 +422,14 @@ class TestResource < PuppetTest::TestCase # #643 - Make sure virtual defines result in virtual resources def test_virtual_defines - @parser = mkparser - define = @parser.newdefine("yayness", + parser = mkparser + define = parser.newdefine("yayness", :code => resourcedef("file", varref("name"), "mode" => "644")) - res = mkresource :type => "yayness", :title => "foo", :params => {} + config = mkconfig(parser) + + res = mkresource :type => "yayness", :title => "foo", :params => {}, :scope => config.topscope res.virtual = true result = nil @@ -483,7 +444,7 @@ class TestResource < PuppetTest::TestCase assert(newres.virtual?, "Virtual defined resource generated non-virtual resources") # Now try it with exported resources - res = mkresource :type => "yayness", :title => "bar", :params => {} + res = mkresource :type => "yayness", :title => "bar", :params => {}, :scope => config.topscope res.exported = true result = nil diff --git a/test/language/scope.rb b/test/language/scope.rb index bd90caa53..fc5e085d4 100755 --- a/test/language/scope.rb +++ b/test/language/scope.rb @@ -27,74 +27,32 @@ class TestScope < Test::Unit::TestCase end def test_variables - scope = nil - over = "over" - - scopes = [] - vars = [] - values = {} - ovalues = [] - - 10.times { |index| - # slap some recursion in there - scope = mkscope(:parent => scope) - scopes.push scope - - var = "var%s" % index - value = rand(1000) - ovalue = rand(1000) - - ovalues.push ovalue + config = mkconfig + topscope = config.topscope + midscope = config.newscope(topscope) + botscope = config.newscope(midscope) - vars.push var - values[var] = value + scopes = {:top => topscope, :mid => midscope, :bot => botscope} - # set the variable in the current scope - assert_nothing_raised { - scope.setvar(var,value) - } + # Set a variable in the top and make sure all three can get it + topscope.setvar("first", "topval") + scopes.each do |name, scope| + assert_equal("topval", scope.lookupvar("first", false), "Could not find var in %s" % name) + end - # this should override previous values - assert_nothing_raised { - scope.setvar(over,ovalue) - } + # Now set a var in the midscope and make sure the mid and bottom can see it but not the top + midscope.setvar("second", "midval") + assert_equal(:undefined, scopes[:top].lookupvar("second", false), "Found child var in top scope") + [:mid, :bot].each do |name| + assert_equal("midval", scopes[name].lookupvar("second", false), "Could not find var in %s" % name) + end - assert_equal(value,scope.lookupvar(var)) - - #puts "%s vars, %s scopes" % [vars.length,scopes.length] - i = 0 - vars.zip(scopes) { |v,s| - # this recurses all the way up the tree as necessary - val = nil - oval = nil - - # look up the values using the bottom scope - assert_nothing_raised { - val = scope.lookupvar(v) - oval = scope.lookupvar(over) - } - - # verify they're correct - assert_equal(values[v],val) - assert_equal(ovalue,oval) - - # verify that we get the most recent value - assert_equal(ovalue,scope.lookupvar(over)) - - # verify that they aren't available in upper scopes - if parent = s.parent - val = nil - assert_nothing_raised { - val = parent.lookupvar(v) - } - assert_equal("", val, "Did not get empty string on missing var") - - # and verify that the parent sees its correct value - assert_equal(ovalues[i - 1],parent.lookupvar(over)) - end - i += 1 - } - } + # And set something in the bottom, and make sure we only find it there. + botscope.setvar("third", "botval") + [:top, :mid].each do |name| + assert_equal(:undefined, scopes[name].lookupvar("third", false), "Found child var in top scope") + end + assert_equal("botval", scopes[:bot].lookupvar("third", false), "Could not find var in bottom scope") end def test_lookupvar @@ -174,18 +132,18 @@ class TestScope < Test::Unit::TestCase defaults = scope.instance_variable_get("@defaults") # First the case where there are no defaults and we pass a single param - param = stub :name => "myparam" + param = stub :name => "myparam", :file => "f", :line => "l" scope.setdefaults(:mytype, param) assert_equal({"myparam" => param}, defaults[:mytype], "Did not set default correctly") # Now the case where we pass in multiple parameters - param1 = stub :name => "one" - param2 = stub :name => "two" + param1 = stub :name => "one", :file => "f", :line => "l" + param2 = stub :name => "two", :file => "f", :line => "l" scope.setdefaults(:newtype, [param1, param2]) assert_equal({"one" => param1, "two" => param2}, defaults[:newtype], "Did not set multiple defaults correctly") # And the case where there's actually a conflict. Use the first default for this. - newparam = stub :name => "myparam" + newparam = stub :name => "myparam", :file => "f", :line => "l" assert_raise(Puppet::ParseError, "Allowed resetting of defaults") do scope.setdefaults(:mytype, param) end @@ -238,7 +196,7 @@ class TestScope < Test::Unit::TestCase assert_equal(:myscope, scope.class_scope(:testing), "Did not pass back the results of config.class_scope") end - def test_strparser + def test_strinterp # Make and evaluate our classes so the qualified lookups work parser = mkparser klass = parser.newclass("") @@ -293,7 +251,7 @@ class TestScope < Test::Unit::TestCase tests.each do |input, output| assert_nothing_raised("Failed to scan %s" % input.inspect) do - assert_equal(output, scope.strparser(input), + assert_equal(output, scope.strinterp(input), 'did not parserret %s correctly' % input.inspect) end end @@ -306,7 +264,7 @@ class TestScope < Test::Unit::TestCase %w{d f h l w z}.each do |l| string = "\\" + l assert_nothing_raised do - assert_equal(string, scope.strparser(string), + assert_equal(string, scope.strinterp(string), 'did not parserret %s correctly' % string) end @@ -317,37 +275,35 @@ class TestScope < Test::Unit::TestCase end def test_setclass - parser, scope, source = mkclassframing - - base = scope.findclass("base") - assert(base, "Could not find base class") - assert(! scope.class_scope(base), "Class incorrectly set") - assert(! scope.classlist.include?("base"), "Class incorrectly in classlist") - assert_nothing_raised do - scope.setclass base - end - - assert(scope.class_scope(base), "Class incorrectly unset") - assert(scope.classlist.include?("base"), "Class not in classlist") - - # Make sure we can retrieve the scope. - assert_equal(scope, scope.class_scope(base), - "class scope was not set correctly") - - # Now try it with a normal string - Puppet[:trace] = false - assert_raise(Puppet::DevError) do - scope.setclass "string" + # Run through it when we're a normal class + config = mkconfig + scope = config.topscope + klass = mock("class") + klass.expects(:classname).returns(:myclass) + klass.expects(:is_a?).with(AST::HostClass).returns(true) + klass.expects(:is_a?).with(AST::Node).returns(false) + config.expects(:class_set).with(:myclass, scope) + scope.setclass(klass) + + # And when we're a node + config = mkconfig + scope = config.topscope + klass = mock("class2") + klass.expects(:classname).returns(:myclass) + klass.expects(:is_a?).with(AST::HostClass).returns(true) + klass.expects(:is_a?).with(AST::Node).returns(true) + config.expects(:class_set).with(:myclass, scope) + scope.setclass(klass) + assert(scope.nodescope?, "Did not set the scope as a node scope when evaluating a node") + + # And when we're invalid + config = mkconfig + scope = config.topscope + klass = mock("class3") + klass.expects(:is_a?).with(AST::HostClass).returns(false) + assert_raise(Puppet::DevError, "Did not fail when scope got passed a non-component") do + scope.setclass(klass) end - - assert(! scope.class_scope("string"), "string incorrectly set") - - # Set "" in the class list, and make sure it doesn't show up in the return - top = scope.findclass("") - assert(top, "Could not find top class") - scope.setclass top - - assert(! scope.classlist.include?(""), "Class list included empty") end def test_validtags @@ -368,7 +324,7 @@ class TestScope < Test::Unit::TestCase end def test_tagfunction - scope = mkscope() + scope = mkscope assert_nothing_raised { scope.function_tag(["yayness", "booness"]) @@ -445,62 +401,15 @@ class TestScope < Test::Unit::TestCase "undef considered true") end - # Verify scope context is handled correctly. - def test_scopeinside - scope = mkscope() - - one = :one - two = :two - - # First just test the basic functionality. - assert_nothing_raised { - scope.inside :one do - assert_equal(:one, scope.inside, "Context did not get set") - end - assert_nil(scope.inside, "Context did not revert") - } - - # Now make sure error settings work. - assert_raise(RuntimeError) { - scope.inside :one do - raise RuntimeError, "This is a failure, yo" - end - } - assert_nil(scope.inside, "Context did not revert") - - # Now test it a bit deeper in. - assert_nothing_raised { - scope.inside :one do - scope.inside :two do - assert_equal(:two, scope.inside, "Context did not get set") - end - assert_equal(:one, scope.inside, "Context did not get set") - end - assert_nil(scope.inside, "Context did not revert") - } - - # And lastly, check errors deeper in - assert_nothing_raised { - scope.inside :one do - begin - scope.inside :two do - raise "a failure" - end - rescue - end - assert_equal(:one, scope.inside, "Context did not get set") - end - assert_nil(scope.inside, "Context did not revert") - } - - end - if defined? ActiveRecord # Verify that we recursively mark as exported the results of collectable # components. def test_exportedcomponents - parser, scope, source = mkclassframing - children = [] + config = mkconfig + parser = config.parser + + # Create a default source + config.topscope.source = parser.newclass "", "" args = AST::ASTArray.new( :file => tempfile(), @@ -538,13 +447,14 @@ class TestScope < Test::Unit::TestCase # And mark it as exported obj.exported = true - obj.evaluate :scope => scope - # And then evaluate it - parser.evaliterate(scope) + obj.evaluate :scope => config.topscope + + # And run the loop. + config.send(:evaluate_generators) %w{file}.each do |type| - objects = scope.lookupexported(type) + objects = config.resources.find_all { |r| r.type == type and r.exported } assert(!objects.empty?, "Did not get an exported %s" % type) end @@ -722,26 +632,6 @@ Host <<||>>" assert_equal("", scope.lookupvar("testing", true), "undef was not returned as '' when string") end - - # #620 - Nodes and classes should conflict, else classes don't get evaluated - def test_nodes_and_classes_name_conflict - scope = mkscope - - node = AST::Node.new :classname => "test", :namespace => "" - scope.setclass(node) - - assert(scope.nodescope?, "Scope was not marked a node scope when a node was set") - - # Now make a subscope that will be a class scope - klass = AST::HostClass.new :classname => "test", :namespace => "" - kscope = klass.subscope(scope) - - # Now make sure we throw a failure, because we're trying to do a class and node - # with the same name - assert_raise(Puppet::ParseError, "Did not fail on class and node with same name") do - kscope.class_scope(klass) - end - end end # $Id$ diff --git a/test/lib/puppettest.rb b/test/lib/puppettest.rb index 5c385afb1..b56bc563e 100755 --- a/test/lib/puppettest.rb +++ b/test/lib/puppettest.rb @@ -283,6 +283,7 @@ module PuppetTest rescue Timeout::Error # just move on end + mocha_verify if File.stat("/dev/null").mode & 007777 != 0666 File.open("/tmp/nullfailure", "w") { |f| f.puts self.class diff --git a/test/lib/puppettest/parsertesting.rb b/test/lib/puppettest/parsertesting.rb index 368e112f9..0a695cbaa 100644 --- a/test/lib/puppettest/parsertesting.rb +++ b/test/lib/puppettest/parsertesting.rb @@ -45,7 +45,7 @@ module PuppetTest::ParserTesting require 'puppet/network/handler/node' parser ||= mkparser node = mknode - return Config.new(parser, node) + return Config.new(node, parser) end def mknode(name = nil) @@ -65,14 +65,14 @@ module PuppetTest::ParserTesting end def mkscope(hash = {}) - hash[:configuration] ||= mkconfig hash[:parser] ||= mkparser - hash[:source] ||= (hash[:parser].findclass("", "") || hash[:parser].newclass("")) + config ||= mkconfig(hash[:parser]) + config.topscope.source = (hash[:parser].findclass("", "") || hash[:parser].newclass("")) - unless hash[:source] + unless config.topscope.source raise "Could not find source for scope" end - Puppet::Parser::Scope.new(hash) + config.topscope end def classobj(name, hash = {}) @@ -308,7 +308,7 @@ module PuppetTest::ParserTesting config = nil assert_nothing_raised { - config = interp.run(Facter["hostname"].value, {}) + config = interp.compile(mknode) } comp = nil -- cgit From 4eb87ed7c8829a6fbc558595be9149e9b3cf5b36 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Mon, 20 Aug 2007 22:25:00 -0500 Subject: A round of bugfixing. Many more tests now pass -- I think we are largely down to tests that (yay!) fail in trunk. --- test/lib/puppettest/parsertesting.rb | 2 +- test/lib/puppettest/railstesting.rb | 8 +- test/lib/puppettest/resourcetesting.rb | 2 +- test/lib/spec/version.rb | 4 +- test/network/client/master.rb | 3 +- test/network/handler/configuration.rb | 4 +- test/network/handler/master.rb | 129 +++++++-------------------------- test/rails/collection.rb | 48 +++++------- test/rails/configuration.rb | 82 +++++++++++++++++++++ test/rails/host.rb | 30 +++----- test/rails/interpreter.rb | 91 ----------------------- test/rails/railsparameter.rb | 4 +- 12 files changed, 152 insertions(+), 255 deletions(-) create mode 100755 test/rails/configuration.rb delete mode 100755 test/rails/interpreter.rb (limited to 'test') diff --git a/test/lib/puppettest/parsertesting.rb b/test/lib/puppettest/parsertesting.rb index 0a695cbaa..3e2930728 100644 --- a/test/lib/puppettest/parsertesting.rb +++ b/test/lib/puppettest/parsertesting.rb @@ -51,7 +51,7 @@ module PuppetTest::ParserTesting def mknode(name = nil) name ||= "nodename" Puppet::Network::Handler.handler(:node) - Puppet::Network::Handler::Node::SimpleNode.new("nodename") + Puppet::Network::Handler::Node::SimpleNode.new(name) end def mkinterp(args = {}) diff --git a/test/lib/puppettest/railstesting.rb b/test/lib/puppettest/railstesting.rb index 8b5f074a2..403bdb756 100644 --- a/test/lib/puppettest/railstesting.rb +++ b/test/lib/puppettest/railstesting.rb @@ -40,12 +40,10 @@ module PuppetTest::RailsTesting # Now try storing our crap host = nil + node = mknode(facts["hostname"]) + node.parameters = facts assert_nothing_raised { - host = Puppet::Rails::Host.store( - :resources => resources, - :facts => facts, - :name => facts["hostname"] - ) + host = Puppet::Rails::Host.store(node, resources) } # Now save the whole thing diff --git a/test/lib/puppettest/resourcetesting.rb b/test/lib/puppettest/resourcetesting.rb index cbcfb0baf..e2176d5ef 100644 --- a/test/lib/puppettest/resourcetesting.rb +++ b/test/lib/puppettest/resourcetesting.rb @@ -28,7 +28,7 @@ module PuppetTest::ResourceTesting def mkresource(args = {}) args[:source] ||= "source" - args[:scope] ||= "scope" + args[:scope] ||= stub :tags => [] {:type => "resource", :title => "testing", :source => "source", :scope => "scope"}.each do |param, value| diff --git a/test/lib/spec/version.rb b/test/lib/spec/version.rb index 924d8458a..a0c0fdbbe 100644 --- a/test/lib/spec/version.rb +++ b/test/lib/spec/version.rb @@ -15,7 +15,7 @@ module Spec # RELEASE_CANDIDATE = "RC1" # RANDOM_TOKEN: 0.375509844656552 - REV = "$LastChangedRevision$".match(/LastChangedRevision: (\d+)/)[1] + REV = "LastChangedRevision: 2283".match(/LastChangedRevision: (\d+)/)[1] STRING = [MAJOR, MINOR, TINY].join('.') FULL_VERSION = "#{STRING} (r#{REV})" @@ -27,4 +27,4 @@ module Spec DESCRIPTION = "#{NAME}-#{FULL_VERSION} - BDD for Ruby\n#{URL}" end end -end \ No newline at end of file +end diff --git a/test/network/client/master.rb b/test/network/client/master.rb index 78a1a0a11..7746d20ff 100755 --- a/test/network/client/master.rb +++ b/test/network/client/master.rb @@ -75,7 +75,7 @@ class TestMasterClient < Test::Unit::TestCase def mk_fake_client server = Puppet::Network::Handler.master.new :Code => "" - master = Puppet::Network::Client.master.new :Server => server, :Local => true + master = Puppet::Network::Client.master.new :Master => server, :Local => true # Now create some objects objects = FakeComponent.new @@ -532,6 +532,7 @@ end master.local = false driver = master.send(:instance_variable_get, "@driver") driver.local = false + driver.send(:config_handler).local = false # Retrieve the configuration master.getconfig diff --git a/test/network/handler/configuration.rb b/test/network/handler/configuration.rb index 525db5e6a..98c3bdcde 100755 --- a/test/network/handler/configuration.rb +++ b/test/network/handler/configuration.rb @@ -170,7 +170,7 @@ class TestHandlerConfiguration < Test::Unit::TestCase handler.expects(:details).with(:client).returns(false) config.expects(:node_handler).returns(handler) interp = Object.new - interp.expects(:configuration_version).returns(:version) + interp.expects(:parsedate).returns(:version) config.expects(:interpreter).returns(interp) assert_equal(:version, config.version(:client), "Did not return configuration version") @@ -182,7 +182,7 @@ class TestHandlerConfiguration < Test::Unit::TestCase config.expects(:update_node_check).with(node) config.expects(:node_handler).returns(handler) interp = Object.new - interp.expects(:configuration_version).returns(:version) + interp.expects(:parsedate).returns(:version) config.expects(:interpreter).returns(interp) assert_equal(:version, config.version(:client), "Did not return configuration version") end diff --git a/test/network/handler/master.rb b/test/network/handler/master.rb index 9cf52b1cd..5ac8cbbbc 100755 --- a/test/network/handler/master.rb +++ b/test/network/handler/master.rb @@ -116,114 +116,39 @@ class TestMaster < Test::Unit::TestCase assert(FileTest.exists?(file2), "Second file %s does not exist" % file2) end - # Make sure we're using the hostname as configured with :node_name - def test_hostname_in_getconfig - master = nil - file = tempfile() - #@createdfile = File.join(tmpdir(), self.class.to_s + "manifesttesting" + - # "_" + @method_name) - file_cert = tempfile() - file_fact = tempfile() - - certname = "y4yn3ss" - factname = Facter.value("hostname") - - File.open(file, "w") { |f| - f.puts %{ - node #{certname} { file { "#{file_cert}": ensure => file, mode => 755 } } - node #{factname} { file { "#{file_fact}": ensure => file, mode => 755 } } -} - } - # create our master - assert_nothing_raised() { - # this is the default server setup - master = Puppet::Network::Handler.master.new( - :Manifest => file, - :UseNodes => true, - :Local => true - ) - } - - result = nil - - # Use the hostname from facter - Puppet[:node_name] = 'facter' - assert_nothing_raised { - result = master.getconfig({"hostname" => factname}, "yaml", certname, "127.0.0.1") - } - - result = result.flatten - - assert(result.find { |obj| obj.name == file_fact }, - "Could not find correct file") - assert(!result.find { |obj| obj.name == file_cert }, - "Found incorrect file") - - # Use the hostname from the cert - Puppet[:node_name] = 'cert' - assert_nothing_raised { - result = master.getconfig({"hostname" => factname}, "yaml", certname, "127.0.0.1") - } - - result = result.flatten - - assert(!result.find { |obj| obj.name == file_fact }, - "Could not find correct file") - assert(result.find { |obj| obj.name == file_cert }, - "Found incorrect file") - end - # Make sure we're correctly doing clientname manipulations. # Testing to make sure we always get a hostname and IP address. def test_clientname - master = nil - file = tempfile() - - File.open(file, "w") { |f| - f.puts %{ - node yay { file { "/something": ensure => file, mode => 755 } } -} - } # create our master - assert_nothing_raised() { - # this is the default server setup - master = Puppet::Network::Handler.master.new( - :Manifest => file, - :UseNodes => true, - :Local => true - ) - } + master = Puppet::Network::Handler.master.new( + :Manifest => tempfile, + :UseNodes => true, + :Local => true + ) + + # First check that 'cert' works Puppet[:node_name] = "cert" - # First act like we're local - fakename = nil - fakeip = nil - - name = ip = nil - facts = Facter.to_hash - assert_nothing_raised do - name, ip = master.clientname(fakename, fakeip, facts) - end - - assert(facts["hostname"], "Removed hostname fact") - assert(facts["ipaddress"], "Removed ipaddress fact") - - assert_equal(facts["hostname"], name) - assert_equal(facts["ipaddress"], ip) - - # Now set them to something real, and make sure we get them back - fakename = "yayness" - fakeip = "192.168.0.1" - facts = Facter.to_hash - assert_nothing_raised do - name, ip = master.clientname(fakename, fakeip, facts) - end - - assert(facts["hostname"], "Removed hostname fact") - assert(facts["ipaddress"], "Removed ipaddress fact") - - assert_equal(fakename, name) - assert_equal(fakeip, ip) + + # Make sure we get the fact data back when nothing is set + facts = {"hostname" => "fact_hostname", "ipaddress" => "fact_ip"} + certname = "cert_hostname" + certip = "cert_ip" + + resname, resip = master.send(:clientname, nil, nil, facts) + assert_equal(facts["hostname"], resname, "Did not use fact hostname when no certname was present") + assert_equal(facts["ipaddress"], resip, "Did not use fact ip when no certname was present") + + # Now try it with the cert stuff present + resname, resip = master.send(:clientname, certname, certip, facts) + assert_equal(certname, resname, "Did not use cert hostname when certname was present") + assert_equal(certip, resip, "Did not use cert ip when certname was present") + + # And reset the node_name stuff and make sure we use it. + Puppet[:node_name] = :facter + resname, resip = master.send(:clientname, certname, certip, facts) + assert_equal(facts["hostname"], resname, "Did not use fact hostname when nodename was set to facter") + assert_equal(facts["ipaddress"], resip, "Did not use fact ip when nodename was set to facter") end end diff --git a/test/rails/collection.rb b/test/rails/collection.rb index d878641be..18de3c77b 100755 --- a/test/rails/collection.rb +++ b/test/rails/collection.rb @@ -22,15 +22,12 @@ class TestRailsCollection < PuppetTest::TestCase def setup super Puppet[:trace] = false - @interp, @scope, @source = mkclassframing + @scope = mkscope end def test_collect_exported railsinit - # Set a hostname - @scope.host = Facter.value(:hostname) - # make an exported resource exported = mkresource(:type => "file", :title => "/tmp/exported", :exported => true, :params => {:owner => "root"}) @@ -51,10 +48,10 @@ class TestRailsCollection < PuppetTest::TestCase end # Set it in our scope - @scope.newcollection(coll) + @scope.configuration.add_collection(coll) # Make sure it's in the collections - assert_equal([coll], @scope.collections) + assert_equal([coll], @scope.configuration.collections) # And try to collect the virtual resources. ret = nil @@ -111,39 +108,39 @@ class TestRailsCollection < PuppetTest::TestCase # Now try storing our crap # Remark this as exported exported.exported = true - host = Puppet::Rails::Host.store( - :resources => [exported], - :facts => facts, - :name => facts["hostname"] - ) + exported.scope.stubs(:tags).returns([]) + node = mknode(facts["hostname"]) + node.parameters = facts + host = Puppet::Rails::Host.store(node, [exported]) assert(host, "did not get rails host") host.save # And make sure it's in there newres = host.resources.find_by_restype_and_title_and_exported("file", "/tmp/exported", true) assert(newres, "Did not find resource in db") - interp, scope, source = mkclassframing - scope.host = "two" + assert(newres.exported?, "Resource was not exported") + + # Make a new set with a different node name + node = mknode("other") + config = Puppet::Parser::Configuration.new(node, mkparser) + config.topscope.source = mock("source") + + # It's important that it's a different name, since same-name resources are ignored. + assert_equal("other", config.node.name, "Did not get correct node name") # Now make a collector coll = nil assert_nothing_raised do - coll = Puppet::Parser::Collector.new(scope, "file", nil, nil, :exported) + coll = Puppet::Parser::Collector.new(config.topscope, "file", nil, nil, :exported) end - # Set it in our scope - scope.newcollection(coll) - - # Make sure it's in the collections - assert_equal([coll], scope.collections) - # And try to collect the virtual resources. ret = nil - assert_nothing_raised do + assert_nothing_raised("Could not collect exported resources") do ret = coll.collect_exported end - assert_equal(["/tmp/exported"], ret.collect { |f| f.title }) + assert_equal(["/tmp/exported"], ret.collect { |f| f.title }, "Did not find resource in collction") # Make sure we can evaluate the same collection multiple times and # that later collections do nothing @@ -167,7 +164,6 @@ class TestRailsCollection < PuppetTest::TestCase normal = mkresource(:type => "file", :title => "/tmp/conflicttest", :params => {:owner => "root"}) @scope.setresource normal - @scope.host = "otherhost" # Now make a collector coll = nil @@ -186,15 +182,13 @@ class TestRailsCollection < PuppetTest::TestCase railsinit # Make our configuration - host = Puppet::Rails::Host.new(:name => "myhost") + host = Puppet::Rails::Host.new(:name => @scope.host) host.resources.build(:title => "/tmp/hosttest", :restype => "file", :exported => true) host.save - @scope.host = "myhost" - # Now make a collector coll = nil assert_nothing_raised do @@ -224,8 +218,6 @@ class TestRailsCollection < PuppetTest::TestCase host.save - @scope.host = "otherhost" - # Now make a collector coll = nil assert_nothing_raised do diff --git a/test/rails/configuration.rb b/test/rails/configuration.rb new file mode 100755 index 000000000..31d1cf779 --- /dev/null +++ b/test/rails/configuration.rb @@ -0,0 +1,82 @@ +#!/usr/bin/env ruby + +$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'puppettest' +require 'puppet/parser/parser' +require 'puppet/network/client' +require 'puppet/rails' +require 'puppettest/resourcetesting' +require 'puppettest/parsertesting' +require 'puppettest/servertest' +require 'puppettest/railstesting' + + +class ConfigurationRailsTests < PuppetTest::TestCase + include PuppetTest + include PuppetTest::ServerTest + include PuppetTest::ParserTesting + include PuppetTest::ResourceTesting + include PuppetTest::RailsTesting + AST = Puppet::Parser::AST + confine "No rails support" => Puppet.features.rails? + + # We need to make sure finished objects are stored in the db. + def test_finish_before_store + railsinit + config = mkconfig + config.ast_nodes = true + parser = config.parser + + node = parser.newnode [config.node.name], :code => AST::ASTArray.new(:children => [ + resourcedef("file", "/tmp/yay", :group => "root"), + defaultobj("file", :owner => "root") + ]) + + # Now do the rails crap + Puppet[:storeconfigs] = true + + Puppet::Rails::Host.expects(:store).with do |node, resources| + if res = resources.find { |r| r.type == "file" and r.title == "/tmp/yay" } + assert_equal("root", res["owner"], "Did not set default on resource") + true + else + raise "Resource was not passed to store()" + end + end + config.compile + end + + def test_hoststorage + assert_nothing_raised { + Puppet[:storeconfigs] = true + } + + file = tempfile() + File.open(file, "w") { |f| + f.puts "file { \"/etc\": owner => root }" + } + + interp = nil + assert_nothing_raised { + interp = Puppet::Parser::Interpreter.new( + :Manifest => file, + :UseNodes => false, + :ForkSave => false + ) + } + + facts = {} + Facter.each { |fact, val| facts[fact] = val } + node = mknode(facts["hostname"]) + node.parameters = facts + + objects = nil + assert_nothing_raised { + objects = interp.compile(node) + } + + obj = Puppet::Rails::Host.find_by_name(node.name) + assert(obj, "Could not find host object") + end +end diff --git a/test/rails/host.rb b/test/rails/host.rb index f3190c047..67095a18a 100755 --- a/test/rails/host.rb +++ b/test/rails/host.rb @@ -56,13 +56,10 @@ class TestRailsHost < PuppetTest::TestCase # Now try storing our crap host = nil + node = mknode(facts["hostname"]) + node.parameters = facts assert_nothing_raised { - host = Puppet::Rails::Host.store( - :resources => resources, - :facts => facts, - :name => facts["hostname"], - :classes => ["one", "two::three", "four"] - ) + host = Puppet::Rails::Host.store(node, resources) } assert(host, "Did not create host") @@ -110,7 +107,7 @@ class TestRailsHost < PuppetTest::TestCase # Change a few resources resources.find_all { |r| r.title =~ /file2/ }.each do |r| - r.set("loglevel", "notice", r.source) + r.send(:set_parameter, "loglevel", "notice") end # And add a new resource @@ -124,13 +121,10 @@ class TestRailsHost < PuppetTest::TestCase facts["test1"] = "changedfact" facts.delete("ipaddress") host = nil + node = mknode(facts["hostname"]) + node.parameters = facts assert_nothing_raised { - host = Puppet::Rails::Host.store( - :resources => resources, - :facts => facts, - :name => facts["hostname"], - :classes => ["one", "two::three", "four"] - ) + host = Puppet::Rails::Host.store(node, resources) } # Make sure it sets the last_compile time @@ -162,7 +156,7 @@ class TestRailsHost < PuppetTest::TestCase Puppet[:storeconfigs] = true # this is the default server setup - master = Puppet::Network::Handler.master.new( + master = Puppet::Network::Handler.configuration.new( :Code => "", :UseNodes => true, :Local => true @@ -172,7 +166,7 @@ class TestRailsHost < PuppetTest::TestCase Puppet::Rails::Host.new(:name => "test", :ip => "192.168.0.3").save assert_nothing_raised("Failed to update last_connect for unknown host") do - master.freshness("created",'192.168.0.1') + master.version("created",'192.168.0.1') end # Make sure it created the host @@ -180,12 +174,10 @@ class TestRailsHost < PuppetTest::TestCase assert(created, "Freshness did not create host") assert(created.last_freshcheck, "Did not set last_freshcheck on created host") - assert_equal("192.168.0.1", created.ip, - "Did not set IP address on created host") # Now check on the existing host assert_nothing_raised("Failed to update last_connect for unknown host") do - master.freshness("test",'192.168.0.2') + master.version("test",'192.168.0.2') end # Recreate it, so we're not using the cached object. @@ -194,8 +186,6 @@ class TestRailsHost < PuppetTest::TestCase # Make sure it created the host assert(host.last_freshcheck, "Did not set last_freshcheck on existing host") - assert_equal("192.168.0.3", host.ip, - "Overrode IP on found host") end end diff --git a/test/rails/interpreter.rb b/test/rails/interpreter.rb deleted file mode 100755 index 0eba3f590..000000000 --- a/test/rails/interpreter.rb +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env ruby - -$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ - -require 'puppettest' -require 'puppet/parser/interpreter' -require 'puppet/parser/parser' -require 'puppet/network/client' -require 'puppet/rails' -require 'puppettest/resourcetesting' -require 'puppettest/parsertesting' -require 'puppettest/servertest' -require 'puppettest/railstesting' - - -class InterpreterRailsTests < PuppetTest::TestCase - include PuppetTest - include PuppetTest::ServerTest - include PuppetTest::ParserTesting - include PuppetTest::ResourceTesting - include PuppetTest::RailsTesting - AST = Puppet::Parser::AST - NodeDef = Puppet::Parser::Interpreter::NodeDef - confine "No rails support" => Puppet.features.rails? - - # We need to make sure finished objects are stored in the db. - def test_finish_before_store - railsinit - interp = mkinterp - - node = interp.newnode ["myhost"], :code => AST::ASTArray.new(:children => [ - resourcedef("file", "/tmp/yay", :group => "root"), - defaultobj("file", :owner => "root") - ]) - - interp.newclass "myclass", :code => AST::ASTArray.new(:children => [ - ]) - - interp.newclass "sub", :parent => "myclass", - :code => AST::ASTArray.new(:children => [ - resourceoverride("file", "/tmp/yay", :owner => "root") - ] - ) - - # Now do the rails crap - Puppet[:storeconfigs] = true - - interp.evaluate("myhost", {}) - - # And then retrieve the object from rails - #res = Puppet::Rails::Resource.find_by_restype_and_title("file", "/tmp/yay", :include => {:param_values => :param_names}) - res = Puppet::Rails::Resource.find_by_restype_and_title("file", "/tmp/yay") - - assert(res, "Did not get resource from rails") - - params = res.parameters - - assert_equal(["root"], params["owner"], "Did not get correct value for owner param") - end - - def test_hoststorage - assert_nothing_raised { - Puppet[:storeconfigs] = true - } - - file = tempfile() - File.open(file, "w") { |f| - f.puts "file { \"/etc\": owner => root }" - } - - interp = nil - assert_nothing_raised { - interp = Puppet::Parser::Interpreter.new( - :Manifest => file, - :UseNodes => false, - :ForkSave => false - ) - } - - facts = {} - Facter.each { |fact, val| facts[fact] = val } - - objects = nil - assert_nothing_raised { - objects = interp.run(facts["hostname"], facts) - } - - obj = Puppet::Rails::Host.find_by_name(facts["hostname"]) - assert(obj, "Could not find host object") - end -end diff --git a/test/rails/railsparameter.rb b/test/rails/railsparameter.rb index 82d978bb4..89c81ad30 100755 --- a/test/rails/railsparameter.rb +++ b/test/rails/railsparameter.rb @@ -21,8 +21,8 @@ class TestRailsParameter < Test::Unit::TestCase railsinit # Now create a source - interp = mkinterp - source = interp.newclass "myclass" + parser = mkparser + source = parser.newclass "myclass" host = Puppet::Rails::Host.new(:name => "myhost") -- cgit From f1727f18ab933df9ecbecc2da8fad72eb441e0d5 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Wed, 22 Aug 2007 16:14:39 -0500 Subject: Adding the topscope metadata to the configuration being returned to the client, just like it expects, and fixing how the resource handler calls the master type. --- test/network/client/client.rb | 7 +------ test/network/handler/resource.rb | 2 +- 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'test') diff --git a/test/network/client/client.rb b/test/network/client/client.rb index 14c90f2a9..3f540d10f 100755 --- a/test/network/client/client.rb +++ b/test/network/client/client.rb @@ -164,15 +164,10 @@ class TestClient < Test::Unit::TestCase # Fake that it's local, so it creates the class file client.local = false + client.expects(:setclasses).with(%w{yaytest bootest}) assert_nothing_raised { client.getconfig } - - assert(FileTest.exists?(Puppet[:classfile]), "Class file does not exist") - - classes = File.read(Puppet[:classfile]).split("\n") - - assert_equal(%w{bootest yaytest}, classes.sort) end def test_client_loading diff --git a/test/network/handler/resource.rb b/test/network/handler/resource.rb index 589d22d83..18f52dbd6 100755 --- a/test/network/handler/resource.rb +++ b/test/network/handler/resource.rb @@ -236,7 +236,7 @@ class TestResourceServer < Test::Unit::TestCase def test_apply server = nil assert_nothing_raised do - server = Puppet::Network::Handler.resource.new() + server = Puppet::Network::Handler.resource.new(:Local => false) end file = tempfile() -- cgit From 8b3361afae35cfb65754d7bd9aff5b820ed714f0 Mon Sep 17 00:00:00 2001 From: Luke Kanies Date: Wed, 22 Aug 2007 17:57:28 -0500 Subject: The last commits before I actually start on the multi-environment support. There are still failing tests, but apparently only those that are also failing in trunk. --- test/language/configuration.rb | 2 +- test/network/handler/node.rb | 68 +----------------------------------- test/network/xmlrpc/processor.rb | 2 +- test/other/node.rb | 75 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+), 69 deletions(-) create mode 100755 test/other/node.rb (limited to 'test') diff --git a/test/language/configuration.rb b/test/language/configuration.rb index fbdf68e73..a17b5a7ae 100755 --- a/test/language/configuration.rb +++ b/test/language/configuration.rb @@ -15,7 +15,7 @@ class TestConfiguration < Test::Unit::TestCase Config = Puppet::Parser::Configuration Scope = Puppet::Parser::Scope Node = Puppet::Network::Handler.handler(:node) - SimpleNode = Node::SimpleNode + SimpleNode = Puppet::Node def mknode(name = "foo") @node = SimpleNode.new(name) diff --git a/test/network/handler/node.rb b/test/network/handler/node.rb index 745c7470e..d5c98fec6 100755 --- a/test/network/handler/node.rb +++ b/test/network/handler/node.rb @@ -12,7 +12,7 @@ require 'puppet/network/handler/node' module NodeTesting include PuppetTest Node = Puppet::Network::Handler::Node - SimpleNode = Puppet::Network::Handler::Node::SimpleNode + SimpleNode = Puppet::Node def mk_node_mapper # First, make sure our nodesearch command works as we expect @@ -342,72 +342,6 @@ class TestNodeHandler < Test::Unit::TestCase end end -class TestSimpleNode < Test::Unit::TestCase - include NodeTesting - - # Make sure we get all the defaults correctly. - def test_simplenode_initialize - node = nil - assert_nothing_raised("could not create a node without classes or parameters") do - node = SimpleNode.new("testing") - end - assert_equal("testing", node.name, "Did not set name correctly") - assert_equal({}, node.parameters, "Node parameters did not default correctly") - assert_equal([], node.classes, "Node classes did not default correctly") - assert_instance_of(Time, node.time, "Did not set the creation time") - - # Now test it with values for both - params = {"a" => "b"} - classes = %w{one two} - assert_nothing_raised("could not create a node with classes and parameters") do - node = SimpleNode.new("testing", :parameters => params, :classes => classes) - end - assert_equal("testing", node.name, "Did not set name correctly") - assert_equal(params, node.parameters, "Node parameters did not get set correctly") - assert_equal(classes, node.classes, "Node classes did not get set correctly") - - # And make sure a single class gets turned into an array - assert_nothing_raised("could not create a node with a class as a string") do - node = SimpleNode.new("testing", :classes => "test") - end - assert_equal(%w{test}, node.classes, "A node class string was not converted to an array") - - # Make sure we get environments - assert_nothing_raised("could not create a node with an environment") do - node = SimpleNode.new("testing", :environment => "test") - end - assert_equal("test", node.environment, "Environment was not set") - - # Now make sure we get the default env - Puppet[:environment] = "prod" - assert_nothing_raised("could not create a node with no environment") do - node = SimpleNode.new("testing") - end - assert_equal("prod", node.environment, "Did not get default environment") - - # But that it stays nil if there's no default env set - Puppet[:environment] = "" - assert_nothing_raised("could not create a node with no environment and no default env") do - node = SimpleNode.new("testing") - end - assert_nil(node.environment, "Got a default env when none was set") - - end - - # Verify that the node source wins over facter. - def test_fact_merge - node = SimpleNode.new("yay", :parameters => {"a" => "one", "b" => "two"}) - - assert_nothing_raised("Could not merge parameters") do - node.fact_merge("b" => "three", "c" => "yay") - end - params = node.parameters - assert_equal("one", params["a"], "Lost nodesource parameters in parameter merge") - assert_equal("two", params["b"], "Overrode nodesource parameters in parameter merge") - assert_equal("yay", params["c"], "Did not get facts in parameter merge") - end -end - # Test our configuration object. class TestNodeSources < Test::Unit::TestCase include NodeTesting diff --git a/test/network/xmlrpc/processor.rb b/test/network/xmlrpc/processor.rb index 101d268b2..6808d0100 100755 --- a/test/network/xmlrpc/processor.rb +++ b/test/network/xmlrpc/processor.rb @@ -64,7 +64,7 @@ class TestXMLRPCProcessor < Test::Unit::TestCase request.expects(:handler=).with("myhandler") request.expects(:method=).with("mymethod") - @processor.expects(:verify).times(2) + @processor.stubs(:verify) @processor.expects(:handle).with(request.call, "params", request.name, request.ip) diff --git a/test/other/node.rb b/test/other/node.rb new file mode 100755 index 000000000..b3f12d11d --- /dev/null +++ b/test/other/node.rb @@ -0,0 +1,75 @@ +#!/usr/bin/env ruby + +$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ + +require 'mocha' +require 'puppettest' +require 'puppet/node' + +class TestNode < Test::Unit::TestCase + include PuppetTest + Node = Puppet::Node + + # Make sure we get all the defaults correctly. + def test_initialize + node = nil + assert_nothing_raised("could not create a node without classes or parameters") do + node = Node.new("testing") + end + assert_equal("testing", node.name, "Did not set name correctly") + assert_equal({}, node.parameters, "Node parameters did not default correctly") + assert_equal([], node.classes, "Node classes did not default correctly") + assert_instance_of(Time, node.time, "Did not set the creation time") + + # Now test it with values for both + params = {"a" => "b"} + classes = %w{one two} + assert_nothing_raised("could not create a node with classes and parameters") do + node = Node.new("testing", :parameters => params, :classes => classes) + end + assert_equal("testing", node.name, "Did not set name correctly") + assert_equal(params, node.parameters, "Node parameters did not get set correctly") + assert_equal(classes, node.classes, "Node classes did not get set correctly") + + # And make sure a single class gets turned into an array + assert_nothing_raised("could not create a node with a class as a string") do + node = Node.new("testing", :classes => "test") + end + assert_equal(%w{test}, node.classes, "A node class string was not converted to an array") + + # Make sure we get environments + assert_nothing_raised("could not create a node with an environment") do + node = Node.new("testing", :environment => "test") + end + assert_equal("test", node.environment, "Environment was not set") + + # Now make sure we get the default env + Puppet[:environment] = "prod" + assert_nothing_raised("could not create a node with no environment") do + node = Node.new("testing") + end + assert_equal("prod", node.environment, "Did not get default environment") + + # But that it stays nil if there's no default env set + Puppet[:environment] = "" + assert_nothing_raised("could not create a node with no environment and no default env") do + node = Node.new("testing") + end + assert_nil(node.environment, "Got a default env when none was set") + + end + + # Verify that the node source wins over facter. + def test_fact_merge + node = Node.new("yay", :parameters => {"a" => "one", "b" => "two"}) + + assert_nothing_raised("Could not merge parameters") do + node.fact_merge("b" => "three", "c" => "yay") + end + params = node.parameters + assert_equal("one", params["a"], "Lost nodesource parameters in parameter merge") + assert_equal("two", params["b"], "Overrode nodesource parameters in parameter merge") + assert_equal("yay", params["c"], "Did not get facts in parameter merge") + end +end + -- cgit