summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rwxr-xr-xtest/language/configuration.rb627
1 files changed, 606 insertions, 21 deletions
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