#!/usr/bin/env ruby

$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/

require 'facter'

require 'puppet'
require 'puppet/parser/interpreter'
require 'puppet/parser/parser'
require 'puppet/network/client'
require 'puppettest'
require 'puppettest/resourcetesting'
require 'puppettest/parsertesting'
require 'puppettest/servertest'
require 'timeout'

class TestInterpreter < PuppetTest::TestCase
	include PuppetTest
    include PuppetTest::ServerTest
    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)
        createdfile = tempfile()

        File.open(file, "w") { |f|
            f.puts "node %s { file { \"%s\": ensure => file, mode => 755 } }\n" %
                [node, createdfile]
        }

        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

        file = tempfile()

        # Create a first version
        createdfile = mknodemanifest(hostname, file)

        interp = nil
        assert_nothing_raised {
            interp = Puppet::Parser::Interpreter.new(:Manifest => file)
        }

        config = nil
        assert_nothing_raised {
            config = interp.run(hostname, {})
        }
        sleep(1)

        # Now create a new file
        createdfile = mknodemanifest(hostname, file)

        newconfig = nil
        assert_nothing_raised {
            newconfig = interp.run(hostname, {})
        }

        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()
        sub = tempfile()
        mainfile = tempfile()
        subfile = tempfile()
        count = 0
        updatemain = proc do
            count += 1
            File.open(main, "w") { |f|
                f.puts "import '#{sub}'
                    file { \"#{mainfile}\": content => #{count} }
                    "
            }
        end
        updatesub = proc do
            count += 1
            File.open(sub, "w") { |f|
                f.puts "file { \"#{subfile}\": content => #{count} }
                "
            }
        end

        updatemain.call
        updatesub.call

        interp = Puppet::Parser::Interpreter.new(
            :Manifest => main,
            :Local => true
        )

        date = interp.parsedate

        # Now update the site file and make sure we catch it
        sleep 1
        updatemain.call
        newdate = interp.parsedate
        assert(date != newdate, "Parsedate was not updated")
        date = newdate

        # And then the subfile
        sleep 1
        updatesub.call
        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
        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
        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 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[0].chomp
            result = {}

            if name =~ /a/
                result[:parameters] = {'one' => ARGV[0] + '1', 'two' => ARGV[0] + '2'}
            end

            if name =~ /p/
                result['classes'] = [1,2,3].collect { |n| ARGV[0] + 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
    
    # 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
        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
    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

    # 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
        Puppet[:filetimeout] = -10
        file = tempfile
        File.open(file, "w") { |f| f.puts %{file { '/tmp': ensure => directory }} }
        interp = mkinterp :Manifest => file, :UseNodes => false

        assert_nothing_raised("Could not compile the first time") do
            interp.run("yay", {})
        end

        oldparser = interp.send(:instance_variable_get, "@parser")

        # 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", {})
        end

        # And make sure the old parser is still there
        newparser = interp.send(:instance_variable_get, "@parser")
        assert_equal(oldparser.object_id, newparser.object_id, "Failed parser still replaced existing parser")
    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: interpreter.rb 2742 2007-08-03 23:49:53Z luke $


syntax highlighted by Code2HTML, v. 0.9.1