diff options
294 files changed, 12325 insertions, 2157 deletions
@@ -1,3 +1,18 @@ + Fixed #997 -- virtual defined types are no longer evaluated. + NOTE: This introduces a behaviour change, in that you previously + could realize a resource within a virtual defined resource, and now + you must realize the entire defined resource, rather than just + the contained resource. + + Fixed #1030 - class and definition evaluation has been significantly + refactored, fixing this problem and making the whole interplay + between the classes, definitions, and nodes, and the Compile class much + cleaner. + + Exec resources must now have unique names. This is easily accomplished by + just specifying a unique name with whatever (unique or otherwise) command + you need. + Fixed #989 -- missing CRL files are correctly ignored, and the value should be set to 'false' to explicitly not look for these files. diff --git a/spec/lib/autotest/discover.rb b/autotest/discover.rb index 0ac563724..0ac563724 100644 --- a/spec/lib/autotest/discover.rb +++ b/autotest/discover.rb diff --git a/spec/lib/autotest/puppet_rspec.rb b/autotest/puppet_rspec.rb index 8536f3912..fc537e016 100644 --- a/spec/lib/autotest/puppet_rspec.rb +++ b/autotest/puppet_rspec.rb @@ -43,4 +43,19 @@ class Autotest::PuppetRspec < Autotest::Rspec }, } end + + # Autotest will look for spec commands in the following + # locations, in this order: + # + # * bin/spec + # * default spec bin/loader installed in Rubygems + # * our local vendor/gems/rspec/bin/spec + def spec_commands + [ + File.join('bin', 'spec'), + File.join(Config::CONFIG['bindir'], 'spec'), + File.join('vendor', 'gems', 'rspec', 'bin', 'spec') + ] + end + end diff --git a/spec/lib/autotest/rspec.rb b/autotest/rspec.rb index d4b77ea6b..d4b77ea6b 100644 --- a/spec/lib/autotest/rspec.rb +++ b/autotest/rspec.rb diff --git a/lib/puppet/node/catalog.rb b/lib/puppet/node/catalog.rb index 9601309d8..b74947107 100644 --- a/lib/puppet/node/catalog.rb +++ b/lib/puppet/node/catalog.rb @@ -1,5 +1,7 @@ require 'puppet/indirector' +require 'puppet/util/tagging' + # This class models a node catalog. It is the thing # meant to be passed from server to client, and it contains all # of the information in the catalog, including the resources @@ -8,6 +10,8 @@ class Puppet::Node::Catalog < Puppet::PGraph extend Puppet::Indirector indirects :catalog, :terminus_class => :compiler + include Puppet::Util::Tagging + # The host name this is a catalog for. attr_accessor :name @@ -58,14 +62,14 @@ class Puppet::Node::Catalog < Puppet::PGraph raise ArgumentError, "Can only add objects that respond to :ref" end + fail_unless_unique(resource) + ref = resource.ref - if @resource_table.include?(ref) - raise ArgumentError, "Resource %s is already defined" % ref - else - @resource_table[ref] = resource - end - resource.catalog = self unless is_relationship_graph - add_vertex!(resource) + + @resource_table[ref] = resource + + resource.catalog = self if resource.respond_to?(:catalog=) and ! is_relationship_graph + add_vertex(resource) end end @@ -268,7 +272,6 @@ class Puppet::Node::Catalog < Puppet::PGraph super() @name = name if name @extraction_format ||= :transportable - @tags = [] @classes = [] @resource_table = {} @transient_resources = [] @@ -313,9 +316,9 @@ class Puppet::Node::Catalog < Puppet::PGraph # First create the dependency graph self.vertices.each do |vertex| - @relationship_graph.add_vertex! vertex + @relationship_graph.add_vertex vertex vertex.builddepends.each do |edge| - @relationship_graph.add_edge!(edge) + @relationship_graph.add_edge(edge) end end @@ -325,7 +328,7 @@ class Puppet::Node::Catalog < Puppet::PGraph unless @relationship_graph.edge?(edge.source, edge.target) # don't let automatic relationships conflict with manual ones. unless @relationship_graph.edge?(edge.target, edge.source) vertex.debug "Autorequiring %s" % [edge.source] - @relationship_graph.add_edge!(edge) + @relationship_graph.add_edge(edge) else vertex.debug "Skipping automatic relationship with %s" % (edge.source == vertex ? edge.target : edge.source) end @@ -381,25 +384,6 @@ class Puppet::Node::Catalog < Puppet::PGraph @resource_table.keys end - # Add a tag. - def tag(*names) - names.each do |name| - name = name.to_s - @tags << name unless @tags.include?(name) - if name.include?("::") - name.split("::").each do |sub| - @tags << sub unless @tags.include?(sub) - end - end - end - nil - end - - # Return the list of tags. - def tags - @tags.dup - end - # Convert our catalog into a RAL catalog. def to_ral to_catalog :to_type @@ -447,6 +431,28 @@ class Puppet::Node::Catalog < Puppet::PGraph end end + # Verify that the given resource isn't defined elsewhere. + def fail_unless_unique(resource) + # Short-curcuit the common case, + return unless existing_resource = @resource_table[resource.ref] + + # Either it's a defined type, which are never + # isomorphic, or it's a non-isomorphic type, so + # we should throw an exception. + msg = "Duplicate definition: %s is already defined" % resource.ref + + if existing_resource.file and existing_resource.line + msg << " in file %s at line %s" % + [existing_resource.file, existing_resource.line] + end + + if resource.line or resource.file + msg << "; cannot redefine" + end + + raise ArgumentError.new(msg) + end + # An abstracted method for converting one catalog into another type of catalog. # This pretty much just converts all of the resources from one class to another, using # a conversion method. @@ -481,7 +487,7 @@ class Puppet::Node::Catalog < Puppet::PGraph raise Puppet::DevError, "Could not find resource %s when converting %s resources" % [edge.target.ref, message] end - result.add_edge!(source, target, edge.label) + result.add_edge(source, target, edge.label) end map.clear diff --git a/lib/puppet/parser/ast.rb b/lib/puppet/parser/ast.rb index 14b686e2f..c9bd7c9e8 100644 --- a/lib/puppet/parser/ast.rb +++ b/lib/puppet/parser/ast.rb @@ -14,30 +14,6 @@ class Puppet::Parser::AST include Puppet::Util::MethodHelper attr_accessor :line, :file, :parent, :scope - # Just used for 'tree', which is only used in debugging. - @@pink = "[0;31m" - @@green = "[0;32m" - @@yellow = "[0;33m" - @@slate = "[0;34m" - @@reset = "[0m" - - # Just used for 'tree', which is only used in debugging. - @@indent = " " * 4 - @@indline = @@pink + ("-" * 4) + @@reset - @@midline = @@slate + ("-" * 4) + @@reset - - @@settypes = {} - - # Just used for 'tree', which is only used in debugging. - def AST.indention - return @@indent * @@indention - end - - # Just used for 'tree', which is only used in debugging. - def AST.midline - return @@midline - end - # Does this ast object set something? If so, it gets evaluated first. def self.settor? if defined? @settor @@ -47,16 +23,12 @@ class Puppet::Parser::AST end end - # Evaluate the current object. Basically just iterates across all + # Evaluate the current object. Just a stub method, since the subclass + # should override this method. # of the contained children and evaluates them in turn, returning a # list of all of the collected values, rejecting nil values - def evaluate(args) - #Puppet.debug("Evaluating ast %s" % @name) - value = self.collect { |obj| - obj.safeevaluate(args) - }.reject { |obj| - obj.nil? - } + def evaluate(*options) + raise Puppet::DevError, "Did not override #evaluate in %s" % self.class end # Throw a parse error. @@ -75,11 +47,11 @@ class Puppet::Parser::AST # correctly handles errors. It is critical to use this method because # it can enable you to catch the error where it happens, rather than # much higher up the stack. - def safeevaluate(options) + def safeevaluate(*options) # We duplicate code here, rather than using exceptwrap, because this # is called so many times during parsing. begin - return self.evaluate(options) + return self.evaluate(*options) rescue Puppet::Error => detail raise adderrorcontext(detail) rescue => detail @@ -90,14 +62,6 @@ class Puppet::Parser::AST end end - # Again, just used for printing out the parse tree. - def typewrap(string) - #return self.class.to_s.sub(/.+::/,'') + - #"(" + @@green + string.to_s + @@reset + ")" - return @@green + string.to_s + @@reset + - "(" + self.class.to_s.sub(/.+::/,'') + ")" - end - # Initialize the object. Requires a hash as the argument, and # takes each of the parameters of the hash and calls the settor # method for them. This is probably pretty inefficient and should @@ -107,13 +71,27 @@ class Puppet::Parser::AST @line = nil set_options(args) end - #--------------------------------------------------------------- - # Now autoload everything. - @autoloader = Puppet::Util::Autoload.new(self, - "puppet/parser/ast" - ) - @autoloader.loadall end +# And include all of the AST subclasses. +require 'puppet/parser/ast/astarray' +require 'puppet/parser/ast/branch' +require 'puppet/parser/ast/caseopt' +require 'puppet/parser/ast/casestatement' +require 'puppet/parser/ast/collection' +require 'puppet/parser/ast/collexpr' +require 'puppet/parser/ast/definition' +require 'puppet/parser/ast/else' +require 'puppet/parser/ast/function' +require 'puppet/parser/ast/hostclass' +require 'puppet/parser/ast/ifstatement' require 'puppet/parser/ast/leaf' - +require 'puppet/parser/ast/node' +require 'puppet/parser/ast/resource' +require 'puppet/parser/ast/resource_defaults' +require 'puppet/parser/ast/resource_override' +require 'puppet/parser/ast/resource_reference' +require 'puppet/parser/ast/resourceparam' +require 'puppet/parser/ast/selector' +require 'puppet/parser/ast/tag' +require 'puppet/parser/ast/vardef' diff --git a/lib/puppet/parser/ast/astarray.rb b/lib/puppet/parser/ast/astarray.rb index 5f1e838d0..b66fd6bba 100644 --- a/lib/puppet/parser/ast/astarray.rb +++ b/lib/puppet/parser/ast/astarray.rb @@ -15,8 +15,7 @@ class Puppet::Parser::AST end # Evaluate our children. - def evaluate(hash) - scope = hash[:scope] + def evaluate(scope) rets = nil # We basically always operate declaratively, and when we # do we need to evaluate the settor-like statements first. This @@ -51,7 +50,7 @@ class Puppet::Parser::AST } rets = [settors, others].flatten.collect { |child| - child.safeevaluate(:scope => scope) + child.safeevaluate(scope) } return rets.reject { |o| o.nil? } end diff --git a/lib/puppet/parser/ast/caseopt.rb b/lib/puppet/parser/ast/caseopt.rb index d1d9d0e9c..824bde853 100644 --- a/lib/puppet/parser/ast/caseopt.rb +++ b/lib/puppet/parser/ast/caseopt.rb @@ -44,17 +44,17 @@ class Puppet::Parser::AST def eachvalue(scope) if @value.is_a?(AST::ASTArray) @value.each { |subval| - yield subval.evaluate(:scope => scope) + yield subval.safeevaluate(scope) } else - yield @value.evaluate(:scope => scope) + yield @value.safeevaluate(scope) end end # Evaluate the actual statements; this only gets called if # our option matched. - def evaluate(hash) - return @statements.safeevaluate(hash) + def evaluate(scope) + return @statements.safeevaluate(scope) end end end diff --git a/lib/puppet/parser/ast/casestatement.rb b/lib/puppet/parser/ast/casestatement.rb index 3c6f9c7e2..aa03090de 100644 --- a/lib/puppet/parser/ast/casestatement.rb +++ b/lib/puppet/parser/ast/casestatement.rb @@ -8,9 +8,8 @@ class Puppet::Parser::AST # Short-curcuit evaluation. Return the value of the statements for # the first option that matches. - def evaluate(hash) - scope = hash[:scope] - value = @test.safeevaluate(:scope => scope) + def evaluate(scope) + value = @test.safeevaluate(scope) sensitive = Puppet[:casesensitive] value = value.downcase if ! sensitive and value.respond_to?(:downcase) @@ -30,7 +29,7 @@ class Puppet::Parser::AST if found # we found a matching option - retvalue = option.safeevaluate(:scope => scope) + retvalue = option.safeevaluate(scope) break end @@ -42,7 +41,7 @@ class Puppet::Parser::AST # Unless we found something, look for the default. unless found if default - retvalue = default.safeevaluate(:scope => scope) + retvalue = default.safeevaluate(scope) else Puppet.debug "No true answers and no default" retvalue = nil diff --git a/lib/puppet/parser/ast/collection.rb b/lib/puppet/parser/ast/collection.rb index e05977a47..9e795a33c 100644 --- a/lib/puppet/parser/ast/collection.rb +++ b/lib/puppet/parser/ast/collection.rb @@ -9,18 +9,16 @@ class Collection < AST::Branch attr_accessor :type, :query, :form # We return an object that does a late-binding evaluation. - def evaluate(hash) - scope = hash[:scope] - + def evaluate(scope) if self.query - str, code = self.query.safeevaluate :scope => scope + str, code = self.query.safeevaluate scope else str = code = nil end newcoll = Puppet::Parser::Collector.new(scope, @type, str, code, self.form) - scope.compile.add_collection(newcoll) + scope.compiler.add_collection(newcoll) newcoll end diff --git a/lib/puppet/parser/ast/collexpr.rb b/lib/puppet/parser/ast/collexpr.rb index 4a96d9c61..3e13d9400 100644 --- a/lib/puppet/parser/ast/collexpr.rb +++ b/lib/puppet/parser/ast/collexpr.rb @@ -9,9 +9,7 @@ class CollExpr < AST::Branch attr_accessor :test1, :test2, :oper, :form, :type, :parens # We return an object that does a late-binding evaluation. - def evaluate(hash) - scope = hash[:scope] - + def evaluate(scope) # Make sure our contained expressions have all the info they need. [@test1, @test2].each do |t| if t.is_a?(self.class) @@ -21,8 +19,8 @@ class CollExpr < AST::Branch end # The code is only used for virtual lookups - str1, code1 = @test1.safeevaluate :scope => scope - str2, code2 = @test2.safeevaluate :scope => scope + str1, code1 = @test1.safeevaluate scope + str2, code2 = @test2.safeevaluate scope # First build up the virtual code. # If we're a conjunction operator, then we're calling code. I did diff --git a/lib/puppet/parser/ast/definition.rb b/lib/puppet/parser/ast/definition.rb index 3d6d6188c..2b7506446 100644 --- a/lib/puppet/parser/ast/definition.rb +++ b/lib/puppet/parser/ast/definition.rb @@ -1,155 +1,148 @@ require 'puppet/parser/ast/branch' -class Puppet::Parser::AST - # Evaluate the stored parse tree for a given component. This will - # receive the arguments passed to the component and also the type and - # name of the component. - class Definition < AST::Branch - include Puppet::Util - include Puppet::Util::Warnings - include Puppet::Util::MethodHelper - class << self - attr_accessor :name - end +require 'puppet/util/warnings' - # The class name - @name = :definition +# The AST class for defined types, which is also the base class +# nodes and classes. +class Puppet::Parser::AST::Definition < Puppet::Parser::AST::Branch + include Puppet::Util::Warnings + class << self + attr_accessor :name + end - attr_accessor :classname, :arguments, :code, :scope, :keyword - attr_accessor :exported, :namespace, :parser, :virtual + # The class name + @name = :definition - # These are retrieved when looking up the superclass - attr_accessor :name + attr_accessor :classname, :arguments, :code, :scope, :keyword + attr_accessor :exported, :namespace, :parser, :virtual, :name - attr_reader :parentclass + attr_reader :parentclass - def child_of?(klass) - false - end + def child_of?(klass) + false + end - def evaluate(options) - origscope = options[:scope] - resource = options[:resource] + # Create a resource that knows how to evaluate our actual code. + def evaluate(scope) + # Do nothing if the resource already exists; this provides the singleton nature classes need. + return if scope.catalog.resource(self.class.name, self.classname) - # Create a new scope. - scope = subscope(origscope, resource) + resource = Puppet::Parser::Resource.new(:type => self.class.name, :title => self.classname, :scope => scope, :source => scope.source) - # Additionally, add a tag for whatever kind of class - # we are - if @classname != "" and ! @classname.nil? - @classname.split(/::/).each { |tag| scope.resource.tag(tag) } - end + scope.catalog.tag(*resource.tags) - [resource.name, resource.title].each do |str| - unless str.nil? or str =~ /[^\w]/ or str == "" - scope.resource.tag(str) - end - end + scope.compiler.add_resource(scope, resource) - set_resource_parameters(scope, resource) + return resource + end - if self.code - return self.code.safeevaluate(:scope => scope) - else - return nil - end + # Now evaluate the code associated with this class or definition. + def evaluate_code(resource) + # Create a new scope. + scope = subscope(resource.scope, resource) + + set_resource_parameters(scope, resource) + + if self.code + return self.code.safeevaluate(scope) + else + return nil end + end - def initialize(hash = {}) - @arguments = nil - @parentclass = nil - super + def initialize(hash = {}) + @arguments = nil + @parentclass = nil + super - # Convert the arguments to a hash for ease of later use. - if @arguments - unless @arguments.is_a? Array - @arguments = [@arguments] - end - oldargs = @arguments - @arguments = {} - oldargs.each do |arg, val| - @arguments[arg] = val - end - else - @arguments = {} + # Convert the arguments to a hash for ease of later use. + if @arguments + unless @arguments.is_a? Array + @arguments = [@arguments] end - - # Deal with metaparams in the argument list. - @arguments.each do |arg, defvalue| - next unless Puppet::Type.metaparamclass(arg) - if defvalue - warnonce "%s is a metaparam; this value will inherit to all contained resources" % arg - else - raise Puppet::ParseError, "%s is a metaparameter; please choose another parameter name in the %s definition" % [arg, self.classname] - end + oldargs = @arguments + @arguments = {} + oldargs.each do |arg, val| + @arguments[arg] = val end + else + @arguments = {} end - def find_parentclass - @parser.findclass(namespace, parentclass) + # Deal with metaparams in the argument list. + @arguments.each do |arg, defvalue| + next unless Puppet::Type.metaparamclass(arg) + if defvalue + warnonce "%s is a metaparam; this value will inherit to all contained resources" % arg + else + raise Puppet::ParseError, "%s is a metaparameter; please choose another parameter name in the %s definition" % [arg, self.classname] + end end + end - # Set our parent class, with a little check to avoid some potential - # weirdness. - def parentclass=(name) - if name == self.classname - parsefail "Parent classes must have dissimilar names" - end + def find_parentclass + @parser.findclass(namespace, parentclass) + end - @parentclass = name + # Set our parent class, with a little check to avoid some potential + # weirdness. + def parentclass=(name) + if name == self.classname + parsefail "Parent classes must have dissimilar names" end - # Hunt down our class object. - def parentobj - if @parentclass - # Cache our result, since it should never change. - unless defined?(@parentobj) - unless tmp = find_parentclass - parsefail "Could not find %s %s" % [self.class.name, @parentclass] - end + @parentclass = name + end - if tmp == self - parsefail "Parent classes must have dissimilar names" - end + # Hunt down our class object. + def parentobj + return nil unless @parentclass - @parentobj = tmp - end - @parentobj - else - nil + # Cache our result, since it should never change. + unless defined?(@parentobj) + unless tmp = find_parentclass + parsefail "Could not find %s parent %s" % [self.class.name, @parentclass] + end + + if tmp == self + parsefail "Parent classes must have dissimilar names" end + + @parentobj = tmp end + @parentobj + end - # Create a new subscope in which to evaluate our code. - def subscope(scope, resource) - args = { - :resource => resource, - :keyword => self.keyword, - :namespace => self.namespace, - :source => self - } + # Create a new subscope in which to evaluate our code. + def subscope(scope, resource) + args = { + :resource => resource, + :keyword => self.keyword, + :namespace => self.namespace, + :source => self + } - oldscope = scope - scope = scope.newscope(args) - scope.source = self + oldscope = scope + scope = scope.newscope(args) + scope.source = self - return scope - end + return scope + end - def to_s - classname - end + def to_s + classname + end - # Check whether a given argument is valid. Searches up through - # any parent classes that might exist. - def validattr?(param) - param = param.to_s + # Check whether a given argument is valid. Searches up through + # any parent classes that might exist. + def validattr?(param) + param = param.to_s - if @arguments.include?(param) - # It's a valid arg for us - return true - elsif param == "name" - return true + if @arguments.include?(param) + # It's a valid arg for us + return true + elsif param == "name" + return true # elsif defined? @parentclass and @parentclass # # Else, check any existing parent # if parent = @scope.lookuptype(@parentclass) and parent != [] @@ -160,53 +153,52 @@ class Puppet::Parser::AST # raise Puppet::Error, "Could not find parent class %s" % # @parentclass # end - elsif Puppet::Type.metaparam?(param) - return true - else - # Or just return false - return false - end + elsif Puppet::Type.metaparam?(param) + return true + else + # Or just return false + return false end + end - private - - # Set any arguments passed by the resource as variables in the scope. - def set_resource_parameters(scope, resource) - args = symbolize_options(resource.to_hash || {}) - - # Verify that all required arguments are either present or - # have been provided with defaults. - if self.arguments - self.arguments.each { |arg, default| - arg = symbolize(arg) - unless args.include?(arg) - if defined? default and ! default.nil? - default = default.safeevaluate :scope => scope - args[arg] = default - #Puppet.debug "Got default %s for %s in %s" % - # [default.inspect, arg.inspect, @name.inspect] - else - parsefail "Must pass %s to %s of type %s" % - [arg, resource.title, @classname] - end + private + + # Set any arguments passed by the resource as variables in the scope. + def set_resource_parameters(scope, resource) + args = symbolize_options(resource.to_hash || {}) + + # Verify that all required arguments are either present or + # have been provided with defaults. + if self.arguments + self.arguments.each { |arg, default| + arg = arg.to_sym + unless args.include?(arg) + if defined? default and ! default.nil? + default = default.safeevaluate scope + args[arg] = default + #Puppet.debug "Got default %s for %s in %s" % + # [default.inspect, arg.inspect, @name.inspect] + else + parsefail "Must pass %s to %s of type %s" % + [arg, resource.title, @classname] end - } - end - - # Set each of the provided arguments as variables in the - # definition's scope. - args.each { |arg,value| - unless validattr?(arg) - parsefail "%s does not accept attribute %s" % [@classname, arg] - end - - exceptwrap do - scope.setvar(arg.to_s, args[arg]) end } - - scope.setvar("title", resource.title) unless args.include? :title - scope.setvar("name", resource.name) unless args.include? :name end + + # Set each of the provided arguments as variables in the + # definition's scope. + args.each { |arg,value| + unless validattr?(arg) + parsefail "%s does not accept attribute %s" % [@classname, arg] + end + + exceptwrap do + scope.setvar(arg.to_s, args[arg]) + end + } + + scope.setvar("title", resource.title) unless args.include? :title + scope.setvar("name", resource.name) unless args.include? :name end end diff --git a/lib/puppet/parser/ast/else.rb b/lib/puppet/parser/ast/else.rb index e76051372..affac625d 100644 --- a/lib/puppet/parser/ast/else.rb +++ b/lib/puppet/parser/ast/else.rb @@ -12,9 +12,8 @@ class Puppet::Parser::AST # Evaluate the actual statements; this only gets called if # our test was true matched. - def evaluate(hash) - scope = hash[:scope] - return @statements.safeevaluate(:scope => scope) + def evaluate(scope) + return @statements.safeevaluate(scope) end end end diff --git a/lib/puppet/parser/ast/function.rb b/lib/puppet/parser/ast/function.rb index 0cd1fff62..63d7c7abf 100644 --- a/lib/puppet/parser/ast/function.rb +++ b/lib/puppet/parser/ast/function.rb @@ -7,18 +7,11 @@ class Puppet::Parser::AST @settor = true - def evaluate(hash) + def evaluate(scope) # We don't need to evaluate the name, because it's plaintext + args = @arguments.safeevaluate(scope) - # Just evaluate the arguments - scope = hash[:scope] - - args = @arguments.safeevaluate(:scope => scope) - - #exceptwrap :message => "Failed to execute %s" % @name, - # :type => Puppet::ParseError do - return scope.send("function_" + @name, args) - #end + return scope.send("function_" + @name, args) end def initialize(hash) diff --git a/lib/puppet/parser/ast/hostclass.rb b/lib/puppet/parser/ast/hostclass.rb index 63900d0e3..8d4d01660 100644 --- a/lib/puppet/parser/ast/hostclass.rb +++ b/lib/puppet/parser/ast/hostclass.rb @@ -1,80 +1,80 @@ require 'puppet/parser/ast/definition' -class Puppet::Parser::AST - # The code associated with a class. This is different from definitions - # in that each class is a singleton -- only one will exist for a given - # node. - class HostClass < AST::Definition - @name = :class +# The code associated with a class. This is different from definitions +# in that each class is a singleton -- only one will exist for a given +# node. +class Puppet::Parser::AST::HostClass < Puppet::Parser::AST::Definition + @name = :class - # Are we a child of the passed class? Do a recursive search up our - # parentage tree to figure it out. - def child_of?(klass) - return false unless self.parentclass + # Are we a child of the passed class? Do a recursive search up our + # parentage tree to figure it out. + def child_of?(klass) + return false unless self.parentclass - if klass == self.parentobj - return true - else - return self.parentobj.child_of?(klass) - end + if klass == self.parentobj + return true + else + return self.parentobj.child_of?(klass) end + end - # Evaluate the code associated with this class. - def evaluate(options) - scope = options[:scope] - raise(ArgumentError, "Classes require resources") unless options[:resource] - # Verify that we haven't already been evaluated. This is - # what provides the singleton aspect. - if existing_scope = scope.compile.class_scope(self) - Puppet.debug "Class '%s' already evaluated; not evaluating again" % (classname == "" ? "main" : classname) - return nil - end - - scope.compile.catalog.tag(self.classname) + # Make sure our parent class has been evaluated, if we have one. + def evaluate(scope) + if parentclass and ! scope.catalog.resource(self.class.name, parentclass) + resource = parentobj.evaluate(scope) + end - pnames = nil - if pklass = self.parentobj - pklass.safeevaluate :scope => scope, :resource => options[:resource] + super + end - scope = parent_scope(scope, pklass) - pnames = scope.namespaces - end + # Evaluate the code associated with this class. + def evaluate_code(resource) + scope = resource.scope + # Verify that we haven't already been evaluated. This is + # what provides the singleton aspect. + if existing_scope = scope.compiler.class_scope(self) + Puppet.debug "Class '%s' already evaluated; not evaluating again" % (classname == "" ? "main" : classname) + return nil + end - # Don't create a subscope for the top-level class, since it already - # has its own scope. - unless options[:resource].title == :main - scope = subscope(scope, options[:resource]) - end + pnames = nil + if pklass = self.parentobj + parent_resource = resource.scope.compiler.catalog.resource(self.class.name, pklass.classname) + # This shouldn't evaluate if the class has already been evaluated. + pklass.evaluate_code(parent_resource) - if pnames - pnames.each do |ns| - scope.add_namespace(ns) - end - end + scope = parent_scope(scope, pklass) + pnames = scope.namespaces + end - # Set the class before we do anything else, so that it's set - # during the evaluation and can be inspected. - scope.compile.class_set(self.classname, scope) + # Don't create a subscope for the top-level class, since it already + # has its own scope. + scope = subscope(scope, resource) unless resource.title == :main - # Now evaluate our code, yo. - if self.code - return self.code.evaluate(:scope => scope) - else - return nil + # Add the parent scope namespaces to our own. + if pnames + pnames.each do |ns| + scope.add_namespace(ns) end end - def initialize(options) - @parentclass = nil - super + # Set the class before we evaluate the code, so that it's set during + # the evaluation and can be inspected. + scope.compiler.class_set(self.classname, scope) + + # Now evaluate our code, yo. + if self.code + return self.code.safeevaluate(scope) + else + return nil end + end - def parent_scope(scope, klass) - if s = scope.compile.class_scope(klass) - return s - else - raise Puppet::DevError, "Could not find scope for %s" % klass.classname - end + def parent_scope(scope, klass) + if s = scope.compiler.class_scope(klass) + return s + else + raise Puppet::DevError, "Could not find scope for %s" % klass.classname end end end diff --git a/lib/puppet/parser/ast/ifstatement.rb b/lib/puppet/parser/ast/ifstatement.rb index 66a07b01f..afa2cd572 100644 --- a/lib/puppet/parser/ast/ifstatement.rb +++ b/lib/puppet/parser/ast/ifstatement.rb @@ -12,15 +12,14 @@ class Puppet::Parser::AST # Short-curcuit evaluation. If we're true, evaluate our statements, # else if there's an 'else' setting, evaluate it. # the first option that matches. - def evaluate(hash) - scope = hash[:scope] - value = @test.safeevaluate(:scope => scope) + def evaluate(scope) + value = @test.safeevaluate(scope) if Puppet::Parser::Scope.true?(value) - return @statements.safeevaluate(:scope => scope) + return @statements.safeevaluate(scope) else if defined? @else - return @else.safeevaluate(:scope => scope) + return @else.safeevaluate(scope) else return nil end diff --git a/lib/puppet/parser/ast/leaf.rb b/lib/puppet/parser/ast/leaf.rb index 225253061..c545c1e47 100644 --- a/lib/puppet/parser/ast/leaf.rb +++ b/lib/puppet/parser/ast/leaf.rb @@ -6,7 +6,7 @@ class Puppet::Parser::AST attr_accessor :value, :type # Return our value. - def evaluate(hash) + def evaluate(scope) return @value end @@ -35,14 +35,14 @@ class Puppet::Parser::AST class String < AST::Leaf # Interpolate the string looking for variables, and then return # the result. - def evaluate(hash) - return hash[:scope].strinterp(@value, @file, @line) + def evaluate(scope) + return scope.strinterp(@value, @file, @line) end end # An uninterpreted string. class FlatString < AST::Leaf - def evaluate(hash) + def evaluate(scope) return @value end end @@ -81,9 +81,9 @@ class Puppet::Parser::AST class Variable < Name # Looks up the value of the object in the scope tree (does # not include syntactical constructs, like '$' and '{}'). - def evaluate(hash) + def evaluate(scope) parsewrap do - return hash[:scope].lookupvar(@value) + return scope.lookupvar(@value) end end end diff --git a/lib/puppet/parser/ast/node.rb b/lib/puppet/parser/ast/node.rb index a296e43ba..2bf6c1882 100644 --- a/lib/puppet/parser/ast/node.rb +++ b/lib/puppet/parser/ast/node.rb @@ -1,67 +1,35 @@ require 'puppet/parser/ast/hostclass' -class Puppet::Parser::AST - # The specific code associated with a host. Nodes are annoyingly unlike - # other objects. That's just the way it is, at least for now. - class Node < AST::HostClass - @name = :node - attr_accessor :name - - def evaluate(options) - scope = options[:scope] - - #pscope = if ! Puppet[:lexical] or options[:asparent] - # @scope - #else - # origscope - #end - - # We don't have to worry about the declarativeness of node parentage, - # because the entry point is always a single node definition. - if parent = self.parentobj - scope = parent.safeevaluate :scope => scope, :resource => options[:resource] - end - - scope = scope.newscope( - :resource => options[:resource], - :keyword => @keyword, - :source => self, - :namespace => "" # nodes are always in "" - ) - - # Mark our node name as a class, too, but strip it of the domain - # name. Make the mark before we evaluate the code, so that it is - # marked within the code itself. - scope.compile.class_set(self.classname, scope) - - # And then evaluate our code if we have any - if self.code - @code.safeevaluate(:scope => scope) - end - - return scope +# The specific code associated with a host. Nodes are annoyingly unlike +# other objects. That's just the way it is, at least for now. +class Puppet::Parser::AST::Node < Puppet::Parser::AST::HostClass + @name = :node + + def initialize(options) + @parentclass = nil + super + + # Do some validation on the node name + if @name =~ /[^-\w.]/ + raise Puppet::ParseError, "Invalid node name %s" % @name end + end - def initialize(options) - @parentclass = nil - super + def namespace + "" + end - # Do some validation on the node name - if @name =~ /[^-\w.]/ - raise Puppet::ParseError, "Invalid node name %s" % @name - end - end + # Make sure node scopes are marked as such. + def subscope(*args) + scope = super + scope.nodescope = true + scope + end - # Make sure node scopes are marked as such. - def subscope(*args) - scope = super - scope.nodescope = true - end + private - private - # Search for the object matching our parent class. - def find_parentclass - @parser.findnode(parentclass) - end + # Search for the object matching our parent class. + def find_parentclass + @parser.findnode(parentclass) end end diff --git a/lib/puppet/parser/ast/resource.rb b/lib/puppet/parser/ast/resource.rb index c53ab0a68..8a60522a3 100644 --- a/lib/puppet/parser/ast/resource.rb +++ b/lib/puppet/parser/ast/resource.rb @@ -9,15 +9,13 @@ class Resource < AST::ResourceReference # Does not actually return an object; instead sets an object # in the current scope. - def evaluate(options) - scope = options[:scope] - + def evaluate(scope) # Evaluate all of the specified params. paramobjects = @params.collect { |param| - param.safeevaluate(:scope => scope) + param.safeevaluate(scope) } - objtitles = @title.safeevaluate(:scope => scope) + objtitles = @title.safeevaluate(scope) # it's easier to always use an array, even for only one name unless objtitles.is_a?(Array) @@ -50,10 +48,10 @@ class Resource < AST::ResourceReference :scope => scope ) - # And then store the resource in the compile. + # And then store the resource in the compiler. # At some point, we need to switch all of this to return # objects instead of storing them like this. - scope.compile.store_resource(scope, obj) + scope.compiler.add_resource(scope, obj) obj end }.reject { |obj| obj.nil? } diff --git a/lib/puppet/parser/ast/resource_defaults.rb b/lib/puppet/parser/ast/resource_defaults.rb index 8f9c1b8df..4856f0594 100644 --- a/lib/puppet/parser/ast/resource_defaults.rb +++ b/lib/puppet/parser/ast/resource_defaults.rb @@ -8,13 +8,11 @@ class Puppet::Parser::AST # As opposed to ResourceDef, this stores each default for the given # object type. - def evaluate(hash) - scope = hash[:scope] - + def evaluate(scope) # Use a resource reference to canonize the type ref = Puppet::ResourceReference.new(@type, "whatever") type = ref.type - params = @params.safeevaluate(:scope => scope) + params = @params.safeevaluate(scope) parsewrap do scope.setdefaults(type, params) diff --git a/lib/puppet/parser/ast/resource_override.rb b/lib/puppet/parser/ast/resource_override.rb index 46c930902..f9464acda 100644 --- a/lib/puppet/parser/ast/resource_override.rb +++ b/lib/puppet/parser/ast/resource_override.rb @@ -17,17 +17,15 @@ class Puppet::Parser::AST # Does not actually return an object; instead sets an object # in the current scope. - def evaluate(hash) - scope = hash[:scope] - + def evaluate(scope) # Get our object reference. - object = @object.safeevaluate(:scope => scope) + object = @object.safeevaluate(scope) hash = {} # Evaluate all of the specified params. params = @params.collect { |param| - param.safeevaluate(:scope => scope) + param.safeevaluate(scope) } # Now we just create a normal resource, but we call a very different @@ -44,7 +42,7 @@ class Puppet::Parser::AST # Now we tell the scope that it's an override, and it behaves as # necessary. - scope.compile.store_override(obj) + scope.compiler.add_override(obj) obj end diff --git a/lib/puppet/parser/ast/resource_reference.rb b/lib/puppet/parser/ast/resource_reference.rb index b06ea17be..4bb41165a 100644 --- a/lib/puppet/parser/ast/resource_reference.rb +++ b/lib/puppet/parser/ast/resource_reference.rb @@ -22,10 +22,8 @@ class Puppet::Parser::AST # Evaluate our object, but just return a simple array of the type # and name. - def evaluate(hash) - scope = hash[:scope] - - title = @title.safeevaluate(:scope => scope) + def evaluate(scope) + title = @title.safeevaluate(scope) if @type.to_s.downcase == "class" objtype = "class" title = qualified_class(scope, title) diff --git a/lib/puppet/parser/ast/resourceparam.rb b/lib/puppet/parser/ast/resourceparam.rb index 8b1e7b367..c552a7ee5 100644 --- a/lib/puppet/parser/ast/resourceparam.rb +++ b/lib/puppet/parser/ast/resourceparam.rb @@ -10,12 +10,10 @@ class Puppet::Parser::AST end # Return the parameter and the value. - def evaluate(hash) - scope = hash[:scope] - + def evaluate(scope) return Puppet::Parser::Resource::Param.new( :name => @param, - :value => @value.safeevaluate(:scope => scope), + :value => @value.safeevaluate(scope), :source => scope.source, :line => self.line, :file => self.file, :add => self.add ) diff --git a/lib/puppet/parser/ast/selector.rb b/lib/puppet/parser/ast/selector.rb index d363ab7e4..399d405a3 100644 --- a/lib/puppet/parser/ast/selector.rb +++ b/lib/puppet/parser/ast/selector.rb @@ -11,13 +11,12 @@ class Puppet::Parser::AST end # Find the value that corresponds with the test. - def evaluate(hash) - scope = hash[:scope] + def evaluate(scope) retvalue = nil found = nil # Get our parameter. - paramvalue = @param.safeevaluate(:scope => scope) + paramvalue = @param.safeevaluate(scope) sensitive = Puppet[:casesensitive] @@ -33,13 +32,13 @@ class Puppet::Parser::AST # Then look for a match in the options. @values.each { |obj| - param = obj.param.safeevaluate(:scope => scope) + param = obj.param.safeevaluate(scope) if ! sensitive && param.respond_to?(:downcase) param = param.downcase end if param == paramvalue # we found a matching option - retvalue = obj.value.safeevaluate(:scope => scope) + retvalue = obj.value.safeevaluate(scope) found = true break elsif obj.param.is_a?(Default) @@ -51,7 +50,7 @@ class Puppet::Parser::AST # Unless we found something, look for the default. unless found if default - retvalue = default.value.safeevaluate(:scope => scope) + retvalue = default.value.safeevaluate(scope) else self.fail Puppet::ParseError, "No matching value for selector param '%s'" % paramvalue diff --git a/lib/puppet/parser/ast/tag.rb b/lib/puppet/parser/ast/tag.rb index e2882d2f0..2909504a7 100644 --- a/lib/puppet/parser/ast/tag.rb +++ b/lib/puppet/parser/ast/tag.rb @@ -8,10 +8,8 @@ class Puppet::Parser::AST @name = :class attr_accessor :type - def evaluate(hash) - scope = hash[:scope] - - types = @type.safeevaluate(:scope => scope) + def evaluate(scope) + types = @type.safeevaluate(scope) types = [types] unless types.is_a? Array diff --git a/lib/puppet/parser/ast/vardef.rb b/lib/puppet/parser/ast/vardef.rb index 1e7f874bc..ee79159d7 100644 --- a/lib/puppet/parser/ast/vardef.rb +++ b/lib/puppet/parser/ast/vardef.rb @@ -9,10 +9,9 @@ class Puppet::Parser::AST # Look up our name and value, and store them appropriately. The # lexer strips off the syntax stuff like '$'. - def evaluate(hash) - scope = hash[:scope] - name = @name.safeevaluate(:scope => scope) - value = @value.safeevaluate(:scope => scope) + def evaluate(scope) + name = @name.safeevaluate(scope) + value = @value.safeevaluate(scope) parsewrap do scope.setvar(name,value, @file, @line) diff --git a/lib/puppet/parser/collector.rb b/lib/puppet/parser/collector.rb index b8165a84f..e0c37cd35 100644 --- a/lib/puppet/parser/collector.rb +++ b/lib/puppet/parser/collector.rb @@ -118,20 +118,20 @@ class Puppet::Parser::Collector # If there are no more resources to find, delete this from the list # of collections. if @resources.empty? - @scope.compile.delete_collection(self) + @scope.compiler.delete_collection(self) end return result end - # Collect just virtual objects, from our local compile. + # Collect just virtual objects, from our local compiler. def collect_virtual(exported = false) if exported method = :exported? else method = :virtual? end - scope.compile.resources.find_all do |resource| + scope.compiler.resources.find_all do |resource| resource.type == @type and resource.send(method) and match?(resource) end end @@ -150,7 +150,7 @@ class Puppet::Parser::Collector resource.exported = false - scope.compile.store_resource(scope, resource) + scope.compiler.add_resource(scope, resource) return resource end diff --git a/lib/puppet/parser/compile.rb b/lib/puppet/parser/compiler.rb index e1e230d48..132ec15db 100644 --- a/lib/puppet/parser/compile.rb +++ b/lib/puppet/parser/compiler.rb @@ -7,7 +7,7 @@ require 'puppet/util/errors' # Maintain a graph of scopes, along with a bunch of data # about the individual catalog we're compiling. -class Puppet::Parser::Compile +class Puppet::Parser::Compiler include Puppet::Util include Puppet::Util::Errors attr_reader :parser, :node, :facts, :collections, :catalog, :node_scope @@ -17,6 +17,29 @@ class Puppet::Parser::Compile @collections << coll end + # Store a resource override. + def add_override(override) + # If possible, merge the override in immediately. + if resource = @catalog.resource(override.ref) + resource.merge(override) + else + # Otherwise, store the override for later; these + # get evaluated in Resource#finish. + @resource_overrides[override.ref] << override + end + end + + # Store a resource in our resource table. + def add_resource(scope, resource) + # Note that this will fail if the resource is not unique. + @catalog.add_resource(resource) + + # And in the resource graph. At some point, this might supercede + # the global resource table, but the table is a lot faster + # so it makes sense to maintain for now. + @catalog.add_edge(scope.resource, resource) + end + # Do we use nodes found in the code, vs. the external node sources? def ast_nodes? parser.nodes.length > 0 @@ -26,10 +49,10 @@ class Puppet::Parser::Compile # the scope in which it was evaluated, so that we can look it up later. def class_set(name, scope) if existing = @class_scopes[name] - if existing.nodescope? or scope.nodescope? + if existing.nodescope? != scope.nodescope? raise Puppet::ParseError, "Cannot have classes, nodes, or definitions with the same name" else - raise Puppet::DevError, "Somehow evaluated the same class twice" + raise Puppet::DevError, "Somehow evaluated %s %s twice" % [ existing.nodescope? ? "node" : "class", name] end end @class_scopes[name] = scope @@ -54,7 +77,7 @@ class Puppet::Parser::Compile return @catalog.classes end - # Compile our catalog. This mostly revolves around finding and evaluating classes. + # Compiler our catalog. This mostly revolves around finding and evaluating classes. # This is the main entry into our catalog. def compile # Set the client's parameters into the top scope. @@ -68,10 +91,10 @@ class Puppet::Parser::Compile evaluate_generators() - fail_on_unevaluated() - finish() + fail_on_unevaluated() + if Puppet[:storeconfigs] store() end @@ -84,11 +107,6 @@ class Puppet::Parser::Compile @collections.delete(coll) if @collections.include?(coll) end - # LAK:FIXME There are no tests for this. - def delete_resource(resource) - @resource_table.delete(resource.ref) if @resource_table.include?(resource.ref) - end - # Return the node's environment. def environment unless defined? @environment @@ -120,16 +138,11 @@ class Puppet::Parser::Compile if klass = scope.findclass(name) found << name and next if class_scope(klass) - # Create a resource to model this class, and then add it to the list - # of resources. - resource = Puppet::Parser::Resource.new(:type => "class", :title => klass.classname, :scope => scope, :source => scope.source) - - store_resource(scope, resource) + resource = klass.evaluate(scope) # If they've disabled lazy evaluation (which the :include function does), # then evaluate our resource immediately. resource.evaluate unless lazy_evaluate - @catalog.tag(klass.classname) found << name else Puppet.info "Could not find class %s for %s" % [name, node.name] @@ -140,10 +153,8 @@ class Puppet::Parser::Compile end # Return a resource by either its ref or its type and title. - def findresource(string, name = nil) - string = "%s[%s]" % [string.capitalize, name] if name - - @resource_table[string] + def findresource(*args) + @catalog.resource(*args) end # Set up our compile. We require a parser @@ -158,7 +169,7 @@ class Puppet::Parser::Compile begin send(param.to_s + "=", value) rescue NoMethodError - raise ArgumentError, "Compile objects do not accept %s" % param + raise ArgumentError, "Compiler objects do not accept %s" % param end end @@ -171,10 +182,10 @@ class Puppet::Parser::Compile # its parent to the graph. def newscope(parent, options = {}) parent ||= topscope - options[:compile] = self + options[:compiler] = self options[:parser] ||= self.parser scope = Puppet::Parser::Scope.new(options) - @scope_graph.add_edge!(parent, scope) + @scope_graph.add_edge(parent, scope) scope end @@ -195,35 +206,7 @@ class Puppet::Parser::Compile # Return a list of all resources. def resources - @resource_table.values - end - - # Store a resource override. - def store_override(override) - override.override = true - - # If possible, merge the override in immediately. - if resource = @resource_table[override.ref] - resource.merge(override) - else - # Otherwise, store the override for later; these - # get evaluated in Resource#finish. - @resource_overrides[override.ref] << override - end - end - - # Store a resource in our resource table. - def store_resource(scope, resource) - # This might throw an exception - verify_uniqueness(resource) - - # Store it in the global table. - @resource_table[resource.ref] = resource - - # And in the resource graph. At some point, this might supercede - # the global resource table, but the table is a lot faster - # so it makes sense to maintain for now. - @catalog.add_edge!(scope.resource, resource) + @catalog.vertices end # The top scope is usually the top-level scope, but if we're using AST nodes, @@ -250,9 +233,7 @@ class Puppet::Parser::Compile # Create a resource to model this node, and then add it to the list # of resources. - resource = Puppet::Parser::Resource.new(:type => "node", :title => astnode.classname, :scope => topscope, :source => topscope.source) - store_resource(topscope, resource) - @catalog.tag(astnode.classname) + resource = astnode.evaluate(topscope) resource.evaluate @@ -285,11 +266,15 @@ class Puppet::Parser::Compile def evaluate_definitions exceptwrap do if ary = unevaluated_resources + evaluated = false ary.each do |resource| - resource.evaluate + if not resource.virtual? + resource.evaluate + evaluated = true + end end # If we evaluated, let the loop know. - return true + return evaluated else return false end @@ -325,9 +310,7 @@ class Puppet::Parser::Compile @main_resource = Puppet::Parser::Resource.new(:type => "class", :title => :main, :scope => @topscope, :source => @main) @topscope.resource = @main_resource - @catalog.add_vertex!(@main_resource) - - @resource_table["Class[main]"] = @main_resource + @catalog.add_resource(@main_resource) @main_resource.evaluate end @@ -383,14 +366,29 @@ class Puppet::Parser::Compile # Make sure all of our resources and such have done any last work # necessary. def finish - @resource_table.each { |name, resource| resource.finish if resource.respond_to?(:finish) } + @catalog.resources.each do |name| + resource = @catalog.resource(name) + + # Add in any resource overrides. + if overrides = resource_overrides(resource) + overrides.each do |over| + resource.merge(over) + end + + # Remove the overrides, so that the configuration knows there + # are none left. + overrides.clear + end + + resource.finish if resource.respond_to?(:finish) + end end # Initialize the top-level scope, class, and resource. def init_main # Create our initial scope and a resource that will evaluate main. - @topscope = Puppet::Parser::Scope.new(:compile => self, :parser => self.parser) - @scope_graph.add_vertex!(@topscope) + @topscope = Puppet::Parser::Scope.new(:compiler => self, :parser => self.parser) + @scope_graph.add_vertex(@topscope) end # Set up all of our internal variables. @@ -399,9 +397,6 @@ class Puppet::Parser::Compile # be used by top scopes and node scopes. @class_scopes = {} - # The table for all defined resources. - @resource_table = {} - # The list of objects that will available for export. @exported_resources = {} @@ -415,9 +410,6 @@ class Puppet::Parser::Compile # but they each refer back to the scope that created them. @collections = [] - # A list of tags we've generated; most class names. - @tags = [] - # A graph for maintaining scope relationships. @scope_graph = Puppet::SimpleGraph.new @@ -446,7 +438,7 @@ class Puppet::Parser::Compile # We used to have hooks here for forking and saving, but I don't # think it's worth retaining at this point. - store_to_active_record(@node, @resource_table.values) + store_to_active_record(@node, @catalog.vertices) end # Do the actual storage. @@ -469,9 +461,7 @@ class Puppet::Parser::Compile # Return an array of all of the unevaluated resources. These will be definitions, # which need to get evaluated into native resources. def unevaluated_resources - ary = @resource_table.find_all do |name, object| - ! object.builtin? and ! object.evaluated? - end.collect { |name, object| object } + ary = @catalog.vertices.reject { |resource| resource.builtin? or resource.evaluated? } if ary.empty? return nil @@ -479,33 +469,4 @@ class Puppet::Parser::Compile return ary end end - - # Verify that the given resource isn't defined elsewhere. - def verify_uniqueness(resource) - # Short-curcuit the common case, - unless existing_resource = @resource_table[resource.ref] - return true - end - - if typeclass = Puppet::Type.type(resource.type) and ! typeclass.isomorphic? - Puppet.info "Allowing duplicate %s" % typeclass.name - return true - end - - # Either it's a defined type, which are never - # isomorphic, or it's a non-isomorphic type, so - # we should throw an exception. - msg = "Duplicate definition: %s is already defined" % resource.ref - - if existing_resource.file and existing_resource.line - msg << " in file %s at line %s" % - [existing_resource.file, existing_resource.line] - end - - if resource.line or resource.file - msg << "; cannot redefine" - end - - raise Puppet::ParseError.new(msg) - end end diff --git a/lib/puppet/parser/functions.rb b/lib/puppet/parser/functions.rb index 34b38b809..e0b60e161 100644 --- a/lib/puppet/parser/functions.rb +++ b/lib/puppet/parser/functions.rb @@ -111,7 +111,7 @@ module Functions vals = [vals] unless vals.is_a?(Array) # The 'false' disables lazy evaluation. - klasses = compile.evaluate_classes(vals, self, false) + klasses = compiler.evaluate_classes(vals, self, false) missing = vals.find_all do |klass| ! klasses.include?(klass) @@ -146,7 +146,7 @@ module Functions tells you whether the current container is tagged with the specified tags. The tags are ANDed, so that all of the specified tags must be included for the function to return true.") do |vals| - configtags = compile.catalog.tags + configtags = compiler.catalog.tags resourcetags = resource.tags retval = true @@ -235,7 +235,7 @@ module Functions vals = [vals] unless vals.is_a?(Array) coll.resources = vals - compile.add_collection(coll) + compiler.add_collection(coll) end newfunction(:search, :doc => "Add another namespace for this class to search. diff --git a/lib/puppet/parser/interpreter.rb b/lib/puppet/parser/interpreter.rb index e29e19944..1d93193dd 100644 --- a/lib/puppet/parser/interpreter.rb +++ b/lib/puppet/parser/interpreter.rb @@ -3,7 +3,7 @@ require 'timeout' require 'puppet/rails' require 'puppet/util/methodhelper' require 'puppet/parser/parser' -require 'puppet/parser/compile' +require 'puppet/parser/compiler' require 'puppet/parser/scope' # The interpreter is a very simple entry-point class that @@ -25,7 +25,7 @@ class Puppet::Parser::Interpreter # evaluate our whole tree def compile(node) raise Puppet::ParseError, "Could not parse configuration; cannot compile" unless env_parser = parser(node.environment) - return Puppet::Parser::Compile.new(node, env_parser).compile + return Puppet::Parser::Compiler.new(node, env_parser).compile end # create our interpreter diff --git a/lib/puppet/parser/resource.rb b/lib/puppet/parser/resource.rb index 58667727f..fb0799011 100644 --- a/lib/puppet/parser/resource.rb +++ b/lib/puppet/parser/resource.rb @@ -58,8 +58,7 @@ class Puppet::Parser::Resource def evaluate if klass = @ref.definedtype finish() - scope.compile.delete_resource(self) - return klass.evaluate(:scope => scope, :resource => self) + return klass.evaluate_code(self) elsif builtin? devfail "Cannot evaluate a builtin type" else @@ -83,7 +82,6 @@ class Puppet::Parser::Resource # Do any finishing work on this object, called before evaluation or # before storage/translation. def finish - add_overrides() add_defaults() add_metaparams() add_scope_tags() @@ -342,19 +340,6 @@ class Puppet::Parser::Resource end end - # Add any overrides for this object. - def add_overrides - if overrides = scope.compile.resource_overrides(self) - overrides.each do |over| - self.merge(over) - end - - # Remove the overrides, so that the configuration knows there - # are none left. - overrides.clear - end - end - def add_scope_tags if scope_resource = scope.resource tag(*scope_resource.tags) diff --git a/lib/puppet/parser/resource/param.rb b/lib/puppet/parser/resource/param.rb index 9352311d6..9dd3f26d2 100644 --- a/lib/puppet/parser/resource/param.rb +++ b/lib/puppet/parser/resource/param.rb @@ -12,7 +12,7 @@ class Puppet::Parser::Resource::Param end def inspect - "#<#{self.class} @name => #{self.name}, @value => #{self.value}, @source => #{self.source.name}>" + "#<#{self.class} @name => #{name}, @value => #{value}, @source => #{source.name}>" end def line_to_i diff --git a/lib/puppet/parser/resource/reference.rb b/lib/puppet/parser/resource/reference.rb index 6e70d23b7..c59748049 100644 --- a/lib/puppet/parser/resource/reference.rb +++ b/lib/puppet/parser/resource/reference.rb @@ -37,10 +37,14 @@ class Puppet::Parser::Resource::Reference < Puppet::ResourceReference if self.title == :main tmp = @scope.findclass("") else - tmp = @scope.findclass(self.title) + unless tmp = @scope.findclass(self.title) + fail Puppet::ParseError, "Could not find class '%s'" % self.title + end end when "Node": # look for node definitions - tmp = @scope.parser.nodes[self.title] + unless tmp = @scope.parser.nodes[self.title] + fail Puppet::ParseError, "Could not find node '%s'" % self.title + end else # normal definitions # We have to swap these variables around so the errors are right. tmp = @scope.finddefine(self.type) @@ -49,7 +53,7 @@ class Puppet::Parser::Resource::Reference < Puppet::ResourceReference if tmp @definedtype = tmp else - fail Puppet::ParseError, "Could not find resource '%s'" % self + fail Puppet::ParseError, "Could not find resource type '%s'" % self.type end end diff --git a/lib/puppet/parser/scope.rb b/lib/puppet/parser/scope.rb index 028414cc0..a6e43e7b3 100644 --- a/lib/puppet/parser/scope.rb +++ b/lib/puppet/parser/scope.rb @@ -17,15 +17,20 @@ class Puppet::Parser::Scope include Puppet::Util::Errors attr_accessor :parent, :level, :parser, :source, :resource attr_accessor :base, :keyword, :nodescope - attr_accessor :top, :translated, :compile + attr_accessor :top, :translated, :compiler + + # A demeterific shortcut to the catalog. + def catalog + compiler.catalog + end # Proxy accessors def host - @compile.node.name + @compiler.node.name end def interpreter - @compile.interpreter + @compiler.interpreter end # Is the value true? This allows us to control the definition of truth @@ -72,7 +77,7 @@ class Puppet::Parser::Scope end def findresource(string, name = nil) - compile.findresource(string, name) + compiler.findresource(string, name) end # Initialize our new scope. Defaults to having no parent. @@ -147,7 +152,7 @@ class Puppet::Parser::Scope unless klass raise Puppet::ParseError, "Could not find class %s" % klassname end - unless kscope = compile.class_scope(klass) + unless kscope = compiler.class_scope(klass) raise Puppet::ParseError, "Class %s has not been evaluated so its variables cannot be referenced" % klass.classname end return kscope.lookupvar(shortname, usestring) @@ -184,7 +189,7 @@ class Puppet::Parser::Scope # Create a new scope and set these options. def newscope(options = {}) - compile.newscope(self, options) + compiler.newscope(self, options) end # Is this class for a node? This is used to make sure that @@ -199,7 +204,7 @@ class Puppet::Parser::Scope # than doing lots of queries. def parent unless defined?(@parent) - @parent = compile.parent(self) + @parent = compiler.parent(self) end @parent end diff --git a/lib/puppet/parser/templatewrapper.rb b/lib/puppet/parser/templatewrapper.rb index 13823d483..7a8f74156 100644 --- a/lib/puppet/parser/templatewrapper.rb +++ b/lib/puppet/parser/templatewrapper.rb @@ -7,7 +7,7 @@ class Puppet::Parser::TemplateWrapper def initialize(scope, file) @scope = scope - @file = Puppet::Module::find_template(file, @scope.compile.environment) + @file = Puppet::Module::find_template(file, @scope.compiler.environment) unless FileTest.exists?(@file) raise Puppet::ParseError, diff --git a/lib/puppet/pgraph.rb b/lib/puppet/pgraph.rb index 54b815b45..71547802e 100644 --- a/lib/puppet/pgraph.rb +++ b/lib/puppet/pgraph.rb @@ -7,17 +7,14 @@ require 'puppet/simple_graph' # This class subclasses a graph class in order to handle relationships # among resources. class Puppet::PGraph < Puppet::SimpleGraph - # This is the type used for splicing. - attr_accessor :container_type - include Puppet::Util - def add_edge!(*args) + def add_edge(*args) @reversal = nil super end - def add_vertex!(*args) + def add_vertex(*args) @reversal = nil super end @@ -57,11 +54,6 @@ class Puppet::PGraph < Puppet::SimpleGraph @reversal.tree_from_vertex(resource, :out).keys end - # Override this method to use our class instead. - def edge_class() - Puppet::Relationship - end - # Determine all of the leaf nodes below a given vertex. def leaves(vertex, direction = :out) tree = tree_from_vertex(vertex, direction) @@ -133,7 +125,7 @@ class Puppet::PGraph < Puppet::SimpleGraph copy_label(s, t, edge.label) next end - add_edge!(s, t, edge.label) + add_edge(s, t, edge.label) end # Now get rid of the edge, so remove_vertex! works correctly. diff --git a/lib/puppet/simple_graph.rb b/lib/puppet/simple_graph.rb index 11542ad53..503e4814c 100644 --- a/lib/puppet/simple_graph.rb +++ b/lib/puppet/simple_graph.rb @@ -100,10 +100,10 @@ class Puppet::SimpleGraph # Return a reversed version of this graph. def reversal result = self.class.new - vertices.each { |vertex| result.add_vertex!(vertex) } + vertices.each { |vertex| result.add_vertex(vertex) } edges.each do |edge| newedge = edge.class.new(edge.target, edge.source, edge.label) - result.add_edge!(newedge) + result.add_edge(newedge) end result end @@ -150,7 +150,7 @@ class Puppet::SimpleGraph end # Add a new vertex to the graph. - def add_vertex!(vertex) + def add_vertex(vertex) return false if vertex?(vertex) setup_vertex(vertex) true # don't return the VertexWrapper instance. @@ -176,7 +176,7 @@ class Puppet::SimpleGraph # Add a new edge. The graph user has to create the edge instance, # since they have to specify what kind of edge it is. - def add_edge!(source, target = nil, label = nil) + def add_edge(source, target = nil, label = nil) if target edge = Puppet::Relationship.new(source, target, label) else diff --git a/lib/puppet/transaction.rb b/lib/puppet/transaction.rb index f304cadc6..976bf7c68 100644 --- a/lib/puppet/transaction.rb +++ b/lib/puppet/transaction.rb @@ -173,7 +173,7 @@ class Transaction relationship_graph.add_resource(gen_child) unless relationship_graph.resource(gen_child.ref) unless relationship_graph.edge?(edge[1], edge[0]) - relationship_graph.add_edge!(*edge) + relationship_graph.add_edge(*edge) else resource.debug "Skipping automatic relationship to %s" % gen_child end diff --git a/lib/puppet/transportable.rb b/lib/puppet/transportable.rb index c1d68a881..f686fbb78 100644 --- a/lib/puppet/transportable.rb +++ b/lib/puppet/transportable.rb @@ -193,7 +193,7 @@ module Puppet next unless resource = child.to_type config.add_resource resource end - config.add_edge!(container, resource) + config.add_edge(container, resource) if child.is_a?(self.class) delver.call(child) end diff --git a/lib/puppet/type/pfile.rb b/lib/puppet/type/pfile.rb index 7d928d959..c32a4d474 100644 --- a/lib/puppet/type/pfile.rb +++ b/lib/puppet/type/pfile.rb @@ -650,7 +650,7 @@ module Puppet # LAK:FIXME This shouldn't be necessary, but as long as we're # modeling the relationship graph specifically, it is. - catalog.relationship_graph.add_edge! self, child + catalog.relationship_graph.add_edge self, child return child end diff --git a/lib/puppet/util/constant_inflector.rb b/lib/puppet/util/constant_inflector.rb new file mode 100644 index 000000000..8b083951f --- /dev/null +++ b/lib/puppet/util/constant_inflector.rb @@ -0,0 +1,14 @@ +# Created on 2008-02-12 +# Copyright Luke Kanies + +# A common module for converting between constants and +# file names. +module Puppet::Util::ConstantInflector + def file2constant(file) + file.split("/").collect { |name| name.capitalize }.join("::").gsub(/_+(.)/) { |term| $1.capitalize } + end + + def constant2file(constant) + constant.to_s.gsub(/([a-z])([A-Z])/) { |term| $1 + "_" + $2 }.gsub("::", "/").downcase + end +end diff --git a/lib/puppet/util/graph.rb b/lib/puppet/util/graph.rb index a9744578b..d1ef36f8e 100644 --- a/lib/puppet/util/graph.rb +++ b/lib/puppet/util/graph.rb @@ -16,7 +16,7 @@ module Puppet::Util::Graph self.each do |child| unless block_given? and ! yield(child) - graph.add_edge!(self, child) + graph.add_edge(self, child) if child.respond_to?(:to_graph) child.to_graph(graph, &block) diff --git a/lib/puppet/util/tagging.rb b/lib/puppet/util/tagging.rb index 25d74c420..9abb3fb2b 100644 --- a/lib/puppet/util/tagging.rb +++ b/lib/puppet/util/tagging.rb @@ -19,6 +19,11 @@ module Puppet::Util::Tagging qualified.collect { |name| name.split("::") }.flatten.each { |tag| @tags << tag unless @tags.include?(tag) } end + # Are we tagged with the provided tag? + def tagged?(tag) + defined?(@tags) and @tags.include?(tag.to_s) + end + # Return a copy of the tag list, so someone can't ask for our tags # and then modify them. def tags diff --git a/spec/lib/monkey_patches/add_confine_and_runnable_to_rspec_dsl.rb b/spec/monkey_patches/add_confine_and_runnable_to_rspec_dsl.rb index bfa2a0c3c..941baa8de 100644 --- a/spec/lib/monkey_patches/add_confine_and_runnable_to_rspec_dsl.rb +++ b/spec/monkey_patches/add_confine_and_runnable_to_rspec_dsl.rb @@ -1,5 +1,5 @@ dir = File.expand_path(File.dirname(__FILE__)) -[ "#{dir}/../../lib", "#{dir}/../../../lib", "#{dir}/../../../test/lib"].each do |dir| +[ "#{dir}/../../lib", "#{dir}/../../test/lib"].each do |dir| fulldir = File.expand_path(dir) $LOAD_PATH.unshift(fulldir) unless $LOAD_PATH.include?(fulldir) end diff --git a/spec/lib/shared_behaviours/file_server_terminus.rb b/spec/shared_behaviours/file_server_terminus.rb index de08f29fc..de08f29fc 100644 --- a/spec/lib/shared_behaviours/file_server_terminus.rb +++ b/spec/shared_behaviours/file_server_terminus.rb diff --git a/spec/lib/shared_behaviours/file_serving.rb b/spec/shared_behaviours/file_serving.rb index b5ab6b0fd..b5ab6b0fd 100644 --- a/spec/lib/shared_behaviours/file_serving.rb +++ b/spec/shared_behaviours/file_serving.rb diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index bfac9095f..3aa3b0202 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,8 +1,19 @@ dir = File.expand_path(File.dirname(__FILE__)) -$LOAD_PATH.unshift("#{dir}/lib") + +$LOAD_PATH.unshift("#{dir}/") $LOAD_PATH.unshift("#{dir}/../lib") $LOAD_PATH.unshift("#{dir}/../test/lib") # Add the old test dir, so that we can still find our local mocha and spec +# include any gems in vendor/gems +Dir["#{dir}/../vendor/gems/**"].map do |path| + libpath = File.join(path, "lib") + if File.directory?(libpath) + $LOAD_PATH.unshift(libpath) + else + $LOAD_PATH.unshift(path) + end +end + require 'puppettest' require 'puppettest/runnable_test' require 'mocha' @@ -19,4 +30,5 @@ Spec::Runner.configure do |config| end end -require "#{dir}/lib/monkey_patches/add_confine_and_runnable_to_rspec_dsl" +# load any monkey-patches +Dir["#{dir}/monkey_patches/*.rb"].map { |file| require file } diff --git a/spec/unit/node/catalog.rb b/spec/unit/node/catalog.rb index 3833890f7..aa49909e2 100755 --- a/spec/unit/node/catalog.rb +++ b/spec/unit/node/catalog.rb @@ -57,11 +57,11 @@ describe Puppet::Node::Catalog, " when extracting transobjects" do def mkscope @parser = Puppet::Parser::Parser.new :Code => "" @node = Puppet::Node.new("mynode") - @compile = Puppet::Parser::Compile.new(@node, @parser) + @compiler = Puppet::Parser::Compiler.new(@node, @parser) # XXX This is ridiculous. - @compile.send(:evaluate_main) - @scope = @compile.topscope + @compiler.send(:evaluate_main) + @scope = @compiler.topscope end def mkresource(type, name) @@ -75,7 +75,7 @@ describe Puppet::Node::Catalog, " when extracting transobjects" do @source = mock 'source' main = mkresource("class", :main) - config.add_vertex!(main) + config.add_vertex(main) bucket = mock 'bucket' bucket.expects(:classes=).with(config.classes) @@ -95,7 +95,7 @@ describe Puppet::Node::Catalog, " when extracting transobjects" do defined = mkresource("class", :main) builtin = mkresource("file", "/yay") - config.add_edge!(defined, builtin) + config.add_edge(defined, builtin) bucket = [] bucket.expects(:classes=).with(config.classes) @@ -121,21 +121,21 @@ describe Puppet::Node::Catalog, " when extracting transobjects" do top.expects(:to_trans).returns(topbucket) topres = mkresource "file", "/top" topres.expects(:to_trans).returns(:topres) - config.add_edge! top, topres + config.add_edge top, topres middle = mkresource "class", "middle" middle.expects(:to_trans).returns([]) - config.add_edge! top, middle + config.add_edge top, middle midres = mkresource "file", "/mid" midres.expects(:to_trans).returns(:midres) - config.add_edge! middle, midres + config.add_edge middle, midres bottom = mkresource "class", "bottom" bottom.expects(:to_trans).returns([]) - config.add_edge! middle, bottom + config.add_edge middle, bottom botres = mkresource "file", "/bot" botres.expects(:to_trans).returns(:botres) - config.add_edge! bottom, botres + config.add_edge bottom, botres toparray = config.extract_to_transportable @@ -196,13 +196,13 @@ describe Puppet::Node::Catalog, " when converting to a transobject catalog" do @resources = [@top, @topobject, @middle, @middleobject, @bottom, @bottomobject] - @original.add_edge!(@top, @topobject) - @original.add_edge!(@top, @virtual) - @original.add_edge!(@virtual, @virtualobject) - @original.add_edge!(@top, @middle) - @original.add_edge!(@middle, @middleobject) - @original.add_edge!(@middle, @bottom) - @original.add_edge!(@bottom, @bottomobject) + @original.add_edge(@top, @topobject) + @original.add_edge(@top, @virtual) + @original.add_edge(@virtual, @virtualobject) + @original.add_edge(@top, @middle) + @original.add_edge(@middle, @middleobject) + @original.add_edge(@middle, @bottom) + @original.add_edge(@bottom, @bottomobject) @catalog = @original.to_transportable end @@ -261,11 +261,11 @@ describe Puppet::Node::Catalog, " when converting to a RAL catalog" do @original.add_resource(*@resources) - @original.add_edge!(@top, @topobject) - @original.add_edge!(@top, @middle) - @original.add_edge!(@middle, @middleobject) - @original.add_edge!(@middle, @bottom) - @original.add_edge!(@bottom, @bottomobject) + @original.add_edge(@top, @topobject) + @original.add_edge(@top, @middle) + @original.add_edge(@middle, @middleobject) + @original.add_edge(@middle, @bottom) + @original.add_edge(@bottom, @bottomobject) @catalog = @original.to_ral end @@ -300,7 +300,7 @@ describe Puppet::Node::Catalog, " when converting to a RAL catalog" do config.add_resource(changer) config.add_resource(@top) - config.add_edge!(@top, changer) + config.add_edge(@top, changer) resource = stub 'resource', :name => "changer2", :title => "changer2", :ref => "Test[changer2]", :catalog= => nil, :remove => nil @@ -365,6 +365,12 @@ describe Puppet::Node::Catalog, " when functioning as a resource container" do it "should not allow two resources with the same resource reference" do @catalog.add_resource(@one) + + # These are used to build the failure + @dupe.stubs(:file) + @dupe.stubs(:line) + @one.stubs(:file) + @one.stubs(:line) proc { @catalog.add_resource(@dupe) }.should raise_error(ArgumentError) end @@ -591,8 +597,8 @@ describe Puppet::Node::Catalog, " when creating a relationship graph" do @file = Puppet::Type.type(:file) @one = @file.create :path => "/one" @two = @file.create :path => "/two" - @catalog.add_edge! @compone, @one - @catalog.add_edge! @comptwo, @two + @catalog.add_edge @compone, @one + @catalog.add_edge @comptwo, @two @three = @file.create :path => "/three" @four = @file.create :path => "/four", :require => ["file", "/three"] @@ -765,7 +771,7 @@ end describe Puppet::Node::Catalog, " when converting to yaml" do before do @catalog = Puppet::Node::Catalog.new("me") - @catalog.add_edge!("one", "two") + @catalog.add_edge("one", "two") end it "should be able to be dumped to yaml" do @@ -776,7 +782,7 @@ end describe Puppet::Node::Catalog, " when converting from yaml" do before do @catalog = Puppet::Node::Catalog.new("me") - @catalog.add_edge!("one", "two") + @catalog.add_edge("one", "two") text = YAML.dump(@catalog) @newcatalog = YAML.load(text) diff --git a/spec/unit/other/pgraph.rb b/spec/unit/other/pgraph.rb index 252a807ec..7d66ae331 100755 --- a/spec/unit/other/pgraph.rb +++ b/spec/unit/other/pgraph.rb @@ -35,8 +35,8 @@ describe Puppet::PGraph do end it "should correctly clear vertices and edges when asked" do - @graph.add_edge!("a", "b") - @graph.add_vertex! "c" + @graph.add_edge("a", "b") + @graph.add_vertex "c" @graph.clear @graph.vertices.should be_empty @graph.edges.should be_empty @@ -52,7 +52,7 @@ describe Puppet::PGraph, " when matching edges" do @edges = {} @edges["a/b"] = Puppet::Relationship.new("a", "b", {:event => :yay, :callback => :refresh}) @edges["a/c"] = Puppet::Relationship.new("a", "c", {:event => :yay, :callback => :refresh}) - @graph.add_edge!(@edges["a/b"]) + @graph.add_edge(@edges["a/b"]) end it "should match edges whose source matches the source of the event" do @@ -64,7 +64,7 @@ describe Puppet::PGraph, " when matching edges" do end it "should match multiple edges" do - @graph.add_edge!(@edges["a/c"]) + @graph.add_edge(@edges["a/c"]) edges = @graph.matching_edges([@event]) edges.should be_include(@edges["a/b"]) edges.should be_include(@edges["a/c"]) @@ -75,9 +75,9 @@ describe Puppet::PGraph, " when determining dependencies" do before do @graph = Puppet::PGraph.new - @graph.add_edge!("a", "b") - @graph.add_edge!("a", "c") - @graph.add_edge!("b", "d") + @graph.add_edge("a", "b") + @graph.add_edge("a", "c") + @graph.add_edge("b", "d") end it "should find all dependents when they are on multiple levels" do @@ -118,19 +118,19 @@ describe Puppet::PGraph, " when splicing the relationship graph" do # We have to add the container to the main graph, else it won't # be spliced in the dependency graph. - @contgraph.add_vertex!(@empty) + @contgraph.add_vertex(@empty) end def dependency_graph @depgraph = Puppet::PGraph.new @contgraph.vertices.each do |v| - @depgraph.add_vertex!(v) + @depgraph.add_vertex(v) end # We have to specify a relationship to our empty container, else it # never makes it into the dep graph in the first place. {@one => @two, "f" => "c", "h" => @middle, "c" => @empty}.each do |source, target| - @depgraph.add_edge!(source, target, :callback => :refresh) + @depgraph.add_edge(source, target, :callback => :refresh) end end @@ -176,13 +176,13 @@ describe Puppet::PGraph, " when splicing the relationship graph" do end it "should not add labels to edges that have none" do - @depgraph.add_edge!(@two, @three) + @depgraph.add_edge(@two, @three) splice @depgraph.edge_label("c", "i").should == {} end it "should copy labels over edges that have none" do - @depgraph.add_edge!("c", @three, {:callback => :refresh}) + @depgraph.add_edge("c", @three, {:callback => :refresh}) splice # And make sure the label got copied. @depgraph.edge_label("c", "i").should == {:callback => :refresh} @@ -190,18 +190,18 @@ describe Puppet::PGraph, " when splicing the relationship graph" do it "should not replace a label with a nil label" do # Lastly, add some new label-less edges and make sure the label stays. - @depgraph.add_edge!(@middle, @three) - @depgraph.add_edge!("c", @three, {:callback => :refresh}) + @depgraph.add_edge(@middle, @three) + @depgraph.add_edge("c", @three, {:callback => :refresh}) splice @depgraph.edge_label("c", "i").should == {:callback => :refresh} end it "should copy labels to all created edges" do - @depgraph.add_edge!(@middle, @three) - @depgraph.add_edge!("c", @three, {:callback => :refresh}) + @depgraph.add_edge(@middle, @three) + @depgraph.add_edge("c", @three, {:callback => :refresh}) splice @three.each do |child| - edge = @depgraph.edge_class.new("c", child) + edge = Puppet::Relationship.new("c", child) @depgraph.should be_edge(edge.source, edge.target) @depgraph.edge_label(edge.source, edge.target).should == {:callback => :refresh} end diff --git a/spec/unit/parser/ast/definition.rb b/spec/unit/parser/ast/definition.rb index a27fb4721..f236e23b7 100755 --- a/spec/unit/parser/ast/definition.rb +++ b/spec/unit/parser/ast/definition.rb @@ -12,8 +12,8 @@ describe Puppet::Parser::AST::Definition, "when evaluating" do @source = @parser.newclass "" @definition = @parser.newdefine "mydefine" @node = Puppet::Node.new("yaynode") - @compile = Puppet::Parser::Compile.new(@node, @parser) - @scope = @compile.topscope + @compiler = Puppet::Parser::Compiler.new(@node, @parser) + @scope = @compiler.topscope @resource = Puppet::Parser::Resource.new(:type => "mydefine", :title => "myresource", :scope => @scope, :source => @source) end @@ -21,12 +21,12 @@ describe Puppet::Parser::AST::Definition, "when evaluating" do it "should create a new scope" do scope = nil code = mock 'code' - code.expects(:safeevaluate).with do |options| - options[:scope].object_id.should_not == @scope.object_id + code.expects(:safeevaluate).with do |scope| + scope.object_id.should_not == @scope.object_id true end @definition.stubs(:code).returns(code) - @definition.evaluate(:scope => @scope, :resource => @resource) + @definition.evaluate_code(@resource) end # it "should copy its namespace to the scope" @@ -44,4 +44,152 @@ describe Puppet::Parser::AST::Definition, "when evaluating" do # it "should not copy the resource's title as the name if 'name' is one of the resource parameters" # # it "should evaluate the associated code with the new scope" + + def test_initialize + parser = mkparser + + # Create a new definition + klass = parser.newdefine "yayness", + :arguments => [["owner", stringobj("nobody")], %w{mode}], + :code => AST::ASTArray.new( + :children => [resourcedef("file", "/tmp/$name", + "owner" => varref("owner"), "mode" => varref("mode"))] + ) + + # Test validattr? a couple different ways + [:owner, "owner", :schedule, "schedule"].each do |var| + assert(klass.validattr?(var), "%s was not considered valid" % var.inspect) + end + + [:random, "random"].each do |var| + assert(! klass.validattr?(var), "%s was considered valid" % var.inspect) + end + + end + + def test_evaluate + parser = mkparser + config = mkcompiler + config.send(:evaluate_main) + scope = config.topscope + klass = parser.newdefine "yayness", + :arguments => [["owner", stringobj("nobody")], %w{mode}], + :code => AST::ASTArray.new( + :children => [resourcedef("file", "/tmp/$name", + "owner" => varref("owner"), "mode" => varref("mode"))] + ) + + resource = Puppet::Parser::Resource.new( + :title => "first", + :type => "yayness", + :exported => false, + :virtual => false, + :scope => scope, + :source => scope.source + ) + resource.send(:set_parameter, "name", "first") + resource.send(:set_parameter, "mode", "755") + + resource.stubs(:title) + assert_nothing_raised do + klass.evaluate_code(resource) + end + + firstobj = config.findresource("File[/tmp/first]") + assert(firstobj, "Did not create /tmp/first obj") + + assert_equal("File", firstobj.type) + assert_equal("/tmp/first", firstobj.title) + assert_equal("nobody", firstobj[:owner]) + assert_equal("755", firstobj[:mode]) + + # Make sure we can't evaluate it with the same args + assert_raise(Puppet::ParseError) do + klass.evaluate_code(resource) + end + + # Now create another with different args + resource2 = Puppet::Parser::Resource.new( + :title => "second", + :type => "yayness", + :exported => false, + :virtual => false, + :scope => scope, + :source => scope.source + ) + resource2.send(:set_parameter, "name", "second") + resource2.send(:set_parameter, "mode", "755") + resource2.send(:set_parameter, "owner", "daemon") + + assert_nothing_raised do + klass.evaluate_code(resource2) + end + + secondobj = config.findresource("File[/tmp/second]") + assert(secondobj, "Did not create /tmp/second obj") + + assert_equal("File", secondobj.type) + assert_equal("/tmp/second", secondobj.title) + assert_equal("daemon", secondobj[:owner]) + assert_equal("755", secondobj[:mode]) + end + + # #539 - definitions should support both names and titles + def test_names_and_titles + parser = mkparser + scope = mkscope :parser => parser + + [ + {:name => "one", :title => "two"}, + {:title => "mytitle"} + ].each_with_index do |hash, i| + # Create a definition that uses both name and title. Put this + # inside the loop so the subscope expectations work. + klass = parser.newdefine "yayness%s" % i + + resource = Puppet::Parser::Resource.new( + :title => hash[:title], + :type => "yayness%s" % i, + :exported => false, + :virtual => false, + :scope => scope, + :source => scope.source + ) + + subscope = klass.subscope(scope, resource) + + klass.expects(:subscope).returns(subscope) + + if hash[:name] + resource.stubs(:to_hash).returns({:name => hash[:name]}) + end + + assert_nothing_raised("Could not evaluate definition with %s" % hash.inspect) do + klass.evaluate_code(resource) + end + + name = hash[:name] || hash[:title] + title = hash[:title] + + assert_equal(name, subscope.lookupvar("name"), + "Name did not get set correctly") + assert_equal(title, subscope.lookupvar("title"), + "title did not get set correctly") + + [:name, :title].each do |param| + val = resource.send(param) + assert(subscope.tags.include?(val), + "Scope was not tagged with %s '%s'" % [param, val]) + end + end + end + + # Testing the root cause of #615. We should be using the fqname for the type, instead + # of just the short name. + def test_fully_qualified_types + parser = mkparser + klass = parser.newclass("one::two") + + assert_equal("one::two", klass.classname, "Class did not get fully qualified class name") + end end diff --git a/spec/unit/parser/ast/hostclass.rb b/spec/unit/parser/ast/hostclass.rb new file mode 100755 index 000000000..422861857 --- /dev/null +++ b/spec/unit/parser/ast/hostclass.rb @@ -0,0 +1,131 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +module HostClassTesting + def setup + @node = Puppet::Node.new "testnode" + @parser = Puppet::Parser::Parser.new :environment => "development" + @scope_resource = stub 'scope_resource', :builtin? => true + @compiler = Puppet::Parser::Compiler.new(@node, @parser) + + @scope = @compiler.topscope + end +end + +describe Puppet::Parser::AST::HostClass, "when evaluating" do + include HostClassTesting + + before do + @top = @parser.newclass "top" + @middle = @parser.newclass "middle", :parent => "top" + end + + it "should create a resource that references itself" do + @top.evaluate(@scope) + + @compiler.catalog.resource(:class, "top").should be_instance_of(Puppet::Parser::Resource) + end + + it "should evaluate the parent class if one exists" do + @middle.evaluate(@scope) + + @compiler.catalog.resource(:class, "top").should be_instance_of(Puppet::Parser::Resource) + end + + it "should fail to evaluate if a parent class is defined but cannot be found" do + othertop = @parser.newclass "something", :parent => "yay" + lambda { othertop.evaluate(@scope) }.should raise_error(Puppet::ParseError) + end + + it "should not create a new resource if one already exists" do + @compiler.catalog.expects(:resource).with(:class, "top").returns("something") + @compiler.catalog.expects(:add_resource).never + @top.evaluate(@scope) + end + + it "should not create a new parent resource if one already exists and it has a parent class" do + @top.evaluate(@scope) + + top_resource = @compiler.catalog.resource(:class, "top") + + @middle.evaluate(@scope) + + @compiler.catalog.resource(:class, "top").should equal(top_resource) + end + + # #795 - tag before evaluation. + it "should tag the catalog with the resource tags when it is evaluated" do + @middle.evaluate(@scope) + + @compiler.catalog.should be_tagged("middle") + end + + it "should tag the catalog with the parent class tags when it is evaluated" do + @middle.evaluate(@scope) + + @compiler.catalog.should be_tagged("top") + end +end + +describe Puppet::Parser::AST::HostClass, "when evaluating code" do + include HostClassTesting + + before do + @top_resource = stub "top_resource" + @top = @parser.newclass "top", :code => @top_resource + + @middle_resource = stub "middle_resource" + @middle = @parser.newclass "top::middle", :parent => "top", :code => @middle_resource + end + + it "should set its namespace to its fully qualified name" do + @middle.namespace.should == "top::middle" + end + + it "should evaluate the code referred to by the class" do + @top_resource.expects(:safeevaluate) + + resource = @top.evaluate(@scope) + + @top.evaluate_code(resource) + end + + it "should evaluate the parent class's code if it has a parent" do + @top_resource.expects(:safeevaluate) + @middle_resource.expects(:safeevaluate) + + resource = @middle.evaluate(@scope) + + @middle.evaluate_code(resource) + end + + it "should not evaluate the parent class's code if the parent has already been evaluated" do + @top_resource.stubs(:safeevaluate) + resource = @top.evaluate(@scope) + @top.evaluate_code(resource) + + @top_resource.expects(:safeevaluate).never + @middle_resource.stubs(:safeevaluate) + resource = @middle.evaluate(@scope) + @middle.evaluate_code(resource) + end + + it "should use the parent class's scope as its parent scope" do + @top_resource.stubs(:safeevaluate) + @middle_resource.stubs(:safeevaluate) + resource = @middle.evaluate(@scope) + @middle.evaluate_code(resource) + + @compiler.class_scope(@middle).parent.should equal(@compiler.class_scope(@top)) + end + + it "should add the parent class's namespace to its namespace search path" do + @top_resource.stubs(:safeevaluate) + @middle_resource.stubs(:safeevaluate) + resource = @middle.evaluate(@scope) + @middle.evaluate_code(resource) + + @compiler.class_scope(@middle).namespaces.should be_include(@top.namespace) + end +end diff --git a/spec/unit/parser/ast/node.rb b/spec/unit/parser/ast/node.rb new file mode 100755 index 000000000..340630194 --- /dev/null +++ b/spec/unit/parser/ast/node.rb @@ -0,0 +1,127 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../../spec_helper' + +module ASTNodeTesting + def setup + @node = Puppet::Node.new "testnode" + @parser = Puppet::Parser::Parser.new :environment => "development" + @scope_resource = stub 'scope_resource', :builtin? => true + @compiler = Puppet::Parser::Compiler.new(@node, @parser) + + @scope = @compiler.topscope + end +end + +describe Puppet::Parser::AST::Node, "when evaluating" do + include ASTNodeTesting + + before do + @top = @parser.newnode("top").shift + @middle = @parser.newnode("middle", :parent => "top").shift + end + + it "should create a resource that references itself" do + @top.evaluate(@scope) + + @compiler.catalog.resource(:node, "top").should be_an_instance_of(Puppet::Parser::Resource) + end + + it "should evaluate the parent class if one exists" do + @middle.evaluate(@scope) + + @compiler.catalog.resource(:node, "top").should be_an_instance_of(Puppet::Parser::Resource) + end + + it "should fail to evaluate if a parent class is defined but cannot be found" do + othertop = @parser.newnode("something", :parent => "yay").shift + lambda { othertop.evaluate(@scope) }.should raise_error(Puppet::ParseError) + end + + it "should not create a new resource if one already exists" do + @compiler.catalog.expects(:resource).with(:node, "top").returns("something") + @compiler.catalog.expects(:add_resource).never + @top.evaluate(@scope) + end + + it "should not create a new parent resource if one already exists and it has a parent class" do + @top.evaluate(@scope) + + top_resource = @compiler.catalog.resource(:node, "top") + + @middle.evaluate(@scope) + + @compiler.catalog.resource(:node, "top").should equal(top_resource) + end + + # #795 - tag before evaluation. + it "should tag the catalog with the resource tags when it is evaluated" do + @middle.evaluate(@scope) + + @compiler.catalog.should be_tagged("middle") + end + + it "should tag the catalog with the parent class tags when it is evaluated" do + @middle.evaluate(@scope) + + @compiler.catalog.should be_tagged("top") + end +end + +describe Puppet::Parser::AST::Node, "when evaluating code" do + include ASTNodeTesting + + before do + @top_resource = stub "top_resource" + @top = @parser.newnode("top", :code => @top_resource).shift + + @middle_resource = stub "middle_resource" + @middle = @parser.newnode("middle", :parent => "top", :code => @middle_resource).shift + end + + it "should evaluate the code referred to by the class" do + @top_resource.expects(:safeevaluate) + + resource = @top.evaluate(@scope) + + @top.evaluate_code(resource) + end + + it "should evaluate the parent class's code if it has a parent" do + @top_resource.expects(:safeevaluate) + @middle_resource.expects(:safeevaluate) + + resource = @middle.evaluate(@scope) + + @middle.evaluate_code(resource) + end + + it "should not evaluate the parent class's code if the parent has already been evaluated" do + @top_resource.stubs(:safeevaluate) + resource = @top.evaluate(@scope) + @top.evaluate_code(resource) + + @top_resource.expects(:safeevaluate).never + @middle_resource.stubs(:safeevaluate) + resource = @middle.evaluate(@scope) + @middle.evaluate_code(resource) + end + + it "should use the parent class's scope as its parent scope" do + @top_resource.stubs(:safeevaluate) + @middle_resource.stubs(:safeevaluate) + resource = @middle.evaluate(@scope) + @middle.evaluate_code(resource) + + @compiler.class_scope(@middle).parent.should equal(@compiler.class_scope(@top)) + end + + it "should add the parent class's namespace to its namespace search path" do + @top_resource.stubs(:safeevaluate) + @middle_resource.stubs(:safeevaluate) + resource = @middle.evaluate(@scope) + @middle.evaluate_code(resource) + + @compiler.class_scope(@middle).namespaces.should be_include(@top.namespace) + end +end diff --git a/spec/unit/parser/collector.rb b/spec/unit/parser/collector.rb index 9b5eab1f4..e1ceb23ed 100755 --- a/spec/unit/parser/collector.rb +++ b/spec/unit/parser/collector.rb @@ -79,8 +79,8 @@ describe Puppet::Parser::Collector, "when collecting specific virtual resources" @collector.resources = ["File[virtual1]"] one = mock 'one' one.stubs(:virtual=) - @compile.expects(:delete_collection).with(@collector) - @scope.expects(:compile).returns(@compile) + @compiler.expects(:delete_collection).with(@collector) + @scope.expects(:compiler).returns(@compiler) @scope.stubs(:findresource).with("File[virtual1]").returns(one) @collector.evaluate end @@ -89,7 +89,7 @@ describe Puppet::Parser::Collector, "when collecting specific virtual resources" @collector.resources = ["File[virtual1]"] one = mock 'one' one.stubs(:virtual=) - @compile.expects(:delete_collection).never + @compiler.expects(:delete_collection).never @scope.stubs(:findresource).with("File[virtual1]").returns(nil) @collector.evaluate end @@ -98,8 +98,8 @@ end describe Puppet::Parser::Collector, "when collecting virtual resources" do before do @scope = mock 'scope' - @compile = mock 'compile' - @scope.stubs(:compile).returns(@compile) + @compiler = mock 'compile' + @scope.stubs(:compiler).returns(@compiler) @resource_type = "Mytype" @vquery = proc { |res| true } @@ -113,7 +113,7 @@ describe Puppet::Parser::Collector, "when collecting virtual resources" do one.stubs(:virtual=) two.stubs(:virtual=) - @compile.expects(:resources).returns([one, two]) + @compiler.expects(:resources).returns([one, two]) @collector.evaluate.should == [one, two] end @@ -123,7 +123,7 @@ describe Puppet::Parser::Collector, "when collecting virtual resources" do one.expects(:virtual=).with(false) - @compile.expects(:resources).returns([one]) + @compiler.expects(:resources).returns([one]) @collector.evaluate end @@ -135,7 +135,7 @@ describe Puppet::Parser::Collector, "when collecting virtual resources" do one.stubs(:virtual=) two.stubs(:virtual=) - @compile.expects(:resources).returns([one, two]) + @compiler.expects(:resources).returns([one, two]) @collector.evaluate.should == [one, two] end @@ -147,7 +147,7 @@ describe Puppet::Parser::Collector, "when collecting virtual resources" do one.expects(:virtual=).with(false) two.expects(:virtual=).with(false) - @compile.expects(:resources).returns([one, two]) + @compiler.expects(:resources).returns([one, two]) @collector = Puppet::Parser::Collector.new(@scope, @resource_type, nil, nil, :virtual) @@ -161,7 +161,7 @@ describe Puppet::Parser::Collector, "when collecting virtual resources" do one.expects(:virtual=).with(false) two.expects(:virtual=).never - @compile.expects(:resources).returns([one, two]) + @compiler.expects(:resources).returns([one, two]) @collector.evaluate.should == [one] end @@ -173,7 +173,7 @@ describe Puppet::Parser::Collector, "when collecting virtual resources" do one.expects(:virtual=).never two.expects(:virtual=).never - @compile.expects(:resources).returns([one, two]) + @compiler.expects(:resources).returns([one, two]) @collector.evaluate.should be_false end @@ -187,7 +187,7 @@ describe Puppet::Parser::Collector, "when collecting virtual resources" do one.expects(:virtual=).with(false) two.expects(:virtual=).never - @compile.expects(:resources).returns([one, two]) + @compiler.expects(:resources).returns([one, two]) @collector.evaluate.should == [one] end @@ -198,8 +198,8 @@ describe Puppet::Parser::Collector, "when collecting exported resources" do before do @scope = stub 'scope', :host => "myhost", :debug => nil - @compile = mock 'compile' - @scope.stubs(:compile).returns(@compile) + @compiler = mock 'compile' + @scope.stubs(:compiler).returns(@compiler) @resource_type = "Mytype" @equery = "test = true" @vquery = proc { |r| true } @@ -218,7 +218,7 @@ describe Puppet::Parser::Collector, "when collecting exported resources" do end it "should use initialize the Rails support if ActiveRecord is not connected" do - @compile.stubs(:resources).returns([]) + @compiler.stubs(:resources).returns([]) ActiveRecord::Base.expects(:connected?).returns(false) Puppet::Rails.expects(:init) Puppet::Rails::Host.stubs(:find_by_name).returns(nil) @@ -238,7 +238,7 @@ describe Puppet::Parser::Collector, "when collecting exported resources" do two.stubs(:exported=) two.stubs(:virtual=) - @compile.expects(:resources).returns([one, two]) + @compiler.expects(:resources).returns([one, two]) @collector.evaluate.should == [one, two] end @@ -251,7 +251,7 @@ describe Puppet::Parser::Collector, "when collecting exported resources" do one.stubs(:exported=) one.expects(:virtual=).with(false) - @compile.expects(:resources).returns([one]) + @compiler.expects(:resources).returns([one]) @collector.evaluate.should == [one] end @@ -268,10 +268,10 @@ describe Puppet::Parser::Collector, "when collecting exported resources" do resource.stubs(:exported=) resource.stubs(:virtual=) - @compile.stubs(:resources).returns([]) + @compiler.stubs(:resources).returns([]) @scope.stubs(:findresource).returns(nil) - @compile.stubs(:store_resource) + @compiler.stubs(:add_resource) @collector.evaluate.should == [resource] end @@ -288,10 +288,10 @@ describe Puppet::Parser::Collector, "when collecting exported resources" do resource.stubs(:exported=) resource.stubs(:virtual=) - @compile.stubs(:resources).returns([]) + @compiler.stubs(:resources).returns([]) @scope.stubs(:findresource).returns(nil) - @compile.expects(:store_resource).with(@scope, resource) + @compiler.expects(:add_resource).with(@scope, resource) @collector.evaluate.should == [resource] end @@ -309,10 +309,10 @@ describe Puppet::Parser::Collector, "when collecting exported resources" do resource.expects(:exported=).with(false) resource.stubs(:virtual=) - @compile.stubs(:resources).returns([]) + @compiler.stubs(:resources).returns([]) @scope.stubs(:findresource).returns(nil) - @compile.stubs(:store_resource) + @compiler.stubs(:add_resource) @collector.evaluate end @@ -328,10 +328,10 @@ describe Puppet::Parser::Collector, "when collecting exported resources" do resource = mock 'resource' - @compile.stubs(:resources).returns([]) + @compiler.stubs(:resources).returns([]) @scope.stubs(:findresource).returns(inmemory) - @compile.stubs(:store_resource) + @compiler.stubs(:add_resource) proc { @collector.evaluate }.should raise_error(Puppet::ParseError) end @@ -347,10 +347,10 @@ describe Puppet::Parser::Collector, "when collecting exported resources" do resource = mock 'resource' - @compile.stubs(:resources).returns([]) + @compiler.stubs(:resources).returns([]) @scope.stubs(:findresource).returns(inmemory) - @compile.stubs(:store_resource) + @compiler.stubs(:add_resource) proc { @collector.evaluate }.should_not raise_error(Puppet::ParseError) end @@ -361,14 +361,14 @@ describe Puppet::Parser::Collector, "when building its ActiveRecord query for co before do @scope = stub 'scope', :host => "myhost", :debug => nil - @compile = mock 'compile' - @scope.stubs(:compile).returns(@compile) + @compiler = mock 'compile' + @scope.stubs(:compiler).returns(@compiler) @resource_type = "Mytype" @equery = nil @vquery = proc { |r| true } @collector = Puppet::Parser::Collector.new(@scope, @resource_type, @equery, @vquery, :exported) - @compile.stubs(:resources).returns([]) + @compiler.stubs(:resources).returns([]) ActiveRecord::Base.stubs(:connected?).returns(false) diff --git a/spec/unit/parser/compile.rb b/spec/unit/parser/compile.rb deleted file mode 100755 index 092bece0c..000000000 --- a/spec/unit/parser/compile.rb +++ /dev/null @@ -1,281 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../../spec_helper' - -describe Puppet::Parser::Compile, " when compiling" do - before do - @node = stub 'node', :name => 'mynode' - @parser = stub 'parser', :version => "1.0" - @compile = Puppet::Parser::Compile.new(@node, @parser) - end - - def compile_methods - [:set_node_parameters, :evaluate_main, :evaluate_ast_node, :evaluate_node_classes, :evaluate_generators, :fail_on_unevaluated, - :finish, :store, :extract] - end - - # Stub all of the main compile methods except the ones we're specifically interested in. - def compile_stub(*except) - (compile_methods - except).each { |m| @compile.stubs(m) } - end - - it "should set node parameters as variables in the top scope" do - params = {"a" => "b", "c" => "d"} - @node.stubs(:parameters).returns(params) - compile_stub(:set_node_parameters) - @compile.compile - @compile.topscope.lookupvar("a").should == "b" - @compile.topscope.lookupvar("c").should == "d" - end - - it "should evaluate any existing classes named in the node" do - classes = %w{one two three four} - main = stub 'main' - one = stub 'one', :classname => "one" - three = stub 'three', :classname => "three" - @node.stubs(:name).returns("whatever") - @node.stubs(:classes).returns(classes) - - @compile.expects(:evaluate_classes).with(classes, @compile.topscope) - @compile.send :evaluate_node_classes - end - - it "should enable ast_nodes if the parser has any nodes" do - @parser.expects(:nodes).returns(:one => :yay) - @compile.ast_nodes?.should be_true - end - - it "should disable ast_nodes if the parser has no nodes" do - @parser.expects(:nodes).returns({}) - @compile.ast_nodes?.should be_false - end -end - -describe Puppet::Parser::Compile, " when evaluating classes" do - before do - @node = stub 'node', :name => 'mynode' - @parser = stub 'parser', :version => "1.0" - @scope = stub 'scope', :source => mock("source") - @compile = Puppet::Parser::Compile.new(@node, @parser) - end - - it "should fail if there's no source listed for the scope" do - scope = stub 'scope', :source => nil - proc { @compile.evaluate_classes(%w{one two}, scope) }.should raise_error(Puppet::DevError) - end - - it "should tag the catalog with the name of each not-found class" do - @compile.catalog.expects(:tag).with("notfound") - @scope.expects(:findclass).with("notfound").returns(nil) - @compile.evaluate_classes(%w{notfound}, @scope) - end -end - -describe Puppet::Parser::Compile, " when evaluating collections" do - before do - @node = stub 'node', :name => 'mynode' - @parser = stub 'parser', :version => "1.0" - @scope = stub 'scope', :source => mock("source") - @compile = Puppet::Parser::Compile.new(@node, @parser) - end - - it "should evaluate each collection" do - 2.times { |i| - coll = mock 'coll%s' % i - @compile.add_collection(coll) - - # This is the hard part -- we have to emulate the fact that - # collections delete themselves if they are done evaluating. - coll.expects(:evaluate).with do - @compile.delete_collection(coll) - end - } - - @compile.class.publicize_methods(:evaluate_collections) { @compile.evaluate_collections } - end -end - - -describe Puppet::Parser::Compile, " when evaluating found classes" do - before do - @node = stub 'node', :name => 'mynode' - @parser = stub 'parser', :version => "1.0" - @scope = stub 'scope', :source => mock("source") - @compile = Puppet::Parser::Compile.new(@node, @parser) - - @class = stub 'class', :classname => "my::class" - @scope.stubs(:findclass).with("myclass").returns(@class) - - @resource = stub 'resource', :ref => 'Class[myclass]' - end - - it "should create a resource for each found class" do - @compile.catalog.stubs(:tag) - - @compile.stubs :store_resource - - Puppet::Parser::Resource.expects(:new).with(:scope => @scope, :source => @scope.source, :title => "my::class", :type => "class").returns(@resource) - @compile.evaluate_classes(%w{myclass}, @scope) - end - - it "should store each created resource in the compile" do - @compile.catalog.stubs(:tag) - - @compile.expects(:store_resource).with(@scope, @resource) - - Puppet::Parser::Resource.stubs(:new).returns(@resource) - @compile.evaluate_classes(%w{myclass}, @scope) - end - - it "should tag the catalog with the fully-qualified name of each found class" do - @compile.catalog.expects(:tag).with("my::class") - - @compile.stubs(:store_resource) - - Puppet::Parser::Resource.stubs(:new).returns(@resource) - @compile.evaluate_classes(%w{myclass}, @scope) - end - - it "should not evaluate the resources created for found classes unless asked" do - @compile.catalog.stubs(:tag) - - @compile.stubs(:store_resource) - @resource.expects(:evaluate).never - - Puppet::Parser::Resource.stubs(:new).returns(@resource) - @compile.evaluate_classes(%w{myclass}, @scope) - end - - it "should immediately evaluate the resources created for found classes when asked" do - @compile.catalog.stubs(:tag) - - @compile.stubs(:store_resource) - @resource.expects(:evaluate) - - Puppet::Parser::Resource.stubs(:new).returns(@resource) - @compile.evaluate_classes(%w{myclass}, @scope, false) - end - - it "should skip classes that have already been evaluated" do - @compile.catalog.stubs(:tag) - - @compile.expects(:class_scope).with(@class).returns("something") - - @compile.expects(:store_resource).never - - @resource.expects(:evaluate).never - - Puppet::Parser::Resource.expects(:new).never - @compile.evaluate_classes(%w{myclass}, @scope, false) - end - - it "should return the list of found classes" do - @compile.catalog.stubs(:tag) - - @compile.stubs(:store_resource) - @scope.stubs(:findclass).with("notfound").returns(nil) - - Puppet::Parser::Resource.stubs(:new).returns(@resource) - @compile.evaluate_classes(%w{myclass notfound}, @scope).should == %w{myclass} - end -end - -describe Puppet::Parser::Compile, " when evaluating AST nodes with no AST nodes present" do - before do - @node = stub 'node', :name => "foo" - @parser = stub 'parser', :version => "1.0", :nodes => {} - @compile = Puppet::Parser::Compile.new(@node, @parser) - end - - it "should do nothing" do - @compile.expects(:ast_nodes?).returns(false) - @compile.parser.expects(:nodes).never - Puppet::Parser::Resource.expects(:new).never - - @compile.send(:evaluate_ast_node) - end -end - -describe Puppet::Parser::Compile, " when evaluating AST nodes with AST nodes present" do - before do - @node = stub 'node', :name => "foo" - @parser = stub 'parser', :version => "1.0", :nodes => {} - @compile = Puppet::Parser::Compile.new(@node, @parser) - - @nodes = mock 'node_hash' - @compile.stubs(:ast_nodes?).returns(true) - @compile.parser.stubs(:nodes).returns(@nodes) - - # Set some names for our test - @node.stubs(:names).returns(%w{a b c}) - @nodes.stubs(:[]).with("a").returns(nil) - @nodes.stubs(:[]).with("b").returns(nil) - @nodes.stubs(:[]).with("c").returns(nil) - - # It should check this last, of course. - @nodes.stubs(:[]).with("default").returns(nil) - end - - it "should fail if the named node cannot be found" do - proc { @compile.send(:evaluate_ast_node) }.should raise_error(Puppet::ParseError) - end - - it "should create a resource for the first node class matching the node name" do - node_class = stub 'node', :classname => "c" - @nodes.stubs(:[]).with("c").returns(node_class) - - node_resource = stub 'node resource', :ref => "Node[c]", :evaluate => nil - Puppet::Parser::Resource.expects(:new).with { |args| args[:title] == "c" and args[:type] == "node" }.returns(node_resource) - - @compile.send(:evaluate_ast_node) - end - - it "should match the default node if no matching node can be found" do - node_class = stub 'node', :classname => "default" - @nodes.stubs(:[]).with("default").returns(node_class) - - node_resource = stub 'node resource', :ref => "Node[default]", :evaluate => nil - Puppet::Parser::Resource.expects(:new).with { |args| args[:title] == "default" and args[:type] == "node" }.returns(node_resource) - - @compile.send(:evaluate_ast_node) - end - - it "should tag the catalog with the found node name" do - node_class = stub 'node', :classname => "c" - @nodes.stubs(:[]).with("c").returns(node_class) - - node_resource = stub 'node resource', :ref => "Node[c]", :evaluate => nil - Puppet::Parser::Resource.stubs(:new).returns(node_resource) - - @compile.catalog.expects(:tag).with("c") - @compile.send(:evaluate_ast_node) - end - - it "should evaluate the node resource immediately rather than using lazy evaluation" do - node_class = stub 'node', :classname => "c" - @nodes.stubs(:[]).with("c").returns(node_class) - - node_resource = stub 'node resource', :ref => "Node[c]" - Puppet::Parser::Resource.stubs(:new).returns(node_resource) - - node_resource.expects(:evaluate) - - @compile.send(:evaluate_ast_node) - end - - it "should set the node's scope as the top scope" do - node_class = stub 'node', :classname => "c" - @nodes.stubs(:[]).with("c").returns(node_class) - - node_resource = stub 'node resource', :ref => "Node[c]" - Puppet::Parser::Resource.stubs(:new).returns(node_resource) - - # The #evaluate method normally does this. - @compile.class_set(node_class.classname, :my_node_scope) - node_resource.stubs(:evaluate) - - @compile.send(:evaluate_ast_node) - - @compile.topscope.should == :my_node_scope - end -end diff --git a/spec/unit/parser/compiler.rb b/spec/unit/parser/compiler.rb new file mode 100755 index 000000000..6b821977d --- /dev/null +++ b/spec/unit/parser/compiler.rb @@ -0,0 +1,544 @@ +#!/usr/bin/env ruby + +require File.dirname(__FILE__) + '/../../spec_helper' + +module CompilerTesting + def setup + @node = Puppet::Node.new "testnode" + @parser = Puppet::Parser::Parser.new :environment => "development" + + @scope_resource = stub 'scope_resource', :builtin? => true + @scope = stub 'scope', :resource => @scope_resource, :source => mock("source") + @compiler = Puppet::Parser::Compiler.new(@node, @parser) + end +end + +describe Puppet::Parser::Compiler do + include CompilerTesting + + it "should be able to store references to class scopes" do + lambda { @compiler.class_set "myname", "myscope" }.should_not raise_error + end + + it "should be able to retrieve class scopes by name" do + @compiler.class_set "myname", "myscope" + @compiler.class_scope("myname").should == "myscope" + end + + it "should be able to retrieve class scopes by object" do + klass = mock 'ast_class' + klass.expects(:classname).returns("myname") + @compiler.class_set "myname", "myscope" + @compiler.class_scope(klass).should == "myscope" + end + + it "should be able to return a class list containing all set classes" do + @compiler.class_set "", "empty" + @compiler.class_set "one", "yep" + @compiler.class_set "two", "nope" + + @compiler.classlist.sort.should == %w{one two}.sort + end +end + +describe Puppet::Parser::Compiler, " when initializing" do + include CompilerTesting + + it "should set its node attribute" do + @compiler.node.should equal(@node) + end + + it "should set its parser attribute" do + @compiler.parser.should equal(@parser) + end + + it "should detect when ast nodes are absent" do + @compiler.ast_nodes?.should be_false + end + + it "should detect when ast nodes are present" do + @parser.nodes["testing"] = "yay" + @compiler.ast_nodes?.should be_true + end +end + +describe Puppet::Parser::Compiler, "when managing scopes" do + include CompilerTesting + + it "should create a top scope" do + @compiler.topscope.should be_instance_of(Puppet::Parser::Scope) + end + + it "should be able to create new scopes" do + @compiler.newscope(@compiler.topscope).should be_instance_of(Puppet::Parser::Scope) + end + + it "should correctly set the level of newly created scopes" do + @compiler.newscope(@compiler.topscope, :level => 5).level.should == 5 + end + + it "should set the parent scope of the new scope to be the passed-in parent" do + scope = mock 'scope' + newscope = @compiler.newscope(scope) + + @compiler.parent(newscope).should equal(scope) + end +end + +describe Puppet::Parser::Compiler, " when compiling" do + include CompilerTesting + + def compile_methods + [:set_node_parameters, :evaluate_main, :evaluate_ast_node, :evaluate_node_classes, :evaluate_generators, :fail_on_unevaluated, + :finish, :store, :extract] + end + + # Stub all of the main compile methods except the ones we're specifically interested in. + def compile_stub(*except) + (compile_methods - except).each { |m| @compiler.stubs(m) } + end + + it "should set node parameters as variables in the top scope" do + params = {"a" => "b", "c" => "d"} + @node.stubs(:parameters).returns(params) + compile_stub(:set_node_parameters) + @compiler.compile + @compiler.topscope.lookupvar("a").should == "b" + @compiler.topscope.lookupvar("c").should == "d" + end + + it "should evaluate any existing classes named in the node" do + classes = %w{one two three four} + main = stub 'main' + one = stub 'one', :classname => "one" + three = stub 'three', :classname => "three" + @node.stubs(:name).returns("whatever") + @node.stubs(:classes).returns(classes) + + @compiler.expects(:evaluate_classes).with(classes, @compiler.topscope) + @compiler.class.publicize_methods(:evaluate_node_classes) { @compiler.evaluate_node_classes } + end + + it "should enable ast_nodes if the parser has any nodes" do + @parser.expects(:nodes).returns(:one => :yay) + @compiler.ast_nodes?.should be_true + end + + it "should disable ast_nodes if the parser has no nodes" do + @parser.expects(:nodes).returns({}) + @compiler.ast_nodes?.should be_false + end + + it "should evaluate the main class if it exists" do + compile_stub(:evaluate_main) + main_class = mock 'main_class' + main_class.expects(:evaluate_code).with { |r| r.is_a?(Puppet::Parser::Resource) } + @compiler.topscope.expects(:source=).with(main_class) + @parser.stubs(:findclass).with("", "").returns(main_class) + + @compiler.compile + end + + it "should evaluate any node classes" do + @node.stubs(:classes).returns(%w{one two three four}) + @compiler.expects(:evaluate_classes).with(%w{one two three four}, @compiler.topscope) + @compiler.send(:evaluate_node_classes) + end + + it "should evaluate all added collections" do + colls = [] + # And when the collections fail to evaluate. + colls << mock("coll1-false") + colls << mock("coll2-false") + colls.each { |c| c.expects(:evaluate).returns(false) } + + @compiler.add_collection(colls[0]) + @compiler.add_collection(colls[1]) + + compile_stub(:evaluate_generators) + @compiler.compile + end + + it "should ignore builtin resources" do + resource = stub 'builtin', :ref => "File[testing]", :builtin? => true + + @compiler.add_resource(@scope, resource) + resource.expects(:evaluate).never + + @compiler.compile + end + + it "should evaluate unevaluated resources" do + resource = stub 'notevaluated', :ref => "File[testing]", :builtin? => false, :evaluated? => false, :virtual? => false + @compiler.add_resource(@scope, resource) + + # We have to now mark the resource as evaluated + resource.expects(:evaluate).with { |*whatever| resource.stubs(:evaluated?).returns true } + + @compiler.compile + end + + it "should not evaluate already-evaluated resources" do + resource = stub 'already_evaluated', :ref => "File[testing]", :builtin? => false, :evaluated? => true, :virtual? => false + @compiler.add_resource(@scope, resource) + resource.expects(:evaluate).never + + @compiler.compile + end + + it "should evaluate unevaluated resources created by evaluating other resources" do + resource = stub 'notevaluated', :ref => "File[testing]", :builtin? => false, :evaluated? => false, :virtual? => false + @compiler.add_resource(@scope, resource) + + resource2 = stub 'created', :ref => "File[other]", :builtin? => false, :evaluated? => false, :virtual? => false + + # We have to now mark the resource as evaluated + resource.expects(:evaluate).with { |*whatever| resource.stubs(:evaluated?).returns(true); @compiler.add_resource(@scope, resource2) } + resource2.expects(:evaluate).with { |*whatever| resource2.stubs(:evaluated?).returns(true) } + + + @compiler.compile + end + + it "should call finish() on all resources" do + # Add a resource that does respond to :finish + resource = Puppet::Parser::Resource.new :scope => @scope, :type => "file", :title => "finish" + resource.expects(:finish) + + @compiler.add_resource(@scope, resource) + + # And one that does not + dnf = stub "dnf", :ref => "File[dnf]" + + @compiler.add_resource(@scope, dnf) + + @compiler.send(:finish) + end + + it "should add resources that do not conflict with existing resources" do + resource = stub "noconflict", :ref => "File[yay]" + @compiler.add_resource(@scope, resource) + + @compiler.catalog.should be_vertex(resource) + end + + it "should fail to add resources that conflict with existing resources" do + type = stub 'faketype', :isomorphic? => true, :name => "mytype" + Puppet::Type.stubs(:type).with("mytype").returns(type) + + resource1 = stub "iso1conflict", :ref => "Mytype[yay]", :type => "mytype", :file => "eh", :line => 0 + resource2 = stub "iso2conflict", :ref => "Mytype[yay]", :type => "mytype", :file => "eh", :line => 0 + + @compiler.add_resource(@scope, resource1) + lambda { @compiler.add_resource(@scope, resource2) }.should raise_error(ArgumentError) + end + + it "should have a method for looking up resources" do + resource = stub 'resource', :ref => "Yay[foo]" + @compiler.add_resource(@scope, resource) + @compiler.findresource("Yay[foo]").should equal(resource) + end + + it "should be able to look resources up by type and title" do + resource = stub 'resource', :ref => "Yay[foo]" + @compiler.add_resource(@scope, resource) + @compiler.findresource("Yay", "foo").should equal(resource) + end + + it "should not evaluate virtual defined resources" do + resource = stub 'notevaluated', :ref => "File[testing]", :builtin? => false, :evaluated? => false, :virtual? => true + @compiler.add_resource(@scope, resource) + + resource.expects(:evaluate).never + + @compiler.compile + end +end + +describe Puppet::Parser::Compiler, " when evaluating collections" do + include CompilerTesting + + it "should evaluate each collection" do + 2.times { |i| + coll = mock 'coll%s' % i + @compiler.add_collection(coll) + + # This is the hard part -- we have to emulate the fact that + # collections delete themselves if they are done evaluating. + coll.expects(:evaluate).with do + @compiler.delete_collection(coll) + end + } + + @compiler.class.publicize_methods(:evaluate_collections) { @compiler.evaluate_collections } + end + + it "should not fail when there are unevaluated resource collections that do not refer to specific resources" do + coll = stub 'coll', :evaluate => false + coll.expects(:resources).returns(nil) + + @compiler.add_collection(coll) + + lambda { @compiler.compile }.should_not raise_error + end + + it "should fail when there are unevaluated resource collections that refer to a specific resource" do + coll = stub 'coll', :evaluate => false + coll.expects(:resources).returns(:something) + + @compiler.add_collection(coll) + + lambda { @compiler.compile }.should raise_error(Puppet::ParseError) + end + + it "should fail when there are unevaluated resource collections that refer to multiple specific resources" do + coll = stub 'coll', :evaluate => false + coll.expects(:resources).returns([:one, :two]) + + @compiler.add_collection(coll) + + lambda { @compiler.compile }.should raise_error(Puppet::ParseError) + end +end + +describe Puppet::Parser::Compiler, "when told to evaluate missing classes" do + include CompilerTesting + + it "should fail if there's no source listed for the scope" do + scope = stub 'scope', :source => nil + proc { @compiler.evaluate_classes(%w{one two}, scope) }.should raise_error(Puppet::DevError) + end + + it "should tag the catalog with the name of each not-found class" do + @compiler.catalog.expects(:tag).with("notfound") + @scope.expects(:findclass).with("notfound").returns(nil) + @compiler.evaluate_classes(%w{notfound}, @scope) + end +end + +describe Puppet::Parser::Compiler, " when evaluating found classes" do + include CompilerTesting + + before do + @class = stub 'class', :classname => "my::class" + @scope.stubs(:findclass).with("myclass").returns(@class) + + @resource = stub 'resource', :ref => "Class[myclass]" + end + + it "should evaluate each class" do + @compiler.catalog.stubs(:tag) + + @class.expects(:evaluate).with(@scope) + + @compiler.evaluate_classes(%w{myclass}, @scope) + end + + it "should not evaluate the resources created for found classes unless asked" do + @compiler.catalog.stubs(:tag) + + @resource.expects(:evaluate).never + + @class.expects(:evaluate).returns(@resource) + + @compiler.evaluate_classes(%w{myclass}, @scope) + end + + it "should immediately evaluate the resources created for found classes when asked" do + @compiler.catalog.stubs(:tag) + + @resource.expects(:evaluate) + @class.expects(:evaluate).returns(@resource) + + @compiler.evaluate_classes(%w{myclass}, @scope, false) + end + + it "should skip classes that have already been evaluated" do + @compiler.catalog.stubs(:tag) + + @compiler.expects(:class_scope).with(@class).returns("something") + + @compiler.expects(:add_resource).never + + @resource.expects(:evaluate).never + + Puppet::Parser::Resource.expects(:new).never + @compiler.evaluate_classes(%w{myclass}, @scope, false) + end + + it "should return the list of found classes" do + @compiler.catalog.stubs(:tag) + + @compiler.stubs(:add_resource) + @scope.stubs(:findclass).with("notfound").returns(nil) + + Puppet::Parser::Resource.stubs(:new).returns(@resource) + @class.stubs :evaluate + @compiler.evaluate_classes(%w{myclass notfound}, @scope).should == %w{myclass} + end +end + +describe Puppet::Parser::Compiler, " when evaluating AST nodes with no AST nodes present" do + include CompilerTesting + + it "should do nothing" do + @compiler.expects(:ast_nodes?).returns(false) + @compiler.parser.expects(:nodes).never + Puppet::Parser::Resource.expects(:new).never + + @compiler.send(:evaluate_ast_node) + end +end + +describe Puppet::Parser::Compiler, " when evaluating AST nodes with AST nodes present" do + include CompilerTesting + + before do + @nodes = mock 'node_hash' + @compiler.stubs(:ast_nodes?).returns(true) + @compiler.parser.stubs(:nodes).returns(@nodes) + + # Set some names for our test + @node.stubs(:names).returns(%w{a b c}) + @nodes.stubs(:[]).with("a").returns(nil) + @nodes.stubs(:[]).with("b").returns(nil) + @nodes.stubs(:[]).with("c").returns(nil) + + # It should check this last, of course. + @nodes.stubs(:[]).with("default").returns(nil) + end + + it "should fail if the named node cannot be found" do + proc { @compiler.send(:evaluate_ast_node) }.should raise_error(Puppet::ParseError) + end + + it "should evaluate the first node class matching the node name" do + node_class = stub 'node', :classname => "c", :evaluate_code => nil + @nodes.stubs(:[]).with("c").returns(node_class) + + node_resource = stub 'node resource', :ref => "Node[c]", :evaluate => nil + node_class.expects(:evaluate).returns(node_resource) + + @compiler.compile + end + + it "should match the default node if no matching node can be found" do + node_class = stub 'node', :classname => "default", :evaluate_code => nil + @nodes.stubs(:[]).with("default").returns(node_class) + + node_resource = stub 'node resource', :ref => "Node[default]", :evaluate => nil + node_class.expects(:evaluate).returns(node_resource) + + @compiler.compile + end + + it "should evaluate the node resource immediately rather than using lazy evaluation" do + node_class = stub 'node', :classname => "c" + @nodes.stubs(:[]).with("c").returns(node_class) + + node_resource = stub 'node resource', :ref => "Node[c]" + node_class.expects(:evaluate).returns(node_resource) + + node_resource.expects(:evaluate) + + @compiler.send(:evaluate_ast_node) + end + + it "should set the node's scope as the top scope" do + node_resource = stub 'node resource', :ref => "Node[c]", :evaluate => nil + node_class = stub 'node', :classname => "c", :evaluate => node_resource + + @nodes.stubs(:[]).with("c").returns(node_class) + + # The #evaluate method normally does this. + scope = stub 'scope', :source => "mysource" + @compiler.class_set(node_class.classname, scope) + node_resource.stubs(:evaluate) + + @compiler.compile + + @compiler.topscope.should equal(scope) + end +end + +describe Puppet::Parser::Compiler, "when storing compiled resources" do + include CompilerTesting + + it "should store the resources" do + Puppet.features.expects(:rails?).returns(true) + Puppet::Rails.expects(:connect) + + @compiler.catalog.expects(:vertices).returns(:resources) + + @compiler.expects(:store_to_active_record).with(@node, :resources) + @compiler.send(:store) + end + + it "should store to active_record" do + @node.expects(:name).returns("myname") + Puppet::Rails::Host.stubs(:transaction).yields + Puppet::Rails::Host.expects(:store).with(@node, :resources) + @compiler.send(:store_to_active_record, @node, :resources) + end +end + +describe Puppet::Parser::Compiler, "when managing resource overrides" do + include CompilerTesting + + before do + @override = stub 'override', :ref => "My[ref]" + @resource = stub 'resource', :ref => "My[ref]", :builtin? => true + end + + it "should be able to store overrides" do + lambda { @compiler.add_override(@override) }.should_not raise_error + end + + it "should apply overrides to the appropriate resources" do + @compiler.add_resource(@scope, @resource) + @resource.expects(:merge).with(@override) + + @compiler.add_override(@override) + + @compiler.compile + end + + it "should accept overrides before the related resource has been created" do + @resource.expects(:merge).with(@override) + + # First store the override + @compiler.add_override(@override) + + # Then the resource + @compiler.add_resource(@scope, @resource) + + # And compile, so they get resolved + @compiler.compile + end + + it "should fail if the compile is finished and resource overrides have not been applied" do + @compiler.add_override(@override) + + lambda { @compiler.compile }.should raise_error(Puppet::ParseError) + end +end + +# #620 - Nodes and classes should conflict, else classes don't get evaluated +describe Puppet::Parser::Compiler, "when evaluating nodes and classes with the same name (#620)" do + include CompilerTesting + + before do + @node = stub :nodescope? => true + @class = stub :nodescope? => false + end + + it "should fail if a node already exists with the same name as the class being evaluated" do + @compiler.class_set("one", @node) + lambda { @compiler.class_set("one", @class) }.should raise_error(Puppet::ParseError) + end + + it "should fail if a class already exists with the same name as the node being evaluated" do + @compiler.class_set("one", @class) + lambda { @compiler.class_set("one", @node) }.should raise_error(Puppet::ParseError) + end +end diff --git a/spec/unit/parser/interpreter.rb b/spec/unit/parser/interpreter.rb index ed30ced93..7885f0542 100755 --- a/spec/unit/parser/interpreter.rb +++ b/spec/unit/parser/interpreter.rb @@ -115,14 +115,14 @@ describe Puppet::Parser::Interpreter, " when compiling catalog" do before do @interp = Puppet::Parser::Interpreter.new @node = stub 'node', :environment => :myenv - @compile = mock 'compile' + @compiler = mock 'compile' @parser = mock 'parser' end it "should create a compile with the node and parser" do - @compile.expects(:compile).returns(:config) + @compiler.expects(:compile).returns(:config) @interp.expects(:parser).with(:myenv).returns(@parser) - Puppet::Parser::Compile.expects(:new).with(@node, @parser).returns(@compile) + Puppet::Parser::Compiler.expects(:new).with(@node, @parser).returns(@compiler) @interp.compile(@node) end diff --git a/spec/unit/parser/resource.rb b/spec/unit/parser/resource.rb index 319d8f7d8..a5a49e2a6 100755 --- a/spec/unit/parser/resource.rb +++ b/spec/unit/parser/resource.rb @@ -15,26 +15,26 @@ describe Puppet::Parser::Resource, " when evaluating" do @class = @parser.newclass "myclass" @nodedef = @parser.newnode("mynode")[0] @node = Puppet::Node.new("yaynode") - @compile = Puppet::Parser::Compile.new(@node, @parser) - @scope = @compile.topscope + @compiler = Puppet::Parser::Compiler.new(@node, @parser) + @scope = @compiler.topscope end it "should evaluate the associated AST definition" do res = @type.new(:type => "mydefine", :title => "whatever", :scope => @scope, :source => @source) - @definition.expects(:evaluate).with(:scope => @scope, :resource => res) + @definition.expects(:evaluate_code).with(res) res.evaluate end it "should evaluate the associated AST class" do res = @type.new(:type => "class", :title => "myclass", :scope => @scope, :source => @source) - @class.expects(:evaluate).with(:scope => @scope, :resource => res) + @class.expects(:evaluate_code).with(res) res.evaluate end it "should evaluate the associated AST node" do res = @type.new(:type => "node", :title => "mynode", :scope => @scope, :source => @source) - @nodedef.expects(:evaluate).with(:scope => @scope, :resource => res) + @nodedef.expects(:evaluate_code).with(res) res.evaluate end end @@ -47,8 +47,8 @@ describe Puppet::Parser::Resource, " when finishing" do @class = @parser.newclass "myclass" @nodedef = @parser.newnode("mynode")[0] @node = Puppet::Node.new("yaynode") - @compile = Puppet::Parser::Compile.new(@node, @parser) - @scope = @compile.topscope + @compiler = Puppet::Parser::Compiler.new(@node, @parser) + @scope = @compiler.topscope @resource = Puppet::Parser::Resource.new(:type => "mydefine", :title => "whatever", :scope => @scope, :source => @source) end diff --git a/spec/unit/parser/resource/reference.rb b/spec/unit/parser/resource/reference.rb index e7385f796..147f772d1 100755 --- a/spec/unit/parser/resource/reference.rb +++ b/spec/unit/parser/resource/reference.rb @@ -52,23 +52,23 @@ describe Puppet::Parser::Resource::Reference, " when modeling defined types" do @nodedef = @parser.newnode("mynode")[0] @node = Puppet::Node.new("yaynode") - @compile = Puppet::Parser::Compile.new(@node, @parser) + @compiler = Puppet::Parser::Compiler.new(@node, @parser) end it "should be able to find defined types" do - ref = @type.new(:type => "mydefine", :title => "/tmp/yay", :scope => @compile.topscope) + ref = @type.new(:type => "mydefine", :title => "/tmp/yay", :scope => @compiler.topscope) ref.builtin?.should be_false ref.definedtype.should equal(@definition) end it "should be able to find classes" do - ref = @type.new(:type => "class", :title => "myclass", :scope => @compile.topscope) + ref = @type.new(:type => "class", :title => "myclass", :scope => @compiler.topscope) ref.builtin?.should be_false ref.definedtype.should equal(@class) end it "should be able to find nodes" do - ref = @type.new(:type => "node", :title => "mynode", :scope => @compile.topscope) + ref = @type.new(:type => "node", :title => "mynode", :scope => @compiler.topscope) ref.builtin?.should be_false ref.definedtype.object_id.should == @nodedef.object_id end diff --git a/spec/unit/ral/type.rb b/spec/unit/ral/type.rb index 25f8cbaf1..5980167d6 100755 --- a/spec/unit/ral/type.rb +++ b/spec/unit/ral/type.rb @@ -11,8 +11,8 @@ describe Puppet::Type, " when in a configuration" do @catalog.add_resource @container @catalog.add_resource @one @catalog.add_resource @two - @catalog.add_edge! @container, @one - @catalog.add_edge! @container, @two + @catalog.add_edge @container, @one + @catalog.add_edge @container, @two end it "should have no parent if there is no in edge" do diff --git a/spec/unit/simple_graph.rb b/spec/unit/simple_graph.rb index 061a07458..c8fe14cf3 100755 --- a/spec/unit/simple_graph.rb +++ b/spec/unit/simple_graph.rb @@ -9,8 +9,8 @@ require 'puppet/simple_graph' describe Puppet::SimpleGraph do it "should return the number of its vertices as its length" do @graph = Puppet::SimpleGraph.new - @graph.add_vertex!("one") - @graph.add_vertex!("two") + @graph.add_vertex("one") + @graph.add_vertex("two") @graph.size.should == 2 end @@ -20,13 +20,13 @@ describe Puppet::SimpleGraph do it "should provide a method for reversing the graph" do @graph = Puppet::SimpleGraph.new - @graph.add_edge!(:one, :two) + @graph.add_edge(:one, :two) @graph.reversal.edge?(:two, :one).should be_true end it "should be able to produce a dot graph" do @graph = Puppet::SimpleGraph.new - @graph.add_edge!(:one, :two) + @graph.add_edge(:one, :two) proc { @graph.to_dot_graph }.should_not raise_error end @@ -38,17 +38,17 @@ describe Puppet::SimpleGraph, " when managing vertices" do end it "should provide a method to add a vertex" do - @graph.add_vertex!(:test) + @graph.add_vertex(:test) @graph.vertex?(:test).should be_true end it "should ignore already-present vertices when asked to add a vertex" do - @graph.add_vertex!(:test) - proc { @graph.add_vertex!(:test) }.should_not raise_error + @graph.add_vertex(:test) + proc { @graph.add_vertex(:test) }.should_not raise_error end it "should return true when asked if a vertex is present" do - @graph.add_vertex!(:test) + @graph.add_vertex(:test) @graph.vertex?(:test).should be_true end @@ -57,15 +57,15 @@ describe Puppet::SimpleGraph, " when managing vertices" do end it "should return all set vertices when asked" do - @graph.add_vertex!(:one) - @graph.add_vertex!(:two) + @graph.add_vertex(:one) + @graph.add_vertex(:two) @graph.vertices.length.should == 2 @graph.vertices.should include(:one) @graph.vertices.should include(:two) end it "should remove a given vertex when asked" do - @graph.add_vertex!(:one) + @graph.add_vertex(:one) @graph.remove_vertex!(:one) @graph.vertex?(:one).should be_false end @@ -86,49 +86,49 @@ describe Puppet::SimpleGraph, " when managing edges" do it "should provide a method to add an edge as an instance of the edge class" do edge = Puppet::Relationship.new(:one, :two) - @graph.add_edge!(edge) + @graph.add_edge(edge) @graph.edge?(:one, :two).should be_true end it "should provide a method to add an edge by specifying the two vertices" do - @graph.add_edge!(:one, :two) + @graph.add_edge(:one, :two) @graph.edge?(:one, :two).should be_true end it "should provide a method to add an edge by specifying the two vertices and a label" do - @graph.add_edge!(:one, :two, :stuff => :awesome) + @graph.add_edge(:one, :two, :stuff => :awesome) @graph.edge?(:one, :two).should be_true end it "should provide a method for retrieving an edge label" do edge = Puppet::Relationship.new(:one, :two, :stuff => :awesome) - @graph.add_edge!(edge) + @graph.add_edge(edge) @graph.edge_label(:one, :two).should == {:stuff => :awesome} end it "should provide a method for retrieving an edge" do edge = Puppet::Relationship.new(:one, :two) - @graph.add_edge!(edge) + @graph.add_edge(edge) @graph.edge(:one, :two).should equal(edge) end it "should add the edge source as a vertex if it is not already" do edge = Puppet::Relationship.new(:one, :two) - @graph.add_edge!(edge) + @graph.add_edge(edge) @graph.vertex?(:one).should be_true end it "should add the edge target as a vertex if it is not already" do edge = Puppet::Relationship.new(:one, :two) - @graph.add_edge!(edge) + @graph.add_edge(edge) @graph.vertex?(:two).should be_true end it "should return all edges as edge instances when asked" do one = Puppet::Relationship.new(:one, :two) two = Puppet::Relationship.new(:two, :three) - @graph.add_edge!(one) - @graph.add_edge!(two) + @graph.add_edge(one) + @graph.add_edge(two) edges = @graph.edges edges.length.should == 2 edges.should include(one) @@ -137,7 +137,7 @@ describe Puppet::SimpleGraph, " when managing edges" do it "should remove an edge when asked" do edge = Puppet::Relationship.new(:one, :two) - @graph.add_edge!(edge) + @graph.add_edge(edge) @graph.remove_edge!(edge) @graph.edge?(edge.source, edge.target).should be_false end @@ -145,8 +145,8 @@ describe Puppet::SimpleGraph, " when managing edges" do it "should remove all related edges when a vertex is removed" do one = Puppet::Relationship.new(:one, :two) two = Puppet::Relationship.new(:two, :three) - @graph.add_edge!(one) - @graph.add_edge!(two) + @graph.add_edge(one) + @graph.add_edge(two) @graph.remove_vertex!(:two) @graph.edge?(:one, :two).should be_false @graph.edge?(:two, :three).should be_false @@ -160,9 +160,9 @@ describe Puppet::SimpleGraph, " when finding adjacent vertices" do @one_two = Puppet::Relationship.new(:one, :two) @two_three = Puppet::Relationship.new(:two, :three) @one_three = Puppet::Relationship.new(:one, :three) - @graph.add_edge!(@one_two) - @graph.add_edge!(@one_three) - @graph.add_edge!(@two_three) + @graph.add_edge(@one_two) + @graph.add_edge(@one_three) + @graph.add_edge(@two_three) end it "should return adjacent vertices" do @@ -193,8 +193,8 @@ describe Puppet::SimpleGraph, " when clearing" do @graph = Puppet::SimpleGraph.new one = Puppet::Relationship.new(:one, :two) two = Puppet::Relationship.new(:two, :three) - @graph.add_edge!(one) - @graph.add_edge!(two) + @graph.add_edge(one) + @graph.add_edge(two) @graph.clear end @@ -214,18 +214,18 @@ describe Puppet::SimpleGraph, " when reversing graphs" do end it "should provide a method for reversing the graph" do - @graph.add_edge!(:one, :two) + @graph.add_edge(:one, :two) @graph.reversal.edge?(:two, :one).should be_true end it "should add all vertices to the reversed graph" do - @graph.add_edge!(:one, :two) + @graph.add_edge(:one, :two) @graph.vertex?(:one).should be_true @graph.vertex?(:two).should be_true end it "should retain labels on edges" do - @graph.add_edge!(:one, :two, :stuff => :awesome) + @graph.add_edge(:one, :two, :stuff => :awesome) edge = @graph.reversal.edge(:two, :one) edge.label.should == {:stuff => :awesome} end @@ -238,7 +238,7 @@ describe Puppet::SimpleGraph, " when sorting the graph" do def add_edges(hash) hash.each do |a,b| - @graph.add_edge!(a, b) + @graph.add_edge(a, b) end end diff --git a/spec/unit/util/constant_inflector.rb b/spec/unit/util/constant_inflector.rb new file mode 100755 index 000000000..5112e730f --- /dev/null +++ b/spec/unit/util/constant_inflector.rb @@ -0,0 +1,70 @@ +#!/usr/bin/env ruby +# +# Created by Luke Kanies on 2008-02-12. +# Copyright (c) 2007. All rights reserved. + +require File.dirname(__FILE__) + '/../../spec_helper' + +require 'puppet/util/constant_inflector' + +describe Puppet::Util::ConstantInflector, "when converting file names to constants" do + before do + @inflector = Object.new + @inflector.extend(Puppet::Util::ConstantInflector) + end + + it "should capitalize terms" do + @inflector.file2constant("file").should == "File" + end + + it "should switch all '/' characters to double colons" do + @inflector.file2constant("file/other").should == "File::Other" + end + + it "should remove underscores and capitalize the proceeding letter" do + @inflector.file2constant("file_other").should == "FileOther" + end + + it "should correctly replace as many underscores as exist in the file name" do + @inflector.file2constant("two_under_scores/with_some_more_underscores").should == "TwoUnderScores::WithSomeMoreUnderscores" + end + + it "should collapse multiple underscores" do + @inflector.file2constant("many___scores").should == "ManyScores" + end + + it "should correctly handle file names deeper than two directories" do + @inflector.file2constant("one_two/three_four/five_six").should == "OneTwo::ThreeFour::FiveSix" + end +end + +describe Puppet::Util::ConstantInflector, "when converting constnats to file names" do + before do + @inflector = Object.new + @inflector.extend(Puppet::Util::ConstantInflector) + end + + it "should convert them to a string if necessary" do + @inflector.constant2file(Puppet::Util::ConstantInflector).should be_instance_of(String) + end + + it "should accept string inputs" do + @inflector.constant2file("Puppet::Util::ConstantInflector").should be_instance_of(String) + end + + it "should downcase all terms" do + @inflector.constant2file("Puppet").should == "puppet" + end + + it "should convert '::' to '/'" do + @inflector.constant2file("Puppet::Util::Constant").should == "puppet/util/constant" + end + + it "should convert mid-word capitalization to an underscore" do + @inflector.constant2file("OneTwo::ThreeFour").should == "one_two/three_four" + end + + it "should correctly handle constants with more than two parts" do + @inflector.constant2file("OneTwoThree::FourFiveSixSeven").should == "one_two_three/four_five_six_seven" + end +end diff --git a/spec/unit/util/tagging.rb b/spec/unit/util/tagging.rb index 51b69a63c..91cbb213d 100755 --- a/spec/unit/util/tagging.rb +++ b/spec/unit/util/tagging.rb @@ -76,4 +76,13 @@ describe Puppet::Util::Tagging, "when adding tags" do @tagger.tags.should be_include("two") @tagger.tags.should be_include("three") end + + it "should indicate when the object is tagged with a provided tag" do + @tagger.tag("one") + @tagger.should be_tagged("one") + end + + it "should indicate when the object is not tagged with a provided tag" do + @tagger.should_not be_tagged("one") + end end diff --git a/test/data/snippets/collection_within_virtual_definitions.pp b/test/data/snippets/collection_within_virtual_definitions.pp new file mode 100644 index 000000000..3c21468b0 --- /dev/null +++ b/test/data/snippets/collection_within_virtual_definitions.pp @@ -0,0 +1,20 @@ +define test($name) { + file {"/tmp/collection_within_virtual_definitions1_$name.txt": + content => "File name $name\n" + } + Test2 <||> +} + +define test2() { + file {"/tmp/collection_within_virtual_definitions2_$name.txt": + content => "This is a test\n" + } +} + +node default { + @test {"foo": + name => "foo" + } + @test2 {"foo2": } + Test <||> +} diff --git a/test/data/snippets/realize_defined_types.pp b/test/data/snippets/realize_defined_types.pp deleted file mode 100644 index a4b562258..000000000 --- a/test/data/snippets/realize_defined_types.pp +++ /dev/null @@ -1,13 +0,0 @@ -define testing { - file { "/tmp/realize_defined_test1": ensure => file } -} -@testing { yay: } - -define deeper { - file { "/tmp/realize_defined_test2": ensure => file } -} - -@deeper { boo: } - -realize Testing[yay] -realize File["/tmp/realize_defined_test2"] diff --git a/test/language/ast.rb b/test/language/ast.rb index b31012d38..8c0f31aba 100755 --- a/test/language/ast.rb +++ b/test/language/ast.rb @@ -35,14 +35,14 @@ class TestAST < Test::Unit::TestCase # We initialized it to true, so we should get that first ret = nil assert_nothing_raised { - ret = astif.evaluate(:scope => "yay") + ret = astif.evaluate("yay") } assert_equal(:if, ret) # Now set it to false and check that faketest.evaluate = false assert_nothing_raised { - ret = astif.evaluate(:scope => "yay") + ret = astif.evaluate("yay") } assert_equal(:else, ret) end @@ -57,10 +57,10 @@ class TestAST < Test::Unit::TestCase end Puppet::Parser::Resource.expects(:new).with { |o| o.is_a?(Hash) }.returns(:override) - scope.compile.expects(:store_override).with(:override) + scope.compiler.expects(:add_override).with(:override) ret = nil assert_nothing_raised do - ret = ref.evaluate :scope => scope + ret = ref.evaluate scope end assert_equal(:override, ret, "Did not return override") @@ -74,7 +74,7 @@ class TestAST < Test::Unit::TestCase args = {:source => "/yay/ness", :group => "yayness"} assert_nothing_raised do obj = defaultobj "file", args - obj.evaluate :scope => scope + obj.evaluate scope end hash = nil @@ -93,56 +93,6 @@ class TestAST < Test::Unit::TestCase end end - def test_node - scope = mkscope - parser = scope.compile.parser - - # Define a base node - basenode = parser.newnode "basenode", :code => AST::ASTArray.new(:children => [ - resourcedef("file", "/tmp/base", "owner" => "root") - ]) - - # Now define a subnode - nodes = parser.newnode ["mynode", "othernode"], - :code => AST::ASTArray.new(:children => [ - resourcedef("file", "/tmp/mynode", "owner" => "root"), - resourcedef("file", "/tmp/basenode", "owner" => "daemon") - ]) - - assert_instance_of(Array, nodes) - - # Make sure we can find them all. - %w{mynode othernode}.each do |node| - assert(parser.nodes[node], "Could not find %s" % node) - end - mynode = parser.nodes["mynode"] - - # Now try evaluating the node - assert_nothing_raised do - mynode.evaluate :scope => scope, :resource => scope.resource - end - - # Make sure that we can find each of the files - myfile = scope.findresource "File[/tmp/mynode]" - assert(myfile, "Could not find file from node") - assert_equal("root", myfile[:owner]) - - basefile = scope.findresource "File[/tmp/basenode]" - assert(basefile, "Could not find file from base node") - assert_equal("daemon", basefile[:owner]) - - # Now make sure we can evaluate nodes with parents - child = parser.newnode(%w{child}, :parent => "basenode").shift - - newscope = mkscope :parser => parser - assert_nothing_raised do - child.evaluate :scope => newscope, :resource => scope.resource - end - - assert(newscope.findresource("File[/tmp/base]"), - "Could not find base resource") - end - def test_collection scope = mkscope @@ -155,13 +105,13 @@ class TestAST < Test::Unit::TestCase ret = nil assert_nothing_raised do - ret = coll.evaluate :scope => scope + ret = coll.evaluate scope end assert_instance_of(Puppet::Parser::Collector, ret) # Now make sure we get it back from the scope - colls = scope.compile.instance_variable_get("@collections") + colls = scope.compiler.instance_variable_get("@collections") assert_equal([ret], colls, "Did not store collector in config's collection list") end @@ -175,7 +125,7 @@ class TestAST < Test::Unit::TestCase run_collection_queries(:virtual) do |string, result, query| code = nil assert_nothing_raised do - str, code = query.evaluate :scope => scope + str, code = query.evaluate scope end assert_instance_of(Proc, code) diff --git a/test/language/ast/casestatement.rb b/test/language/ast/casestatement.rb index 0a744b686..d95d788d9 100755 --- a/test/language/ast/casestatement.rb +++ b/test/language/ast/casestatement.rb @@ -45,7 +45,7 @@ class TestCaseStatement < Test::Unit::TestCase result = nil assert_nothing_raised do - result = ast.evaluate :scope => scope + result = ast.evaluate scope end assert(result, "did not get valid result") assert_equal(["upper"], $evaluated, "Did not match case-sensitively") @@ -56,7 +56,7 @@ class TestCaseStatement < Test::Unit::TestCase $evaluated.clear hash["MyParam"].reset assert_nothing_raised do - result = ast.evaluate :scope => scope + result = ast.evaluate scope end assert(result, "did not get valid result") assert_equal(["lower"], result, "Did not match case-insensitively") @@ -92,7 +92,7 @@ class TestCaseStatement < Test::Unit::TestCase scope = mkscope scope.setvar("testparam", value) assert_nothing_raised do - result = ast.evaluate(:scope => scope) + result = ast.evaluate(scope) end assert_equal(should, result, "Got incorrect result for %s" % value) diff --git a/test/language/ast/definition.rb b/test/language/ast/definition.rb deleted file mode 100755 index 2a71aaa45..000000000 --- a/test/language/ast/definition.rb +++ /dev/null @@ -1,166 +0,0 @@ -#!/usr/bin/env ruby -# -# Created by Luke A. Kanies on 2006-02-20. -# Copyright (c) 2006. All rights reserved. - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' -require 'mocha' -require 'puppettest/parsertesting' -require 'puppettest/resourcetesting' - -class TestASTDefinition < Test::Unit::TestCase - include PuppetTest - include PuppetTest::ParserTesting - include PuppetTest::ResourceTesting - AST = Puppet::Parser::AST - - def test_initialize - parser = mkparser - - # Create a new definition - klass = parser.newdefine "yayness", - :arguments => [["owner", stringobj("nobody")], %w{mode}], - :code => AST::ASTArray.new( - :children => [resourcedef("file", "/tmp/$name", - "owner" => varref("owner"), "mode" => varref("mode"))] - ) - - # Test validattr? a couple different ways - [:owner, "owner", :schedule, "schedule"].each do |var| - assert(klass.validattr?(var), "%s was not considered valid" % var.inspect) - end - - [:random, "random"].each do |var| - assert(! klass.validattr?(var), "%s was considered valid" % var.inspect) - end - - end - - def test_evaluate - parser = mkparser - config = mkcompile - config.send(:evaluate_main) - scope = config.topscope - klass = parser.newdefine "yayness", - :arguments => [["owner", stringobj("nobody")], %w{mode}], - :code => AST::ASTArray.new( - :children => [resourcedef("file", "/tmp/$name", - "owner" => varref("owner"), "mode" => varref("mode"))] - ) - - resource = Puppet::Parser::Resource.new( - :title => "first", - :type => "yayness", - :exported => false, - :virtual => false, - :scope => scope, - :source => scope.source - ) - resource.send(:set_parameter, "name", "first") - resource.send(:set_parameter, "mode", "755") - - resource.stubs(:title) - assert_nothing_raised do - klass.evaluate(:scope => scope, :resource => resource) - end - - firstobj = config.findresource("File[/tmp/first]") - assert(firstobj, "Did not create /tmp/first obj") - - assert_equal("File", firstobj.type) - assert_equal("/tmp/first", firstobj.title) - assert_equal("nobody", firstobj[:owner]) - assert_equal("755", firstobj[:mode]) - - # Make sure we can't evaluate it with the same args - assert_raise(Puppet::ParseError) do - klass.evaluate(:scope => scope, :resource => resource) - end - - # Now create another with different args - resource2 = Puppet::Parser::Resource.new( - :title => "second", - :type => "yayness", - :exported => false, - :virtual => false, - :scope => scope, - :source => scope.source - ) - resource2.send(:set_parameter, "name", "second") - resource2.send(:set_parameter, "mode", "755") - resource2.send(:set_parameter, "owner", "daemon") - - assert_nothing_raised do - klass.evaluate(:scope => scope, :resource => resource2) - end - - secondobj = config.findresource("File[/tmp/second]") - assert(secondobj, "Did not create /tmp/second obj") - - assert_equal("File", secondobj.type) - assert_equal("/tmp/second", secondobj.title) - assert_equal("daemon", secondobj[:owner]) - assert_equal("755", secondobj[:mode]) - end - - # #539 - definitions should support both names and titles - def test_names_and_titles - parser = mkparser - scope = mkscope :parser => parser - - [ - {:name => "one", :title => "two"}, - {:title => "mytitle"} - ].each_with_index do |hash, i| - # Create a definition that uses both name and title. Put this - # inside the loop so the subscope expectations work. - klass = parser.newdefine "yayness%s" % i - - resource = Puppet::Parser::Resource.new( - :title => hash[:title], - :type => "yayness%s" % i, - :exported => false, - :virtual => false, - :scope => scope, - :source => scope.source - ) - - subscope = klass.subscope(scope, resource) - - klass.expects(:subscope).returns(subscope) - - if hash[:name] - resource.stubs(:to_hash).returns({:name => hash[:name]}) - end - - assert_nothing_raised("Could not evaluate definition with %s" % hash.inspect) do - klass.evaluate(:scope => scope, :resource => resource) - end - - name = hash[:name] || hash[:title] - title = hash[:title] - - assert_equal(name, subscope.lookupvar("name"), - "Name did not get set correctly") - assert_equal(title, subscope.lookupvar("title"), - "title did not get set correctly") - - [:name, :title].each do |param| - val = resource.send(param) - assert(subscope.tags.include?(val), - "Scope was not tagged with %s '%s'" % [param, val]) - end - end - end - - # Testing the root cause of #615. We should be using the fqname for the type, instead - # of just the short name. - def test_fully_qualified_types - parser = mkparser - klass = parser.newclass("one::two") - - assert_equal("one::two", klass.classname, "Class did not get fully qualified class name") - end -end diff --git a/test/language/ast/hostclass.rb b/test/language/ast/hostclass.rb deleted file mode 100755 index 80032f30c..000000000 --- a/test/language/ast/hostclass.rb +++ /dev/null @@ -1,184 +0,0 @@ -#!/usr/bin/env ruby -# -# Created by Luke A. Kanies on 2006-02-20. -# Copyright (c) 2006. All rights reserved. - -require File.dirname(__FILE__) + '/../../lib/puppettest' - -require 'puppettest' -require 'puppettest/parsertesting' -require 'puppettest/resourcetesting' -require 'mocha' - -class TestASTHostClass < Test::Unit::TestCase - include PuppetTest - include PuppetTest::ParserTesting - include PuppetTest::ResourceTesting - AST = Puppet::Parser::AST - - def test_hostclass - scope = mkscope - parser = scope.compile.parser - - # Create the class we're testing, first with no parent - klass = parser.newclass "first", - :code => AST::ASTArray.new( - :children => [resourcedef("file", "/tmp", - "owner" => "nobody", "mode" => "755")] - ) - - resource = Puppet::Parser::Resource.new(:type => "class", :title => "first", :scope => scope) - assert_nothing_raised do - klass.evaluate(:scope => scope, :resource => resource) - end - - # Then try it again - assert_nothing_raised do - klass.evaluate(:scope => scope, :resource => resource) - end - - assert(scope.compile.class_scope(klass), "Class was not considered evaluated") - - tmp = scope.findresource("File[/tmp]") - assert(tmp, "Could not find file /tmp") - assert_equal("nobody", tmp[:owner]) - assert_equal("755", tmp[:mode]) - - # Now create a couple more classes. - newbase = parser.newclass "newbase", - :code => AST::ASTArray.new( - :children => [resourcedef("file", "/tmp/other", - "owner" => "nobody", "mode" => "644")] - ) - - newsub = parser.newclass "newsub", - :parent => "newbase", - :code => AST::ASTArray.new( - :children => [resourcedef("file", "/tmp/yay", - "owner" => "nobody", "mode" => "755"), - resourceoverride("file", "/tmp/other", - "owner" => "daemon") - ] - ) - - # Override a different variable in the top scope. - moresub = parser.newclass "moresub", - :parent => "newbase", - :code => AST::ASTArray.new( - :children => [resourceoverride("file", "/tmp/other", - "mode" => "755")] - ) - - assert_nothing_raised do - newsub.evaluate(:scope => scope, :resource => resource) - end - - assert_nothing_raised do - moresub.evaluate(:scope => scope, :resource => resource) - end - - assert(scope.compile.class_scope(newbase), "Did not eval newbase") - assert(scope.compile.class_scope(newsub), "Did not eval newsub") - - yay = scope.findresource("File[/tmp/yay]") - assert(yay, "Did not find file /tmp/yay") - assert_equal("nobody", yay[:owner]) - assert_equal("755", yay[:mode]) - - other = scope.findresource("File[/tmp/other]") - assert(other, "Did not find file /tmp/other") - assert_equal("daemon", other[:owner]) - assert_equal("755", other[:mode]) - end - - # Make sure that classes set their namespaces to themselves. This - # way they start looking for definitions in their own namespace. - def test_hostclass_namespace - scope = mkscope - parser = scope.compile.parser - - # Create a new class - klass = nil - assert_nothing_raised do - klass = parser.newclass "funtest" - end - - # Now define a definition in that namespace - - define = nil - assert_nothing_raised do - define = parser.newdefine "funtest::mydefine" - end - - assert_equal("funtest", klass.namespace, - "component namespace was not set in the class") - - assert_equal("funtest", define.namespace, - "component namespace was not set in the definition") - - newscope = klass.subscope(scope, mock("resource")) - - assert_equal(["funtest"], newscope.namespaces, - "Scope did not inherit namespace") - - # Now make sure we can find the define - assert(newscope.finddefine("mydefine"), - "Could not find definition in my enclosing class") - end - - # Make sure that our scope is a subscope of the parentclass's scope. - # At the same time, make sure definitions in the parent class can be - # found within the subclass (#517). - def test_parent_scope_from_parentclass - scope = mkscope - parser = scope.compile.parser - - source = parser.newclass "" - 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.compile.evaluate_classes(["sub"], scope) - end - scope.compile.send(:evaluate_generators) - - subscope = scope.compile.class_scope(scope.findclass("sub")) - assert(subscope, "could not find sub scope") - mscope = scope.compile.class_scope(scope.findclass("middle")) - assert(mscope, "could not find middle scope") - pscope = scope.compile.class_scope(scope.findclass("base")) - assert(pscope, "could not find parent scope") - - assert(pscope == mscope.parent, "parent scope of middle was not set correctly") - assert(mscope == subscope.parent, "parent scope of sub was not set correctly") - - result = mscope.finddefine("fun") - assert(result, "could not find parent-defined definition from middle") - assert(fun == result, "found incorrect parent-defined definition from middle") - - result = subscope.finddefine("fun") - assert(result, "could not find parent-defined definition from sub") - assert(fun == result, "found incorrect parent-defined definition from sub") - end - - # #795 - make sure the subclass's tags get set before we - # evaluate the parent class, so we can be sure that the parent - # class can switch based on the sub classes. - def test_tags_set_before_parent_is_evaluated - scope = mkscope - parser = scope.compile.parser - base = parser.newclass "base" - sub = parser.newclass "sub", :parent => "base" - - base.expects(:safeevaluate).with do |args| - assert(scope.compile.catalog.tags.include?("sub"), "Did not tag with sub class name before evaluating base class") - base.evaluate(args) - true - end - sub.evaluate :scope => scope, :resource => scope.resource - end -end diff --git a/test/language/ast/resource.rb b/test/language/ast/resource.rb index c99d98eeb..97541d92f 100755 --- a/test/language/ast/resource.rb +++ b/test/language/ast/resource.rb @@ -16,8 +16,7 @@ class TestASTResource< Test::Unit::TestCase def setup super @scope = mkscope - @parser = @scope.compile.parser - @scope.compile.send(:evaluate_main) + @parser = @scope.compiler.parser end def newdef(type, title, params = nil) @@ -36,24 +35,24 @@ class TestASTResource< Test::Unit::TestCase title = "title" # First try a qualified type - assert_equal("One::Two", newdef("two", title).evaluate(:scope => twoscope)[0].type, + assert_equal("One::Two", newdef("two", title).evaluate(twoscope)[0].type, "Defined type was not made fully qualified") # Then try a type that does not need to be qualified - assert_equal("One", newdef("one", title).evaluate(:scope => twoscope)[0].type, + assert_equal("One", newdef("one", title).evaluate(twoscope)[0].type, "Unqualified defined type was not handled correctly") # Then an unqualified type from within the one namespace - assert_equal("Three", newdef("three", title).evaluate(:scope => twoscope)[0].type, + assert_equal("Three", newdef("three", title).evaluate(twoscope)[0].type, "Defined type was not made fully qualified") # Then a builtin type - assert_equal("File", newdef("file", title).evaluate(:scope => twoscope)[0].type, + assert_equal("File", newdef("file", title).evaluate(twoscope)[0].type, "Builtin type was not handled correctly") # Now try a type that does not exist, which should throw an error. assert_raise(Puppet::ParseError, "Did not fail on a missing type in a resource reference") do - newdef("nosuchtype", title).evaluate(:scope => twoscope) + newdef("nosuchtype", title).evaluate(twoscope) end end end diff --git a/test/language/ast/resource_reference.rb b/test/language/ast/resource_reference.rb index c9fde078f..1f554d90f 100755 --- a/test/language/ast/resource_reference.rb +++ b/test/language/ast/resource_reference.rb @@ -20,7 +20,7 @@ class TestASTResourceReference < Test::Unit::TestCase def setup super @scope = mkscope - @parser = @scope.compile.parser + @parser = @scope.compiler.parser end def test_evaluate @@ -31,7 +31,7 @@ class TestASTResourceReference < Test::Unit::TestCase evaled = nil assert_nothing_raised("Could not evaluate resource ref") do - evaled = ref.evaluate(:scope => @scope) + evaled = ref.evaluate(@scope) end assert_equal(type, evaled.type, "Type did not translate correctly") @@ -44,7 +44,7 @@ class TestASTResourceReference < Test::Unit::TestCase ref = newref("Class", "one") evaled = nil assert_nothing_raised("Could not evaluate resource ref") do - evaled = ref.evaluate(:scope => @scope) + evaled = ref.evaluate(@scope) end assert_equal("Class", evaled.type, "Did not set type to 'class'") @@ -61,24 +61,24 @@ class TestASTResourceReference < Test::Unit::TestCase title = "title" # First try a qualified type - assert_equal("One::Two", newref("two", title).evaluate(:scope => twoscope).type, + assert_equal("One::Two", newref("two", title).evaluate(twoscope).type, "Defined type was not made fully qualified") # Then try a type that does not need to be qualified - assert_equal("One", newref("one", title).evaluate(:scope => twoscope).type, + assert_equal("One", newref("one", title).evaluate(twoscope).type, "Unqualified defined type was not handled correctly") # Then an unqualified type from within the one namespace - assert_equal("Three", newref("three", title).evaluate(:scope => twoscope).type, + assert_equal("Three", newref("three", title).evaluate(twoscope).type, "Defined type was not made fully qualified") # Then a builtin type - assert_equal("File", newref("file", title).evaluate(:scope => twoscope).type, + assert_equal("File", newref("file", title).evaluate(twoscope).type, "Builtin type was not handled correctly") # Now try a type that does not exist, which should throw an error. assert_raise(Puppet::ParseError, "Did not fail on a missing type in a resource reference") do - newref("nosuchtype", title).evaluate(:scope => twoscope) + newref("nosuchtype", title).evaluate(twoscope) end # Now run the same tests, but with the classes @@ -86,20 +86,20 @@ class TestASTResourceReference < Test::Unit::TestCase @parser.newclass "one::five" # First try an unqualified type - assert_equal("four", newref("class", "four").evaluate(:scope => twoscope).title, + assert_equal("four", newref("class", "four").evaluate(twoscope).title, "Unqualified class was not found") # Then a qualified class - assert_equal("one::five", newref("class", "five").evaluate(:scope => twoscope).title, + assert_equal("one::five", newref("class", "five").evaluate(twoscope).title, "Class was not made fully qualified") # Then try a type that does not need to be qualified - assert_equal("four", newref("class", "four").evaluate(:scope => twoscope).title, + assert_equal("four", newref("class", "four").evaluate(twoscope).title, "Unqualified class was not handled correctly") # Now try a type that does not exist, which should throw an error. assert_raise(Puppet::ParseError, "Did not fail on a missing type in a resource reference") do - newref("class", "nosuchclass").evaluate(:scope => twoscope) + newref("class", "nosuchclass").evaluate(twoscope) end end end diff --git a/test/language/ast/selector.rb b/test/language/ast/selector.rb index 535fcbf70..6e923bdcb 100755 --- a/test/language/ast/selector.rb +++ b/test/language/ast/selector.rb @@ -37,7 +37,7 @@ class TestSelector < Test::Unit::TestCase params = maker.call() sel = AST::Selector.new(:param => param, :values => params.values) result = nil - assert_nothing_raised { result = sel.evaluate(:scope => scope) } + assert_nothing_raised { result = sel.evaluate(scope) } assert_equal(should[str], result, "did not case-sensitively match %s" % str) end @@ -53,7 +53,7 @@ class TestSelector < Test::Unit::TestCase params.delete(:upper) sel = AST::Selector.new(:param => param, :values => params.values) result = nil - assert_nothing_raised { result = sel.evaluate(:scope => scope) } + assert_nothing_raised { result = sel.evaluate(scope) } assert_equal("lower", result, "did not case-insensitively match %s" % str) end end diff --git a/test/language/ast/variable.rb b/test/language/ast/variable.rb index 09122ce16..bde397bb4 100755 --- a/test/language/ast/variable.rb +++ b/test/language/ast/variable.rb @@ -22,9 +22,9 @@ class TestVariable < Test::Unit::TestCase end def test_evaluate - assert_equal("", @var.evaluate(:scope => @scope), "did not return empty string on unset var") + assert_equal("", @var.evaluate(@scope), "did not return empty string on unset var") @scope.setvar(@name, "something") - assert_equal("something", @var.evaluate(:scope => @scope), "incorrect variable value") + assert_equal("something", @var.evaluate(@scope), "incorrect variable value") end end diff --git a/test/language/compile.rb b/test/language/compile.rb deleted file mode 100755 index 082b37a1c..000000000 --- a/test/language/compile.rb +++ /dev/null @@ -1,569 +0,0 @@ -#!/usr/bin/env ruby - -require File.dirname(__FILE__) + '/../lib/puppettest' - -require 'mocha' -require 'puppettest' -require 'puppettest/parsertesting' -require 'puppet/parser/compile' - -# Test our compile object. -class TestCompile < Test::Unit::TestCase - include PuppetTest - include PuppetTest::ParserTesting - - Compile = Puppet::Parser::Compile - Scope = Puppet::Parser::Scope - Node = Puppet::Network::Handler.handler(:node) - SimpleNode = Puppet::Node - - def mknode(name = "foo") - @node = SimpleNode.new(name) - end - - def mkparser - # This should mock an interpreter - @parser = stub 'parser', :version => "1.0", :nodes => {} - end - - def mkcompile(options = {}) - if node = options[:node] - options.delete(:node) - else - node = mknode - end - @compile = Compile.new(node, mkparser, options) - end - - def test_initialize - compile = nil - node = stub 'node', :name => "foo" - parser = stub 'parser', :version => "1.0", :nodes => {} - assert_nothing_raised("Could not init compile with all required options") do - compile = Compile.new(node, parser) - end - - assert_equal(node, compile.node, "Did not set node correctly") - assert_equal(parser, compile.parser, "Did not set parser correctly") - - # 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 compile with extra options") do - compile = Compile.new(node, parser) - end - - assert_equal(false, compile.ast_nodes?, "Did not set ast_nodes? correctly") - end - - def test_initvars - compile = mkcompile - [:class_scopes, :resource_table, :exported_resources, :resource_overrides].each do |table| - assert_instance_of(Hash, compile.send(:instance_variable_get, "@#{table}"), "Did not set %s table correctly" % table) - end - assert_instance_of(Scope, compile.topscope, "Did not create a topscope") - graph = compile.instance_variable_get("@scope_graph") - assert_instance_of(Puppet::SimpleGraph, graph, "Did not create scope graph") - assert(graph.vertex?(compile.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 = mock 'ast_class' - klass.expects(:classname).returns("myname") - - compile = mkcompile - compile.catalog.expects(:tag).with("myname") - - assert_nothing_raised("Could not set class") do - compile.class_set "myname", "myscope" - end - # First try to retrieve it by name. - assert_equal("myscope", compile.class_scope("myname"), "Could not retrieve class scope by name") - - # Then by object - assert_equal("myscope", compile.class_scope(klass), "Could not retrieve class scope by object") - end - - def test_classlist - compile = mkcompile - - compile.class_set "", "empty" - compile.class_set "one", "yep" - compile.class_set "two", "nope" - - # Make sure our class list is correct - assert_equal(%w{one two}.sort, compile.classlist.sort, "Did not get correct class list") - end - - # Make sure collections get added to our internal array - def test_add_collection - compile = mkcompile - assert_nothing_raised("Could not add collection") do - compile.add_collection "nope" - end - assert_equal(%w{nope}, compile.instance_variable_get("@collections"), "Did not add collection") - end - - # Make sure we create a graph of scopes. - def test_newscope - compile = mkcompile - graph = compile.instance_variable_get("@scope_graph") - assert_instance_of(Scope, compile.topscope, "Did not create top scope") - assert_instance_of(Puppet::SimpleGraph, graph, "Did not create graph") - - assert(graph.vertex?(compile.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 = compile.newscope(compile.topscope) - end - assert_instance_of(Scope, subscope, "Did not create subscope") - assert(graph.edge?(compile.topscope, subscope), "An edge between top scope and subscope was not added") - - # Make sure a scope can find its parent. - assert(compile.parent(subscope), "Could not look up parent scope on compile") - assert_equal(compile.topscope.object_id, compile.parent(subscope).object_id, "Did not get correct parent scope from compile") - assert_equal(compile.topscope.object_id, subscope.parent.object_id, "Scope did not correctly retrieve its parent scope") - - # Now create another, this time specifying options - another = nil - assert_nothing_raised("Could not create subscope") do - another = compile.newscope(subscope, :level => 5) - end - assert_equal(5, another.level, "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") - - # Make sure it can find its parent. - assert(compile.parent(another), "Could not look up parent scope of second subscope on compile") - assert_equal(subscope.object_id, compile.parent(another).object_id, "Did not get correct parent scope of second subscope from compile") - 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, compile.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 - compile = mkcompile - [:set_node_parameters, :evaluate_main, :evaluate_ast_node, :evaluate_node_classes, :evaluate_generators, :fail_on_unevaluated, :finish].each do |method| - compile.expects(method) - end - assert_instance_of(Puppet::Node::Catalog, compile.compile, "Did not return the catalog") - end - - # Test setting the node's parameters into the top scope. - def test_set_node_parameters - compile = mkcompile - @node.parameters = {"a" => "b", "c" => "d"} - scope = compile.topscope - @node.parameters.each do |param, value| - scope.expects(:setvar).with(param, value) - end - - assert_nothing_raised("Could not call 'set_node_parameters'") do - compile.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 - compile = mkcompile - main_class = mock 'main_class' - compile.topscope.expects(:source=).with(main_class) - @parser.expects(:findclass).with("", "").returns(main_class) - - main_resource = mock 'main resource' - Puppet::Parser::Resource.expects(:new).with { |args| args[:title] == :main }.returns(main_resource) - - main_resource.expects(:evaluate) - - assert_nothing_raised("Could not call evaluate_main") do - compile.send(:evaluate_main) - end - end - - def test_evaluate_node_classes - compile = mkcompile - @node.classes = %w{one two three four} - compile.expects(:evaluate_classes).with(%w{one two three four}, compile.topscope) - assert_nothing_raised("could not call evaluate_node_classes") do - compile.send(:evaluate_node_classes) - end - end - - def test_evaluate_collections - compile = mkcompile - - colls = [] - - # Make sure we return false when there's nothing there. - assert(! compile.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) } - - compile.instance_variable_set("@collections", colls) - assert(! compile.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(compile.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(compile.send(:evaluate_collections), "Did not return true when both collections evaluated true") - end - - def test_unevaluated_resources - compile = mkcompile - resources = {} - compile.instance_variable_set("@resource_table", resources) - - # First test it when the table is empty - assert_nil(compile.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(compile.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(compile.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"]], compile.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 = compile.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 - compile = mkcompile - compile.expects(:unevaluated_resources).returns(nil) - - assert_nothing_raised("Could not test for unevaluated resources") do - assert(! compile.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 - compile = mkcompile - compile.expects(:unevaluated_resources).returns(resources) - - assert_nothing_raised("Could not test for unevaluated resources") do - assert(compile.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 - compile = mkcompile - compile.expects(:evaluate_definitions).returns(false) - compile.expects(:evaluate_collections).returns(false) - - assert_nothing_raised("Could not call :eval_iterate") do - compile.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. - #compile = mkcompile - #compile.expects(:evaluate_collections).returns(true).returns(false) - #compile.expects(:evaluate_definitions).returns(false) - #compile.send(:eval_iterate) - end - - def test_store - compile = mkcompile - Puppet.features.expects(:rails?).returns(true) - Puppet::Rails.expects(:connect) - - node = mock 'node' - resource_table = mock 'resources' - resource_table.expects(:values).returns(:resources) - compile.instance_variable_set("@node", node) - compile.instance_variable_set("@resource_table", resource_table) - compile.expects(:store_to_active_record).with(node, :resources) - compile.send(:store) - end - - def test_store_to_active_record - compile = mkcompile - node = mock 'node' - node.expects(:name).returns("myname") - Puppet::Rails::Host.stubs(:transaction).yields - Puppet::Rails::Host.expects(:store).with(node, :resources) - compile.send(:store_to_active_record, node, :resources) - end - - # Make sure that 'finish' gets called on all of our resources. - def test_finish - compile = mkcompile - table = compile.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 - - compile.send(:finish) - end - - def test_verify_uniqueness - compile = mkcompile - - resources = compile.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 - compile.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 - compile.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 - compile.send(:verify_uniqueness, conflict) - end - end - - def test_store_resource - # Run once when there's no conflict - compile = mkcompile - table = compile.instance_variable_get("@resource_table") - resource = mock("resource") - resource.expects(:ref).returns("yay") - compile.expects(:verify_uniqueness).with(resource) - scope = stub("scope", :resource => mock('resource')) - - compile.catalog.expects(:add_edge!).with(scope.resource, resource) - - assert_nothing_raised("Could not store resource") do - compile.store_resource(scope, resource) - end - assert_equal(resource, table["yay"], "Did not store resource in table") - - # Now for conflicts - compile = mkcompile - table = compile.instance_variable_get("@resource_table") - resource = mock("resource") - compile.expects(:verify_uniqueness).with(resource).raises(ArgumentError) - - assert_raise(ArgumentError, "Did not raise uniqueness exception") do - compile.store_resource(scope, resource) - end - assert(table.empty?, "Conflicting resource was stored in table") - end - - def test_fail_on_unevaluated - compile = mkcompile - compile.expects(:fail_on_unevaluated_overrides) - compile.expects(:fail_on_unevaluated_resource_collections) - compile.send :fail_on_unevaluated - end - - def test_store_override - # First test the case when the resource is not present. - compile = mkcompile - overrides = compile.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 - compile.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 = compile.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 - compile.store_override(override) - end - end - - def test_resource_overrides - compile = mkcompile - overrides = compile.instance_variable_get("@resource_overrides") - overrides[:test] = :yay - resource = mock 'resource' - resource.expects(:ref).returns(:test) - - assert_equal(:yay, compile.resource_overrides(resource), "Did not return overrides from table") - end - - def test_fail_on_unevaluated_resource_collections - compile = mkcompile - collections = compile.instance_variable_get("@collections") - - # Make sure we're fine when the list is empty - assert_nothing_raised("Failed when no collections were present") do - compile.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 - compile.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 - compile.send :fail_on_unevaluated_resource_collections - end - end - - def test_fail_on_unevaluated_overrides - compile = mkcompile - overrides = compile.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 - compile.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 - compile.send :fail_on_unevaluated_overrides - end - end - - def test_find_resource - compile = mkcompile - resources = compile.instance_variable_get("@resource_table") - - assert_nothing_raised("Could not call findresource when the resource table was empty") do - assert_nil(compile.findresource("yay", "foo"), "Returned a non-existent resource") - assert_nil(compile.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, compile.findresource("foo", "bar"), "Returned a non-existent resource") - assert_equal(:yay, compile.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 - compile = mkcompile - node = stub :nodescope? => true - klass = stub :nodescope? => false - compile.class_set("one", node) - assert_raise(Puppet::ParseError, "Did not fail when replacing node with class") do - compile.class_set("one", klass) - end - - # and class then node - compile = mkcompile - node = stub :nodescope? => true - klass = stub :nodescope? => false - compile.class_set("two", klass) - assert_raise(Puppet::ParseError, "Did not fail when replacing node with class") do - compile.class_set("two", node) - end - end -end diff --git a/test/language/functions.rb b/test/language/functions.rb index 132ee97ac..a5d52d7ac 100755 --- a/test/language/functions.rb +++ b/test/language/functions.rb @@ -41,7 +41,7 @@ class TestLangFunctions < Test::Unit::TestCase scope = mkscope val = nil assert_nothing_raised do - val = func.evaluate(:scope => scope) + val = func.evaluate(scope) end assert_equal("output avalue", val) @@ -57,7 +57,7 @@ class TestLangFunctions < Test::Unit::TestCase val = nil assert_nothing_raised do - val = func.evaluate(:scope => scope) + val = func.evaluate(scope) end assert_equal(retval, val, "'tagged' returned %s for %s" % [val, tag]) @@ -66,7 +66,7 @@ class TestLangFunctions < Test::Unit::TestCase # Now make sure we correctly get tags. scope.resource.tag("resourcetag") assert(scope.function_tagged("resourcetag"), "tagged function did not catch resource tags") - scope.compile.catalog.tag("configtag") + scope.compiler.catalog.tag("configtag") assert(scope.function_tagged("configtag"), "tagged function did not catch catalog tags") end @@ -86,7 +86,7 @@ class TestLangFunctions < Test::Unit::TestCase scope = mkscope val = nil assert_raise(Puppet::ParseError) do - val = func.evaluate(:scope => scope) + val = func.evaluate(scope) end end @@ -117,16 +117,16 @@ class TestLangFunctions < Test::Unit::TestCase scope = mkscope assert_raise(Puppet::ParseError) do - ast.evaluate(:scope => scope) + ast.evaluate(scope) end scope.setvar("one", "One") assert_raise(Puppet::ParseError) do - ast.evaluate(:scope => scope) + ast.evaluate(scope) end scope.setvar("two", "Two") assert_nothing_raised do - ast.evaluate(:scope => scope) + ast.evaluate(scope) end assert_equal("template One\ntemplate Two\n", scope.lookupvar("output"), @@ -155,13 +155,13 @@ class TestLangFunctions < Test::Unit::TestCase scope = mkscope assert_raise(Puppet::ParseError) do - ast.evaluate(:scope => scope) + ast.evaluate(scope) end scope.setvar("yayness", "this is yayness") assert_nothing_raised do - ast.evaluate(:scope => scope) + ast.evaluate(scope) end assert_equal("template this is yayness\n", scope.lookupvar("output"), @@ -191,7 +191,7 @@ class TestLangFunctions < Test::Unit::TestCase scope = mkscope scope.setvar("myvar", "this is yayness") assert_raise(Puppet::ParseError) do - ast.evaluate(:scope => scope) + ast.evaluate(scope) end end @@ -264,14 +264,14 @@ class TestLangFunctions < Test::Unit::TestCase }.each do |string, value| scope = mkscope assert_raise(Puppet::ParseError) do - ast.evaluate(:scope => scope) + ast.evaluate(scope) end scope.setvar("yayness", string) assert_equal(string, scope.lookupvar("yayness", false)) assert_nothing_raised("An empty string was not a valid variable value") do - ast.evaluate(:scope => scope) + ast.evaluate(scope) end assert_equal("template #{value}\n", scope.lookupvar("output"), @@ -308,7 +308,7 @@ class TestLangFunctions < Test::Unit::TestCase def test_realize scope = mkscope - parser = scope.compile.parser + parser = scope.compiler.parser # Make a definition parser.newdefine("mytype") @@ -318,7 +318,7 @@ class TestLangFunctions < Test::Unit::TestCase virtual = mkresource(:type => type, :title => title, :virtual => true, :params => {}, :scope => scope) - scope.compile.store_resource(scope, virtual) + scope.compiler.add_resource(scope, virtual) ref = Puppet::Parser::Resource::Reference.new( :type => type, :title => title, @@ -330,13 +330,13 @@ class TestLangFunctions < Test::Unit::TestCase end # Make sure it created a collection - assert_equal(1, scope.compile.collections.length, + assert_equal(1, scope.compiler.collections.length, "Did not set collection") assert_nothing_raised do - scope.compile.collections.each do |coll| coll.evaluate end + scope.compiler.collections.each do |coll| coll.evaluate end end - scope.compile.collections.clear + scope.compiler.collections.clear # Now make sure the virtual resource is no longer virtual assert(! virtual.virtual?, "Did not make virtual resource real") @@ -354,17 +354,17 @@ class TestLangFunctions < Test::Unit::TestCase end # Make sure it created a collection - assert_equal(1, scope.compile.collections.length, + assert_equal(1, scope.compiler.collections.length, "Did not set collection") # And the collection has our resource in it - assert_equal([none.to_s], scope.compile.collections[0].resources, + assert_equal([none.to_s], scope.compiler.collections[0].resources, "Did not set resources in collection") end def test_defined scope = mkscope - parser = scope.compile.parser + parser = scope.compiler.parser parser.newclass("yayness") parser.newdefine("rahness") @@ -385,7 +385,7 @@ class TestLangFunctions < Test::Unit::TestCase "Multiple falses were somehow true") # Now make sure we can test resources - scope.compile.store_resource(scope, mkresource(:type => "file", :title => "/tmp/rahness", + scope.compiler.add_resource(scope, mkresource(:type => "file", :title => "/tmp/rahness", :scope => scope, :source => scope.source, :params => {:owner => "root"})) @@ -420,7 +420,7 @@ class TestLangFunctions < Test::Unit::TestCase def test_include scope = mkscope - parser = scope.compile.parser + parser = scope.compiler.parser assert_raise(Puppet::ParseError, "did not throw error on missing class") do scope.function_include("nosuchclass") @@ -428,7 +428,7 @@ class TestLangFunctions < Test::Unit::TestCase parser.newclass("myclass") - scope.compile.expects(:evaluate_classes).with(%w{myclass otherclass}, scope, false).returns(%w{myclass otherclass}) + scope.compiler.expects(:evaluate_classes).with(%w{myclass otherclass}, scope, false).returns(%w{myclass otherclass}) assert_nothing_raised do scope.function_include(["myclass", "otherclass"]) @@ -480,7 +480,7 @@ class TestLangFunctions < Test::Unit::TestCase assert_equal("yay-foo\n", %x{#{command} foo}, "command did not work") scope = mkscope - parser = scope.compile.parser + parser = scope.compiler.parser val = nil assert_nothing_raised("Could not call generator with no args") do diff --git a/test/language/parser.rb b/test/language/parser.rb index 1bbd894e4..2a0e9c02d 100755 --- a/test/language/parser.rb +++ b/test/language/parser.rb @@ -45,9 +45,9 @@ class TestParser < Test::Unit::TestCase assert_raise(Puppet::ParseError, "Did not fail while parsing %s" % file) { parser.file = file ast = parser.parse - config = mkcompile(parser) + config = mkcompiler(parser) config.compile - #ast.classes[""].evaluate :scope => config.topscope + #ast.classes[""].evaluate config.topscope } Puppet::Type.allclear } @@ -868,7 +868,7 @@ file { "/tmp/yayness": def test_newclass scope = mkscope - parser = scope.compile.parser + parser = scope.compiler.parser mkcode = proc do |ary| classes = ary.collect do |string| @@ -891,7 +891,7 @@ file { "/tmp/yayness": assert(parser.classes["myclass"], "Could not find definition") assert_equal("myclass", parser.classes["myclass"].classname) assert_equal(%w{original code}, - parser.classes["myclass"].code.evaluate(:scope => scope)) + parser.classes["myclass"].code.evaluate(scope)) # Newclass behaves differently than the others -- it just appends # the code to the existing class. @@ -901,7 +901,7 @@ file { "/tmp/yayness": end assert(klass, "Did not return class when appending") assert_equal(%w{original code something new}, - parser.classes["myclass"].code.evaluate(:scope => scope)) + parser.classes["myclass"].code.evaluate(scope)) # Now create the same class name in a different scope assert_nothing_raised { @@ -914,7 +914,7 @@ file { "/tmp/yayness": assert_equal("other::myclass", other.classname) assert_equal("other::myclass", other.namespace) assert_equal(%w{something diff}, - other.code.evaluate(:scope => scope)) + other.code.evaluate(scope)) # Make sure newclass deals correctly with nodes with no code klass = parser.newclass("nocode") @@ -925,7 +925,7 @@ file { "/tmp/yayness": end assert(klass, "Did not return class with no code") assert_equal(%w{yay test}, - parser.classes["nocode"].code.evaluate(:scope => scope)) + parser.classes["nocode"].code.evaluate(scope)) # Then try merging something into nothing parser.newclass("nocode2", :code => mkcode.call(%w{foo test})) @@ -936,7 +936,7 @@ file { "/tmp/yayness": end assert(klass, "Did not return class with no code") assert_equal(%w{foo test}, - parser.classes["nocode2"].code.evaluate(:scope => scope)) + parser.classes["nocode2"].code.evaluate(scope)) # And lastly, nothing and nothing klass = parser.newclass("nocode3") diff --git a/test/language/resource.rb b/test/language/resource.rb index 5a3916159..608e7c995 100755 --- a/test/language/resource.rb +++ b/test/language/resource.rb @@ -106,7 +106,6 @@ class TestResource < PuppetTest::TestCase def test_finish res = mkresource - res.expects(:add_overrides) res.expects(:add_defaults) res.expects(:add_metaparams) res.expects(:validate) @@ -266,48 +265,12 @@ class TestResource < PuppetTest::TestCase ref.expects(:definedtype).returns(type) res.expects(:finish) res.scope = mock("scope") - config = mock("config") - res.scope.expects(:compile).returns(config) - config.expects(:delete_resource).with(res) - args = {:scope => res.scope, :resource => res} - type.expects(:evaluate).with(args) + type.expects(:evaluate_code).with(res) res.evaluate end - def test_add_overrides - # Try it with nil - res = mkresource - res.scope = mock('scope') - config = mock("config") - res.scope.expects(:compile).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(:compile).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(:compile).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 res = Parser::Resource.new :type => "evaltest", :title => "yay", :source => mock("source"), :scope => mkscope @@ -378,7 +341,7 @@ class TestResource < PuppetTest::TestCase {:name => "one", :title => "two"}, {:title => "three"}, ].each do |hash| - config = mkcompile parser + config = mkcompiler parser args = {:type => "yayness", :title => hash[:title], :source => klass, :scope => config.topscope} if hash[:name] @@ -425,7 +388,7 @@ class TestResource < PuppetTest::TestCase :code => resourcedef("file", varref("name"), "mode" => "644")) - config = mkcompile(parser) + config = mkcompiler(parser) res = mkresource :type => "yayness", :title => "foo", :params => {}, :scope => config.topscope res.virtual = true diff --git a/test/language/scope.rb b/test/language/scope.rb index ec11a864e..c96581a23 100755 --- a/test/language/scope.rb +++ b/test/language/scope.rb @@ -27,7 +27,7 @@ class TestScope < Test::Unit::TestCase end def test_variables - config = mkcompile + config = mkcompiler topscope = config.topscope midscope = config.newscope(topscope) botscope = config.newscope(midscope) @@ -94,7 +94,7 @@ class TestScope < Test::Unit::TestCase classes = ["", "one", "one::two", "one::two::three"].each do |name| klass = parser.newclass(name) Puppet::Parser::Resource.new(:type => "class", :title => name, :scope => scope, :source => mock('source')).evaluate - scopes[name] = scope.compile.class_scope(klass) + scopes[name] = scope.compiler.class_scope(klass) end classes.each do |name| @@ -125,7 +125,7 @@ class TestScope < Test::Unit::TestCase end def test_setdefaults - config = mkcompile + config = mkcompiler scope = config.topscope @@ -151,7 +151,7 @@ class TestScope < Test::Unit::TestCase end def test_lookupdefaults - config = mkcompile + config = mkcompiler top = config.topscope # Make a subscope @@ -179,7 +179,7 @@ class TestScope < Test::Unit::TestCase end def test_parent - config = mkcompile + config = mkcompiler top = config.topscope # Make a subscope @@ -205,7 +205,7 @@ class TestScope < Test::Unit::TestCase %w{one one::two one::two::three}.each do |name| klass = parser.newclass(name) Puppet::Parser::Resource.new(:type => "class", :title => name, :scope => scope, :source => mock('source')).evaluate - scopes[name] = scope.compile.class_scope(klass) + scopes[name] = scope.compiler.class_scope(klass) scopes[name].setvar("test", "value-%s" % name.sub(/.+::/,'')) end @@ -284,13 +284,13 @@ class TestScope < Test::Unit::TestCase ) assert_nothing_raised do - function.evaluate :scope => scope + function.evaluate scope end - scope.compile.send(:evaluate_generators) + scope.compiler.send(:evaluate_generators) [myclass, otherclass].each do |klass| - assert(scope.compile.class_scope(klass), + assert(scope.compiler.class_scope(klass), "%s was not set" % klass.classname) end end @@ -328,18 +328,17 @@ class TestScope < Test::Unit::TestCase "undef considered true") end - if defined? ActiveRecord # Verify that we recursively mark as exported the results of collectable # components. - def test_exportedcomponents - config = mkcompile + def test_virtual_definitions_do_not_get_evaluated + config = mkcompiler parser = config.parser # Create a default source config.topscope.source = parser.newclass "", "" # And a scope resource - scope_res = stub 'scope_resource', :virtual? => true, :exported? => false, :tags => [] + scope_res = stub 'scope_resource', :virtual? => true, :exported? => false, :tags => [], :builtin? => true, :type => "eh", :title => "bee" config.topscope.resource = scope_res args = AST::ASTArray.new( @@ -348,7 +347,7 @@ class TestScope < Test::Unit::TestCase :children => [nameobj("arg")] ) - # Create a top-level component + # Create a top-level define parser.newdefine "one", :arguments => [%w{arg}], :code => AST::ASTArray.new( :children => [ @@ -356,41 +355,26 @@ class TestScope < Test::Unit::TestCase ] ) - # And a component that calls it - parser.newdefine "two", :arguments => [%w{arg}], - :code => AST::ASTArray.new( - :children => [ - resourcedef("one", "ptest", {"arg" => varref("arg")}) - ] - ) - - # And then a third component that calls the second - parser.newdefine "three", :arguments => [%w{arg}], - :code => AST::ASTArray.new( - :children => [ - resourcedef("two", "yay", {"arg" => varref("arg")}) - ] - ) - - # lastly, create an object that calls our third component - obj = resourcedef("three", "boo", {"arg" => "parentfoo"}) + # create a resource that calls our third define + obj = resourcedef("one", "boo", {"arg" => "parentfoo"}) - # And mark it as exported - obj.exported = true + # And mark it as virtual + obj.virtual = true # And then evaluate it - obj.evaluate :scope => config.topscope + obj.evaluate config.topscope # And run the loop. config.send(:evaluate_generators) %w{File}.each do |type| - objects = config.resources.find_all { |r| r.type == type and r.exported } + objects = config.resources.find_all { |r| r.type == type and r.virtual } - assert(!objects.empty?, "Did not get an exported %s" % type) + assert(objects.empty?, "Virtual define got evaluated") end end + if defined? ActiveRecord # Verify that we can both store and collect an object in the same # run, whether it's in the same scope as a collection or a different # scope. diff --git a/test/language/snippets.rb b/test/language/snippets.rb index 2a4ba0220..982ddfec4 100755 --- a/test/language/snippets.rb +++ b/test/language/snippets.rb @@ -15,6 +15,8 @@ class TestSnippets < Test::Unit::TestCase def setup super @file = Puppet::Type.type(:file) + Facter.stubs(:to_hash).returns({}) + Facter.stubs(:value).returns("whatever") end def self.snippetdir @@ -422,6 +424,11 @@ class TestSnippets < Test::Unit::TestCase assert_file("/tmp/realize_defined_test2") end + def snippet_collection_within_virtual_definitions + assert_file("/tmp/collection_within_virtual_definitions1_foo.txt") + assert_file("/tmp/collection_within_virtual_definitions2_foo2.txt") + end + def snippet_fqparents assert_file("/tmp/fqparent1", "Did not make file from parent class") assert_file("/tmp/fqparent2", "Did not make file from subclass") diff --git a/test/lib/puppettest/parsertesting.rb b/test/lib/puppettest/parsertesting.rb index 36bb68a77..1a08ecbae 100644 --- a/test/lib/puppettest/parsertesting.rb +++ b/test/lib/puppettest/parsertesting.rb @@ -5,7 +5,7 @@ module PuppetTest::ParserTesting include PuppetTest AST = Puppet::Parser::AST - Compile = Puppet::Parser::Compile + Compiler = Puppet::Parser::Compiler # A fake class that we can use for testing evaluation. class FakeAST @@ -41,10 +41,10 @@ module PuppetTest::ParserTesting ) end - def mkcompile(parser = nil) + def mkcompiler(parser = nil) parser ||= mkparser node = mknode - return Compile.new(node, parser) + return Compiler.new(node, parser) end def mknode(name = nil) @@ -64,15 +64,15 @@ module PuppetTest::ParserTesting def mkscope(hash = {}) hash[:parser] ||= mkparser - compile ||= mkcompile(hash[:parser]) - compile.topscope.source = (hash[:parser].findclass("", "") || hash[:parser].newclass("")) + compiler ||= mkcompiler(hash[:parser]) + compiler.topscope.source = (hash[:parser].findclass("", "") || hash[:parser].newclass("")) - unless compile.topscope.source + unless compiler.topscope.source raise "Could not find source for scope" end # Make the 'main' stuff - compile.send(:evaluate_main) - compile.topscope + compiler.send(:evaluate_main) + compiler.topscope end def classobj(name, hash = {}) diff --git a/test/lib/puppettest/support/resources.rb b/test/lib/puppettest/support/resources.rb index 384f61c33..255c55569 100755 --- a/test/lib/puppettest/support/resources.rb +++ b/test/lib/puppettest/support/resources.rb @@ -18,7 +18,7 @@ module PuppetTest::Support::Resources if resource.is_a?(String) resource = tree_resource(resource) end - config.add_edge!(comp, resource) + config.add_edge(comp, resource) config.add_resource resource unless config.resource(resource.ref) end return comp diff --git a/test/other/transactions.rb b/test/other/transactions.rb index 79971a28b..105698da1 100755 --- a/test/other/transactions.rb +++ b/test/other/transactions.rb @@ -348,12 +348,12 @@ class TestTransactions < Test::Unit::TestCase fcomp = Puppet::Type.type(:component).create(:name => "file") config.add_resource fcomp config.add_resource file - config.add_edge!(fcomp, file) + config.add_edge(fcomp, file) ecomp = Puppet::Type.type(:component).create(:name => "exec") config.add_resource ecomp config.add_resource exec - config.add_edge!(ecomp, exec) + config.add_edge(ecomp, exec) # 'subscribe' expects an array of arrays #component[:require] = [[file.class.name,file.name]] @@ -828,10 +828,10 @@ class TestTransactions < Test::Unit::TestCase c = trigger.new(:c) nope = Puppet::Relationship.new(a, b) yep = Puppet::Relationship.new(a, c, {:callback => :refresh}) - graph.add_edge!(nope) + graph.add_edge(nope) # And a triggering one. - graph.add_edge!(yep) + graph.add_edge(yep) # Create our transaction trans = Puppet::Transaction.new(graph) diff --git a/test/ral/manager/type.rb b/test/ral/manager/type.rb index 6a044687e..6c5587ddd 100755 --- a/test/ral/manager/type.rb +++ b/test/ral/manager/type.rb @@ -708,7 +708,7 @@ class TestType < Test::Unit::TestCase res = type.create(hash) config.add_resource res if parent - config.add_edge!(parent, res) + config.add_edge(parent, res) end res end @@ -741,7 +741,7 @@ class TestType < Test::Unit::TestCase newcomp = Puppet::Type.newcomponent :type => "yay", :name => "Good[bad]" config.add_resource newcomp - config.add_edge! comp, newcomp + config.add_edge comp, newcomp exec = mk.call(6, :parent => newcomp) assert_equal("//Good[bad]/Exec[exec6]", exec.path) end diff --git a/test/ral/types/basic.rb b/test/ral/types/basic.rb index 7bbadc5bc..3c5faeee0 100755 --- a/test/ral/types/basic.rb +++ b/test/ral/types/basic.rb @@ -36,8 +36,8 @@ class TestBasic < Test::Unit::TestCase ) } @config = mk_catalog(@component, @configfile, @command) - @config.add_edge! @component, @configfile - @config.add_edge! @component, @command + @config.add_edge @component, @configfile + @config.add_edge @component, @command end def teardown diff --git a/vendor/gems/rspec/CHANGES b/vendor/gems/rspec/CHANGES new file mode 100644 index 000000000..e17793323 --- /dev/null +++ b/vendor/gems/rspec/CHANGES @@ -0,0 +1,885 @@ +== Version 1.0.8 + +Another bugfix release - this time to resolve the version mismatch + +== Version 1.0.7 + +Quick bugfix release to ensure that you don't have to have the rspec gem installed +in order to use autotest with rspec_on_rails. + +* Fixed [#13015] autotest gives failure in 'spec_command' after upgrade 1.0.5 to 1.0.6 + +== Version 1.0.6 + +The "holy cow, batman, it's been a long time since we released and there are a ton of bug +fixes, patches and even new features" release. + +Warning: Spec::Rails users: In fixing 11508, we've removed the raise_controller_errors method. As long as you +follow the upgrade instructions and run 'script/generate rspec' you'll be fine, but if you skip this +step you need to manually go into spec_helper.rb and remove the call to that method (if present - it +might not be if you haven't upgraded in a while). + +Warning: Implementors of custom formatters. Formatters will now be sent an Example object instead of just a +String for #example_started, #example_passed and #example_failed. In certain scenarios +(Spec::Ui with Spec::Distributed), the formatter must ask the Example for its sequence number instead of +keeping track of a sequence number internal to the formatter. Most of you shouldn't need to upgrade +your formatters though - the Example#to_s method returns the example name/description, so you should be +able to use the passed Example instance as if it were a String. + +* Applied [#12986] Autotest Specs + Refactoring (Patch from Scott Tayler) +* Added a #close method to formatters, which allows them to gracefully close streams. +* Applied [#12935] Remove requirement that mocha must be installed as a gem when used as mocking framework. (Patch from Ryan Kinderman). +* Fixed [#12893] RSpec's Autotest should work with rspec's trunk +* Fixed [#12865] Partial mock error when object has an @options instance var +* Applied [#12701] Allow checking of content captured with content_for in view specs (Patch from Jens Krmer) +* Applied [#12817] Cannot include same shared behaviour when required with absolute paths (Patch from Ian Leitch) +* Applied [#12719] rspec_on_rails should not include pagination helper (Patch from Matthijs Langenberg) +* Fixed [#12714] helper spec not finding rails core helpers +* Applied [#12611] should_not redirect_to implementation (Patch from Yurii Rashkovskii) +* Applied [#12682] Not correctly aliasing original 'stub!' and 'should_receive' methods for ApplicationController (Patch from Matthijs Langenberg) +* Disabled controller.should_receive(:render) and controller.stub!(:render). Use expect_render or stub_render instead. +* Applied [#12484] Allow a Behaviour's Description to flow through to the Formatter (Patch from Bob Cotton) +* Fixed [#12448] The spec:plugins rake task from rspec_on_rails should ignore specs from the rspec_on_rails plugin +* Applied [#12300] rr integration (patch from Kyle Hargraves) +* Implemented [#12284] mock_with :rr (integration with RR mock framework: http://rubyforge.org/projects/pivotalrb/) +* Applied [#12237] (tiny) added full path to mate in switch_command (Patch from Carl Porth) +* Formatters will now be sent an Example object instead of just a String for certain methods +* All Spec::Rake::SpecTask attributes can now be procs, which allows for lazy evaluation. +* Changed the Spec::Ui interfaces slightly. See examples. +* Applied [#12174] mishandling of paths with spaces in spec_mate switch_command (Patch from Carl Porth) +* Implemented [#8315] File "Go to..." functionality +* Applied [#11917] Cleaner Spec::Ui error for failed Selenium connection (Patch from Ian Dees) +* Applied [#11888] rspec_on_rails spews out warnings when assert_select is used with an XML response (Patch from Ian Leitch) +* Applied [#12010] Nicer failure message formatting (Patch from Wincent Colaiuta) +* Applied [#12156] smooth open mate patch (Patch from Ienaga Eiji) +* Applied [#10577] Rails with Oracle breaks 0.9.2. (Patch from Sinclair Bain) +* Fixed [#12079] auto-generated example name incomplete: should have 1 error on ....] +* Applied [#12066] Docfix for mocks/mocks.page (Patch from Kyle Hargraves) +* Fixed [#11891] script/generate rspec_controller fails to create appropriate views (from templates) on edge rails +* Applied [#11921] Adds the correct controller_name from derived_controller_name() to the ViewExampleController (Patch from Eloy Duran) +* Fixed [#11903] config.include with behaviour_type 'hash' does not work +* Examples without blocks and pending is now reported with a P instead of a * +* Pending blocks that now pass are rendered blue +* New behaviour for after: If an after block raises an error, the other ones will still run instead of bailing at the first. +* Made it possible to run spec from RSpec.tmbundle with --drb against a Rails spec_server. +* Applied [#11868] Add ability for pending to optionally hold a failing block and to fail when it passes (Patch from Bob Cotton) +* Fixed [#11843] watir_behaviour missing from spec_ui gem +* Added 'switch between source and spec file' command in Spec::Mate (based on code from Ruy Asan) +* Applied [#11509] Documentation - RSpec requires hpricot +* Applied [#11807] Daemonize spec_server and rake tasks to manage them. (patch from Kyosuke MOROHASHI) +* Added pending(message) method +* Fixed [#11777] should render_template doesn't check paths correctly +* Fixed [#11749] Use of 'rescue => e' does not catch all exceptions +* Fixed [#11793] should raise_error('with a message') does not work correctly +* Fixed [#11774] Mocks should respond to :kind_of? in the same way they respond to :is_a? +* Fixed [#11508] Exceptions are not raised for Controller Specs (removed experimental raise_controller_errors) +* Applied [#11615] Partial mock methods give ambiguous failures when given a method name as a String (Patch from Jay Phillips) +* Fixed [#11545] Rspec doesn't handle should_receive on ActiveRecord associations (Patch from Ian White) +* Fixed [#11514] configuration.use_transactional_fixtures is ALWAYS true, regardless of assignment +* Improved generated RESTful controller examples to cover both successful and unsuccessful POST and PUT +* Changed TextMate snippets for controllers to pass controller class names to #describe rather than controller_name. +* Changed TextMate snippets for mocks to use no_args() and any_args() instead of the deprecated Symbols. +* Applied [#11500] Documentation: no rails integration specs in 1.0 +* Renamed SpecMate's shortcuts for running all examples and focused examples to avoid conflicts (CMD-d and CMD-i) +* Added a TextMate snippet for custom matchers, lifted from Geoffrey Grosenbach's RSpec peepcode show. +* The translator translates mock constraints to the new matchers that were introduced in 1.0.4 +* Documented environment variables for Spec::Rake::SpecTask. Renamed SPECOPTS and RCOVOPTS to SPEC_OPTS and RCOV_OPTS. +* Fixed [#10534] Windows: undefined method 'controller_name' + +== Version 1.0.5 +Bug fixes. Autotest plugin tweaks. + +* Fixed [#11378] fix to 10814 broke drb (re-opened #10814) +* Fixed [#11223] Unable to access flash from rails helper specs +* Fixed [#11337] autotest runs specs redundantly +* Fixed [#11258] windows: autotest won't run +* Applied [#11253] Tweaks to autotest file mappings (Patch from Wincent Colaiuta) +* Applied [#11252] Should be able to re-load file containing shared behaviours without raising an exception (Patch from Wincent Colaiuta) +* Fixed [#11247] standalone autotest doesn't work because of unneeded autotest.rb +* Applied [#11221] Autotest support does not work w/o Rails Gem installed (Patch from Josh Knowles) + +== Version 1.0.4 +The getting ready for JRuby release. + +* Fixed [#11181] behaviour_type scoping of config.before(:each) is not working +* added mock argument constraint matchers (anything(), boolean(), an_instance_of(Type)) which work with rspec or mocha +* added mock argument constraint matchers (any_args(), no_args()) which only work with rspec +* deprecated rspec's symbol mock argument constraint matchers (:any_args, :no_args, :anything, :boolean, :numeric, :string) +* Added tarball of rspec_on_rails to the release build to support folks working behind a firewall that blocks svn access. +* Fixed [#11137] rspec incorrectly handles flash after resetting the session +* Fixed [#11143] Views code for ActionController::Base#render broke between 1.0.0 and 1.0.3 on Rails Edge r6731 +* Added raise_controller_errors for controller examples in Spec::Rails + +== Version 1.0.3 +Bug fixes. + +* Fixed [#11104] Website uses old specify notation +* Applied [#11101] StringHelpers.starts_with?(prefix) assumes a string parameter for _prefix_ +* Removed 'rescue nil' which was hiding errors in controller examples. +* Fixed [#11075] controller specs fail when using mocha without integrated_views +* Fixed problem with redirect_to failing incorrectly against edge rails. +* Fixed [#11082] RspecResourceGenerator should be RspecScaffoldGenerator +* Fixed [#10959] Focused Examples do not work for Behaviour defined with constant with modules + +== Version 1.0.2 +This is just to align the version numbers in rspec and rspec_on_rails. + +== Version 1.0.1 +This is a maintenance release with mostly cleaning up, and one minor enhancement - +Modules are automatically included when described directly. + +* Renamed Spec::Rails' rspec_resource generator to rspec_scaffold. +* Removed Spec::Rails' be_feed matcher since it's based on assert_select_feed which is not part of Rails (despite that docs for assert_select_encoded says it is). +* describe(SomeModule) will include that module in the examples. Like for Spec::Rails helpers, but now also in core. +* Header in HTML report will be yellow instead of red if there is one failed example +* Applied [#10951] Odd instance variable name in rspec_model template (patch from Kyle Hargraves) +* Improved integration with autotest (Patches from Ryan Davis and David Goodland) +* Some small fixes to make all specs run on JRuby. + +== Version 1.0.0 +The stake in the ground release. This represents a commitment to the API as it is. No significant +backwards compatibility changes in the API are expected after this release. + +* Fixed [#10923] have_text matcher does not support should_not +* Fixed [#10673] should > and should >= broken +* Applied [#10921] Allow verify_rcov to accept greater than threshold coverage %'s via configuration +* Applied [#10920] Added support for not implemented examples (Patch from Chad Humphries and Ken Barker) +* Patch to allow not implemented examples. This works by not providing a block to the example. (Patch from Chad Humphries, Ken Barker) +* Yanked support for Rails 1.1.6 in Spec::Rails +* RSpec.tmbundle uses CMD-SHIFT-R to run focused examples now. +* Spec::Rails now bundles a spec:rcov task by default (suggestion from Kurt Schrader) +* Fixed [#10814] Runner loads shared code, test cases require them again +* Fixed [#10753] Global before and after +* Fixed [#10774] Allow before and after to be specified in config II +* Refactored Spec::Ui examples to use new global before and after blocks. +* Added instructions about how to get Selenium working with Spec::Ui (spec_ui/examples/selenium/README.txt) +* Fixed [#10805] selenium.rb missing from gem? +* Added rdocs explaining how to deal with errors in Rails' controller actions +* Applied [#10770] Finer grained includes. +* Fixed [#10747] Helper methods defined in shared specs are not visible when shared spec is used +* Fixed [#10748] Shared descriptions in separate files causes 'already exists' error +* Applied [#10698] Running with --drb executes specs twice (patch from Ruy Asan) +* Fixed [#10871] 0.9.4 - Focussed spec runner fails to run specs in descriptions with type and string when there is no leading space in the string + +== Version 0.9.4 +This release introduces massive improvements to Spec::Ui - the user interface functional testing +extension to RSpec. There are also some minor bug fixes to the RSpec core. + +* Massive improvements to Spec::Ui. Complete support for all Watir's ie.xxx(how, what) methods. Inline screenshots and HTML. +* Reactivated --timeout, which had mysteriously been deactivated in a recent release. +* Fixed [#10669] Kernel#describe override does not cover Kernel#context +* Applied [#10636] Added spec for OptionParser in Runner (Patch from Scott Taylor) +* Added [#10516] should_include should be able to accept multiple items +* Applied [#10631] redirect_to matcher doesn't respect request.host (Patch from Tim Lucas) +* Each formatter now flushes their own IO. This is to avoid buffering of output. +* Fixed [#10670] IVarProxy#delete raises exception when instance variable does not exist + +== Version 0.9.3 +This is a bugfix release. + +* Fixed [#10594] Failing Custom Matcher show NAME NOT GENERATED description +* describe(SomeType, "#message") will not add a space: "SomeType#message" (likewise for '.') +* describe(SomeType, "message") will have a decription with a space: "SomeType message" +* Applied [#10566] prepend_before and prepend_after callbacks +* Applied [#10567] Call setup and teardown using before and after callbacks + +== Version 0.9.2 +This is a quick maintenance release. + +* Added some website love +* Fixed [#10542] reverse predicate matcher syntax +* Added a spec:translate Rake task to make 0.9 translation easier with Spec:Rails +* Better translation of should_redirect_to +* Fixed --colour support for Windows. This is a regression that was introduced in 0.9.1 +* Applied [#10460] Make SpecRunner easier to instantiate without using commandline args + +== Version 0.9.1 + +This release introduces #describe and #it (aliased as #context and #specify for +backwards compatibility). This allows you to express specs like this: + + describe SomeClass do # Creates a Behaviour + it "should do something" do # Creates an Example + end + end + +The command line features four new options that give you more control over what specs +are being run and in what order. This can be used to verify that your specs are +independent (by running in opposite order with --reverse). It can also be used to cut +down feedback time by running the most recently modified specs first (--loadby mtime --reverse). + +Further, --example replaces the old --spec option, and it can now take a file name of +spec names as an alternative to just a spec name. The --format failing_examples:file.txt +option allows you to output an --example compatible file, which makes it possible to only +rerun the specs that failed in the last run. Spec::Rails uses all of these four options +by default to optimise your RSpec experience. + +There is now a simple configuration model. For Spec::Rails, you do something like this: + + Spec::Runner.configure do |config| + config.use_transactional_fixtures = true + config.use_instantiated_fixtures = false + config.fixture_path = RAILS_ROOT + '/spec/fixtures' + end + +You can now use mocha or flexmock with RSpec if you prefer either to +RSpec's own mock framework. Just put this: + + Spec::Runner.configure do |config| + config.mock_with :mocha + end + +or this: + + Spec::Runner.configure do |config| + config.mock_with :flexmock + end + +in a file that is loaded before your specs. You can also +configure included modules and predicate_matchers: + + Spec::Runner.configure do |config| + config.include SomeModule + config.predicate_matchers[:does_something?] = :do_something + end + +See Spec::DSL::Behaviour for more on predicate_matchers + +* Sugar FREE! +* Added [10434 ] Please Make -s synonymous with -e for autotest compat. This is temporary until autotest uses -e instead of -s. +* Fixed [#10133] custom predicate matchers +* Applied [#10473] Add should exist (new matcher) - Patch from Bret Pettichord +* Added another formatter: failing_behaviours. Writes the names of the failing behaviours for use with --example. +* Applied [#10315] Patch to fix pre_commit bug 10313 - pre_commit_rails: doesn't always build correctly (Patch from Antii Tarvainen) +* Applied [#10245] Patch to HTML escape the behavior name when using HTML Formatter (Patch from Josh Knowles) +* Applied [#10410] redirect_to does not behave consistently with regards to query string parameter ordering (Patch from Nicholas Evans) +* Applied [#9605] Patch for ER 9472, shared behaviour (Patch by Bob Cotton) +* The '--format rdoc' option no longer causes a dry-run by default. --dry-run must be used explicitly. +* It's possible to specify the output file in the --format option (See explanation in --help) +* Several --format options may be specified to output several formats in one run. +* The --out option is gone. Use --format html:path/to/my.html instead (or similar). +* Spec::Runner::Formatter::BaseTextFormatter#initialize only takes one argument - an IO. dry_run and color are setters. +* Made Spec::Ui *much* easier to install. It will be released separately. Check out trunk/spec_ui/examples +* HTML reports now include a syntax highlighted snippet of the source code where the spec failed (needs the syntax gem) +* Added [#10262] Better Helper testing of Erb evaluation block helpers +* Added [#9735] support flexmock (thanks to Jim Weirich for his modifications to flexmock to support this) +* Spec::Rails controller specs will no longer let mock exception ripple through to the response. +* Fixed [#9260] IvarProxy does not act like a hash. +* Applied [#9458] The rspec_scaffold generator does not take into account class nesting (Patch from Steve Tendon) +* Applied [#9132] Rakefile spec:doc can fail without preparing database (Patch from Steve Ross) +* Applied [#9678] Custom runner command line switch, and multi-threaded runner (Patch from Bob Cotton) +* Applied [#9926] Rakefile - RSPEC_DEPS constant as an Array of Hashes instead of an Array of Arrays (Patch from Scott Taylor) +* Applied [#9925] Changed ".rhtml" to "template" in REST spec generator (Patch from Scott Taylor) +* Applied [#9852] Patch for RSpec's Website using Webgen 0.4.2 (Patch from Scott Taylor) +* Fixed [#6523] Run rspec on rails without a db +* Fixed [#9295] rake spec should run anything in the spec directory (not just rspec's standard dirs) +* Added [#9786] infer controller and helper names from the described type +* Fixed [#7795] form_tag renders action='/view_spec' in view specs +* Fixed [#9767] rspec_on_rails should not define rescue_action on controllers +* Fixed [#9421] --line doesn't work with behaviours that use class names +* Fixed [#9760] rspec generators incompatible with changes to edge rails +* Added [#9786] infer controller and helper names from the described type +* Applied a simplified version of [#9282] Change to allow running specs from textmate with rspec installed as a rails plugin (and no rspec gem installed) +* Applied [#9700] Make Spec::DSL::Example#name public / Add a --timeout switch. A great way to prevent specs from getting slow. +* In Rails, script/generate rspec will generate a spec.opts file that optimises faster/more efficient running of specs. +* Added [#9522] support using rspec's expectations with test/unit +* Moved rspec_on_rails up to the project root, simplifying the download url +* Fixed [#8103] RSpec not installing spec script correctly. +* The --spec option is replaced by the --example option. +* The --loadby option no longer supports a file argument. Use --example file_name instead. +* The --example option can now take a file name as an argument. The file should contain example names. +* Internal classes are named Behaviour/Example (rather than Context/Specification). +* You can now use mocha by saying config.mock_with :mocha in a spec_helper +* before_context_eval is replaced by before_eval. +* Applied [#9509] allow spaced options in spec.opts +* Applied [#9510] Added File for Ruby 1.8.6 +* Applied [#9511] Clarification to README file in spec/ +* Moved all of the Spec::Rails specs down to the plugins directory - now you can run the specs after you install. +* Updated RSpec.tmbundle to the 0.9 syntax and replaced context/specify with describe/it. +* Applied [#9232] ActionController::Base#render is sometimes protected (patch from Dan Manges) +* Added --reverse option, allowing contexts/specs to be run in reverse order. +* Added --loadby option, allowing better control over load order for spec files. mtime and file.txt supported. +* Implemented [#8696] --order option (see --reverse and --loadby) +* Added describe/it as aliases for context/specify - suggestion from Dan North. +* Applied [#7637] [PATCH] add skip-migration option to rspec_scaffold generator +* Added [#9167] string.should have_tag +* Changed script/rails_spec_server to script/spec_server and added script/spec (w/ path to vendor/plugins/rspec) +* Fixed [#8897] Error when mixing controller spec with/without integrated views and using template system other than rhtml +* Updated sample app specs to 0.9 syntax +* Updated generated specs to 0.9 syntax +* Applied [#8994] trunk: generated names for be_ specs (Multiple patches from Yurii Rashkovskii) +* Applied [#9983]: Allow before and after to be called in BehaviourEval. This is useful for shared examples. + +== Version 0.8.2 + +Replaced assert_select fork with an assert_select wrapper for have_tag. This means that "should have_rjs" no longer supports :hide or :effect, but you can still use should_have_rjs for those. + +== Version 0.8.1 + +Quick "in house" bug-fix + +== Version 0.8.0 + +This release introduces a new approach to handling expectations using Expression Matchers. + +See Upgrade[http://rspec.rubyforge.org/upgrade.html], Spec::Expectations, Spec::Matchers and RELEASE-PLAN for more info. + +This release also improves the spec command line by adding DRb support and making it possible to +store command line options in a file. This means a more flexible RSpec experience with Rails, +Rake and editor plugins like TextMate. + +It also sports myriad new features, bug fixes, patches and general goodness: + +* Fixed [#8928] rspec_on_rails 0.8.0-RC1 controller tests make double call to setup_with_fixtures +* Fixed [#8925] Documentation bug in 0.8.0RC1 rspec website +* Applied [#8132] [PATCH] RSpec breaks "rake db:sessions:create" in a rails project that has the rspec_on_rails plugin (Patch from Erik Kastner) +* Fixed [#8789] --line and --spec not working when the context has parenhesis in the name +* Added [#8783] auto generate spec names from last expectation +* --heckle now fails if the heckled class or module is not found. +* Fixed [#8771] Spec::Mocks::BaseExpectation#with converts hash params to array of arrays with #collect +* Fixed [#8750] should[_not]_include backwards compatibility between 0.8.0-RC1 and 0.7.5.1 broken +* Fixed [#8646] Context Runner does not report on Non standard exceptions and return a 0 return code +* RSpec on Rails' spec_helper.rb will only force RAILS_ENV to test if it was not specified on the command line. +* Fixed [#5485] proc#should_raise and proc#should_not_raise output +* Added [#8484] should_receive with blocks +* Applied [#8218] heckle_runner.rb doesn't work with heckle >= 1.2.0 (Patch from Michal Kwiatkowski) +* Fixed [#8240] Cryptic error message when no controller_name +* Applied [#7461] [PATCH] Contexts don't call Module::included when they include a module +* Removed unintended block of test/unit assertions in rspec_on_rails - they should all, in theory, now be accessible +* Added mock_model method to RSpec on Rails, which stubs common methods. Based on http://metaclass.org/2006/12/22/making-a-mockery-of-activerecord +* Fixed [#8165] Partial Mock Errors when respond_to? is true but the method is not in the object +* Fixed [#7611] Partial Mocks override Subclass methods +* Fixed [#8302] Strange side effect when mocking a class method +* Applied [#8316] to_param should return a stringified key in resource generator's controller spec (Patch from Chris Anderson) +* Applied [#8216] shortcut for creating object stub +* Applied [#8008] Correct generated specs for view when calling resource generator (Patch from Jonathan Tron) +* Fixed [#7754] Command-R fails to run spec in TextMate (added instruction from Luke Redpath to the website) +* Fixed [#7826] RSpect.tmbundle web page out of date. +* RSpec on Rails specs are now running against RoR 1.2.1 and 1.2.2 +* rspec_scaffold now generates specs for views +* In a Rails app, RSpec core is only loaded when RAILS_ENV==test (init.rb) +* Added support for target.should arbitrary_expectation_handler and target.should_not arbitrary_expectation_handler +* Fixed [#7533] Spec suite fails and the process exits with a code 0 +* Fixed [#7565] Subsequent stub! calls for method fail to override the first call to method +* Applied [#7524] Incorrect Documentation for 'pattern' in Rake task (patch from Stephen Duncan) +* Fixed [#7409] default fixtures do not appear to run. +* Fixed [#7507] "render..and return" doesn't return +* Fixed [#7509] rcov/rspec incorrectly includes boot.rb (Patch from Courtenay) +* Fixed [#7506] unnecessary complex output on failure of response.should be_redirect +* Applied [#6098] Make scaffold_resource generator. Based on code from Pat Maddox. +* The drbspec command is gone. Use spec --drb instead. +* The drb option is gone from the Rake task. Pass --drb to spec_opts instead. +* New -X/--drb option for running specs against a server like spec/rails' script/rails_spec_server +* New -O/--options and -G/--generate flags for file-based options (handy for spec/rails) +* Applied [#7339] Turn off caching in HTML reports +* Applied [#7419] "c option for colorizing output does not work with rails_spec" (Patch from Shintaro Kakutani) +* Applied [#7406] [PATCH] 0.7.5 rspec_on_rails loads fixtures into development database (Patch from Wilson Bilkovich) +* Applied [#7387] Allow stubs to return consecutive values (Patch from Pat Maddox) +* Applied [#7393] Fix for rake task (Patch from Pat Maddox) +* Reinstated support for response.should_render (in addition to controller.should_render) + +== Version 0.7.5.1 + +Bug fix release to allow downloads of rspec gem using rubygems 0.9.1. + +== Version 0.7.5 +This release adds support for Heckle - Seattle'rb's code mutation tool. +There are also several bug fixes to the RSpec core and the RSpec on Rails plugin. + +* Removed svn:externals on rails versions and plugins +* Applied [#7345] Adding context_setup and context_teardown, with specs and 100% rcov +* Applied [#7320] [PATCH] Allow XHR requests in controller specs to render RJS templates +* Applied [#7319] Migration code uses drop_column when it should use remove_column (patch from Pat Maddox) +* Added support for Heckle +* Applied [#7282] dump results even if spec is interrupted (patch from Kouhei Sutou) +* Applied [#7277] model.should_have(n).errors_on(:attribute) (patch from Wilson Bilkovich) +* Applied [#7270] RSpec render_partial colliding with simply_helpful (patch from David Goodlad) +* Added [#7250] stubs should support throwing +* Added [#7249] stubs should support yielding +* Fixed [#6760] fatal error when accessing nested finders in rspec +* Fixed [#7179] script/generate rspec_scaffold generates incorrect helper name +* Added preliminary support for assert_select (response.should_have) +* Fixed [#6971] and_yield does not work when the arity is -1 +* Fixed [#6898] Can we separate rspec from the plugins? +* Added [#7025] should_change should accept a block +* Applied [#6989] partials with locals (patch from Micah Martin) +* Applied [#7023] Typo in team.page + +== Version 0.7.4 + +This release features a complete redesign of the reports generated with --format html. +As usual there are many bug fixes - mostly related to spec/rails. + +* Applied [#7010] Fixes :spacer_template does not work w/ view spec (patch from Shintaro Kakutani) +* Applied [#6798] ensure two ':' in the first backtrace line for Emacs's 'next-error' command (patch from Kouhei Sutou) +* Added Much nicer reports to generated website +* Much nicer reports with --format --html (patch from Luke Redpath) +* Applied [#6959] Calls to render and redirect in controllers should return true +* Fixed [#6981] helper method is not available in partial template. +* Added [#6978] mock should tell you the expected and actual args when receiving the right message with the wrong args +* Added the possibility to tweak the output of the HtmlFormatter (by overriding extra_failure_content). +* Fixed [#6936] View specs don't include ApplicationHelper by default +* Fixed [#6903] Rendering a partial in a view makes the view spec blow up +* Added callback library from Brian Takita +* Added [#6925] support controller.should_render :action_name +* Fixed [#6884] intermittent errors related to method binding +* Fixed [#6870] rspec on edge rails spec:controller fixture loading fails +* Using obj.inspect for all messages +* Improved performance by getting rid of instance_exec (instance_eval is good enough because we never need to pass it args) + +== Version 0.7.3 + +Almost normal bug fix/new feature release. + +A couple of things you need to change in your rails specs: +# spec_helper.rb is a little different (see http://rspec.rubyforge.org/upgrade.html) +# use controller.should_render before OR after the action (controller.should_have_rendered is deprecated) + +* Applied [#6577] messy mock backtrace when frozen to edge rails (patch from Jay Levitt) +* Fixed [#6674] rspec_on_rails fails on @session deprecation warning +* Fixed [#6780] routing() was failing...fix included - works for 1.1.6 and edge (1.2) +* Fixed [#6835] bad message with arbitrary predicate +* Added [#6731] Partial templates rendered +* Fixed [#6713] helper methods not rendered in view tests? +* Fixed [#6707] cannot run controller / helper tests via rails_spec or spec only works with rake +* Applied [#6417] lambda {...}.should_change(receiver, :message) (patch from Wilson Bilkovich) +* Eliminated dependency on ZenTest +* Fixed [#6650] Reserved characters in the TextMate bundle break svn on Win32 +* Fixed [#6643] script/generate rspec_controller: invalid symbol generation for 'controller_name' for *modularized* controllers +* The script/rails_spec command has been moved to bin/drbspec in RSpec core (installed by the gem) + +== Version 0.7.2 + +This release introduces a brand new RSpec bundle for TextMate, plus some small bugfixes. + +* Packaged RSpec.tmbundle.tgz as part of the distro +* Fixed [#6593] Add moving progress bar to HtmlFormatter using Javascript +* Applied [#6265] should_raise should accept an Exception object +* Fixed [#6616] Can't run Rails specs with RSpec.tmbundle +* Fixed [#6411] Can't run Rails specs with ruby +* Added [#6589] New -l --line option. This is useful for IDE/editor runners/extensions. +* Fixed [#6615] controller.should_render_rjs should support :partial => 'path/to/template' + +== Version 0.7.1 + +Bug fixes and a couple o' new features. + +* Fixed [#6575] Parse error in aliasing the partial mock original method (patch by Brian Takita) +* Fixed [#6277] debris left by stubbing (trunk) [submitted by dastels] (fixed by fix to [#6575]) +* Fixed [#6575] Parse error in aliasing the partial mock original method +* Fixed [#6555] should_have_tag does not match documentation +* Fixed [#6567] SyntaxError should not stop entire run +* Fixed [#6558] integrated views look for template even when redirected +* Fixed [#6547] response.should be_redirect broken in 0.7.0 +* Applied [#6471] Easy way to spec routes +* Applied [#6587] Rspec on Rails displays "Spec::Rails::ContextFactory" as context name +* Applied [#6514] Document has trivial typos. +* Added [#6560] controller.session should be available before the action +* Added support for should_have_rjs :visual_effect +* Different printing and colours for unmet expectations (red) and other exceptions (magenta) +* Simplified method_missing on mock_methods to make it less invasive on partial mocks. + +== Version 0.7.0 + +This is the "Grow up and eat your own dog food release". RSpec is now used on itself and +we're no longer using Test::Unit to test it. Although, we are still extending Test::Unit +for the rails plugin (indirectly - through ZenTest) + +IMPORTANT NOTE: THIS RELEASE IS NOT 100% BACKWARDS COMPATIBLE TO 0.6.x + +There are a few changes that will require that you change your existing specs. + +RSpec now handles equality exactly like ruby does: + +# actual.should_equal(expected) will pass if actual.equal?(expected) returns true +# actual.should eql(expected) will pass if actual.eql?(expected) returns true +# actual.should == expected will pass if actual == expected) returns true + +At the high level, eql? implies equivalence, while equal? implies object identity. For more +information on how ruby deals w/ equality, you should do this: + +ri equal? + +or look at this: + +http://www.ruby-doc.org/core/classes/Object.html#M001057 + +Also, we left in should_be as a synonym for should_equal, so the only specs that should break are the +ones using should_equal (which used to use <code>==</code> instead of <code>.equal?</code>). + +Lastly, should_be used to handle true and false differently from any other values. We've removed +this special handling, so now actual.should_be true will fail for any value other than true (it +used to pass for any non-nil, non-false value), and actual.should_be false will fail for any +value other than false (it used to pass for nil or false). + +Here's what you'll need to do to update your specs: +# search for "should_equal" and replace with "should_eql" +# run specs + +If any specs still fail, they are probably related to should be_true or should_be_false using +non-boolean values. Those you'll just have to inspect manually and adjust appropriately (sorry!). + +-------------------------------------------------- +Specifying multiple return values in mocks now works like this: + +mock.should_receive(:message).and_return(1,2,3) + +It used to work like this: + +mock.should_receive(:message).and_return([1,2,3]) + +but we decided that was counter intuitive and otherwise lame. + +Here's what you'll need to do to update your specs: +# search for "and_return([" +# get rid of the "[" and "]" + +-------------------------------------------------- +RSpec on Rails now supports the following (thanks to ZenTest upon which it is built): + +# Separate specs for models, views, controllers and helpers +# Controller specs are completely decoupled from the views by default (though you can tell them to couple themselves if you prefer) +# View specs are completely decoupled from app-specific controllers + +See http://rspec.rubyforge.org/documentation/rails/index.html for more information +-------------------------------------------------- +As usual, there are also other new features and bug fixes: + +* Added lots of documentation on mocks/stubs and the rails plugin. +* Added support for assigns[key] syntax for controller specs (to align w/ pre-existing syntax for view specs) +* Added support for controller.should_redirect_to +* RSpec on Rails automatically checks whether it's compatible with the installed RSpec +* Applied [#6393] rspec_on_rails uses deprecated '@response' instead of the accessor +* RSpec now has 100% spec coverage(!) +* Added support for stubbing and partial mocking +* Progress (....F..F.) is now coloured. Tweaked patch from KAKUTANI Shintaro. +* Backtrace now excludes the rcov runner (/usr/local/bin/rcov) +* Fixed [#5539] predicates do not work w/ rails +* Added [#6091] support for Regexp matching messages sent to should_raise +* Added [#6333] support for Regexp matching in mock arguments +* Applied [#6283] refactoring of diff support to allow selectable formats and custom differs +* Fixed [#5564] "ruby spec_file.rb" doesn't work the same way as "spec spec_file.rb" +* Fixed [#6056] Multiple output of failing-spec notice +* Fixed [#6233] Colours in specdoc +* Applied [#6207] Allows --diff option to diff target and expected's #inspect output (Patch by Lachie Cox) +* Fixed [#6203] Failure messages are misleading - consider using inspect. +* Added [#6334] subject.should_have_xyz will try to call subject.has_xyz? - use this for hash.should_have_key(key) +* Fixed [#6017] Rake task should ignore empty or non-existent spec-dirs + +== Version 0.6.4 + +In addition to a number of bug fixes and patches, this release begins to formalize the support for +RSpec on Rails. + +* Added Christopher Petrilli's TextMate bundle to vendor/textmate/RSpec.tmbundle +* Fixed [#5909], once again supporting multi_word_predicates +* Applied [#5873] - response.should_have_rjs (initial patch from Jake Howerton, based on ARTS by Kevin Clark) +* Added generation of view specs for rspec_on_rails +* Applied [#5815] active_record_subclass.should_have(3).records +* Added support in "rake stats" for view specs (in spec/views) +* Applied [#5801] QuickRef.pdf should say RSpec, not rSpec +* Applied [#5728] rails_spec_runner fails on Windows (Patch from Lindsay Evans). +* Applied [#5708] RSpec Rails plugin rspec_controller generator makes specs that do not parse. +* Cleaned up RSpec on Rails so it doesn't pollute as much during bootstrapping. +* Added support for response.should_have_tag and response.should_not_have_tag (works just like assert_tag in rails) +* Added new -c, --colour, --color option for colourful (red/green) output. Inspired from Pat Eyler's Redgreen gem. +* Added examples for Watir and Selenium under the gem's vendor directory. +* Renamed rails_spec_runner to rails_spec_server (as referred to in the docs) +* Added support for trying a plural for arbitrary predicates. E.g. Album.should_exist(:name => "Hey Jude") will call Album.exists?(:name => "Hey Jude") +* Added support for should_have to work with methods taking args returning a collection. E.g. @dave.should_have(3).albums_i_have_that_this_guy_doesnt(@aslak) +* Added [#5570] should_not_receive(:msg).with(:specific, "args") +* Applied [#5065] to support using define_method rather than method_missing to capture expected messages on mocks. Thanks to Eero Saynatkari for the tip that made it work. +* Restructured directories and Modules in order to separate rspec into three distinct Modules: Spec::Expectations, Spec::Runner and Spec::Mocks. This will allow us to more easily integrate other mock frameworks and/or allow test/unit users to take advantage of the expectation API. +* Applied [#5620] support any boolean method and arbitrary comparisons (5.should_be < 6) (Patch from Mike Williams) + +== Version 0.6.3 + +This release fixes some minor bugs related to RSpec on Rails +Note that if you upgrade a rails app with this version of the rspec_on_rails plugin +you should remove your lib/tasks/rspec.rake if it exists. + +* Backtraces from drb (and other standard ruby libraries) are now stripped from backtraces. +* Applied [#5557] Put rspec.rake into the task directory of the RSpec on Rails plugin (Patch from Daniel Siemssen) +* Applied [#5556] rails_spec_server loads environment.rb twice (Patch from Daniel Siemssen) + +== Version 0.6.2 +This release fixes a couple of regressions with the rake task that were introduced in the previous version (0.6.1) + +* Fixed [#5518] ruby -w: warnings in 0.6.1 +* Applied [#5525] fix rake task path to spec tool for gem-installed rspec (patch from Riley Lynch) +* Fixed a teensey regression with the rake task - introduced in 0.6.1. The spec command is now quoted so it works on windows. + +== Version 0.6.1 +This is the "fix the most annoying bugs release" of RSpec. There are 9 bugfixes this time. +Things that may break backwards compatibility: +1) Spec::Rake::SpecTask no longer has the options attribute. Use ruby_opts, spec_opts and rcov_opts instead. + +* Fixed [#4891] RCOV task failing on windows +* Fixed [#4896] Shouldn't modify user's $LOAD_PATH (Tip from Gavin Sinclair) +* Fixed [#5369] ruby -w: warnings in RSpec 0.5.16 (Tip from Suraj Kurapati) +* Applied [#5141] ExampleMatcher doesn't escape strings before matching (Patch from Nikolai Weibull). +* Fixed [#5224] Move 'require diff-lcs' from test_helper.rb to diff_test.rb (Tip from Chris Roos) +* Applied [#5449] Rake stats for specs (Patch from Nick Sieger) +* Applied [#5468, #5058] Fix spec runner to correctly run controller specs (Patch from Daniel Siemssen) +* Applied fixes to rails_spec_server to improve its ability to run several times. (Patch from Daniel Siemssen) +* Changed RCov::VerifyTask to fail if the coverage is above the threshold. This is to ensure it gets bumped when coverage improves. + +== Version 0.6.0 +This release makes an official commitment to underscore_syntax (with no more support for dot.syntax) + +* Fixed bug (5292) that caused mock argument matching to fail +* Converted ALL tests to use underscore syntax +* Fixed all remaining problems with underscores revealed by converting all the tests to underscores +* Enhanced sugar to support combinations of methods (i.e. once.and_return) +* Simplified helper structure taking advantage of dot/underscore combos (i.e. should.be.an_instance_of, which can be expressed as should be_an_instance_of) +* Added support for at_most in mocks +* Added support for should_not_receive(:msg) (will be removing should_receive(:msg).never some time soon) +* Added support for should_have_exactly(5).items_in_collection + +== Version 0.5.16 +This release improves Rails support and test2spec translation. + +* Fixed underscore problems that occurred when RSpec was used in Rails +* Simplified the Rails support by packaging it as a plugin instead of a generator gem. +* Fixed [#5063] 'rspec_on_rails' require line in spec_helper.rb +* Added pre_commit rake task to reduce risk of regressions. Useful for RSpec developers and patchers. +* Added failure_message to RSpec Rake task +* test2spec now defines converted helper methods outside of the setup block (bug #5057). + +== Version 0.5.15 +This release removes a prematurely added feature that shouldn't have been added. + +* Removed support for differences that was added in 0.5.14. The functionality is not aligned with RSpec's vision. + +== Version 0.5.14 +This release introduces better ways to extend specs, improves some of the core API and +a experimental support for faster rails specs. + +* Added proc methods for specifying differences (increments and decrements). See difference_test.rb +* Methods can now be defined alongside specs. This obsoletes the need for defining methods in setup. (Patch #5002 from Brian Takita) +* Sugar (underscores) now works correctly with should be_a_kind_of and should be_an_instance_of +* Added support for include and inherit in contexts. (Patch #4971 from Brian Takita) +* Added rails_spec and rails_spec_server for faster specs on rails (still buggy - help needed) +* Fixed bug that caused should_render to break if given a :symbol (in Rails) +* Added support for comparing exception message in should_raise and should_not_raise + +== Version 0.5.13 +This release fixes some subtle bugs in the mock API. + +* Use fully-qualified class name of Exceptions in failure message. Easier to debug that way. +* Fixed a bug that caused mocks to yield a one-element array (rather than the element) when one yield arg specified. +* Mocks not raise AmbiguousReturnError if an explicit return is used at the same time as an expectation block. +* Blocks passed to yielding mocks can now raise without causing mock verification to fail. + +== Version 0.5.12 +This release adds diff support for failure messages, a HTML formatter plus some other +minor enhancements. + +* Added HTML formatter. +* Added fail_on_error option to spectask. +* Added support for diffing, using the diff-lcs Rubygem (#2648). +* Remove RSpec on Rails files from backtrace (#4694). +* All of RSpec's own tests run successfully after translation with test2spec. +* Added --verbose mode for test2spec - useful for debugging when classes fail to translate. +* Output of various formatters is now flushed - to get more continuous output. + +== Version 0.5.11 +This release makes test2spec usable with Rails (with some manual steps). +See http://rspec.rubyforge.org/tools/rails.html for more details + +* test2spec now correctly translates bodies of helper methods (non- test_*, setup and teardown ones). +* Added more documentation about how to get test2spec to work with Rails. + +== Version 0.5.10 +This version features a second rewrite of test2spec - hopefully better than the previous one. + +* Improved test2spec's internals. It now transforms the syntax tree before writing out the code. + +== Version 0.5.9 +This release improves test2spec by allowing more control over the output + +* Added --template option to test2spec, which allows for custom output driven by ERB +* Added --quiet option to test2spec +* Removed unnecessary dependency on RubyToC + +== Version 0.5.8 +This release features a new Test::Unit to RSpec translation tool. +Also note that the RubyGem of the previous release (0.5.7) was corrupt. +We're close to being able to translate all of RSpec's own Test::Unit +tests and have them run successfully! + +* Updated test2spec documentation. +* Replaced old test2rspec with a new test2spec, which is based on ParseTree and RubyInline. + +== Version 0.5.7 +This release changes examples and documentation to recommend underscores rather than dots, +and addresses some bugfixes and changes to the spec commandline. + +* spec DIR now works correctly, recursing down and slurping all *.rb files +* All documentation and examples are now using '_' instead of '.' +* Custom external formatters can now be specified via --require and --format. + +== Version 0.5.6 +This release fixes a bug in the Rails controller generator + +* The controller generator did not write correct source code (missing 'do'). Fixed. + +== Version 0.5.5 +This release adds initial support for Ruby on Rails in the rspec_generator gem. + +* [Rails] Reorganised Lachie's original code to be a generator packaged as a gem rather than a plugin. +* [Rails] Imported code from http://lachie.info/svn/projects/rails_plugins/rspec_on_rails (Written by Lachie Cox) +* Remove stack trace lines from TextMate's Ruby bundle +* Better error message from spectask when no spec files are found. + +== Version 0.5.4 +The "the tutorial is ahead of the gem" release + +* Support for running a single spec with --spec +* Exitcode is now 1 unless all specs pass, in which case it's 0. +* -v, --version now both mean the same thing +* For what was verbose output (-v), use --format specdoc or -f s +* --format rdoc always runs in dry-run mode +* Removed --doc and added --format and --dry-run +* Refactored towards more pluggable formatters +* Use webgen's execute tag when generating website (more accurate) +* Fixed incorrect quoting of spec_opts in SpecTask +* Added patch to enable underscored shoulds like 1.should_equal(1) - patch from Rich Kilmer +* Removed most inherited instance method from Mock, making more methods mockable. +* Made the RCovVerify task part of the standard toolset. +* Documented Rake task and how to use it with Rcov +* Implemented <ruby></ruby> tags for website (hooking into ERB, RedCloth and syntax) +* RSpec Rake task now takes spec_opts and out params so it can be used for doc generation +* RCov integration for RSpec Rake task (#4058) +* Group all results instead of printing them several times (#4057) +* Mocks can now yield +* Various improvements to error reporting (including #4191) +* backtrace excludes rspec code - use -b to include it +* split examples into examples (passing) and failing_examples + +== Version 0.5.3 +The "hurry up, CoR is in two days" release. + +* Don't run rcov by default +* Make separate task for running tests with RCov +* Added Rake task to fail build if coverage drops below a certain threshold +* Even more failure output cleanup (simplification) +* Added duck_type constraint for mocks + +== Version 0.5.2 +This release has minor improvements to the commandline and fixes some gem warnings + +* Readded README to avoid RDoc warnings +* Added --version switch to commandline +* More changes to the mock API + +== Version 0.5.1 +This release is the first release of RSpec with a new website. It will look better soon. + +* Added initial documentation for API +* Added website based on webgen +* Modified test task to use rcov +* Deleted unused code (thanks, rcov!) +* Various changes to the mock API, +* Various improvements to failure reporting + +== Version 0.5.0 +This release introduces a new API and obsolesces previous versions. + +* Moved source code to separate subfolders +* Added new DSL runner based on instance_exec +* Added spike for testdox/rdoc generation +* merge Astels' and Chelimsky's work on ShouldHelper +* this would be 0.5.0 if I updated the documentation +* it breaks all of your existing specifications. We're not sorry. + +== Version 0.3.2 + +The "srbaker is an idiot" release. + +* also forgot to update the path to the actual Subversion repository +* this should be it + +== Version 0.3.1 + +This is just 0.3.0, but with the TUTORIAL added to the documentation list. + +* forgot to include TUTORIAL in the documentation + +== Version 0.3.0 + +It's been a while since last release, lots of new stuff is available. For instance: + +* improvements to the runners +* addition of should_raise expectation (thanks to Brian Takita) +* some documentation improvements +* RSpec usable as a DSL + +== Version 0.2.0 + +This release provides a tutorial for new users wishing to get started with +RSpec, and many improvements. + +* improved reporting in the spec runner output +* update the examples to the new mock api +* added TUTORIAL, a getting started document for new users of RSpec + +== Version 0.1.7 + +This release improves installation and documentation, mock integration and error reporting. + +* Comparison errors now print the class name too. +* Mocks now take an optional +options+ parameter to specify behaviour. +* Removed __expects in favour of should_receive +* Added line number reporting in mock error messages for unreceived message expectations. +* Added should_match and should_not_match. +* Added a +mock+ method to Spec::Context which will create mocks that autoverify (no need to call __verify). +* Mocks now require names in the constructor to ensure sensible error messages. +* Made 'spec' executable and updated usage instructions in README accordingly. +* Made more parts of the Spec::Context API private to avoid accidental usage. +* Added more RDoc to Spec::Context. + +== Version 0.1.6 + +More should methods. + +* Added should_match and should_not_match. + +== Version 0.1.5 + +Included examples and tests in gem. + +== Version 0.1.4 + +More tests on block based Mock expectations. + +== Version 0.1.3 + +Improved mocking: + +* block based Mock expectations. + +== Version 0.1.2 + +This release adds some improvements to the mock API and minor syntax improvements + +* Added Mock.should_expect for a more consistent DSL. +* Added MockExpectation.and_returns for a better DSL. +* Made Mock behave as a null object after a call to Mock.ignore_missing +* Internal syntax improvements. +* Improved exception trace by adding exception class name to error message. +* Renamed some tests for better consistency. + +== Version 0.1.1 + +This release adds some shoulds and improves error reporting + +* Added should be_same_as and should_not be_same_as. +* Improved error reporting for comparison expectations. + +== Version 0.1.0 + +This is the first preview release of RSpec, a Behaviour-Driven Development library for Ruby + +* Added Rake script with tasks for gems, rdoc etc. +* Added an XForge task to make release go easier. diff --git a/vendor/gems/rspec/EXAMPLES.rd b/vendor/gems/rspec/EXAMPLES.rd new file mode 100644 index 000000000..ac1d40b3e --- /dev/null +++ b/vendor/gems/rspec/EXAMPLES.rd @@ -0,0 +1,111 @@ +# Examples with no descriptions +# * should equal 5 +# * should be < 5 +# * should include "a" +# * should respond to #size +# State created in before(:all) +# * should be accessible from example +# * should not have sideffects +# BehaveAsExample::BluesGuitarist +# * should behave as guitarist +# BehaveAsExample::RockGuitarist +# * should behave as guitarist +# BehaveAsExample::ClassicGuitarist +# * should not behave as guitarist +# Animals::Mouse +# * should eat cheese +# * should not eat cat +# Some integers +# * The root of 1 square should be 1 +# * The root of 2 square should be 2 +# * The root of 3 square should be 3 +# * The root of 4 square should be 4 +# * The root of 5 square should be 5 +# * The root of 6 square should be 6 +# * The root of 7 square should be 7 +# * The root of 8 square should be 8 +# * The root of 9 square should be 9 +# * The root of 10 square should be 10 +# A FileAccessor +# * should open a file and pass it to the processor's process method +# Greeter +# * should say Hi to person +# * should say Hi to nobody +# a context with helper a method +# * should make that method available to specs +# An IoProcessor +# * should raise nothing when the file is exactly 32 bytes +# * should raise an exception when the file length is less than 32 bytes +# A legacy spec +# * should work fine +# A consumer of a mock +# * should be able to send messages to the mock +# a mock +# * should be able to mock the same message twice w/ different args +# * should be able to mock the same message twice w/ different args in reverse order +# A partial mock +# * should work at the class level +# * should revert to the original after each spec +# * can be mocked w/ ordering +# pending example (using pending method) +# * pending example (using pending method) should be reported as "PENDING: for some reason" [PENDING: for some reason] +# pending example (with no block) +# * pending example (with no block) should be reported as "PENDING: Not Yet Implemented" [PENDING: Not Yet Implemented] +# pending example (with block for pending) +# * pending example (with block for pending) should have a failing block, passed to pending, reported as "PENDING: for some reason" [PENDING: for some reason] +# BDD framework +# * should be adopted quickly +# * should be intuitive +# SharedBehaviourExample::OneThing +# * should do what things do +# * should have access to helper methods defined in the shared behaviour +# SharedBehaviourExample::AnotherThing +# * should do what things do +# Stack (empty) +# * should be empty +# * should not be full +# * should add to the top when sent #push +# * should complain when sent #peek +# * should complain when sent #pop +# Stack (with one item) +# * should not be empty +# * should return the top item when sent #peek +# * should NOT remove the top item when sent #peek +# * should return the top item when sent #pop +# * should remove the top item when sent #pop +# * should not be full +# * should add to the top when sent #push +# Stack (with one item less than capacity) +# * should not be empty +# * should return the top item when sent #peek +# * should NOT remove the top item when sent #peek +# * should return the top item when sent #pop +# * should remove the top item when sent #pop +# * should not be full +# * should add to the top when sent #push +# Stack (full) +# * should be full +# * should not be empty +# * should return the top item when sent #peek +# * should NOT remove the top item when sent #peek +# * should return the top item when sent #pop +# * should remove the top item when sent #pop +# * should complain on #push +# A consumer of a stub +# * should be able to stub methods on any Object +# A stubbed method on a class +# * should return the stubbed value +# * should revert to the original method after each spec +# * can stub! and mock the same message +# A mock +# * can stub! +# * can stub! and mock +# * can stub! and mock the same message +# RSpec should integrate with Test::Unit::TestCase +# * TestCase#setup should be called. +# * RSpec should be able to access TestCase methods +# * RSpec should be able to accept included modules + +Finished in 0.030063 seconds + +78 examples, 0 failures, 3 pending diff --git a/vendor/gems/rspec/MIT-LICENSE b/vendor/gems/rspec/MIT-LICENSE new file mode 100644 index 000000000..1d11ea59e --- /dev/null +++ b/vendor/gems/rspec/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2005-2007 The RSpec Development Team + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/gems/rspec/README b/vendor/gems/rspec/README new file mode 100644 index 000000000..ee351245d --- /dev/null +++ b/vendor/gems/rspec/README @@ -0,0 +1,71 @@ +== RSpec + +RSpec is a Behaviour Definition Framework intended for use in Behaviour +Driven Development. RSpec plays the same role that a unit testing framework +would play in a Test Driven Development environment, but does so using +words and structures that better support BDD. + +RSpec ships with four modules: + +Spec::Matchers provides Expression Matchers for use with Spec::Expectations +and Spec::Mocks. + +Spec::Expectations supports setting expectations on your objects so you +can do things like: + + result.should equal(expected_result) + +Spec::Mocks supports creating Mock Objects, Stubs, and adding Mock/Stub +behaviour to your existing objects. + +Spec::Runner provides a very small but powerful DSL for writing executable +examples of how your code should work. + +== Installation + +The simplest approach is to install the gem: + + gem install -r rspec #mac users must sudo + +== Building the RSpec gem +If you prefer to build the gem locally, check out source from svn://rubyforge.org/var/svn/rspec/trunk. Then +do the following: + + rake gem + gem install pkg/rspec-0.x.x.gem (you may have to sudo) + +== Running RSpec's specs +In order to run RSpec's full suite of specs (rake pre_commit) you must install the following gems: + +* rake # Runs the build script +* rcov # Verifies that the code is 100% covered by specs +* webgen # Generates the static HTML website +* RedCloth # Required by webgen +* syntax # Required by our own custom webgen extension to highlight ruby code +* diff-lcs # Required if you use the --diff switch +* win32console # Required by the --colour switch if you're on Windows +* meta_project # Required in order to make releases at RubyForge +* heckle # Required if you use the --heckle switch +* hpricot # Used for parsing HTML from the HTML output formatter in RSpec's own specs + +Once those are all installed, you should be able to run the suite with the following steps: + +* svn co svn://rubyforge.org/var/svn/rspec/trunk rspec +* cd rspec +* rake install_dependencies +* cd example_rails_app +* export RSPEC_RAILS_VERSION=1.2.3 +* rake rspec:generate_mysql_config +* mysql -u root < db/mysql_setup.sql +* cd .. +* rake pre_commit + + +Note that RSpec itself - once built - doesn't have any dependencies outside the Ruby core +and stdlib - with a few exceptions: + +* The spec command line uses diff-lcs when --diff is specified. +* The spec command line uses heckle when --heckle is specified. +* The Spec::Rake::SpecTask needs RCov if RCov is enabled in the task. + +See http://rspec.rubyforge.org for further documentation. diff --git a/vendor/gems/rspec/Rakefile b/vendor/gems/rspec/Rakefile new file mode 100644 index 000000000..24ed57963 --- /dev/null +++ b/vendor/gems/rspec/Rakefile @@ -0,0 +1,304 @@ +$:.unshift('lib') +require 'rubygems' +require 'rake/gempackagetask' +require 'rake/contrib/rubyforgepublisher' +require 'rake/clean' +require 'rake/rdoctask' +require 'spec/version' +dir = File.dirname(__FILE__) +$LOAD_PATH.unshift(File.expand_path("#{dir}/../pre_commit/lib")) +require "pre_commit" + +# Some of the tasks are in separate files since they are also part of the website documentation +load File.dirname(__FILE__) + '/rake_tasks/examples.rake' +load File.dirname(__FILE__) + '/rake_tasks/examples_specdoc.rake' +load File.dirname(__FILE__) + '/rake_tasks/examples_with_rcov.rake' +load File.dirname(__FILE__) + '/rake_tasks/failing_examples_with_html.rake' +load File.dirname(__FILE__) + '/rake_tasks/verify_rcov.rake' + +PKG_NAME = "rspec" +PKG_VERSION = Spec::VERSION::STRING +PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}" +PKG_FILES = FileList[ + '[A-Z]*', + 'lib/**/*.rb', + 'spec/**/*.rb', + 'examples/**/*', + 'plugins/**/*' +] +FileUtils.touch(File.dirname(__FILE__) + '/previous_failures.txt') + +task :default => [:verify_rcov] + +desc "Run all specs" +Spec::Rake::SpecTask.new do |t| + t.spec_files = FileList[ + 'spec/**/*_spec.rb', + '../RSpec.tmbundle/Support/spec/*_spec.rb' + # TODO: get these in too - need to fix coverage + # '../spec_ui/spec/**/*_spec.rb' + ] + t.spec_opts = ['--options', 'spec.opts'] + t.rcov = true + t.rcov_dir = '../doc/output/coverage' + t.rcov_opts = ['--exclude', 'spec\/spec,bin\/spec,examples'] +end + +desc "Run all translated specs" +Spec::Rake::SpecTask.new('translated_specs') do |t| + t.spec_files = FileList['translated_specs/**/*_spec.rb'].exclude( # These translate, but have other quirks + 'translated_specs/spec/translator_spec.rb', + 'translated_specs/spec/runner/formatter/html_formatter_spec.rb', + 'translated_specs/spec/runner/option_parser_spec.rb' + ) + t.spec_opts = ['--options', 'spec.opts'] + t.rcov = true + t.rcov_dir = '../doc/output/coverage' + t.rcov_opts = ['--exclude', 'spec\/spec,bin\/spec,examples'] +end + +desc "Run all specs and store html output in doc/output/report.html" +Spec::Rake::SpecTask.new('spec_html') do |t| + t.spec_files = FileList['spec/**/*_spec.rb', 'vendor/RSpec.tmbundle/Support/spec/*_spec.rb'] + t.spec_opts = ['--format html:../doc/output/report.html','--backtrace'] +end + +desc "Run all failing examples" +Spec::Rake::SpecTask.new('failing_examples') do |t| + t.spec_files = FileList['failing_examples/**/*_spec.rb'] +end + +desc 'Generate HTML documentation for website' +task :webgen do + core.webgen +end + +desc 'Generate RDoc' +rd = Rake::RDocTask.new do |rdoc| + rdoc.rdoc_dir = '../doc/output/rdoc' + rdoc.options << '--title' << 'RSpec' << '--line-numbers' << '--inline-source' << '--main' << 'README' + rdoc.rdoc_files.include('README', 'CHANGES', 'MIT-LICENSE', 'EXAMPLES.rd', 'UPGRADE', 'lib/**/*.rb') +end + +desc "Generate EXAMPLES.rb" +task :rdoc do + core.rdoc +end + +spec = Gem::Specification.new do |s| + s.name = PKG_NAME + s.version = PKG_VERSION + s.summary = Spec::VERSION::DESCRIPTION + s.description = <<-EOF + RSpec is a behaviour driven development (BDD) framework for Ruby. RSpec was + created in response to Dave Astels' article _A New Look at Test Driven Development_ + which can be read at: http://daveastels.com/index.php?p=5 RSpec is intended to + provide the features discussed in Dave's article. + EOF + + s.files = PKG_FILES.to_a + s.require_path = 'lib' + + s.has_rdoc = true + s.rdoc_options = rd.options + s.extra_rdoc_files = rd.rdoc_files.reject { |fn| fn =~ /\.rb$|^EXAMPLES.rd$/ }.to_a + + s.autorequire = 'spec' + s.bindir = 'bin' + s.executables = ['spec', 'spec_translator'] + s.default_executable = 'spec' + s.author = "RSpec Development Team" + s.email = "rspec-devel@rubyforge.org" + s.homepage = "http://rspec.rubyforge.org" + s.rubyforge_project = "rspec" +end + +Rake::GemPackageTask.new(spec) do |pkg| + pkg.need_zip = true + pkg.need_tar = true +end + +def egrep(pattern) + Dir['**/*.rb'].each do |fn| + count = 0 + open(fn) do |f| + while line = f.gets + count += 1 + if line =~ pattern + puts "#{fn}:#{count}:#{line}" + end + end + end + end +end + +desc "Look for TODO and FIXME tags in the code" +task :todo do + egrep /(FIXME|TODO|TBD)/ +end + +task :clobber do + core.clobber +end + +task :release => [:clobber, :verify_committed, :verify_user, :spec, :publish_packages, :tag, :publish_website, :publish_news] + +desc "Verifies that there is no uncommitted code" +task :verify_committed do + IO.popen('svn stat') do |io| + io.each_line do |line| + raise "\n!!! Do a svn commit first !!!\n\n" if line =~ /^\s*M\s*/ + end + end +end + +desc "Creates a tag in svn" +task :tag do + from = `svn info #{File.dirname(__FILE__)}`.match(/URL: (.*)\/rspec/n)[1] + to = from.gsub(/trunk/, "tags/#{Spec::VERSION::TAG}") + current = from.gsub(/trunk/, "tags/CURRENT") + + puts "Creating tag in SVN" + tag_cmd = "svn cp #{from} #{to} -m \"Tag release #{Spec::VERSION::FULL_VERSION}\"" + `#{tag_cmd}` ; raise "ERROR: #{tag_cmd}" unless $? == 0 + + puts "Removing CURRENT" + remove_current_cmd = "svn rm #{current} -m \"Remove tags/CURRENT\"" + `#{remove_current_cmd}` ; raise "ERROR: #{remove_current_cmd}" unless $? == 0 + + puts "Re-Creating CURRENT" + create_current_cmd = "svn cp #{to} #{current} -m \"Copy #{Spec::VERSION::TAG} to tags/CURRENT\"" + `#{create_current_cmd}` ; "ERROR: #{create_current_cmd}" unless $? == 0 +end + +desc "Run this task before you commit. You should see 'OK TO COMMIT'" +task(:pre_commit) {core.pre_commit} + +desc "Build the website, but do not publish it" +task(:website) {core.website} + +task :rdoc_rails do + core.rdoc_rails +end + +task :verify_user do + raise "RUBYFORGE_USER environment variable not set!" unless ENV['RUBYFORGE_USER'] +end + +desc "Upload Website to RubyForge" +task :publish_website => [:verify_user, :website] do + unless Spec::VERSION::RELEASE_CANDIDATE + publisher = Rake::SshDirPublisher.new( + "rspec-website@rubyforge.org", + "/var/www/gforge-projects/#{PKG_NAME}", + "../doc/output" + ) + publisher.upload + else + puts "** Not publishing packages to RubyForge - this is a prerelease" + end +end + +desc "Upload Website archive to RubyForge" +task :archive_website => [:verify_user, :website] do + publisher = Rake::SshDirPublisher.new( + "rspec-website@rubyforge.org", + "/var/www/gforge-projects/#{PKG_NAME}/#{Spec::VERSION::TAG}", + "../doc/output" + ) + publisher.upload +end + +desc "Package the Rails plugin" +task :package_rspec_on_rails do + mkdir 'pkg' rescue nil + rm_rf 'pkg/rspec_on_rails' rescue nil + `svn export ../rspec_on_rails pkg/rspec_on_rails-#{PKG_VERSION}` + Dir.chdir 'pkg' do + `tar cvzf rspec_on_rails-#{PKG_VERSION}.tgz rspec_on_rails-#{PKG_VERSION}` + end +end +task :pkg => :package_rspec_on_rails + +desc "Package the RSpec.tmbundle" +task :package_tmbundle do + mkdir 'pkg' rescue nil + rm_rf 'pkg/RSpec.tmbundle' rescue nil + `svn export ../RSpec.tmbundle pkg/RSpec.tmbundle` + Dir.chdir 'pkg' do + `tar cvzf RSpec-#{PKG_VERSION}.tmbundle.tgz RSpec.tmbundle` + end +end +task :pkg => :package_tmbundle + +desc "Package the Spec::Ui gem" +task :package_spec_ui do + Dir.chdir '../spec_ui' do + `rake clobber gem` + end +end +task :pkg => :package_spec_ui + +desc "Publish gem+tgz+zip on RubyForge. You must make sure lib/version.rb is aligned with the CHANGELOG file" +task :publish_packages => [:verify_user, :package] do + require File.dirname(__FILE__) + '/../spec_ui/lib/spec/ui/version' + release_files = FileList[ + "pkg/#{PKG_FILE_NAME}.gem", + "pkg/#{PKG_FILE_NAME}.tgz", + "pkg/rspec_on_rails-#{PKG_VERSION}.tgz", + "pkg/#{PKG_FILE_NAME}.zip", + "pkg/RSpec-#{PKG_VERSION}.tmbundle.tgz", + "../spec_ui/pkg/spec_ui-#{Spec::Ui::VERSION::STRING}.gem" + ] + unless Spec::VERSION::RELEASE_CANDIDATE + require 'meta_project' + require 'rake/contrib/xforge' + + Rake::XForge::Release.new(MetaProject::Project::XForge::RubyForge.new(PKG_NAME)) do |xf| + # Never hardcode user name and password in the Rakefile! + xf.user_name = ENV['RUBYFORGE_USER'] + xf.files = release_files.to_a + xf.release_name = "RSpec #{PKG_VERSION}" + end + else + puts "SINCE THIS IS A PRERELEASE, FILES ARE UPLOADED WITH SSH, NOT TO THE RUBYFORGE FILE SECTION" + puts "YOU MUST TYPE THE PASSWORD #{release_files.length} TIMES..." + + host = "rspec-website@rubyforge.org" + remote_dir = "/var/www/gforge-projects/#{PKG_NAME}" + + publisher = Rake::SshFilePublisher.new( + host, + remote_dir, + File.dirname(__FILE__), + *release_files + ) + publisher.upload + + puts "UPLADED THE FOLLOWING FILES:" + release_files.each do |file| + name = file.match(/pkg\/(.*)/)[1] + puts "* http://rspec.rubyforge.org/#{name}" + end + + puts "They are not linked to anywhere, so don't forget to tell people!" + end +end + +desc "Publish news on RubyForge" +task :publish_news => [:verify_user] do + unless Spec::VERSION::RELEASE_CANDIDATE + require 'meta_project' + require 'rake/contrib/xforge' + Rake::XForge::NewsPublisher.new(MetaProject::Project::XForge::RubyForge.new(PKG_NAME)) do |news| + # Never hardcode user name and password in the Rakefile! + news.user_name = ENV['RUBYFORGE_USER'] + end + else + puts "** Not publishing news to RubyForge - this is a prerelease" + end +end + +def core + PreCommit::Core.new(self) +end diff --git a/vendor/gems/rspec/UPGRADE b/vendor/gems/rspec/UPGRADE new file mode 100644 index 000000000..0a2c6f528 --- /dev/null +++ b/vendor/gems/rspec/UPGRADE @@ -0,0 +1,31 @@ += Upgrading existing code to RSpec-0.9 + +== General (see below for Spec::Rails specifics) + +=== New Syntax for should and should_not + +* Use translator (should get 90% of your code) +* Manually fix "parenthesis" warnings + +=== Change before_context_eval to before_eval + +before_context_eval is an un-published hook used by +Spec::Rails to create specialized behaviour contexts. +Most of you don't need to change this, but for those +who have exploited it, you'll need to change it to +before_eval. + +== Spec::Rails + +=== spec_helper.rb + +We've added a new way to configure Spec::Runner to do +things like use_transactional_fixtures and use_instantiated_fixtures. +You'll need to update spec/spec_helper.rb accordingly. You can either +just re-generate it: + + script/generate rspec + +Or modify spec_helper.rb based on the template, which can be found at: + + vendor/plugins/rspec_on_rails/generators/rspec/templates/spec_helper.rb
\ No newline at end of file diff --git a/spec/bin/spec b/vendor/gems/rspec/bin/spec index aaf320f34..a7e6ce0cb 100755 --- a/spec/bin/spec +++ b/vendor/gems/rspec/bin/spec @@ -1,4 +1,3 @@ -#!/usr/bin/env ruby $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib")) require 'spec' ::Spec::Runner::CommandLine.run(ARGV, STDERR, STDOUT, true, true) diff --git a/vendor/gems/rspec/bin/spec_translator b/vendor/gems/rspec/bin/spec_translator new file mode 100644 index 000000000..9df11dad2 --- /dev/null +++ b/vendor/gems/rspec/bin/spec_translator @@ -0,0 +1,8 @@ +#!/usr/bin/env ruby
+raise "\n\nUsage: spec_translator from_dir to_dir\n\n" if ARGV.size != 2
+$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
+require 'spec/translator'
+t = ::Spec::Translator.new
+from = ARGV[0]
+to = ARGV[1]
+t.translate(from, to)
diff --git a/vendor/gems/rspec/examples/auto_spec_description_example.rb b/vendor/gems/rspec/examples/auto_spec_description_example.rb new file mode 100644 index 000000000..a4928ef4a --- /dev/null +++ b/vendor/gems/rspec/examples/auto_spec_description_example.rb @@ -0,0 +1,19 @@ +require File.dirname(__FILE__) + '/spec_helper' + +# Run spec w/ -fs to see the output of this file + +describe "Examples with no descriptions" do + + # description is auto-generated as "should equal(5)" based on the last #should + it do + 3.should equal(3) + 5.should equal(5) + end + + it { 3.should be < 5 } + + it { ["a"].should include("a") } + + it { [1,2,3].should respond_to(:size) } + +end diff --git a/vendor/gems/rspec/examples/before_and_after_example.rb b/vendor/gems/rspec/examples/before_and_after_example.rb new file mode 100644 index 000000000..09e3805fb --- /dev/null +++ b/vendor/gems/rspec/examples/before_and_after_example.rb @@ -0,0 +1,39 @@ +$global = 0 + +describe "State created in before(:all)" do + before :all do + @sideeffect = 1 + $global +=1 + end + + before :each do + @isolated = 1 + end + + it "should be accessible from example" do + @sideeffect.should == 1 + $global.should == 1 + @isolated.should == 1 + + @sideeffect += 1 + @isolated += 1 + end + + it "should not have sideffects" do + @sideeffect.should == 1 + $global.should == 2 + @isolated.should == 1 + + @sideeffect += 1 + @isolated += 1 + end + + after :each do + $global += 1 + end + + after :all do + $global.should == 3 + $global = 0 + end +end diff --git a/vendor/gems/rspec/examples/behave_as_example.rb b/vendor/gems/rspec/examples/behave_as_example.rb new file mode 100644 index 000000000..e95d1469a --- /dev/null +++ b/vendor/gems/rspec/examples/behave_as_example.rb @@ -0,0 +1,45 @@ +require File.dirname(__FILE__) + '/spec_helper' + +def behave_as_electric_musician + respond_to(:read_notes, :turn_down_amp) +end + +def behave_as_musician + respond_to(:read_notes) +end + +module BehaveAsExample + + class BluesGuitarist + def read_notes; end + def turn_down_amp; end + end + + class RockGuitarist + def read_notes; end + def turn_down_amp; end + end + + class ClassicGuitarist + def read_notes; end + end + + describe BluesGuitarist do + it "should behave as guitarist" do + BluesGuitarist.new.should behave_as_electric_musician + end + end + + describe RockGuitarist do + it "should behave as guitarist" do + RockGuitarist.new.should behave_as_electric_musician + end + end + + describe ClassicGuitarist do + it "should not behave as guitarist" do + ClassicGuitarist.new.should behave_as_musician + end + end + +end diff --git a/vendor/gems/rspec/examples/custom_expectation_matchers.rb b/vendor/gems/rspec/examples/custom_expectation_matchers.rb new file mode 100644 index 000000000..075bb542d --- /dev/null +++ b/vendor/gems/rspec/examples/custom_expectation_matchers.rb @@ -0,0 +1,54 @@ +module AnimalSpecHelper + class Eat + def initialize(food) + @food = food + end + + def matches?(animal) + @animal = animal + @animal.eats?(@food) + end + + def failure_message + "expected #{@animal} to eat #{@food}, but it does not" + end + + def negative_failure_message + "expected #{@animal} not to eat #{@food}, but it does" + end + end + + def eat(food) + Eat.new(food) + end +end + +module Animals + class Animal + def eats?(food) + return foods_i_eat.include?(food) + end + end + + class Mouse < Animal + def foods_i_eat + [:cheese] + end + end + + describe Mouse do + include AnimalSpecHelper + before(:each) do + @mouse = Animals::Mouse.new + end + + it "should eat cheese" do + @mouse.should eat(:cheese) + end + + it "should not eat cat" do + @mouse.should_not eat(:cat) + end + end + +end diff --git a/vendor/gems/rspec/examples/custom_formatter.rb b/vendor/gems/rspec/examples/custom_formatter.rb new file mode 100644 index 000000000..851c9906f --- /dev/null +++ b/vendor/gems/rspec/examples/custom_formatter.rb @@ -0,0 +1,11 @@ +require 'spec/runner/formatter/progress_bar_formatter' + +# Example of a formatter with custom bactrace printing. Run me with: +# ruby bin/spec failing_examples -r examples/custom_formatter.rb -f CustomFormatter +class CustomFormatter < Spec::Runner::Formatter::ProgressBarFormatter + def backtrace_line(line) + line.gsub(/([^:]*\.rb):(\d*)/) do + "<a href=\"file://#{File.expand_path($1)}\">#{$1}:#{$2}</a> " + end + end +end diff --git a/vendor/gems/rspec/examples/dynamic_spec.rb b/vendor/gems/rspec/examples/dynamic_spec.rb new file mode 100644 index 000000000..15d473d61 --- /dev/null +++ b/vendor/gems/rspec/examples/dynamic_spec.rb @@ -0,0 +1,9 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "Some integers" do + (1..10).each do |n| + it "The root of #{n} square should be #{n}" do + Math.sqrt(n*n).should == n + end + end +end diff --git a/vendor/gems/rspec/examples/file_accessor.rb b/vendor/gems/rspec/examples/file_accessor.rb new file mode 100644 index 000000000..16bc45dbb --- /dev/null +++ b/vendor/gems/rspec/examples/file_accessor.rb @@ -0,0 +1,18 @@ +class FileAccessor + def open_and_handle_with(pathname, processor) + pathname.open do |io| + processor.process(io) + end + end +end + +if __FILE__ == $0 + require File.dirname(__FILE__) + '/io_processor' + require 'pathname' + + accessor = FileAccessor.new + io_processor = IoProcessor.new + file = Pathname.new ARGV[0] + + accessor.open_and_handle_with(file, io_processor) +end diff --git a/vendor/gems/rspec/examples/file_accessor_spec.rb b/vendor/gems/rspec/examples/file_accessor_spec.rb new file mode 100644 index 000000000..628d4c0b0 --- /dev/null +++ b/vendor/gems/rspec/examples/file_accessor_spec.rb @@ -0,0 +1,38 @@ +require File.dirname(__FILE__) + '/spec_helper' +require File.dirname(__FILE__) + '/file_accessor' +require 'stringio' + +describe "A FileAccessor" do + # This sequence diagram illustrates what this spec specifies. + # + # +--------------+ +----------+ +-------------+ + # | FileAccessor | | Pathname | | IoProcessor | + # +--------------+ +----------+ +-------------+ + # | | | + # open_and_handle_with | | | + # -------------------->| | open | | + # | |--------------->| | | + # | | io | | | + # | |<...............| | | + # | | | process(io) | + # | |---------------------------------->| | + # | | | | | + # | |<..................................| | + # | | | + # + it "should open a file and pass it to the processor's process method" do + # This is the primary actor + accessor = FileAccessor.new + + # These are the primary actor's neighbours, which we mock. + file = mock "Pathname" + io_processor = mock "IoProcessor" + + io = StringIO.new "whatever" + file.should_receive(:open).and_yield io + io_processor.should_receive(:process).with(io) + + accessor.open_and_handle_with(file, io_processor) + end + +end diff --git a/vendor/gems/rspec/examples/greeter_spec.rb b/vendor/gems/rspec/examples/greeter_spec.rb new file mode 100644 index 000000000..7d67e3187 --- /dev/null +++ b/vendor/gems/rspec/examples/greeter_spec.rb @@ -0,0 +1,30 @@ +# greeter.rb +# +# Based on http://glu.ttono.us/articles/2006/12/19/tormenting-your-tests-with-heckle +# +# Run with: +# +# spec greeter_spec.rb --heckle Greeter +# +class Greeter + def initialize(person = nil) + @person = person + end + + def greet + @person.nil? ? "Hi there!" : "Hi #{@person}!" + end +end + +describe "Greeter" do + it "should say Hi to person" do + greeter = Greeter.new("Kevin") + greeter.greet.should == "Hi Kevin!" + end + + it "should say Hi to nobody" do + greeter = Greeter.new + # Uncomment the next line to make Heckle happy + #greeter.greet.should == "Hi there!" + end +end diff --git a/vendor/gems/rspec/examples/helper_method_example.rb b/vendor/gems/rspec/examples/helper_method_example.rb new file mode 100644 index 000000000..5f94cf151 --- /dev/null +++ b/vendor/gems/rspec/examples/helper_method_example.rb @@ -0,0 +1,11 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "a context with helper a method" do + def helper_method + "received call" + end + + it "should make that method available to specs" do + helper_method.should == "received call" + end +end diff --git a/vendor/gems/rspec/examples/io_processor.rb b/vendor/gems/rspec/examples/io_processor.rb new file mode 100644 index 000000000..6b15147b6 --- /dev/null +++ b/vendor/gems/rspec/examples/io_processor.rb @@ -0,0 +1,8 @@ +class DataTooShort < StandardError; end + +class IoProcessor + # Does some fancy stuff unless the length of +io+ is shorter than 32 + def process(io) + raise DataTooShort if io.read.length < 32 + end +end diff --git a/vendor/gems/rspec/examples/io_processor_spec.rb b/vendor/gems/rspec/examples/io_processor_spec.rb new file mode 100644 index 000000000..5cab7bf31 --- /dev/null +++ b/vendor/gems/rspec/examples/io_processor_spec.rb @@ -0,0 +1,21 @@ +require File.dirname(__FILE__) + '/spec_helper' +require File.dirname(__FILE__) + '/io_processor' +require 'stringio' + +describe "An IoProcessor" do + before(:each) do + @processor = IoProcessor.new + end + + it "should raise nothing when the file is exactly 32 bytes" do + lambda { + @processor.process(StringIO.new("z"*32)) + }.should_not raise_error + end + + it "should raise an exception when the file length is less than 32 bytes" do + lambda { + @processor.process(StringIO.new("z"*31)) + }.should raise_error(DataTooShort) + end +end diff --git a/vendor/gems/rspec/examples/legacy_spec.rb b/vendor/gems/rspec/examples/legacy_spec.rb new file mode 100644 index 000000000..61669e7e6 --- /dev/null +++ b/vendor/gems/rspec/examples/legacy_spec.rb @@ -0,0 +1,10 @@ +context "A legacy spec" do + setup do + end + + specify "should work fine" do + end + + teardown do + end +end diff --git a/vendor/gems/rspec/examples/mocking_example.rb b/vendor/gems/rspec/examples/mocking_example.rb new file mode 100644 index 000000000..6adbef59d --- /dev/null +++ b/vendor/gems/rspec/examples/mocking_example.rb @@ -0,0 +1,27 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "A consumer of a mock" do + it "should be able to send messages to the mock" do + mock = mock("poke me") + mock.should_receive(:poke) + mock.poke + end +end + +describe "a mock" do + it "should be able to mock the same message twice w/ different args" do + mock = mock("mock") + mock.should_receive(:msg).with(:arg1).and_return(:val1) + mock.should_receive(:msg).with(:arg2).and_return(:val2) + mock.msg(:arg1).should eql(:val1) + mock.msg(:arg2).should eql(:val2) + end + + it "should be able to mock the same message twice w/ different args in reverse order" do + mock = mock("mock") + mock.should_receive(:msg).with(:arg1).and_return(:val1) + mock.should_receive(:msg).with(:arg2).and_return(:val2) + mock.msg(:arg2).should eql(:val2) + mock.msg(:arg1).should eql(:val1) + end +end diff --git a/vendor/gems/rspec/examples/multi_threaded_behaviour_runner.rb b/vendor/gems/rspec/examples/multi_threaded_behaviour_runner.rb new file mode 100644 index 000000000..e2824a61e --- /dev/null +++ b/vendor/gems/rspec/examples/multi_threaded_behaviour_runner.rb @@ -0,0 +1,25 @@ + +class MultiThreadedBehaviourRunner < Spec::Runner::BehaviourRunner + def initialize(options) + super + # configure these + @thread_count = 4 + @thread_wait = 0 + end + + def run_behaviours(behaviours) + @threads = [] + q = Queue.new + behaviours.each { |b| q << b} + @thread_count.times do + @threads << Thread.new(q) do |queue| + while not queue.empty? + behaviour = queue.pop + behaviour.run(@options.reporter, @options.dry_run, @options.reverse) + end + end + sleep @thread_wait + end + @threads.each {|t| t.join} + end +end diff --git a/vendor/gems/rspec/examples/partial_mock_example.rb b/vendor/gems/rspec/examples/partial_mock_example.rb new file mode 100644 index 000000000..841ec8847 --- /dev/null +++ b/vendor/gems/rspec/examples/partial_mock_example.rb @@ -0,0 +1,28 @@ +require File.dirname(__FILE__) + '/spec_helper' + +class MockableClass + def self.find id + return :original_return + end +end + +describe "A partial mock" do + + it "should work at the class level" do + MockableClass.should_receive(:find).with(1).and_return {:stub_return} + MockableClass.find(1).should equal(:stub_return) + end + + it "should revert to the original after each spec" do + MockableClass.find(1).should equal(:original_return) + end + + it "can be mocked w/ ordering" do + MockableClass.should_receive(:msg_1).ordered + MockableClass.should_receive(:msg_2).ordered + MockableClass.should_receive(:msg_3).ordered + MockableClass.msg_1 + MockableClass.msg_2 + MockableClass.msg_3 + end +end diff --git a/vendor/gems/rspec/examples/pending_example.rb b/vendor/gems/rspec/examples/pending_example.rb new file mode 100644 index 000000000..13f3d00c4 --- /dev/null +++ b/vendor/gems/rspec/examples/pending_example.rb @@ -0,0 +1,20 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "pending example (using pending method)" do + it %Q|should be reported as "PENDING: for some reason"| do + pending("for some reason") + end +end + +describe "pending example (with no block)" do + it %Q|should be reported as "PENDING: Not Yet Implemented"| +end + +describe "pending example (with block for pending)" do + it %Q|should have a failing block, passed to pending, reported as "PENDING: for some reason"| do + pending("for some reason") do + raise "some reason" + end + end +end + diff --git a/vendor/gems/rspec/examples/predicate_example.rb b/vendor/gems/rspec/examples/predicate_example.rb new file mode 100644 index 000000000..1202bb670 --- /dev/null +++ b/vendor/gems/rspec/examples/predicate_example.rb @@ -0,0 +1,27 @@ +require File.dirname(__FILE__) + '/spec_helper' + +class BddFramework + def intuitive? + true + end + + def adopted_quickly? + true + end +end + +describe "BDD framework" do + + before(:each) do + @bdd_framework = BddFramework.new + end + + it "should be adopted quickly" do + @bdd_framework.should be_adopted_quickly + end + + it "should be intuitive" do + @bdd_framework.should be_intuitive + end + +end diff --git a/vendor/gems/rspec/examples/priority.txt b/vendor/gems/rspec/examples/priority.txt new file mode 100644 index 000000000..5b00064e2 --- /dev/null +++ b/vendor/gems/rspec/examples/priority.txt @@ -0,0 +1 @@ +examples/custom_expectation_matchers.rb
\ No newline at end of file diff --git a/vendor/gems/rspec/examples/shared_behaviours_example.rb b/vendor/gems/rspec/examples/shared_behaviours_example.rb new file mode 100644 index 000000000..33c924643 --- /dev/null +++ b/vendor/gems/rspec/examples/shared_behaviours_example.rb @@ -0,0 +1,39 @@ +require File.dirname(__FILE__) + '/spec_helper' + +module SharedBehaviourExample + class OneThing + def what_things_do + "stuff" + end + end + + class AnotherThing + def what_things_do + "stuff" + end + end + + describe "All Things", :shared => true do + def helper_method + "helper method" + end + + it "should do what things do" do + @thing.what_things_do.should == "stuff" + end + end + + describe OneThing do + it_should_behave_like "All Things" + before(:each) { @thing = OneThing.new } + + it "should have access to helper methods defined in the shared behaviour" do + helper_method.should == "helper method" + end + end + + describe AnotherThing do + it_should_behave_like "All Things" + before(:each) { @thing = AnotherThing.new } + end +end diff --git a/vendor/gems/rspec/examples/spec_helper.rb b/vendor/gems/rspec/examples/spec_helper.rb new file mode 100644 index 000000000..61f51fbdb --- /dev/null +++ b/vendor/gems/rspec/examples/spec_helper.rb @@ -0,0 +1 @@ +require File.dirname(__FILE__) + '/../lib/spec' diff --git a/vendor/gems/rspec/examples/stack.rb b/vendor/gems/rspec/examples/stack.rb new file mode 100644 index 000000000..407173f7b --- /dev/null +++ b/vendor/gems/rspec/examples/stack.rb @@ -0,0 +1,36 @@ +class StackUnderflowError < RuntimeError +end + +class StackOverflowError < RuntimeError +end + +class Stack + + def initialize + @items = [] + end + + def push object + raise StackOverflowError if @items.length == 10 + @items.push object + end + + def pop + raise StackUnderflowError if @items.empty? + @items.delete @items.last + end + + def peek + raise StackUnderflowError if @items.empty? + @items.last + end + + def empty? + @items.empty? + end + + def full? + @items.length == 10 + end + +end diff --git a/vendor/gems/rspec/examples/stack_spec.rb b/vendor/gems/rspec/examples/stack_spec.rb new file mode 100644 index 000000000..22d8a652b --- /dev/null +++ b/vendor/gems/rspec/examples/stack_spec.rb @@ -0,0 +1,97 @@ +require File.dirname(__FILE__) + '/spec_helper' +require File.dirname(__FILE__) + "/stack" + +describe "non-empty Stack", :shared => true do + # NOTE that this one auto-generates the description "should not be empty" + it { @stack.should_not be_empty } + + it "should return the top item when sent #peek" do + @stack.peek.should == @last_item_added + end + + it "should NOT remove the top item when sent #peek" do + @stack.peek.should == @last_item_added + @stack.peek.should == @last_item_added + end + + it "should return the top item when sent #pop" do + @stack.pop.should == @last_item_added + end + + it "should remove the top item when sent #pop" do + @stack.pop.should == @last_item_added + unless @stack.empty? + @stack.pop.should_not == @last_item_added + end + end +end + +describe "non-full Stack", :shared => true do + # NOTE that this one auto-generates the description "should not be full" + it { @stack.should_not be_full } + + it "should add to the top when sent #push" do + @stack.push "newly added top item" + @stack.peek.should == "newly added top item" + end +end + +describe Stack, " (empty)" do + before(:each) do + @stack = Stack.new + end + + # NOTE that this one auto-generates the description "should be empty" + it { @stack.should be_empty } + + it_should_behave_like "non-full Stack" + + it "should complain when sent #peek" do + lambda { @stack.peek }.should raise_error(StackUnderflowError) + end + + it "should complain when sent #pop" do + lambda { @stack.pop }.should raise_error(StackUnderflowError) + end +end + +describe Stack, " (with one item)" do + before(:each) do + @stack = Stack.new + @stack.push 3 + @last_item_added = 3 + end + + it_should_behave_like "non-empty Stack" + it_should_behave_like "non-full Stack" + +end + +describe Stack, " (with one item less than capacity)" do + before(:each) do + @stack = Stack.new + (1..9).each { |i| @stack.push i } + @last_item_added = 9 + end + + it_should_behave_like "non-empty Stack" + it_should_behave_like "non-full Stack" +end + +describe Stack, " (full)" do + before(:each) do + @stack = Stack.new + (1..10).each { |i| @stack.push i } + @last_item_added = 10 + end + + # NOTE that this one auto-generates the description "should be full" + it { @stack.should be_full } + + it_should_behave_like "non-empty Stack" + + it "should complain on #push" do + lambda { @stack.push Object.new }.should raise_error(StackOverflowError) + end + +end diff --git a/vendor/gems/rspec/examples/stubbing_example.rb b/vendor/gems/rspec/examples/stubbing_example.rb new file mode 100644 index 000000000..31354aec6 --- /dev/null +++ b/vendor/gems/rspec/examples/stubbing_example.rb @@ -0,0 +1,69 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "A consumer of a stub" do + it "should be able to stub methods on any Object" do + obj = Object.new + obj.stub!(:foobar).and_return {:return_value} + obj.foobar.should equal(:return_value) + end +end + +class StubbableClass + def self.find id + return :original_return + end +end + +describe "A stubbed method on a class" do + it "should return the stubbed value" do + StubbableClass.stub!(:find).and_return(:stub_return) + StubbableClass.find(1).should equal(:stub_return) + end + + it "should revert to the original method after each spec" do + StubbableClass.find(1).should equal(:original_return) + end + + it "can stub! and mock the same message" do + StubbableClass.stub!(:msg).and_return(:stub_value) + StubbableClass.should_receive(:msg).with(:arg).and_return(:mock_value) + + StubbableClass.msg.should equal(:stub_value) + StubbableClass.msg(:other_arg).should equal(:stub_value) + StubbableClass.msg(:arg).should equal(:mock_value) + StubbableClass.msg(:another_arg).should equal(:stub_value) + StubbableClass.msg(:yet_another_arg).should equal(:stub_value) + StubbableClass.msg.should equal(:stub_value) + end +end + +describe "A mock" do + it "can stub!" do + mock = mock("stubbing mock") + mock.stub!(:msg).and_return(:value) + (1..10).each {mock.msg.should equal(:value)} + end + + it "can stub! and mock" do + mock = mock("stubbing mock") + mock.stub!(:stub_message).and_return(:stub_value) + mock.should_receive(:mock_message).once.and_return(:mock_value) + (1..10).each {mock.stub_message.should equal(:stub_value)} + mock.mock_message.should equal(:mock_value) + (1..10).each {mock.stub_message.should equal(:stub_value)} + end + + it "can stub! and mock the same message" do + mock = mock("stubbing mock") + mock.stub!(:msg).and_return(:stub_value) + mock.should_receive(:msg).with(:arg).and_return(:mock_value) + mock.msg.should equal(:stub_value) + mock.msg(:other_arg).should equal(:stub_value) + mock.msg(:arg).should equal(:mock_value) + mock.msg(:another_arg).should equal(:stub_value) + mock.msg(:yet_another_arg).should equal(:stub_value) + mock.msg.should equal(:stub_value) + end +end + + diff --git a/vendor/gems/rspec/examples/test_case_adapter_example.rb b/vendor/gems/rspec/examples/test_case_adapter_example.rb new file mode 100644 index 000000000..02ba3be17 --- /dev/null +++ b/vendor/gems/rspec/examples/test_case_adapter_example.rb @@ -0,0 +1,26 @@ +#This is an example of using RSpec's expectations in test/unit. +$LOAD_PATH.unshift File.join(File.dirname(__FILE__), "..", "lib") + +require 'test/unit' +require 'spec/test_case_adapter' + +class IntegratingRSpecExpectationsIntoTestCaseTest < Test::Unit::TestCase + + def test_should_support_rspecs_equality_expectations + 5.should == 5 + end + + def test_should_support_rspecs_comparison_expectations + 5.should be > 4 + end + + class Band + def players + ["John", "Paul", "George", "Ringo"] + end + end + + def test_should_support_rspecs_collection_expectations + Band.new.should have(4).players + end +end diff --git a/vendor/gems/rspec/examples/test_case_spec.rb b/vendor/gems/rspec/examples/test_case_spec.rb new file mode 100644 index 000000000..4ffa2c598 --- /dev/null +++ b/vendor/gems/rspec/examples/test_case_spec.rb @@ -0,0 +1,65 @@ +require File.dirname(__FILE__) + '/spec_helper' +require 'test/unit' + +class RSpecIntegrationTest < Test::Unit::TestCase + def self.fixtures(*args) + @@fixtures = true + end + + def self.verify_class_method + @@fixtures.should == true + end + + def setup + @test_case_setup_called = true + end + + def teardown + @test_case_teardown_called = true + end + + def run(result) + end + + def helper_method + @helper_method_called = true + end +end + +module RandomHelperModule + def random_task + @random_task_called = true + end +end + +describe "RSpec should integrate with Test::Unit::TestCase" do + inherit RSpecIntegrationTest + include RandomHelperModule + + fixtures :some_table + + prepend_before(:each) {setup} + + before(:each) do + @rspec_setup_called = true + end + + it "TestCase#setup should be called." do + @test_case_setup_called.should be_true + @rspec_setup_called.should be_true + end + + it "RSpec should be able to access TestCase methods" do + helper_method + @helper_method_called.should be_true + end + + it "RSpec should be able to accept included modules" do + random_task + @random_task_called.should be_true + end + + after(:each) do + RSpecIntegrationTest.verify_class_method + end +end diff --git a/vendor/gems/rspec/lib/autotest/discover.rb b/vendor/gems/rspec/lib/autotest/discover.rb new file mode 100644 index 000000000..81914c3b7 --- /dev/null +++ b/vendor/gems/rspec/lib/autotest/discover.rb @@ -0,0 +1,3 @@ +Autotest.add_discovery do + "rspec" if File.exist?('spec') +end diff --git a/vendor/gems/rspec/lib/autotest/rspec.rb b/vendor/gems/rspec/lib/autotest/rspec.rb new file mode 100644 index 000000000..d4b77ea6b --- /dev/null +++ b/vendor/gems/rspec/lib/autotest/rspec.rb @@ -0,0 +1,95 @@ +require 'autotest' + +class RspecCommandError < StandardError; end + +class Autotest::Rspec < Autotest + + def initialize(kernel=Kernel, separator=File::SEPARATOR, alt_separator=File::ALT_SEPARATOR) # :nodoc: + super() + @kernel, @separator, @alt_separator = kernel, separator, alt_separator + @spec_command = spec_command + + # watch out: Ruby bug (1.8.6): + # %r(/) != /\// + # since Ruby compares the REGEXP source, not the resulting pattern + @test_mappings = { + %r%^spec/.*\.rb$% => kernel.proc { |filename, _| + filename + }, + %r%^lib/(.*)\.rb$% => kernel.proc { |_, m| + ["spec/#{m[1]}_spec.rb"] + }, + %r%^spec/(spec_helper|shared/.*)\.rb$% => kernel.proc { + files_matching %r%^spec/.*_spec\.rb$% + } + } + end + + def tests_for_file(filename) + super.select { |f| @files.has_key? f } + end + + alias :specs_for_file :tests_for_file + + def failed_results(results) + results.scan(/^\d+\)\n(?:\e\[\d*m)?(?:.*?Error in )?'([^\n]*)'(?: FAILED)?(?:\e\[\d*m)?\n(.*?)\n\n/m) + end + + def handle_results(results) + @files_to_test = consolidate_failures failed_results(results) + unless @files_to_test.empty? then + hook :red + else + hook :green + end unless $TESTING + @tainted = true unless @files_to_test.empty? + end + + def consolidate_failures(failed) + filters = Hash.new { |h,k| h[k] = [] } + failed.each do |spec, failed_trace| + @files.keys.select{|f| f =~ /spec\//}.each do |f| + if failed_trace =~ Regexp.new(f) + filters[f] << spec + break + end + end + end + return filters + end + + def make_test_cmd(files_to_test) + return "#{ruby} -S #{@spec_command} #{add_options_if_present} #{files_to_test.keys.flatten.join(' ')}" + end + + def add_options_if_present + File.exist?("spec/spec.opts") ? "-O spec/spec.opts " : "" + end + + # Finds the proper spec command to use. Precendence + # is set in the lazily-evaluated method spec_commands. Alias + Override + # that in ~/.autotest to provide a different spec command + # then the default paths provided. + def spec_command + spec_commands.each do |command| + if File.exists?(command) + return @alt_separator ? (command.gsub @separator, @alt_separator) : command + end + end + + raise RspecCommandError, "No spec command could be found!" + end + + # Autotest will look for spec commands in the following + # locations, in this order: + # + # * bin/spec + # * default spec bin/loader installed in Rubygems + def spec_commands + [ + File.join('bin', 'spec'), + File.join(Config::CONFIG['bindir'], 'spec') + ] + end + +end diff --git a/spec/lib/spec.rb b/vendor/gems/rspec/lib/spec.rb index 48c12595c..48c12595c 100644 --- a/spec/lib/spec.rb +++ b/vendor/gems/rspec/lib/spec.rb diff --git a/spec/lib/spec/dsl.rb b/vendor/gems/rspec/lib/spec/dsl.rb index f960eb907..f960eb907 100644 --- a/spec/lib/spec/dsl.rb +++ b/vendor/gems/rspec/lib/spec/dsl.rb diff --git a/spec/lib/spec/dsl/behaviour.rb b/vendor/gems/rspec/lib/spec/dsl/behaviour.rb index cc71ccffe..5158bb673 100644 --- a/spec/lib/spec/dsl/behaviour.rb +++ b/vendor/gems/rspec/lib/spec/dsl/behaviour.rb @@ -1,7 +1,6 @@ -require(File.expand_path(File.dirname(__FILE__) + '../../../../../test/lib/puppettest/runnable_test.rb')) - module Spec module DSL + class EvalModule < Module; end class Behaviour extend BehaviourCallbacks diff --git a/spec/lib/spec/dsl/behaviour_callbacks.rb b/vendor/gems/rspec/lib/spec/dsl/behaviour_callbacks.rb index 8b69ad9e5..8b69ad9e5 100644 --- a/spec/lib/spec/dsl/behaviour_callbacks.rb +++ b/vendor/gems/rspec/lib/spec/dsl/behaviour_callbacks.rb diff --git a/spec/lib/spec/dsl/behaviour_eval.rb b/vendor/gems/rspec/lib/spec/dsl/behaviour_eval.rb index 9f7b8281e..9f7b8281e 100644 --- a/spec/lib/spec/dsl/behaviour_eval.rb +++ b/vendor/gems/rspec/lib/spec/dsl/behaviour_eval.rb diff --git a/spec/lib/spec/dsl/behaviour_factory.rb b/vendor/gems/rspec/lib/spec/dsl/behaviour_factory.rb index 44b60c641..44b60c641 100755..100644 --- a/spec/lib/spec/dsl/behaviour_factory.rb +++ b/vendor/gems/rspec/lib/spec/dsl/behaviour_factory.rb diff --git a/spec/lib/spec/dsl/composite_proc_builder.rb b/vendor/gems/rspec/lib/spec/dsl/composite_proc_builder.rb index 373f44953..373f44953 100644 --- a/spec/lib/spec/dsl/composite_proc_builder.rb +++ b/vendor/gems/rspec/lib/spec/dsl/composite_proc_builder.rb diff --git a/spec/lib/spec/dsl/configuration.rb b/vendor/gems/rspec/lib/spec/dsl/configuration.rb index 709574ded..709574ded 100755..100644 --- a/spec/lib/spec/dsl/configuration.rb +++ b/vendor/gems/rspec/lib/spec/dsl/configuration.rb diff --git a/spec/lib/spec/dsl/description.rb b/vendor/gems/rspec/lib/spec/dsl/description.rb index fe8c9b0c9..fe8c9b0c9 100755..100644 --- a/spec/lib/spec/dsl/description.rb +++ b/vendor/gems/rspec/lib/spec/dsl/description.rb diff --git a/spec/lib/spec/dsl/errors.rb b/vendor/gems/rspec/lib/spec/dsl/errors.rb index ba7046a89..ba7046a89 100644 --- a/spec/lib/spec/dsl/errors.rb +++ b/vendor/gems/rspec/lib/spec/dsl/errors.rb diff --git a/spec/lib/spec/dsl/example.rb b/vendor/gems/rspec/lib/spec/dsl/example.rb index d04073f7e..d04073f7e 100644 --- a/spec/lib/spec/dsl/example.rb +++ b/vendor/gems/rspec/lib/spec/dsl/example.rb diff --git a/spec/lib/spec/dsl/example_matcher.rb b/vendor/gems/rspec/lib/spec/dsl/example_matcher.rb index 18cc47409..18cc47409 100755..100644 --- a/spec/lib/spec/dsl/example_matcher.rb +++ b/vendor/gems/rspec/lib/spec/dsl/example_matcher.rb diff --git a/spec/lib/spec/dsl/example_should_raise_handler.rb b/vendor/gems/rspec/lib/spec/dsl/example_should_raise_handler.rb index 942327317..942327317 100644 --- a/spec/lib/spec/dsl/example_should_raise_handler.rb +++ b/vendor/gems/rspec/lib/spec/dsl/example_should_raise_handler.rb diff --git a/spec/lib/spec/expectations.rb b/vendor/gems/rspec/lib/spec/expectations.rb index 65ea47425..65ea47425 100644 --- a/spec/lib/spec/expectations.rb +++ b/vendor/gems/rspec/lib/spec/expectations.rb diff --git a/spec/lib/spec/expectations/differs/default.rb b/vendor/gems/rspec/lib/spec/expectations/differs/default.rb index 87e59b3a6..87e59b3a6 100644 --- a/spec/lib/spec/expectations/differs/default.rb +++ b/vendor/gems/rspec/lib/spec/expectations/differs/default.rb diff --git a/spec/lib/spec/expectations/errors.rb b/vendor/gems/rspec/lib/spec/expectations/errors.rb index 03e81a064..03e81a064 100644 --- a/spec/lib/spec/expectations/errors.rb +++ b/vendor/gems/rspec/lib/spec/expectations/errors.rb diff --git a/spec/lib/spec/expectations/extensions.rb b/vendor/gems/rspec/lib/spec/expectations/extensions.rb index 60c9b9e7d..60c9b9e7d 100644 --- a/spec/lib/spec/expectations/extensions.rb +++ b/vendor/gems/rspec/lib/spec/expectations/extensions.rb diff --git a/spec/lib/spec/expectations/extensions/object.rb b/vendor/gems/rspec/lib/spec/expectations/extensions/object.rb index f59af722e..f59af722e 100644 --- a/spec/lib/spec/expectations/extensions/object.rb +++ b/vendor/gems/rspec/lib/spec/expectations/extensions/object.rb diff --git a/spec/lib/spec/expectations/extensions/string_and_symbol.rb b/vendor/gems/rspec/lib/spec/expectations/extensions/string_and_symbol.rb index 29cfbddfa..29cfbddfa 100644 --- a/spec/lib/spec/expectations/extensions/string_and_symbol.rb +++ b/vendor/gems/rspec/lib/spec/expectations/extensions/string_and_symbol.rb diff --git a/spec/lib/spec/expectations/handler.rb b/vendor/gems/rspec/lib/spec/expectations/handler.rb index 4caa321e4..4caa321e4 100644 --- a/spec/lib/spec/expectations/handler.rb +++ b/vendor/gems/rspec/lib/spec/expectations/handler.rb diff --git a/spec/lib/spec/extensions.rb b/vendor/gems/rspec/lib/spec/extensions.rb index 824f03bfb..824f03bfb 100755..100644 --- a/spec/lib/spec/extensions.rb +++ b/vendor/gems/rspec/lib/spec/extensions.rb diff --git a/spec/lib/spec/extensions/object.rb b/vendor/gems/rspec/lib/spec/extensions/object.rb index 6218aa770..6218aa770 100755..100644 --- a/spec/lib/spec/extensions/object.rb +++ b/vendor/gems/rspec/lib/spec/extensions/object.rb diff --git a/spec/lib/spec/matchers.rb b/vendor/gems/rspec/lib/spec/matchers.rb index fd208d628..fd208d628 100644 --- a/spec/lib/spec/matchers.rb +++ b/vendor/gems/rspec/lib/spec/matchers.rb diff --git a/spec/lib/spec/matchers/be.rb b/vendor/gems/rspec/lib/spec/matchers/be.rb index 0eb1629a6..0eb1629a6 100644 --- a/spec/lib/spec/matchers/be.rb +++ b/vendor/gems/rspec/lib/spec/matchers/be.rb diff --git a/spec/lib/spec/matchers/be_close.rb b/vendor/gems/rspec/lib/spec/matchers/be_close.rb index 7763eb97e..7763eb97e 100644 --- a/spec/lib/spec/matchers/be_close.rb +++ b/vendor/gems/rspec/lib/spec/matchers/be_close.rb diff --git a/spec/lib/spec/matchers/change.rb b/vendor/gems/rspec/lib/spec/matchers/change.rb index 41a718aca..41a718aca 100644 --- a/spec/lib/spec/matchers/change.rb +++ b/vendor/gems/rspec/lib/spec/matchers/change.rb diff --git a/spec/lib/spec/matchers/eql.rb b/vendor/gems/rspec/lib/spec/matchers/eql.rb index 280ca5454..280ca5454 100644 --- a/spec/lib/spec/matchers/eql.rb +++ b/vendor/gems/rspec/lib/spec/matchers/eql.rb diff --git a/spec/lib/spec/matchers/equal.rb b/vendor/gems/rspec/lib/spec/matchers/equal.rb index 4bfc74951..4bfc74951 100644 --- a/spec/lib/spec/matchers/equal.rb +++ b/vendor/gems/rspec/lib/spec/matchers/equal.rb diff --git a/spec/lib/spec/matchers/has.rb b/vendor/gems/rspec/lib/spec/matchers/has.rb index cc5a250b8..cc5a250b8 100644 --- a/spec/lib/spec/matchers/has.rb +++ b/vendor/gems/rspec/lib/spec/matchers/has.rb diff --git a/spec/lib/spec/matchers/have.rb b/vendor/gems/rspec/lib/spec/matchers/have.rb index f28b86ad3..f28b86ad3 100644 --- a/spec/lib/spec/matchers/have.rb +++ b/vendor/gems/rspec/lib/spec/matchers/have.rb diff --git a/spec/lib/spec/matchers/include.rb b/vendor/gems/rspec/lib/spec/matchers/include.rb index 5476f97d8..5476f97d8 100644 --- a/spec/lib/spec/matchers/include.rb +++ b/vendor/gems/rspec/lib/spec/matchers/include.rb diff --git a/spec/lib/spec/matchers/match.rb b/vendor/gems/rspec/lib/spec/matchers/match.rb index 61ab52429..61ab52429 100644 --- a/spec/lib/spec/matchers/match.rb +++ b/vendor/gems/rspec/lib/spec/matchers/match.rb diff --git a/spec/lib/spec/matchers/operator_matcher.rb b/vendor/gems/rspec/lib/spec/matchers/operator_matcher.rb index 2d47ea85a..2d47ea85a 100755..100644 --- a/spec/lib/spec/matchers/operator_matcher.rb +++ b/vendor/gems/rspec/lib/spec/matchers/operator_matcher.rb diff --git a/spec/lib/spec/matchers/raise_error.rb b/vendor/gems/rspec/lib/spec/matchers/raise_error.rb index b45dcf65c..b45dcf65c 100644 --- a/spec/lib/spec/matchers/raise_error.rb +++ b/vendor/gems/rspec/lib/spec/matchers/raise_error.rb diff --git a/spec/lib/spec/matchers/respond_to.rb b/vendor/gems/rspec/lib/spec/matchers/respond_to.rb index 3d23422aa..3d23422aa 100644 --- a/spec/lib/spec/matchers/respond_to.rb +++ b/vendor/gems/rspec/lib/spec/matchers/respond_to.rb diff --git a/spec/lib/spec/matchers/satisfy.rb b/vendor/gems/rspec/lib/spec/matchers/satisfy.rb index 6c0ca95bc..6c0ca95bc 100644 --- a/spec/lib/spec/matchers/satisfy.rb +++ b/vendor/gems/rspec/lib/spec/matchers/satisfy.rb diff --git a/spec/lib/spec/matchers/throw_symbol.rb b/vendor/gems/rspec/lib/spec/matchers/throw_symbol.rb index 6d047bc39..6d047bc39 100644 --- a/spec/lib/spec/matchers/throw_symbol.rb +++ b/vendor/gems/rspec/lib/spec/matchers/throw_symbol.rb diff --git a/spec/lib/spec/mocks.rb b/vendor/gems/rspec/lib/spec/mocks.rb index 66cbafb3c..66cbafb3c 100644 --- a/spec/lib/spec/mocks.rb +++ b/vendor/gems/rspec/lib/spec/mocks.rb diff --git a/spec/lib/spec/mocks/argument_constraint_matchers.rb b/vendor/gems/rspec/lib/spec/mocks/argument_constraint_matchers.rb index 0e4777082..0e4777082 100644 --- a/spec/lib/spec/mocks/argument_constraint_matchers.rb +++ b/vendor/gems/rspec/lib/spec/mocks/argument_constraint_matchers.rb diff --git a/spec/lib/spec/mocks/argument_expectation.rb b/vendor/gems/rspec/lib/spec/mocks/argument_expectation.rb index 5da069b87..5da069b87 100644 --- a/spec/lib/spec/mocks/argument_expectation.rb +++ b/vendor/gems/rspec/lib/spec/mocks/argument_expectation.rb diff --git a/spec/lib/spec/mocks/error_generator.rb b/vendor/gems/rspec/lib/spec/mocks/error_generator.rb index 01d8f720d..01d8f720d 100644 --- a/spec/lib/spec/mocks/error_generator.rb +++ b/vendor/gems/rspec/lib/spec/mocks/error_generator.rb diff --git a/spec/lib/spec/mocks/errors.rb b/vendor/gems/rspec/lib/spec/mocks/errors.rb index 68fdfe006..68fdfe006 100644 --- a/spec/lib/spec/mocks/errors.rb +++ b/vendor/gems/rspec/lib/spec/mocks/errors.rb diff --git a/spec/lib/spec/mocks/extensions/object.rb b/vendor/gems/rspec/lib/spec/mocks/extensions/object.rb index 4b7531066..4b7531066 100644 --- a/spec/lib/spec/mocks/extensions/object.rb +++ b/vendor/gems/rspec/lib/spec/mocks/extensions/object.rb diff --git a/spec/lib/spec/mocks/message_expectation.rb b/vendor/gems/rspec/lib/spec/mocks/message_expectation.rb index 74ade3c58..74ade3c58 100644 --- a/spec/lib/spec/mocks/message_expectation.rb +++ b/vendor/gems/rspec/lib/spec/mocks/message_expectation.rb diff --git a/spec/lib/spec/mocks/methods.rb b/vendor/gems/rspec/lib/spec/mocks/methods.rb index 3d898cf31..3d898cf31 100644 --- a/spec/lib/spec/mocks/methods.rb +++ b/vendor/gems/rspec/lib/spec/mocks/methods.rb diff --git a/spec/lib/spec/mocks/mock.rb b/vendor/gems/rspec/lib/spec/mocks/mock.rb index aa380e0af..aa380e0af 100644 --- a/spec/lib/spec/mocks/mock.rb +++ b/vendor/gems/rspec/lib/spec/mocks/mock.rb diff --git a/spec/lib/spec/mocks/order_group.rb b/vendor/gems/rspec/lib/spec/mocks/order_group.rb index 9983207eb..9983207eb 100644 --- a/spec/lib/spec/mocks/order_group.rb +++ b/vendor/gems/rspec/lib/spec/mocks/order_group.rb diff --git a/spec/lib/spec/mocks/proxy.rb b/vendor/gems/rspec/lib/spec/mocks/proxy.rb index 6c79d1068..6c79d1068 100644 --- a/spec/lib/spec/mocks/proxy.rb +++ b/vendor/gems/rspec/lib/spec/mocks/proxy.rb diff --git a/spec/lib/spec/mocks/space.rb b/vendor/gems/rspec/lib/spec/mocks/space.rb index e04bc5ccb..e04bc5ccb 100644 --- a/spec/lib/spec/mocks/space.rb +++ b/vendor/gems/rspec/lib/spec/mocks/space.rb diff --git a/spec/lib/spec/mocks/spec_methods.rb b/vendor/gems/rspec/lib/spec/mocks/spec_methods.rb index fd67fd210..fd67fd210 100644 --- a/spec/lib/spec/mocks/spec_methods.rb +++ b/vendor/gems/rspec/lib/spec/mocks/spec_methods.rb diff --git a/spec/lib/spec/rake/spectask.rb b/vendor/gems/rspec/lib/spec/rake/spectask.rb index f8c6809a9..f8c6809a9 100644 --- a/spec/lib/spec/rake/spectask.rb +++ b/vendor/gems/rspec/lib/spec/rake/spectask.rb diff --git a/spec/lib/spec/rake/verify_rcov.rb b/vendor/gems/rspec/lib/spec/rake/verify_rcov.rb index 9715744e9..9715744e9 100644 --- a/spec/lib/spec/rake/verify_rcov.rb +++ b/vendor/gems/rspec/lib/spec/rake/verify_rcov.rb diff --git a/spec/lib/spec/runner.rb b/vendor/gems/rspec/lib/spec/runner.rb index 9d801adc3..9d801adc3 100644 --- a/spec/lib/spec/runner.rb +++ b/vendor/gems/rspec/lib/spec/runner.rb diff --git a/spec/lib/spec/runner/backtrace_tweaker.rb b/vendor/gems/rspec/lib/spec/runner/backtrace_tweaker.rb index aacc2c8b8..aacc2c8b8 100644 --- a/spec/lib/spec/runner/backtrace_tweaker.rb +++ b/vendor/gems/rspec/lib/spec/runner/backtrace_tweaker.rb diff --git a/spec/lib/spec/runner/behaviour_runner.rb b/vendor/gems/rspec/lib/spec/runner/behaviour_runner.rb index 1ac891f3c..1ac891f3c 100644 --- a/spec/lib/spec/runner/behaviour_runner.rb +++ b/vendor/gems/rspec/lib/spec/runner/behaviour_runner.rb diff --git a/spec/lib/spec/runner/command_line.rb b/vendor/gems/rspec/lib/spec/runner/command_line.rb index 0d70337e1..0d70337e1 100644 --- a/spec/lib/spec/runner/command_line.rb +++ b/vendor/gems/rspec/lib/spec/runner/command_line.rb diff --git a/spec/lib/spec/runner/drb_command_line.rb b/vendor/gems/rspec/lib/spec/runner/drb_command_line.rb index 7e745fb71..7e745fb71 100644 --- a/spec/lib/spec/runner/drb_command_line.rb +++ b/vendor/gems/rspec/lib/spec/runner/drb_command_line.rb diff --git a/spec/lib/spec/runner/extensions/kernel.rb b/vendor/gems/rspec/lib/spec/runner/extensions/kernel.rb index 75f2c335e..75f2c335e 100644 --- a/spec/lib/spec/runner/extensions/kernel.rb +++ b/vendor/gems/rspec/lib/spec/runner/extensions/kernel.rb diff --git a/spec/lib/spec/runner/extensions/object.rb b/vendor/gems/rspec/lib/spec/runner/extensions/object.rb index 49745352f..49745352f 100644 --- a/spec/lib/spec/runner/extensions/object.rb +++ b/vendor/gems/rspec/lib/spec/runner/extensions/object.rb diff --git a/spec/lib/spec/runner/formatter.rb b/vendor/gems/rspec/lib/spec/runner/formatter.rb index 17512d958..17512d958 100644 --- a/spec/lib/spec/runner/formatter.rb +++ b/vendor/gems/rspec/lib/spec/runner/formatter.rb diff --git a/spec/lib/spec/runner/formatter/base_formatter.rb b/vendor/gems/rspec/lib/spec/runner/formatter/base_formatter.rb index 7cc43ef0e..7cc43ef0e 100644 --- a/spec/lib/spec/runner/formatter/base_formatter.rb +++ b/vendor/gems/rspec/lib/spec/runner/formatter/base_formatter.rb diff --git a/spec/lib/spec/runner/formatter/base_text_formatter.rb b/vendor/gems/rspec/lib/spec/runner/formatter/base_text_formatter.rb index c3cf01b76..c3cf01b76 100644 --- a/spec/lib/spec/runner/formatter/base_text_formatter.rb +++ b/vendor/gems/rspec/lib/spec/runner/formatter/base_text_formatter.rb diff --git a/spec/lib/spec/runner/formatter/failing_behaviours_formatter.rb b/vendor/gems/rspec/lib/spec/runner/formatter/failing_behaviours_formatter.rb index 2b3940fd3..2b3940fd3 100644 --- a/spec/lib/spec/runner/formatter/failing_behaviours_formatter.rb +++ b/vendor/gems/rspec/lib/spec/runner/formatter/failing_behaviours_formatter.rb diff --git a/spec/lib/spec/runner/formatter/failing_examples_formatter.rb b/vendor/gems/rspec/lib/spec/runner/formatter/failing_examples_formatter.rb index 9728deaf0..9728deaf0 100644 --- a/spec/lib/spec/runner/formatter/failing_examples_formatter.rb +++ b/vendor/gems/rspec/lib/spec/runner/formatter/failing_examples_formatter.rb diff --git a/spec/lib/spec/runner/formatter/html_formatter.rb b/vendor/gems/rspec/lib/spec/runner/formatter/html_formatter.rb index d9c422e55..d9c422e55 100644 --- a/spec/lib/spec/runner/formatter/html_formatter.rb +++ b/vendor/gems/rspec/lib/spec/runner/formatter/html_formatter.rb diff --git a/spec/lib/spec/runner/formatter/progress_bar_formatter.rb b/vendor/gems/rspec/lib/spec/runner/formatter/progress_bar_formatter.rb index 624f06e7c..624f06e7c 100644 --- a/spec/lib/spec/runner/formatter/progress_bar_formatter.rb +++ b/vendor/gems/rspec/lib/spec/runner/formatter/progress_bar_formatter.rb diff --git a/spec/lib/spec/runner/formatter/rdoc_formatter.rb b/vendor/gems/rspec/lib/spec/runner/formatter/rdoc_formatter.rb index 0fd22ba6c..0fd22ba6c 100644 --- a/spec/lib/spec/runner/formatter/rdoc_formatter.rb +++ b/vendor/gems/rspec/lib/spec/runner/formatter/rdoc_formatter.rb diff --git a/spec/lib/spec/runner/formatter/snippet_extractor.rb b/vendor/gems/rspec/lib/spec/runner/formatter/snippet_extractor.rb index 41119fe46..41119fe46 100644 --- a/spec/lib/spec/runner/formatter/snippet_extractor.rb +++ b/vendor/gems/rspec/lib/spec/runner/formatter/snippet_extractor.rb diff --git a/spec/lib/spec/runner/formatter/specdoc_formatter.rb b/vendor/gems/rspec/lib/spec/runner/formatter/specdoc_formatter.rb index ad794b238..ad794b238 100644 --- a/spec/lib/spec/runner/formatter/specdoc_formatter.rb +++ b/vendor/gems/rspec/lib/spec/runner/formatter/specdoc_formatter.rb diff --git a/spec/lib/spec/runner/heckle_runner.rb b/vendor/gems/rspec/lib/spec/runner/heckle_runner.rb index b6de4ef73..b6de4ef73 100644 --- a/spec/lib/spec/runner/heckle_runner.rb +++ b/vendor/gems/rspec/lib/spec/runner/heckle_runner.rb diff --git a/spec/lib/spec/runner/heckle_runner_unsupported.rb b/vendor/gems/rspec/lib/spec/runner/heckle_runner_unsupported.rb index 02aa37953..02aa37953 100644 --- a/spec/lib/spec/runner/heckle_runner_unsupported.rb +++ b/vendor/gems/rspec/lib/spec/runner/heckle_runner_unsupported.rb diff --git a/spec/lib/spec/runner/option_parser.rb b/vendor/gems/rspec/lib/spec/runner/option_parser.rb index 1facb85a8..1facb85a8 100644 --- a/spec/lib/spec/runner/option_parser.rb +++ b/vendor/gems/rspec/lib/spec/runner/option_parser.rb diff --git a/spec/lib/spec/runner/options.rb b/vendor/gems/rspec/lib/spec/runner/options.rb index a940133eb..a940133eb 100644 --- a/spec/lib/spec/runner/options.rb +++ b/vendor/gems/rspec/lib/spec/runner/options.rb diff --git a/spec/lib/spec/runner/reporter.rb b/vendor/gems/rspec/lib/spec/runner/reporter.rb index b1dc2a27a..b1dc2a27a 100644 --- a/spec/lib/spec/runner/reporter.rb +++ b/vendor/gems/rspec/lib/spec/runner/reporter.rb diff --git a/spec/lib/spec/runner/spec_parser.rb b/vendor/gems/rspec/lib/spec/runner/spec_parser.rb index bc9170065..bc9170065 100644 --- a/spec/lib/spec/runner/spec_parser.rb +++ b/vendor/gems/rspec/lib/spec/runner/spec_parser.rb diff --git a/spec/lib/spec/test_case_adapter.rb b/vendor/gems/rspec/lib/spec/test_case_adapter.rb index 992e098fd..992e098fd 100755..100644 --- a/spec/lib/spec/test_case_adapter.rb +++ b/vendor/gems/rspec/lib/spec/test_case_adapter.rb diff --git a/spec/lib/spec/translator.rb b/vendor/gems/rspec/lib/spec/translator.rb index c1e07eda4..c1e07eda4 100644 --- a/spec/lib/spec/translator.rb +++ b/vendor/gems/rspec/lib/spec/translator.rb diff --git a/spec/lib/spec/version.rb b/vendor/gems/rspec/lib/spec/version.rb index 5b1db9b37..5b1db9b37 100644 --- a/spec/lib/spec/version.rb +++ b/vendor/gems/rspec/lib/spec/version.rb diff --git a/spec/plugins/mock_frameworks/flexmock.rb b/vendor/gems/rspec/plugins/mock_frameworks/flexmock.rb index 6875a5222..6875a5222 100644 --- a/spec/plugins/mock_frameworks/flexmock.rb +++ b/vendor/gems/rspec/plugins/mock_frameworks/flexmock.rb diff --git a/spec/plugins/mock_frameworks/mocha.rb b/vendor/gems/rspec/plugins/mock_frameworks/mocha.rb index 69d11636c..69d11636c 100644 --- a/spec/plugins/mock_frameworks/mocha.rb +++ b/vendor/gems/rspec/plugins/mock_frameworks/mocha.rb diff --git a/spec/plugins/mock_frameworks/rr.rb b/vendor/gems/rspec/plugins/mock_frameworks/rr.rb index c019c18a1..c019c18a1 100644 --- a/spec/plugins/mock_frameworks/rr.rb +++ b/vendor/gems/rspec/plugins/mock_frameworks/rr.rb diff --git a/spec/plugins/mock_frameworks/rspec.rb b/vendor/gems/rspec/plugins/mock_frameworks/rspec.rb index e606c3089..e606c3089 100644 --- a/spec/plugins/mock_frameworks/rspec.rb +++ b/vendor/gems/rspec/plugins/mock_frameworks/rspec.rb diff --git a/vendor/gems/rspec/spec/autotest/discover_spec.rb b/vendor/gems/rspec/spec/autotest/discover_spec.rb new file mode 100644 index 000000000..da5cb1445 --- /dev/null +++ b/vendor/gems/rspec/spec/autotest/discover_spec.rb @@ -0,0 +1,19 @@ +require File.dirname(__FILE__) + "/../autotest_helper" + +module DiscoveryHelper + def load_discovery + require File.dirname(__FILE__) + "/../../lib/autotest/discover" + end +end + + +class Autotest + describe Rspec, "discovery" do + include DiscoveryHelper + + it "should add the rspec autotest plugin" do + Autotest.should_receive(:add_discovery).and_yield + load_discovery + end + end +end diff --git a/vendor/gems/rspec/spec/autotest/rspec_spec.rb b/vendor/gems/rspec/spec/autotest/rspec_spec.rb new file mode 100644 index 000000000..52b5b4885 --- /dev/null +++ b/vendor/gems/rspec/spec/autotest/rspec_spec.rb @@ -0,0 +1,258 @@ +require File.dirname(__FILE__) + "/../autotest_helper" + +class Autotest + + module AutotestHelper + def rspec_output + <<-HERE +.............PPF + +1) +'false should be false' FAILED +expected: true, + got: false (using ==) +./spec/autotest/rspec_spec.rb:203: + +Finished in 0.158674 seconds + +16 examples, 1 failure, 2 pending + +Pending: +Autotest::Rspec handling failed results should return an array of failed examples and errors (TODO) +Autotest::Rspec tests/specs for a given file should find all the specs for a given file (TODO) +HERE + end + + + def common_setup + @proc = mock Proc + @kernel = mock Kernel + @kernel.stub!(:proc).and_return @proc + + File.stub!(:exists).and_return true + @windows_alt_separator = "\\" + @posix_separator = '/' + + @rspec_output = rspec_output + end + end + + describe Rspec, "rspec_commands" do + it "should contain the various commands, ordered by preference" do + Rspec.new.spec_commands.should == ["bin/spec", "#{Config::CONFIG['bindir']}/spec"] + end + end + + describe Rspec, "selection of rspec command" do + include AutotestHelper + + before :each do + common_setup + @rspec_autotest = Rspec.new(@kernel) + end + + it "should try to find the spec command if it exists in ./bin and use it above everything else" do + File.stub!(:exists?).and_return true + + File.should_receive(:exists?).with("bin/spec").and_return true + @rspec_autotest.spec_command.should == "bin/spec" + end + + it "should otherwise select the default spec command in gem_dir/bin/spec" do + @rspec_autotest.stub!(:spec_commands).and_return ["/foo/spec"] + Config::CONFIG.stub!(:[]).and_return "/foo" + File.should_receive(:exists?).with("/foo/spec").and_return(true) + + @rspec_autotest.spec_command.should == "/foo/spec" + end + + it "should raise an error if no spec command is found at all" do + File.stub!(:exists?).and_return false + + lambda { + @rspec_autotest.spec_command + }.should raise_error(RspecCommandError, "No spec command could be found!") + end + + end + + describe Rspec, "selection of rspec command (windows compatibility issues)" do + include AutotestHelper + + before :each do + common_setup + end + + it "should use the ALT_SEPARATOR if it is non-nil" do + @rspec_autotest = Rspec.new(@kernel, @posix_separator, @windows_alt_separator) + @rspec_autotest.stub!(:spec_commands).and_return [File.join('bin', 'spec')] + @rspec_autotest.spec_command.should == "bin\\spec" + end + + it "should not use the ALT_SEPATOR if it is nil" do + @windows_alt_separator = nil + @rspec_autotest = Rspec.new(@kernel, @posix_separator, @windows_alt_separator) + @rspec_autotest.stub!(:spec_commands).and_return [File.join('bin', 'spec')] + @rspec_autotest.spec_command.should == "bin/spec" + end + end + + describe Rspec, "adding spec.opts --options" do + before :each do + @rspec_autotest = Rspec.new + end + + it "should return the command line option to add spec.opts if the options file exists" do + File.stub!(:exist?).and_return true + @rspec_autotest.add_options_if_present.should == "-O spec/spec.opts " + end + + it "should return an empty string if no spec.opts exists" do + File.stub!(:exist?).and_return false + Rspec.new.add_options_if_present.should == "" + end + end + + describe Rspec do + before :each do + @rspec_autotest = Rspec.new + @rspec_autotest.stub!(:ruby).and_return "ruby" + @rspec_autotest.stub!(:add_options_if_present).and_return "-O spec/spec.opts" + + @ruby = @rspec_autotest.ruby + @spec_command = @rspec_autotest.spec_command + @options = @rspec_autotest.add_options_if_present + @files_to_test = { + :spec => ["file_one", "file_two"] + } + # this is not the inner representation of Autotest! + @rspec_autotest.stub!(:files_to_test).and_return @files_to_test + @files_to_test.stub!(:keys).and_return @files_to_test[:spec] + @to_test = @files_to_test.keys.flatten.join ' ' + end + + it "should make the apropriate test command" do + @rspec_autotest.make_test_cmd(@files_to_test).should == "#{@ruby} -S #{@spec_command} #{@options} #{@to_test}" + end + end + + describe Rspec, "test mappings" do + before :each do + @proc = mock Proc + @kernel = mock Kernel + @kernel.stub!(:proc).and_return @proc + @rspec_autotest = Rspec.new(@kernel) + end + + it "should map all filenames in spec/ which end in .rb" do + @rspec_autotest.test_mappings[%r%^spec/.*\.rb$%].should == @proc + end + + it "should map all names in lib which end in .rb to the corresponding ones in spec/" do + @rspec_autotest.test_mappings[%r%^lib/(.*)\.rb$%].should == @proc + end + + it "should find all files in spec/shares/* and the spec helper in spec/spec_helper" do + @rspec_autotest.test_mappings[%r%^spec/(spec_helper|shared/.*)\.rb$%].should == @proc + end + end + + describe Rspec, "handling results" do + include AutotestHelper + + before :each do + common_setup + @rspec_autotest = Rspec.new(@kernel, @posix_separator, @windows_alt_separator) + @rspec_autotest.stub!(:hook) + + @results = mock String + @results.stub!(:scan).and_return "" + end + + it "should call hook(:red) if there are failures" do + @rspec_autotest.stub!(:consolidate_failures).and_return ["spec/some_spec.rb"] + + @rspec_autotest.should_receive(:hook).with(:red) + @rspec_autotest.handle_results(@results) + end + + it "should call hook(:green) if there are no failures" do + @rspec_autotest.stub!(:consolidate_failures).and_return [] + @rspec_autotest.should_receive(:hook).with(:green) + @rspec_autotest.handle_results(@results) + end + end + + describe Rspec, "handling failed results" do + include AutotestHelper + + before :each do + common_setup + end + + it %(should scan the output into a multi-dimensional array, + consisting of the failing spec's name as the first element, + and the failure as the second) do + @rspec_autotest = Rspec.new + @rspec_autotest.failed_results(@rspec_output).should == [ + [ + "false should be false", + "expected: true,\n got: false (using ==)\n./spec/autotest/rspec_spec.rb:203:" + ] + ] + end + end + + describe Rspec, "specs for a given file" do + before :each do + @lib_file = "lib/something.rb" + @spec_file = "spec/something_spec.rb" + @rspec_autotest = Rspec.new + + @rspec_autotest.instance_variable_set("@files", {@lib_file => Time.now, @spec_file => Time.now}) + @rspec_autotest.stub!(:find_files_to_test).and_return true + end + + it "should find the spec file for a given lib file" do + @rspec_autotest.specs_for_file(@lib_file).should == [@spec_file] + end + + it "should find the spec file if given a spec file" do + @rspec_autotest.specs_for_file(@spec_file).should == [@spec_file] + end + + it "should only find the file if the file is being tracked (in @file)" do + @other_file = "lib/some_non_tracked_file" + @rspec_autotest.specs_for_file(@other_file).should == [] + end + end + + describe Rspec, "consolidating failures" do + include AutotestHelper + + before :each do + common_setup + @rspec_autotest = Rspec.new + + @spec_file = "./spec/autotest/rspec_spec.rb" + @rspec_autotest.instance_variable_set("@files", {@spec_file => Time.now}) + @rspec_autotest.stub!(:find_files_to_test).and_return true + end + + it "should return no failures if no failures were given in the output" do + @rspec_autotest.stub!(:failed_results).and_return [[]] + @rspec_autotest.consolidate_failures(@rspec_autotest.failed_results).should == {} + end + + it "should return a hash with the spec filename => spec name for each failure or error" do + @rspec_autotest.stub!(:failed_results).and_return([ + [ + "false should be false", + "expected: true,\n got: false (using ==)\n./spec/autotest/rspec_spec.rb:203:" + ] + ]) + @rspec_autotest.consolidate_failures(@rspec_autotest.failed_results).should == {@spec_file => ["false should be false"]} + end + + end +end diff --git a/vendor/gems/rspec/spec/autotest_helper.rb b/vendor/gems/rspec/spec/autotest_helper.rb new file mode 100644 index 000000000..172bb3a4a --- /dev/null +++ b/vendor/gems/rspec/spec/autotest_helper.rb @@ -0,0 +1,4 @@ +require 'autotest' +require File.dirname(__FILE__) + "/../lib/autotest/rspec" + + diff --git a/vendor/gems/rspec/spec/spec/dsl/behaviour_eval_spec.rb b/vendor/gems/rspec/spec/spec/dsl/behaviour_eval_spec.rb new file mode 100644 index 000000000..c3ed4e282 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/dsl/behaviour_eval_spec.rb @@ -0,0 +1,79 @@ +require File.dirname(__FILE__) + '/../../spec_helper' + +module Spec + module DSL + describe BehaviourEval do + def count + @count ||= 0 + @count = @count + 1 + @count + end + + before(:all) do + count.should == 1 + end + + before(:all) do + count.should == 2 + end + + before(:each) do + count.should == 3 + end + + before(:each) do + count.should == 4 + end + + it "should run before(:all), before(:each), example, after(:each), after(:all) in order" do + count.should == 5 + end + + after(:each) do + count.should == 7 + end + + after(:each) do + count.should == 6 + end + + after(:all) do + count.should == 9 + end + + after(:all) do + count.should == 8 + end + end + + describe BehaviourEval, "instance methods" do + it "should support pending" do + lambda { + pending("something") + }.should raise_error(Spec::DSL::ExamplePendingError, "something") + end + + it "should have #pending raise a Pending error when its block fails" do + block_ran = false + lambda { + pending("something") do + block_ran = true + raise "something wrong with my example" + end + }.should raise_error(Spec::DSL::ExamplePendingError, "something") + block_ran.should == true + end + + it "should have #pending raise Spec::DSL::PendingFixedError when its block does not fail" do + block_ran = false + lambda { + pending("something") do + block_ran = true + end + }.should raise_error(Spec::DSL::PendingFixedError, "Expected pending 'something' to fail. No Error was raised.") + block_ran.should == true + end + + end + end +end diff --git a/vendor/gems/rspec/spec/spec/dsl/behaviour_factory_spec.rb b/vendor/gems/rspec/spec/spec/dsl/behaviour_factory_spec.rb new file mode 100644 index 000000000..91008a660 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/dsl/behaviour_factory_spec.rb @@ -0,0 +1,48 @@ +require File.dirname(__FILE__) + '/../../spec_helper' + +module Spec + module DSL + describe BehaviourFactory do + it "should create a Spec::DSL::Behaviour by default" do + Spec::DSL::BehaviourFactory.create("behaviour") { + }.should be_an_instance_of(Spec::DSL::Behaviour) + end + + it "should create a Spec::DSL::Behaviour when :behaviour_type => :default" do + Spec::DSL::BehaviourFactory.create("behaviour", :behaviour_type => :default) { + }.should be_an_instance_of(Spec::DSL::Behaviour) + end + + it "should create specified type when :behaviour_type => :something_other_than_default" do + behaviour_class = Class.new do + def initialize(*args, &block); end + end + Spec::DSL::BehaviourFactory.add_behaviour_class(:something_other_than_default, behaviour_class) + Spec::DSL::BehaviourFactory.create("behaviour", :behaviour_type => :something_other_than_default) { + }.should be_an_instance_of(behaviour_class) + end + + it "should type indicated by spec_path" do + behaviour_class = Class.new do + def initialize(*args, &block); end + end + Spec::DSL::BehaviourFactory.add_behaviour_class(:something_other_than_default, behaviour_class) + Spec::DSL::BehaviourFactory.create("behaviour", :spec_path => "./spec/something_other_than_default/some_spec.rb") { + }.should be_an_instance_of(behaviour_class) + end + + it "should type indicated by spec_path (with spec_path generated by caller on windows)" do + behaviour_class = Class.new do + def initialize(*args, &block); end + end + Spec::DSL::BehaviourFactory.add_behaviour_class(:something_other_than_default, behaviour_class) + Spec::DSL::BehaviourFactory.create("behaviour", :spec_path => "./spec\\something_other_than_default\\some_spec.rb") { + }.should be_an_instance_of(behaviour_class) + end + + after(:each) do + Spec::DSL::BehaviourFactory.remove_behaviour_class(:something_other_than_default) + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/dsl/behaviour_spec.rb b/vendor/gems/rspec/spec/spec/dsl/behaviour_spec.rb new file mode 100644 index 000000000..fa6774c65 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/dsl/behaviour_spec.rb @@ -0,0 +1,661 @@ +require File.dirname(__FILE__) + '/../../spec_helper' + +module Spec + module DSL + class FakeReporter < Spec::Runner::Reporter + attr_reader :added_behaviour + def add_behaviour(description) + @added_behaviour = description + end + end + + describe Behaviour, "class methods" do + before :each do + @reporter = FakeReporter.new(mock("formatter", :null_object => true), mock("backtrace_tweaker", :null_object => true)) + @behaviour = Behaviour.new("example") {} + end + + after :each do + Behaviour.clear_before_and_after! + end + + it "should not run before(:all) or after(:all) on dry run" do + before_all_ran = false + after_all_ran = false + Behaviour.before(:all) { before_all_ran = true } + Behaviour.after(:all) { after_all_ran = true } + @behaviour.it("should") {} + @behaviour.run(@reporter, true) + before_all_ran.should be_false + after_all_ran.should be_false + end + + it "should not run any example if before(:all) fails" do + spec_ran = false + Behaviour.before(:all) { raise NonStandardError } + @behaviour.it("test") {spec_ran = true} + @behaviour.run(@reporter) + spec_ran.should be_false + end + + it "should run after(:all) if before(:all) fails" do + after_all_ran = false + Behaviour.before(:all) { raise NonStandardError } + Behaviour.after(:all) { after_all_ran = true } + @behaviour.run(@reporter) + after_all_ran.should be_true + end + + it "should run after(:all) if before(:each) fails" do + after_all_ran = false + Behaviour.before(:each) { raise NonStandardError } + Behaviour.after(:all) { after_all_ran = true } + @behaviour.run(@reporter) + after_all_ran.should be_true + end + + it "should run after(:all) if any example fails" do + after_all_ran = false + @behaviour.it("should") { raise NonStandardError } + Behaviour.after(:all) { after_all_ran = true } + @behaviour.run(@reporter) + after_all_ran.should be_true + end + + + it "should unregister a given after(:each) block" do + after_all_ran = false + @behaviour.it("example") {} + proc = Proc.new { after_all_ran = true } + Behaviour.after(:each, &proc) + @behaviour.run(@reporter) + after_all_ran.should be_true + + after_all_ran = false + Behaviour.remove_after(:each, &proc) + @behaviour.run(@reporter) + after_all_ran.should be_false + end + + it "should run second after(:each) block even if the first one fails" do + example = @behaviour.it("example") {} + second_after_ran = false + @behaviour.after(:each) do + second_after_ran = true + raise "second" + end + first_after_ran = false + @behaviour.after(:each) do + first_after_ran = true + raise "first" + end + + @reporter.should_receive(:example_finished) do |example, error, location, example_not_implemented| + example.should equal(example) + error.message.should eql("first") + location.should eql("after(:each)") + example_not_implemented.should be_false + end + @behaviour.run(@reporter) + first_after_ran.should be_true + second_after_ran.should be_true + end + + it "should not run second before(:each) if the first one fails" do + @behaviour.it("example") {} + first_before_ran = false + @behaviour.before(:each) do + first_before_ran = true + raise "first" + end + second_before_ran = false + @behaviour.before(:each) do + second_before_ran = true + raise "second" + end + + @reporter.should_receive(:example_finished) do |name, error, location, example_not_implemented| + name.should eql("example") + error.message.should eql("first") + location.should eql("before(:each)") + example_not_implemented.should be_false + end + @behaviour.run(@reporter) + first_before_ran.should be_true + second_before_ran.should be_false + end + + it "should supply before(:all) as description if failure in before(:all)" do + @reporter.should_receive(:example_finished) do |example, error, location| + example.description.should eql("before(:all)") + error.message.should == "in before(:all)" + location.should eql("before(:all)") + end + + Behaviour.before(:all) { raise NonStandardError.new("in before(:all)") } + @behaviour.it("test") {true} + @behaviour.run(@reporter) + end + + it "should provide after(:all) as description if failure in after(:all)" do + @reporter.should_receive(:example_finished) do |example, error, location| + example.description.should eql("after(:all)") + error.message.should eql("in after(:all)") + location.should eql("after(:all)") + end + + Behaviour.after(:all) { raise NonStandardError.new("in after(:all)") } + @behaviour.run(@reporter) + end + end + + describe Behaviour do + before :each do + @reporter = FakeReporter.new(mock("formatter", :null_object => true), mock("backtrace_tweaker", :null_object => true)) + @behaviour = Behaviour.new("example") {} + end + + after :each do + Behaviour.clear_before_and_after! + end + + it "should send reporter add_behaviour" do + @behaviour.run(@reporter) + @reporter.added_behaviour.should == "example" + end + + it "should run example on run" do + example_ran = false + @behaviour.it("should") {example_ran = true} + @behaviour.run(@reporter) + example_ran.should be_true + end + + it "should not run example on dry run" do + example_ran = false + @behaviour.it("should") {example_ran = true} + @behaviour.run(@reporter, true) + example_ran.should be_false + end + + it "should not run before(:all) or after(:all) on dry run" do + before_all_ran = false + after_all_ran = false + @behaviour.before(:all) { before_all_ran = true } + @behaviour.after(:all) { after_all_ran = true } + @behaviour.it("should") {} + @behaviour.run(@reporter, true) + before_all_ran.should be_false + after_all_ran.should be_false + end + + it "should not run any example if before(:all) fails" do + spec_ran = false + @behaviour.before(:all) { raise "help" } + @behaviour.it("test") {spec_ran = true} + @behaviour.run(@reporter) + spec_ran.should be_false + end + + it "should run after(:all) if before(:all) fails" do + after_all_ran = false + @behaviour.before(:all) { raise } + @behaviour.after(:all) { after_all_ran = true } + @behaviour.run(@reporter) + after_all_ran.should be_true + end + + it "should run after(:all) if before(:each) fails" do + after_all_ran = false + @behaviour.before(:each) { raise } + @behaviour.after(:all) { after_all_ran = true } + @behaviour.run(@reporter) + after_all_ran.should be_true + end + + it "should run after(:all) if any example fails" do + after_all_ran = false + @behaviour.it("should") { raise "before all error" } + @behaviour.after(:all) { after_all_ran = true } + @behaviour.run(@reporter) + after_all_ran.should be_true + end + + it "should supply before(:all) as description if failure in before(:all)" do + @reporter.should_receive(:example_finished) do |example, error, location| + example.description.should eql("before(:all)") + error.message.should eql("in before(:all)") + location.should eql("before(:all)") + end + + @behaviour.before(:all) { raise "in before(:all)" } + @behaviour.it("test") {true} + @behaviour.run(@reporter) + end + + it "should provide after(:all) as description if failure in after(:all)" do + @reporter.should_receive(:example_finished) do |example, error, location| + example.description.should eql("after(:all)") + error.message.should eql("in after(:all)") + location.should eql("after(:all)") + end + + @behaviour.after(:all) { raise "in after(:all)" } + @behaviour.run(@reporter) + end + + it "should run before(:all) block only once" do + before_all_run_count_run_count = 0 + @behaviour.before(:all) {before_all_run_count_run_count += 1} + @behaviour.it("test") {true} + @behaviour.it("test2") {true} + @behaviour.run(@reporter) + before_all_run_count_run_count.should == 1 + end + + it "calls spec_inherited class method" do + super_class_before_ran = false + super_class = Class.new do + def self.spec_inherited(mod) + mod.before {setup} + end + + define_method :setup do + super_class_before_ran = true + end + end + @behaviour.inherit super_class + + before_ran = false + @behaviour.before {before_ran = true} + @behaviour.it("test") {true} + @behaviour.run(@reporter) + super_class_before_ran.should be_true + before_ran.should be_true + end + + it "should run after(:all) block only once" do + after_all_run_count = 0 + @behaviour.after(:all) {after_all_run_count += 1} + @behaviour.it("test") {true} + @behaviour.it("test2") {true} + @behaviour.run(@reporter) + after_all_run_count.should == 1 + @reporter.rspec_verify + end + + it "after(:all) should have access to all instance variables defined in before(:all)" do + context_instance_value_in = "Hello there" + context_instance_value_out = "" + @behaviour.before(:all) { @instance_var = context_instance_value_in } + @behaviour.after(:all) { context_instance_value_out = @instance_var } + @behaviour.it("test") {true} + @behaviour.run(@reporter) + context_instance_value_in.should == context_instance_value_out + end + + it "should copy instance variables from before(:all)'s execution context into spec's execution context" do + context_instance_value_in = "Hello there" + context_instance_value_out = "" + @behaviour.before(:all) { @instance_var = context_instance_value_in } + @behaviour.it("test") {context_instance_value_out = @instance_var} + @behaviour.run(@reporter) + context_instance_value_in.should == context_instance_value_out + end + + it "should not add global before callbacks for untargetted behaviours" do + fiddle = [] + + Behaviour.before(:all) { fiddle << "Behaviour.before(:all)" } + Behaviour.prepend_before(:all) { fiddle << "Behaviour.prepend_before(:all)" } + Behaviour.before(:each, :behaviour_type => :special) { fiddle << "Behaviour.before(:each, :behaviour_type => :special)" } + Behaviour.prepend_before(:each, :behaviour_type => :special) { fiddle << "Behaviour.prepend_before(:each, :behaviour_type => :special)" } + Behaviour.before(:all, :behaviour_type => :special) { fiddle << "Behaviour.before(:all, :behaviour_type => :special)" } + Behaviour.prepend_before(:all, :behaviour_type => :special) { fiddle << "Behaviour.prepend_before(:all, :behaviour_type => :special)" } + + behaviour = Behaviour.new("I'm not special", :behaviour_type => :not_special) {} + behaviour.run(@reporter) + fiddle.should == [ + 'Behaviour.prepend_before(:all)', + 'Behaviour.before(:all)', + ] + end + + it "should add global before callbacks for targetted behaviours" do + fiddle = [] + + Behaviour.before(:all) { fiddle << "Behaviour.before(:all)" } + Behaviour.prepend_before(:all) { fiddle << "Behaviour.prepend_before(:all)" } + Behaviour.before(:each, :behaviour_type => :special) { fiddle << "Behaviour.before(:each, :behaviour_type => :special)" } + Behaviour.prepend_before(:each, :behaviour_type => :special) { fiddle << "Behaviour.prepend_before(:each, :behaviour_type => :special)" } + Behaviour.before(:all, :behaviour_type => :special) { fiddle << "Behaviour.before(:all, :behaviour_type => :special)" } + Behaviour.prepend_before(:all, :behaviour_type => :special) { fiddle << "Behaviour.prepend_before(:all, :behaviour_type => :special)" } + + Behaviour.append_before(:behaviour_type => :special) { fiddle << "Behaviour.append_before(:each, :behaviour_type => :special)" } + + behaviour = Behaviour.new("I'm not special", :behaviour_type => :special) {} + behaviour.it("test") {true} + behaviour.run(@reporter) + fiddle.should == [ + 'Behaviour.prepend_before(:all)', + 'Behaviour.before(:all)', + 'Behaviour.prepend_before(:all, :behaviour_type => :special)', + 'Behaviour.before(:all, :behaviour_type => :special)', + 'Behaviour.prepend_before(:each, :behaviour_type => :special)', + 'Behaviour.before(:each, :behaviour_type => :special)', + 'Behaviour.append_before(:each, :behaviour_type => :special)', + ] + end + + it "before callbacks are ordered from global to local" do + fiddle = [] + super_class = Class.new do + define_method :setup do + fiddle << "superclass setup" + end + end + @behaviour.inherit super_class + + Behaviour.prepend_before(:all) { fiddle << "Behaviour.prepend_before(:all)" } + Behaviour.before(:all) { fiddle << "Behaviour.before(:all)" } + @behaviour.prepend_before(:all) { fiddle << "prepend_before(:all)" } + @behaviour.before(:all) { fiddle << "before(:all)" } + @behaviour.prepend_before(:each) { fiddle << "prepend_before(:each)" } + @behaviour.before(:each) { fiddle << "before(:each)" } + @behaviour.it("test") {true} + @behaviour.run(@reporter) + fiddle.should == [ + 'Behaviour.prepend_before(:all)', + 'Behaviour.before(:all)', + 'prepend_before(:all)', + 'before(:all)', + 'prepend_before(:each)', + 'before(:each)' + ] + end + + it "after callbacks are ordered from local to global" do + @reporter.should_receive(:add_behaviour).with any_args() + @reporter.should_receive(:example_finished).with any_args() + + fiddle = [] + super_class = Class.new do + define_method :teardown do + fiddle << "superclass teardown" + end + end + @behaviour.inherit super_class + + @behaviour.after(:each) { fiddle << "after(:each)" } + @behaviour.append_after(:each) { fiddle << "append_after(:each)" } + @behaviour.after(:all) { fiddle << "after(:all)" } + @behaviour.append_after(:all) { fiddle << "append_after(:all)" } + Behaviour.after(:all) { fiddle << "Behaviour.after(:all)" } + Behaviour.append_after(:all) { fiddle << "Behaviour.append_after(:all)" } + @behaviour.it("test") {true} + @behaviour.run(@reporter) + fiddle.should == [ + 'after(:each)', + 'append_after(:each)', + 'after(:all)', + 'append_after(:all)', + 'Behaviour.after(:all)', + 'Behaviour.append_after(:all)' + ] + end + + it "should run superclass teardown method and after block" do + super_class_teardown_ran = false + super_class = Class.new do + define_method :teardown do + super_class_teardown_ran = true + end + end + @behaviour.inherit super_class + + teardown_ran = false + @behaviour.after {teardown_ran = true} + @behaviour.it("test") {true} + @behaviour.run(@reporter) + super_class_teardown_ran.should be_false + teardown_ran.should be_true + @reporter.rspec_verify + end + + it "should have accessible methods from inherited superclass" do + helper_method_ran = false + super_class = Class.new do + define_method :helper_method do + helper_method_ran = true + end + end + @behaviour.inherit super_class + + @behaviour.it("test") {helper_method} + @behaviour.run(@reporter) + helper_method_ran.should be_true + end + + it "should have accessible class methods from inherited superclass" do + class_method_ran = false + super_class = Class.new + (class << super_class; self; end).class_eval do + define_method :class_method do + class_method_ran = true + end + end + @behaviour.inherit super_class + @behaviour.class_method + class_method_ran.should be_true + + lambda {@behaviour.foobar}.should raise_error(NoMethodError) + end + + it "should include inherited class methods" do + class_method_ran = false + super_class = Class.new + class << super_class + def super_class_class_method; end + end + @behaviour.inherit super_class + + @behaviour.methods.should include("super_class_class_method") + end + + it "should have accessible instance methods from included module" do + @reporter.should_receive(:add_behaviour).with any_args() + @reporter.should_receive(:example_finished).with any_args() + + mod1_method_called = false + mod1 = Module.new do + define_method :mod1_method do + mod1_method_called = true + end + end + + mod2_method_called = false + mod2 = Module.new do + define_method :mod2_method do + mod2_method_called = true + end + end + + @behaviour.include mod1, mod2 + + @behaviour.it("test") do + mod1_method + mod2_method + end + @behaviour.run(@reporter) + mod1_method_called.should be_true + mod2_method_called.should be_true + end + + it "should have accessible class methods from included module" do + mod1_method_called = false + mod1 = Module.new do + class_methods = Module.new do + define_method :mod1_method do + mod1_method_called = true + end + end + + metaclass.class_eval do + define_method(:included) do |receiver| + receiver.extend class_methods + end + end + end + + mod2_method_called = false + mod2 = Module.new do + class_methods = Module.new do + define_method :mod2_method do + mod2_method_called = true + end + end + + metaclass.class_eval do + define_method(:included) do |receiver| + receiver.extend class_methods + end + end + end + + @behaviour.include mod1, mod2 + + @behaviour.mod1_method + @behaviour.mod2_method + mod1_method_called.should be_true + mod2_method_called.should be_true + end + + it "should count number of specs" do + @behaviour.it("one") {} + @behaviour.it("two") {} + @behaviour.it("three") {} + @behaviour.it("four") {} + @behaviour.number_of_examples.should == 4 + end + + it "should not match anything when there are no examples" do + @behaviour.should_not be_matches(['context']) + end + + it "should match when one of the examples match" do + example = mock('my example') + example.should_receive(:matches?).and_return(true) + @behaviour.stub!(:examples).and_return([example]) + @behaviour.should be_matches(['jalla']) + end + + it "should include targetted modules included using configuration" do + $included_modules = [] + + mod1 = Module.new do + class << self + def included(mod) + $included_modules << self + end + end + end + + mod2 = Module.new do + class << self + def included(mod) + $included_modules << self + end + end + end + + mod3 = Module.new do + class << self + def included(mod) + $included_modules << self + end + end + end + + begin + Spec::Runner.configuration.include(mod1, mod2) + Spec::Runner.configuration.include(mod3, :behaviour_type => :cat) + + behaviour = Behaviour.new("I'm special", :behaviour_type => :dog) do + end.run(@reporter) + + $included_modules.should include(mod1) + $included_modules.should include(mod2) + $included_modules.should_not include(mod3) + ensure + Spec::Runner.configuration.exclude(mod1, mod2, mod3) + end + end + + it "should include any predicate_matchers included using configuration" do + $included_predicate_matcher_found = false + Spec::Runner.configuration.predicate_matchers[:do_something] = :does_something? + Behaviour.new('example') do + it "should respond to do_something" do + $included_predicate_matcher_found = respond_to?(:do_something) + end + end.run(@reporter) + $included_predicate_matcher_found.should be(true) + end + + it "should use a mock framework set up in config" do + mod = Module.new do + class << self + def included(mod) + $included_module = mod + end + end + end + + begin + $included_module = nil + Spec::Runner.configuration.mock_with mod + + behaviour = Behaviour.new('example') do + end.run(@reporter) + + $included_module.should_not be_nil + ensure + Spec::Runner.configuration.mock_with :rspec + end + end + + end + + class BehaviourSubclass < Behaviour + public :described_type + end + + describe Behaviour, " subclass" do + it "should have access to the described_type" do + BehaviourSubclass.new(Example){}.described_type.should == Example + end + + it "should figure out its behaviour_type based on its name ()" do + BehaviourSubclass.new(Object){}.behaviour_type.should == :subclass + end + + # TODO - add an example about shared behaviours + end + + describe Enumerable do + def each(&block) + ["4", "2", "1"].each(&block) + end + + it "should be included in examples because it is a module" do + map{|e| e.to_i}.should == [4,2,1] + end + end + + describe String do + it "should not be included in examples because it is not a module" do + lambda{self.map}.should raise_error(NoMethodError, /undefined method `map' for/) + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/dsl/composite_proc_builder_spec.rb b/vendor/gems/rspec/spec/spec/dsl/composite_proc_builder_spec.rb new file mode 100644 index 000000000..487677828 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/dsl/composite_proc_builder_spec.rb @@ -0,0 +1,44 @@ +require File.dirname(__FILE__) + '/../../spec_helper' + +module Spec + module DSL + describe CompositeProcBuilder do + before(:each) do + @klass = Class.new do + attr_reader :an_attribute + + def an_attribute_setter + @an_attribute = :the_value + end + end + + @parent = @klass.new + @builder = CompositeProcBuilder.new {} + end + + it "calls all of its child procs" do + @builder << proc {:proc1} + @builder << proc {:proc2} + @builder.proc.call.should == [:proc1, :proc2] + end + + it "evals procs in the caller's instance" do + the_proc = proc do + @an_attribute = :the_value + end + the_proc.class.should == Proc + @builder << the_proc + @parent.instance_eval &@builder.proc + @parent.an_attribute.should == :the_value + end + + it "binds unbound methods to the parent" do + unbound_method = @klass.instance_method(:an_attribute_setter) + unbound_method.class.should == UnboundMethod + @builder << unbound_method + @parent.instance_eval &@builder.proc + @parent.an_attribute.should == :the_value + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/dsl/configuration_spec.rb b/vendor/gems/rspec/spec/spec/dsl/configuration_spec.rb new file mode 100644 index 000000000..d0377d068 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/dsl/configuration_spec.rb @@ -0,0 +1,55 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module DSL + describe Configuration do + before(:each) do + @config = Configuration.new + @behaviour = mock("behaviour") + end + + it "should default mock framework to rspec" do + @config.mock_framework.should =~ /\/plugins\/mock_frameworks\/rspec$/ + end + + it "should let you set rspec mocking explicitly" do + @config.mock_with(:rspec) + @config.mock_framework.should =~ /\/plugins\/mock_frameworks\/rspec$/ + end + + it "should let you set mocha" do + @config.mock_with(:mocha) + @config.mock_framework.should =~ /\/plugins\/mock_frameworks\/mocha$/ + end + + it "should let you set flexmock" do + @config.mock_with(:flexmock) + @config.mock_framework.should =~ /\/plugins\/mock_frameworks\/flexmock$/ + end + + it "should let you set rr" do + @config.mock_with(:rr) + @config.mock_framework.should =~ /\/plugins\/mock_frameworks\/rr$/ + end + + it "should let you set an arbitrary adapter module" do + adapter = Module.new + @config.mock_with(adapter) + @config.mock_framework.should == adapter + end + + it "should let you define modules to be included" do + mod = Module.new + @config.include mod + @config.modules_for(nil).should include(mod) + end + + [:prepend_before, :append_before, :prepend_after, :append_after].each do |m| + it "should delegate ##{m} to Behaviour class" do + Behaviour.should_receive(m).with(:whatever) + @config.__send__(m, :whatever) + end + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/dsl/description_spec.rb b/vendor/gems/rspec/spec/spec/dsl/description_spec.rb new file mode 100644 index 000000000..d9fe4100f --- /dev/null +++ b/vendor/gems/rspec/spec/spec/dsl/description_spec.rb @@ -0,0 +1,89 @@ +require File.dirname(__FILE__) + '/../../spec_helper' + +module Spec + module DSL + describe Description, " constructed with a single String" do + before(:each) {@description = Description.new("abc")} + + it "should provide that string as its name" do + @description.description.should == "abc" + end + it "should provide nil as its type" do + @description.described_type.should be_nil + end + it "should respond to []" do + @description[:key].should be_nil + end + it "should respond to []=" do + @description[:key] = :value + @description[:key].should == :value + end + it "should return for == when value matches description" do + @description.should == "abc" + end + it "should return for == when value is other description that matches description" do + @description.should == Description.new("abc") + end + end + + describe Description, " constructed with a Type" do + before(:each) {@description = Description.new(Behaviour)} + + it "should provide a String representation of that type (fully qualified) as its name" do + @description.description.should == "Spec::DSL::Behaviour" + end + it "should provide that type (fully qualified) as its type" do + @description.described_type.should == Spec::DSL::Behaviour + end + end + + describe Description, " constructed with a Type and a String" do + before(:each) {@description = Description.new(Behaviour, " behaving")} + + it "should include the type and second String in its name" do + @description.description.should == "Spec::DSL::Behaviour behaving" + end + it "should provide that type (fully qualified) as its type" do + @description.described_type.should == Spec::DSL::Behaviour + end + end + + describe Description, "constructed with a Type and a String not starting with a space" do + before(:each) {@description = Description.new(Behaviour, "behaving")} + + it "should include the type and second String with a space in its name" do + @description.description.should == "Spec::DSL::Behaviour behaving" + end + end + + describe Description, "constructed with a Type and a String starting with a ." do + before(:each) {@description = Description.new(Behaviour, ".behaving")} + + it "should include the type and second String with a space in its name" do + @description.description.should == "Spec::DSL::Behaviour.behaving" + end + end + + describe Description, "constructed with a Type and a String starting with a #" do + before(:each) {@description = Description.new(Behaviour, "#behaving")} + + it "should include the type and second String with a space in its name" do + @description.description.should == "Spec::DSL::Behaviour#behaving" + end + end + + describe Description, " constructed with options" do + before(:each) do + @description = Description.new(Behaviour, :a => "b", :spec_path => "blah") + end + + it "should provide its options" do + @description[:a].should == "b" + end + + it "should wrap spec path using File.expand_path" do + @description[:spec_path].should == File.expand_path("blah") + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/dsl/example_class_spec.rb b/vendor/gems/rspec/spec/spec/dsl/example_class_spec.rb new file mode 100644 index 000000000..474d24e44 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/dsl/example_class_spec.rb @@ -0,0 +1,24 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module DSL + describe Example, " class" do + + def run(example) + example.run(@reporter, nil, nil, nil, Object.new) + end + + before do + @reporter = stub("reporter", :example_started => nil, :example_finished => nil) + @example_class = Example.dup + end + + it "should report errors in example" do + error = Exception.new + example = @example_class.new("example") {raise(error)} + @reporter.should_receive(:example_finished).with(equal(example), error, "example", false) + run(example) + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/dsl/example_instance_spec.rb b/vendor/gems/rspec/spec/spec/dsl/example_instance_spec.rb new file mode 100644 index 000000000..67b19604c --- /dev/null +++ b/vendor/gems/rspec/spec/spec/dsl/example_instance_spec.rb @@ -0,0 +1,160 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module DSL + describe Example, " instance" do + predicate_matchers[:is_a] = [:is_a?] + + before(:each) do + @reporter = stub("reporter", :example_started => nil, :example_finished => nil) + end + + it "should send reporter example_started" do + example=Example.new("example") {} + @reporter.should_receive(:example_started).with(equal(example)) + example.run(@reporter, nil, nil, false, nil) + end + + it "should report its name for dry run" do + example=Example.new("example") {} + @reporter.should_receive(:example_finished).with(equal(example)) + example.run(@reporter, nil, nil, true, nil) #4th arg indicates dry run + end + + it "should report success" do + example=Example.new("example") {} + @reporter.should_receive(:example_finished).with(equal(example), nil, nil, false) + example.run(@reporter, nil, nil, nil, nil) + end + + it "should report failure due to failure" do + example=Example.new("example") do + (2+2).should == 5 + end + @reporter.should_receive(:example_finished).with(equal(example), is_a(Spec::Expectations::ExpectationNotMetError), "example", false) + example.run(@reporter, nil, nil, nil, nil) + end + + it "should report failure due to error" do + error=NonStandardError.new + example=Example.new("example") do + raise(error) + end + @reporter.should_receive(:example_finished).with(equal(example), error, "example", false) + example.run(@reporter, nil, nil, nil, nil) + end + + it "should run example in scope of supplied object" do + scope_class = Class.new + example=Example.new("should pass") do + self.instance_of?(Example).should == false + self.instance_of?(scope_class).should == true + end + @reporter.should_receive(:example_finished).with(equal(example), nil, nil, false) + example.run(@reporter, nil, nil, nil, scope_class.new) + end + + it "should not run example block if before_each fails" do + example_ran = false + example=Example.new("should pass") {example_ran = true} + before_each = lambda {raise NonStandardError} + example.run(@reporter, before_each, nil, nil, Object.new) + example_ran.should == false + end + + it "should run after_each block if before_each fails" do + after_each_ran = false + example=Example.new("should pass") {} + before_each = lambda {raise NonStandardError} + after_each = lambda {after_each_ran = true} + example.run(@reporter, before_each, after_each, nil, Object.new) + after_each_ran.should == true + end + + it "should run after_each block when example fails" do + example=Example.new("example") do + raise(NonStandardError.new("in body")) + end + after_each=lambda do + raise("in after_each") + end + @reporter.should_receive(:example_finished) do |example, error, location| + example.should equal(example) + location.should eql("example") + error.message.should eql("in body") + end + example.run(@reporter, nil, after_each, nil, nil) + end + + it "should report failure location when in before_each" do + example=Example.new("example") {} + before_each=lambda { raise(NonStandardError.new("in before_each")) } + @reporter.should_receive(:example_finished) do |name, error, location| + name.should equal(example) + error.message.should eql("in before_each") + location.should eql("before(:each)") + end + example.run(@reporter, before_each, nil, nil, nil) + end + + it "should report failure location when in after_each" do + example = Example.new("example") {} + after_each = lambda { raise(NonStandardError.new("in after_each")) } + @reporter.should_receive(:example_finished) do |name, error, location| + name.should equal(example) + error.message.should eql("in after_each") + location.should eql("after(:each)") + end + example.run(@reporter, nil, after_each, nil, nil) + end + + it "should accept an options hash following the example name" do + example = Example.new("name", :key => 'value') + end + + it "should report NO NAME when told to use generated description with --dry-run" do + example = Example.new(:__generate_description) { + 5.should == 5 + } + @reporter.should_receive(:example_finished) do |example, error, location| + example.description.should == "NO NAME (Because of --dry-run)" + end + example.run(@reporter, lambda{}, lambda{}, true, Object.new) + end + + it "should report NO NAME when told to use generated description with no expectations" do + example = Example.new(:__generate_description) {} + @reporter.should_receive(:example_finished) do |example, error, location| + example.description.should == "NO NAME (Because there were no expectations)" + end + example.run(@reporter, lambda{}, lambda{}, false, Object.new) + end + + it "should report NO NAME when told to use generated description and matcher fails" do + example = Example.new(:__generate_description) do + 5.should "" # Has no matches? method.. + end + @reporter.should_receive(:example_finished) do |example, error, location| + example.description.should == "NO NAME (Because of Error raised in matcher)" + end + example.run(@reporter, nil, nil, nil, Object.new) + end + + it "should report generated description when told to and it is available" do + example = Example.new(:__generate_description) { + 5.should == 5 + } + @reporter.should_receive(:example_finished) do |example, error, location| + example.description.should == "should == 5" + end + example.run(@reporter, nil, nil, nil, Object.new) + end + + it "should unregister description_generated callback (lest a memory leak should build up)" do + example = Example.new("something") + Spec::Matchers.should_receive(:unregister_description_generated).with(is_a(Proc)) + example.run(@reporter, nil, nil, nil, Object.new) + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/dsl/example_matcher_spec.rb b/vendor/gems/rspec/spec/spec/dsl/example_matcher_spec.rb new file mode 100644 index 000000000..ea2f2a787 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/dsl/example_matcher_spec.rb @@ -0,0 +1,91 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module DSL + module ExampleMatcherSpecHelper + class MatchDescription + def initialize(description) + @description = description + end + + def matches?(matcher) + matcher.matches?(@description) + end + + def failure_message + "expected matcher.matches?(#{@description.inspect}) to return true, got false" + end + + def negative_failure_message + "expected matcher.matches?(#{@description.inspect}) to return false, got true" + end + end + def match_description(description) + MatchDescription.new(description) + end + end + + describe ExampleMatcher do + include ExampleMatcherSpecHelper + + it "should match correct behaviour and example" do + matcher = ExampleMatcher.new("behaviour", "example") + matcher.should match_description("behaviour example") + end + + it "should not match wrong example" do + matcher = ExampleMatcher.new("behaviour", "other example") + matcher.should_not match_description("behaviour example") + end + + it "should not match wrong behaviour" do + matcher = ExampleMatcher.new("other behaviour", "example") + matcher.should_not match_description("behaviour example") + end + + it "should match example only" do + matcher = ExampleMatcher.new("behaviour", "example") + matcher.should match_description("example") + end + + it "should match behaviour only" do + matcher = ExampleMatcher.new("behaviour", "example") + matcher.should match_description("behaviour") + end + + it "should escape regexp chars" do + matcher = ExampleMatcher.new("(con|text)", "[example]") + matcher.should_not match_description("con p") + end + + it "should match when behaviour is modularized" do + matcher = ExampleMatcher.new("MyModule::MyClass", "example") + matcher.should match_description("MyClass example") + end + end + + describe ExampleMatcher, "normal case" do + it "matches when passed in example matches" do + matcher = ExampleMatcher.new("Foo", "bar") + matcher.matches?(["no match", "Foo bar"]).should == true + end + + it "does not match when no passed in examples match" do + matcher = ExampleMatcher.new("Foo", "bar") + matcher.matches?(["no match1", "no match2"]).should == false + end + end + + describe ExampleMatcher, "where description has '::' in it" do + it "matches when passed in example matches" do + matcher = ExampleMatcher.new("Foo::Bar", "baz") + matcher.matches?(["no match", "Foo::Bar baz"]).should == true + end + + it "does not match when no passed in examples match" do + matcher = ExampleMatcher.new("Foo::Bar", "baz") + matcher.matches?(["no match1", "no match2"]).should == false + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/dsl/example_should_raise_spec.rb b/vendor/gems/rspec/spec/spec/dsl/example_should_raise_spec.rb new file mode 100644 index 000000000..a6d582068 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/dsl/example_should_raise_spec.rb @@ -0,0 +1,137 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module DSL + describe Example, " declared with {:should_raise => ...}" do + before(:each) do + @reporter = mock("reporter") + @reporter.stub!(:example_started) + end + + def verify_error(error, message=nil) + error.should be_an_instance_of(Spec::Expectations::ExpectationNotMetError) + unless message.nil? + return error.message.should =~ message if Regexp === message + return error.message.should == message + end + end + + it "true} should pass when there is an ExpectationNotMetError" do + example = Spec::DSL:: Example.new("example", :should_raise => true) do + raise Spec::Expectations::ExpectationNotMetError + end + @reporter.should_receive(:example_finished) do |description, error| + error.should be_nil + end + example.run(@reporter, nil, nil, nil, nil) + end + + it "true} should fail if nothing is raised" do + example = Spec::DSL:: Example.new("example", :should_raise => true) {} + @reporter.should_receive(:example_finished) do |example_name, error| + verify_error(error, /example block expected Exception but nothing was raised/) + end + example.run(@reporter, nil, nil, nil, nil) + end + + it "NameError} should pass when there is a NameError" do + example = Spec::DSL:: Example.new("example", :should_raise => NameError) do + raise NameError + end + @reporter.should_receive(:example_finished) do |example_name, error| + error.should be_nil + end + example.run(@reporter, nil, nil, nil, nil) + end + + it "NameError} should fail when there is no error" do + example = Spec::DSL:: Example.new("example", :should_raise => NameError) do + #do nothing + end + @reporter.should_receive(:example_finished) do |example_name, error| + verify_error(error,/example block expected NameError but nothing was raised/) + end + example.run(@reporter, nil, nil, nil, nil) + end + + it "NameError} should fail when there is the wrong error" do + example = Spec::DSL:: Example.new("example", :should_raise => NameError) do + raise RuntimeError + end + @reporter.should_receive(:example_finished) do |example_name, error| + verify_error(error, /example block expected NameError but raised.+RuntimeError/) + end + example.run(@reporter, nil, nil, nil, nil) + end + + it "[NameError]} should pass when there is a NameError" do + example = Spec::DSL:: Example.new("spec", :should_raise => [NameError]) do + raise NameError + end + @reporter.should_receive(:example_finished) do |description, error| + error.should be_nil + end + example.run(@reporter, nil, nil, nil, nil) + end + + it "[NameError]} should fail when there is no error" do + example = Spec::DSL:: Example.new("spec", :should_raise => [NameError]) do + end + @reporter.should_receive(:example_finished) do |description, error| + verify_error(error, /example block expected NameError but nothing was raised/) + end + example.run(@reporter, nil, nil, nil, nil) + end + + it "[NameError]} should fail when there is the wrong error" do + example = Spec::DSL:: Example.new("spec", :should_raise => [NameError]) do + raise RuntimeError + end + @reporter.should_receive(:example_finished) do |description, error| + verify_error(error, /example block expected NameError but raised.+RuntimeError/) + end + example.run(@reporter, nil, nil, nil, nil) + end + + it "[NameError, 'message'} should pass when there is a NameError with the right message" do + example = Spec::DSL:: Example.new("spec", :should_raise => [NameError, 'expected']) do + raise NameError, 'expected' + end + @reporter.should_receive(:example_finished) do |description, error| + error.should be_nil + end + example.run(@reporter, nil, nil, nil, nil) + end + + it "[NameError, 'message'} should pass when there is a NameError with a message matching a regex" do + example = Spec::DSL:: Example.new("spec", :should_raise => [NameError, /xpec/]) do + raise NameError, 'expected' + end + @reporter.should_receive(:example_finished) do |description, error| + error.should be_nil + end + example.run(@reporter, nil, nil, nil, nil) + end + + it "[NameError, 'message'} should fail when there is a NameError with the wrong message" do + example = Spec::DSL:: Example.new("spec", :should_raise => [NameError, 'expected']) do + raise NameError, 'wrong message' + end + @reporter.should_receive(:example_finished) do |description, error| + verify_error(error, /example block expected #<NameError: expected> but raised #<NameError: wrong message>/) + end + example.run(@reporter, nil, nil, nil, nil) + end + + it "[NameError, 'message'} should fail when there is a NameError with a message not matching regexp" do + example = Spec::DSL:: Example.new("spec", :should_raise => [NameError, /exp/]) do + raise NameError, 'wrong message' + end + @reporter.should_receive(:example_finished) do |description, error| + verify_error(error, /example block expected #<NameError: \(\?-mix:exp\)> but raised #<NameError: wrong message>/) + end + example.run(@reporter, nil, nil, nil, nil) + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/dsl/predicate_matcher_spec.rb b/vendor/gems/rspec/spec/spec/dsl/predicate_matcher_spec.rb new file mode 100644 index 000000000..02cd89399 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/dsl/predicate_matcher_spec.rb @@ -0,0 +1,21 @@ +require File.dirname(__FILE__) + '/../../spec_helper' + +module Spec + module DSL + class Fish + def can_swim?(distance_in_yards) + distance_in_yards < 1000 + end + end + + describe "predicate_matcher[method_on_object] = matcher_method" do + predicate_matchers[:swim] = :can_swim? + it "should match matcher_method if method_on_object returns true" do + swim(100).matches?(Fish.new).should be_true + end + it "should not match matcher_method if method_on_object returns false" do + swim(10000).matches?(Fish.new).should be_false + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/dsl/shared_behaviour_spec.rb b/vendor/gems/rspec/spec/spec/dsl/shared_behaviour_spec.rb new file mode 100644 index 000000000..a4288360c --- /dev/null +++ b/vendor/gems/rspec/spec/spec/dsl/shared_behaviour_spec.rb @@ -0,0 +1,252 @@ +require File.dirname(__FILE__) + '/../../spec_helper' + +module Spec + module DSL + describe Behaviour, ", with :shared => true" do + + before(:each) do + @formatter = Spec::Mocks::Mock.new("formatter", :null_object => true) + @behaviour = behaviour_class.new("behaviour") {} + end + + after(:each) do + @formatter.rspec_verify + @behaviour_class = nil + $shared_behaviours.clear unless $shared_behaviours.nil? + end + + def behaviour_class + unless @behaviour_class + @behaviour_class = Behaviour.dup + # dup copies the class instance vars + @behaviour_class.instance_variable_set(:@shared_behaviours, nil) + end + @behaviour_class + end + + def make_shared_behaviour(name, opts=nil, &block) + behaviour = behaviour_class.new(name, :shared => true, &block) + behaviour_class.add_shared_behaviour(behaviour) + behaviour + end + + def non_shared_behaviour() + @non_shared_behaviour ||= behaviour_class.new("behaviour") {} + end + + it "should accept an optional options hash" do + lambda { behaviour_class.new("context") {} }.should_not raise_error(Exception) + lambda { behaviour_class.new("context", :shared => true) {} }.should_not raise_error(Exception) + end + + it "should return all shared behaviours" do + b1 = make_shared_behaviour("b1", :shared => true) {} + b2 = make_shared_behaviour("b2", :shared => true) {} + + b1.should_not be(nil) + b2.should_not be(nil) + + behaviour_class.find_shared_behaviour("b1").should equal(b1) + behaviour_class.find_shared_behaviour("b2").should equal(b2) + end + + it "should be shared when configured as shared" do + behaviour = make_shared_behaviour("behaviour") {} + behaviour.should be_shared + end + + it "should not be shared when not configured as shared" do + non_shared_behaviour.should_not be_shared + end + + it "should raise if run when shared" do + behaviour = make_shared_behaviour("context") {} + $example_ran = false + behaviour.it("test") {$example_ran = true} + lambda { behaviour.run(@formatter) }.should raise_error + $example_ran.should be_false + end + + it "should contain examples when shared" do + shared_behaviour = make_shared_behaviour("shared behaviour") {} + shared_behaviour.it("shared example") {} + shared_behaviour.number_of_examples.should == 1 + end + + it "should complain when adding a second shared behaviour with the same description" do + describe "shared behaviour", :shared => true do + end + lambda do + describe "shared behaviour", :shared => true do + end + end.should raise_error(ArgumentError) + end + + it "should NOT complain when adding the same shared behaviour instance again" do + shared_behaviour = behaviour_class.new("shared behaviour", :shared => true) {} + behaviour_class.add_shared_behaviour(shared_behaviour) + behaviour_class.add_shared_behaviour(shared_behaviour) + end + + it "should NOT complain when adding the same shared behaviour again (i.e. file gets reloaded)" do + lambda do + 2.times do + describe "shared behaviour which gets loaded twice", :shared => true do + end + end + end.should_not raise_error(ArgumentError) + end + + it "should NOT complain when adding the same shared behaviour in same file with different absolute path" do + shared_behaviour_1 = behaviour_class.new("shared behaviour", :shared => true) {} + shared_behaviour_2 = behaviour_class.new("shared behaviour", :shared => true) {} + + shared_behaviour_1.description[:spec_path] = "/my/spec/a/../shared.rb" + shared_behaviour_2.description[:spec_path] = "/my/spec/b/../shared.rb" + + behaviour_class.add_shared_behaviour(shared_behaviour_1) + behaviour_class.add_shared_behaviour(shared_behaviour_2) + end + + it "should complain when adding a different shared behaviour with the same name in a different file with the same basename" do + shared_behaviour_1 = behaviour_class.new("shared behaviour", :shared => true) {} + shared_behaviour_2 = behaviour_class.new("shared behaviour", :shared => true) {} + + shared_behaviour_1.description[:spec_path] = "/my/spec/a/shared.rb" + shared_behaviour_2.description[:spec_path] = "/my/spec/b/shared.rb" + + behaviour_class.add_shared_behaviour(shared_behaviour_1) + lambda do + behaviour_class.add_shared_behaviour(shared_behaviour_2) + end.should raise_error(ArgumentError, /already exists/) + end + + it "should add examples to current behaviour when calling it_should_behave_like" do + shared_behaviour = make_shared_behaviour("shared behaviour") {} + shared_behaviour.it("shared example") {} + shared_behaviour.it("shared example 2") {} + + @behaviour.it("example") {} + @behaviour.number_of_examples.should == 1 + @behaviour.it_should_behave_like("shared behaviour") + @behaviour.number_of_examples.should == 3 + end + + it "should run shared examples" do + shared_example_ran = false + shared_behaviour = make_shared_behaviour("shared behaviour") {} + shared_behaviour.it("shared example") { shared_example_ran = true } + + example_ran = false + + @behaviour.it_should_behave_like("shared behaviour") + @behaviour.it("example") {example_ran = true} + @behaviour.run(@formatter) + example_ran.should be_true + shared_example_ran.should be_true + end + + it "should run setup and teardown from shared behaviour" do + shared_setup_ran = false + shared_teardown_ran = false + shared_behaviour = make_shared_behaviour("shared behaviour") {} + shared_behaviour.before { shared_setup_ran = true } + shared_behaviour.after { shared_teardown_ran = true } + shared_behaviour.it("shared example") { shared_example_ran = true } + + example_ran = false + + @behaviour.it_should_behave_like("shared behaviour") + @behaviour.it("example") {example_ran = true} + @behaviour.run(@formatter) + example_ran.should be_true + shared_setup_ran.should be_true + shared_teardown_ran.should be_true + end + + it "should run before(:all) and after(:all) only once from shared behaviour" do + shared_before_all_run_count = 0 + shared_after_all_run_count = 0 + shared_behaviour = make_shared_behaviour("shared behaviour") {} + shared_behaviour.before(:all) { shared_before_all_run_count += 1} + shared_behaviour.after(:all) { shared_after_all_run_count += 1} + shared_behaviour.it("shared example") { shared_example_ran = true } + + example_ran = false + + @behaviour.it_should_behave_like("shared behaviour") + @behaviour.it("example") {example_ran = true} + @behaviour.run(@formatter) + example_ran.should be_true + shared_before_all_run_count.should == 1 + shared_after_all_run_count.should == 1 + end + + it "should include modules, included into shared behaviour, into current behaviour" do + @formatter.should_receive(:add_behaviour).with(any_args) + @formatter.should_receive(:example_finished).twice.with(any_args) + + shared_behaviour = make_shared_behaviour("shared behaviour") {} + shared_behaviour.it("shared example") { shared_example_ran = true } + + mod1_method_called = false + mod1 = Module.new do + define_method :mod1_method do + mod1_method_called = true + end + end + + mod2_method_called = false + mod2 = Module.new do + define_method :mod2_method do + mod2_method_called = true + end + end + + shared_behaviour.include mod2 + + @behaviour.it_should_behave_like("shared behaviour") + @behaviour.include mod1 + + @behaviour.it("test") do + mod1_method + mod2_method + end + @behaviour.run(@formatter) + mod1_method_called.should be_true + mod2_method_called.should be_true + end + + it "should make methods defined in the shared behaviour available in consuming behaviour" do + shared_behaviour = make_shared_behaviour("shared behaviour xyz") do + def a_shared_helper_method + "this got defined in a shared behaviour" + end + end + @behaviour.it_should_behave_like("shared behaviour xyz") + success = false + @behaviour.it("should access a_shared_helper_method") do + a_shared_helper_method + success = true + end + @behaviour.run(@formatter) + success.should be_true + end + + it "should error if told to inherit from a class" do + shared_behaviour = make_shared_behaviour("shared behaviour") {} + shared_behaviour.it("shared example") { shared_example_ran = true } + lambda { shared_behaviour.inherit Object }.should raise_error(ArgumentError) + end + + it "should raise when named shared behaviour can not be found" do + begin + @behaviour.it_should_behave_like("non-existent shared behaviour") + violated + rescue => e + e.message.should == "Shared Behaviour 'non-existent shared behaviour' can not be found" + end + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/expectations/differs/default_spec.rb b/vendor/gems/rspec/spec/spec/expectations/differs/default_spec.rb new file mode 100644 index 000000000..ae5551aaf --- /dev/null +++ b/vendor/gems/rspec/spec/spec/expectations/differs/default_spec.rb @@ -0,0 +1,107 @@ +require File.dirname(__FILE__) + '/../../../spec_helper.rb' +require File.dirname(__FILE__) + '/../../../../lib/spec/expectations/differs/default' + +module Spec + module Fixtures + class Animal + def initialize(name,species) + @name,@species = name,species + end + + def inspect + <<-EOA +<Animal + name=#{@name}, + species=#{@species} +> + EOA + end + end + end +end + +describe "Diff" do + before(:each) do + @differ = Spec::Expectations::Differs::Default.new + end + + it "should output unified diff of two strings" do + expected="foo\nbar\nzap\nthis\nis\nsoo\nvery\nvery\nequal\ninsert\na\nline\n" + actual="foo\nzap\nbar\nthis\nis\nsoo\nvery\nvery\nequal\ninsert\na\nanother\nline\n" + expected_diff="\n\n@@ -1,6 +1,6 @@\n foo\n-bar\n zap\n+bar\n this\n is\n soo\n@@ -9,5 +9,6 @@\n equal\n insert\n a\n+another\n line\n" + diff = @differ.diff_as_string(expected, actual) + diff.should eql(expected_diff) + end + + it "should output unified diff message of two arrays" do + expected = [ :foo, 'bar', :baz, 'quux', :metasyntactic, 'variable', :delta, 'charlie', :width, 'quite wide' ] + actual = [ :foo, 'bar', :baz, 'quux', :metasyntactic, 'variable', :delta, 'tango' , :width, 'very wide' ] + + expected_diff = <<'EOD' + + +@@ -5,7 +5,7 @@ + :metasyntactic, + "variable", + :delta, +- "charlie", ++ "tango", + :width, +- "quite wide"] ++ "very wide"] +EOD + + + diff = @differ.diff_as_object(expected,actual) + diff.should == expected_diff + end + + it "should output unified diff message of two objects" do + expected = Spec::Fixtures::Animal.new "bob", "giraffe" + actual = Spec::Fixtures::Animal.new "bob", "tortoise" + + expected_diff = <<'EOD' + +@@ -1,5 +1,5 @@ + <Animal + name=bob, +- species=giraffe ++ species=tortoise + > +EOD + + diff = @differ.diff_as_object(expected,actual) + diff.should == expected_diff + end + +end + + +describe "Diff in context format" do + before(:each) do + @differ = Spec::Expectations::Differs::Default.new(:context) + end + + it "should output unified diff message of two objects" do + expected = Spec::Fixtures::Animal.new "bob", "giraffe" + actual = Spec::Fixtures::Animal.new "bob", "tortoise" + + expected_diff = <<'EOD' + +*************** +*** 1,5 **** + <Animal + name=bob, +! species=giraffe + > +--- 1,5 ---- + <Animal + name=bob, +! species=tortoise + > +EOD + + diff = @differ.diff_as_object(expected,actual) + diff.should == expected_diff + end +end diff --git a/vendor/gems/rspec/spec/spec/expectations/extensions/object_spec.rb b/vendor/gems/rspec/spec/spec/expectations/extensions/object_spec.rb new file mode 100644 index 000000000..587053293 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/expectations/extensions/object_spec.rb @@ -0,0 +1,46 @@ +require File.dirname(__FILE__) + '/../../../spec_helper.rb' + +describe Object, "#should" do + before(:each) do + @target = "target" + @matcher = mock("matcher") + @matcher.stub!(:matches?).and_return(true) + @matcher.stub!(:failure_message) + end + + it "should accept and interact with a matcher" do + @matcher.should_receive(:matches?).with(@target).and_return(true) + + @target.should @matcher + end + + it "should ask for a failure_message when matches? returns false" do + @matcher.should_receive(:matches?).with(@target).and_return(false) + @matcher.should_receive(:failure_message).and_return("the failure message") + lambda { + @target.should @matcher + }.should fail_with("the failure message") + end +end + +describe Object, "#should_not" do + before(:each) do + @target = "target" + @matcher = mock("matcher") + end + + it "should accept and interact with a matcher" do + @matcher.should_receive(:matches?).with(@target).and_return(false) + @matcher.stub!(:negative_failure_message) + + @target.should_not @matcher + end + + it "should ask for a negative_failure_message when matches? returns true" do + @matcher.should_receive(:matches?).with(@target).and_return(true) + @matcher.should_receive(:negative_failure_message).and_return("the negative failure message") + lambda { + @target.should_not @matcher + }.should fail_with("the negative failure message") + end +end diff --git a/vendor/gems/rspec/spec/spec/expectations/fail_with_spec.rb b/vendor/gems/rspec/spec/spec/expectations/fail_with_spec.rb new file mode 100644 index 000000000..4c369ce3a --- /dev/null +++ b/vendor/gems/rspec/spec/spec/expectations/fail_with_spec.rb @@ -0,0 +1,71 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +describe Spec::Expectations, "#fail_with with no diff" do + before(:each) do + @old_differ = Spec::Expectations.differ + Spec::Expectations.differ = nil + end + + it "should handle just a message" do + lambda { + Spec::Expectations.fail_with "the message" + }.should fail_with("the message") + end + + it "should handle an Array" do + lambda { + Spec::Expectations.fail_with ["the message","expected","actual"] + }.should fail_with("the message") + end + + after(:each) do + Spec::Expectations.differ = @old_differ + end +end + +describe Spec::Expectations, "#fail_with with diff" do + before(:each) do + @old_differ = Spec::Expectations.differ + @differ = mock("differ") + Spec::Expectations.differ = @differ + end + + it "should not call differ if no expected/actual" do + lambda { + Spec::Expectations.fail_with "the message" + }.should fail_with("the message") + end + + it "should call differ if expected/actual are presented separately" do + @differ.should_receive(:diff_as_string).and_return("diff") + lambda { + Spec::Expectations.fail_with "the message", "expected", "actual" + }.should fail_with("the message\nDiff:diff") + end + + it "should call differ if expected/actual are not strings" do + @differ.should_receive(:diff_as_object).and_return("diff") + lambda { + Spec::Expectations.fail_with "the message", :expected, :actual + }.should fail_with("the message\nDiff:diff") + end + + it "should not call differ if expected or actual are procs" do + @differ.should_not_receive(:diff_as_string) + @differ.should_not_receive(:diff_as_object) + lambda { + Spec::Expectations.fail_with "the message", lambda {}, lambda {} + }.should fail_with("the message") + end + + it "should call differ if expected/actual are presented in an Array with message" do + @differ.should_receive(:diff_as_string).with("actual","expected").and_return("diff") + lambda { + Spec::Expectations.fail_with(["the message", "expected", "actual"]) + }.should fail_with(/the message\nDiff:diff/) + end + + after(:each) do + Spec::Expectations.differ = @old_differ + end +end diff --git a/vendor/gems/rspec/spec/spec/matchers/be_close_spec.rb b/vendor/gems/rspec/spec/spec/matchers/be_close_spec.rb new file mode 100644 index 000000000..d8452d408 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/matchers/be_close_spec.rb @@ -0,0 +1,39 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' +module Spec + module Matchers + describe BeClose do + it "should match when value == target" do + BeClose.new(5.0, 0.5).matches?(5.0).should be_true + end + it "should match when value < (target + delta)" do + BeClose.new(5.0, 0.5).matches?(5.49).should be_true + end + it "should match when value > (target - delta)" do + BeClose.new(5.0, 0.5).matches?(4.51).should be_true + end + it "should not match when value == (target - delta)" do + BeClose.new(5.0, 0.5).matches?(4.5).should be_false + end + it "should not match when value < (target - delta)" do + BeClose.new(5.0, 0.5).matches?(4.49).should be_false + end + it "should not match when value == (target + delta)" do + BeClose.new(5.0, 0.5).matches?(5.5).should be_false + end + it "should not match when value > (target + delta)" do + BeClose.new(5.0, 0.5).matches?(5.51).should be_false + end + it "should provide a useful failure message" do + #given + matcher = BeClose.new(5.0, 0.5) + #when + matcher.matches?(5.51) + #then + matcher.failure_message.should == "expected 5.0 +/- (< 0.5), got 5.51" + end + it "should describe itself" do + BeClose.new(5.0, 0.5).description.should == "be close to 5.0 (within +- 0.5)" + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/matchers/be_spec.rb b/vendor/gems/rspec/spec/spec/matchers/be_spec.rb new file mode 100644 index 000000000..84653873c --- /dev/null +++ b/vendor/gems/rspec/spec/spec/matchers/be_spec.rb @@ -0,0 +1,209 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +describe "should be_predicate" do + it "should pass when actual returns true for :predicate?" do + actual = stub("actual", :happy? => true) + actual.should be_happy + end + + it "should pass when actual returns true for :predicates? (present tense)" do + actual = stub("actual", :exists? => true) + actual.should be_exist + end + + it "should fail when actual returns false for :predicate?" do + actual = stub("actual", :happy? => false) + lambda { + actual.should be_happy + }.should fail_with("expected happy? to return true, got false") + end + + it "should fail when actual does not respond to :predicate?" do + lambda { + Object.new.should be_happy + }.should raise_error(NameError) + end +end + +describe "should_not be_predicate" do + it "should pass when actual returns false for :sym?" do + actual = stub("actual", :happy? => false) + actual.should_not be_happy + end + + it "should fail when actual returns true for :sym?" do + actual = stub("actual", :happy? => true) + lambda { + actual.should_not be_happy + }.should fail_with("expected happy? to return false, got true") + end + + it "should fail when actual does not respond to :sym?" do + lambda { + Object.new.should_not be_happy + }.should raise_error(NameError) + end +end + +describe "should be_predicate(*args)" do + it "should pass when actual returns true for :predicate?(*args)" do + actual = mock("actual") + actual.should_receive(:older_than?).with(3).and_return(true) + actual.should be_older_than(3) + end + + it "should fail when actual returns false for :predicate?(*args)" do + actual = mock("actual") + actual.should_receive(:older_than?).with(3).and_return(false) + lambda { + actual.should be_older_than(3) + }.should fail_with("expected older_than?(3) to return true, got false") + end + + it "should fail when actual does not respond to :predicate?" do + lambda { + Object.new.should be_older_than(3) + }.should raise_error(NameError) + end +end + +describe "should_not be_predicate(*args)" do + it "should pass when actual returns false for :predicate?(*args)" do + actual = mock("actual") + actual.should_receive(:older_than?).with(3).and_return(false) + actual.should_not be_older_than(3) + end + + it "should fail when actual returns true for :predicate?(*args)" do + actual = mock("actual") + actual.should_receive(:older_than?).with(3).and_return(true) + lambda { + actual.should_not be_older_than(3) + }.should fail_with("expected older_than?(3) to return false, got true") + end + + it "should fail when actual does not respond to :predicate?" do + lambda { + Object.new.should_not be_older_than(3) + }.should raise_error(NameError) + end +end + +describe "should be_true" do + it "should pass when actual equal(true)" do + true.should be_true + end + + it "should fail when actual equal(false)" do + lambda { + false.should be_true + }.should fail_with("expected true, got false") + end +end + +describe "should be_false" do + it "should pass when actual equal(false)" do + false.should be_false + end + + it "should fail when actual equal(true)" do + lambda { + true.should be_false + }.should fail_with("expected false, got true") + end +end + +describe "should be_nil" do + it "should pass when actual is nil" do + nil.should be_nil + end + + it "should fail when actual is not nil" do + lambda { + :not_nil.should be_nil + }.should fail_with("expected nil, got :not_nil") + end +end + +describe "should_not be_nil" do + it "should pass when actual is not nil" do + :not_nil.should_not be_nil + end + + it "should fail when actual is nil" do + lambda { + nil.should_not be_nil + }.should fail_with("expected not nil, got nil") + end +end + +describe "should be <" do + it "should pass when < operator returns true" do + 3.should be < 4 + end + + it "should fail when < operator returns false" do + lambda { 3.should be < 3 }.should fail_with("expected < 3, got 3") + end +end + +describe "should be <=" do + it "should pass when <= operator returns true" do + 3.should be <= 4 + 4.should be <= 4 + end + + it "should fail when <= operator returns false" do + lambda { 3.should be <= 2 }.should fail_with("expected <= 2, got 3") + end +end + +describe "should be >=" do + it "should pass when >= operator returns true" do + 4.should be >= 4 + 5.should be >= 4 + end + + it "should fail when >= operator returns false" do + lambda { 3.should be >= 4 }.should fail_with("expected >= 4, got 3") + end +end + +describe "should be >" do + it "should pass when > operator returns true" do + 5.should be > 4 + end + + it "should fail when > operator returns false" do + lambda { 3.should be > 4 }.should fail_with("expected > 4, got 3") + end +end + +describe "should be ==" do + it "should pass when == operator returns true" do + 5.should be == 5 + end + + it "should fail when == operator returns false" do + lambda { 3.should be == 4 }.should fail_with("expected == 4, got 3") + end +end + +describe "should be ===" do + it "should pass when === operator returns true" do + Hash.should be === Hash.new + end + + it "should fail when === operator returns false" do + lambda { Hash.should be === "not a hash" }.should fail_with(%[expected === "not a hash", got Hash]) + end +end + +describe "should be(value)" do + it "should pass if actual.equal?(value)" do + 5.should be(5) + end + it "should fail if !actual.equal?(value)" do + lambda { 5.should be(6) }.should fail_with("expected 6, got 5") + end +end diff --git a/vendor/gems/rspec/spec/spec/matchers/change_spec.rb b/vendor/gems/rspec/spec/spec/matchers/change_spec.rb new file mode 100644 index 000000000..70e55328e --- /dev/null +++ b/vendor/gems/rspec/spec/spec/matchers/change_spec.rb @@ -0,0 +1,232 @@ +#Based on patch from Wilson Bilkovich + +require File.dirname(__FILE__) + '/../../spec_helper.rb' +class SomethingExpected + attr_accessor :some_value +end + +describe "should change(actual, message)" do + before(:each) do + @instance = SomethingExpected.new + @instance.some_value = 5 + end + + it "should pass when actual is modified by the block" do + lambda {@instance.some_value = 6}.should change(@instance, :some_value) + end + + it "should fail when actual is not modified by the block" do + lambda do + lambda {}.should change(@instance, :some_value) + end.should fail_with("some_value should have changed, but is still 5") + end +end + +describe "should_not change(actual, message)" do + before(:each) do + @instance = SomethingExpected.new + @instance.some_value = 5 + end + + it "should pass when actual is not modified by the block" do + lambda { }.should_not change(@instance, :some_value) + end + + it "should fail when actual is not modified by the block" do + lambda do + lambda {@instance.some_value = 6}.should_not change(@instance, :some_value) + end.should fail_with("some_value should not have changed, but did change from 5 to 6") + end +end + +describe "should change { block }" do + before(:each) do + @instance = SomethingExpected.new + @instance.some_value = 5 + end + + it "should pass when actual is modified by the block" do + lambda {@instance.some_value = 6}.should change { @instance.some_value } + end + + it "should fail when actual is not modified by the block" do + lambda do + lambda {}.should change{ @instance.some_value } + end.should fail_with("result should have changed, but is still 5") + end + + it "should warn if passed a block using do/end" do + lambda do + lambda {}.should change do + end + end.should raise_error(Spec::Matchers::MatcherError, /block passed to should or should_not/) + end +end + +describe "should_not change { block }" do + before(:each) do + @instance = SomethingExpected.new + @instance.some_value = 5 + end + + it "should pass when actual is modified by the block" do + lambda {}.should_not change{ @instance.some_value } + end + + it "should fail when actual is not modified by the block" do + lambda do + lambda {@instance.some_value = 6}.should_not change { @instance.some_value } + end.should fail_with("result should not have changed, but did change from 5 to 6") + end + + it "should warn if passed a block using do/end" do + lambda do + lambda {}.should_not change do + end + end.should raise_error(Spec::Matchers::MatcherError, /block passed to should or should_not/) + end +end + +describe "should change(actual, message).by(expected)" do + before(:each) do + @instance = SomethingExpected.new + @instance.some_value = 5 + end + + it "should pass when attribute is changed by expected amount" do + lambda { @instance.some_value += 1 }.should change(@instance, :some_value).by(1) + end + + it "should fail when the attribute is changed by unexpected amount" do + lambda do + lambda { @instance.some_value += 2 }.should change(@instance, :some_value).by(1) + end.should fail_with("some_value should have been changed by 1, but was changed by 2") + end + + it "should fail when the attribute is changed by unexpected amount in the opposite direction" do + lambda do + lambda { @instance.some_value -= 1 }.should change(@instance, :some_value).by(1) + end.should fail_with("some_value should have been changed by 1, but was changed by -1") + end +end + +describe "should change{ block }.by(expected)" do + before(:each) do + @instance = SomethingExpected.new + @instance.some_value = 5 + end + + it "should pass when attribute is changed by expected amount" do + lambda { @instance.some_value += 1 }.should change{@instance.some_value}.by(1) + end + + it "should fail when the attribute is changed by unexpected amount" do + lambda do + lambda { @instance.some_value += 2 }.should change{@instance.some_value}.by(1) + end.should fail_with("result should have been changed by 1, but was changed by 2") + end + + it "should fail when the attribute is changed by unexpected amount in the opposite direction" do + lambda do + lambda { @instance.some_value -= 1 }.should change{@instance.some_value}.by(1) + end.should fail_with("result should have been changed by 1, but was changed by -1") + end +end + +describe "should change(actual, message).from(old)" do + before(:each) do + @instance = SomethingExpected.new + @instance.some_value = 'string' + end + + it "should pass when attribute is == to expected value before executing block" do + lambda { @instance.some_value = "astring" }.should change(@instance, :some_value).from("string") + end + + it "should fail when attribute is not == to expected value before executing block" do + lambda do + lambda { @instance.some_value = "knot" }.should change(@instance, :some_value).from("cat") + end.should fail_with("some_value should have initially been \"cat\", but was \"string\"") + end +end + +describe "should change{ block }.from(old)" do + before(:each) do + @instance = SomethingExpected.new + @instance.some_value = 'string' + end + + it "should pass when attribute is == to expected value before executing block" do + lambda { @instance.some_value = "astring" }.should change{@instance.some_value}.from("string") + end + + it "should fail when attribute is not == to expected value before executing block" do + lambda do + lambda { @instance.some_value = "knot" }.should change{@instance.some_value}.from("cat") + end.should fail_with("result should have initially been \"cat\", but was \"string\"") + end +end + +describe "should change(actual, message).to(new)" do + before(:each) do + @instance = SomethingExpected.new + @instance.some_value = 'string' + end + + it "should pass when attribute is == to expected value after executing block" do + lambda { @instance.some_value = "cat" }.should change(@instance, :some_value).to("cat") + end + + it "should fail when attribute is not == to expected value after executing block" do + lambda do + lambda { @instance.some_value = "cat" }.should change(@instance, :some_value).from("string").to("dog") + end.should fail_with("some_value should have been changed to \"dog\", but is now \"cat\"") + end +end + +describe "should change{ block }.to(new)" do + before(:each) do + @instance = SomethingExpected.new + @instance.some_value = 'string' + end + + it "should pass when attribute is == to expected value after executing block" do + lambda { @instance.some_value = "cat" }.should change{@instance.some_value}.to("cat") + end + + it "should fail when attribute is not == to expected value after executing block" do + lambda do + lambda { @instance.some_value = "cat" }.should change{@instance.some_value}.from("string").to("dog") + end.should fail_with("result should have been changed to \"dog\", but is now \"cat\"") + end +end + +describe "should change(actual, message).from(old).to(new)" do + before(:each) do + @instance = SomethingExpected.new + @instance.some_value = 'string' + end + + it "should pass when #to comes before #from" do + lambda { @instance.some_value = "cat" }.should change(@instance, :some_value).to("cat").from("string") + end + + it "should pass when #from comes before #to" do + lambda { @instance.some_value = "cat" }.should change(@instance, :some_value).from("string").to("cat") + end +end + +describe "should change{ block }.from(old).to(new)" do + before(:each) do + @instance = SomethingExpected.new + @instance.some_value = 'string' + end + + it "should pass when #to comes before #from" do + lambda { @instance.some_value = "cat" }.should change{@instance.some_value}.to("cat").from("string") + end + + it "should pass when #from comes before #to" do + lambda { @instance.some_value = "cat" }.should change{@instance.some_value}.from("string").to("cat") + end +end diff --git a/vendor/gems/rspec/spec/spec/matchers/description_generation_spec.rb b/vendor/gems/rspec/spec/spec/matchers/description_generation_spec.rb new file mode 100644 index 000000000..d1246ad04 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/matchers/description_generation_spec.rb @@ -0,0 +1,159 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +describe "Matchers should be able to generate their own descriptions" do + before(:each) do + @desc = nil + @callback = lambda { |desc| @desc = desc } + Spec::Matchers.description_generated(@callback) + end + + it "should == expected" do + "this".should == "this" + @desc.should == "should == \"this\"" + end + + it "should not == expected" do + "this".should_not == "that" + @desc.should == "should not == \"that\"" + end + + it "should be empty (arbitrary predicate)" do + [].should be_empty + @desc.should == "should be empty" + end + + it "should not be empty (arbitrary predicate)" do + [1].should_not be_empty + @desc.should == "should not be empty" + end + + it "should be true" do + true.should be_true + @desc.should == "should be true" + end + + it "should be false" do + false.should be_false + @desc.should == "should be false" + end + + it "should be nil" do + nil.should be_nil + @desc.should == "should be nil" + end + + it "should be > n" do + 5.should be > 3 + @desc.should == "should be > 3" + end + + it "should be predicate arg1, arg2 and arg3" do + 5.0.should be_between(0,10) + @desc.should == "should be between 0 and 10" + end + + it "should be_few_words predicate should be transformed to 'be few words'" do + 5.should be_kind_of(Fixnum) + @desc.should == "should be kind of Fixnum" + end + + it "should preserve a proper prefix for be predicate" do + 5.should be_a_kind_of(Fixnum) + @desc.should == "should be a kind of Fixnum" + 5.should be_an_instance_of(Fixnum) + @desc.should == "should be an instance of Fixnum" + end + + it "should equal" do + expected = "expected" + expected.should equal(expected) + @desc.should == "should equal \"expected\"" + end + + it "should_not equal" do + 5.should_not equal(37) + @desc.should == "should not equal 37" + end + + it "should eql" do + "string".should eql("string") + @desc.should == "should eql \"string\"" + end + + it "should not eql" do + "a".should_not eql(:a) + @desc.should == "should not eql :a" + end + + it "should have_key" do + {:a => "a"}.should have_key(:a) + @desc.should == "should have key :a" + end + + it "should have n items" do + team.should have(3).players + @desc.should == "should have 3 players" + end + + it "should have at least n items" do + team.should have_at_least(2).players + @desc.should == "should have at least 2 players" + end + + it "should have at most n items" do + team.should have_at_most(4).players + @desc.should == "should have at most 4 players" + end + + it "should include" do + [1,2,3].should include(3) + @desc.should == "should include 3" + end + + it "should match" do + "this string".should match(/this string/) + @desc.should == "should match /this string/" + end + + it "should raise_error" do + lambda { raise }.should raise_error + @desc.should == "should raise Exception" + end + + it "should raise_error with type" do + lambda { raise }.should raise_error(RuntimeError) + @desc.should == "should raise RuntimeError" + end + + it "should raise_error with type and message" do + lambda { raise "there was an error" }.should raise_error(RuntimeError, "there was an error") + @desc.should == "should raise RuntimeError with \"there was an error\"" + end + + it "should respond_to" do + [].should respond_to(:insert) + @desc.should == "should respond to #insert" + end + + it "should throw symbol" do + lambda { throw :what_a_mess }.should throw_symbol + @desc.should == "should throw a Symbol" + end + + it "should throw symbol (with named symbol)" do + lambda { throw :what_a_mess }.should throw_symbol(:what_a_mess) + @desc.should == "should throw :what_a_mess" + end + + def team + Class.new do + def players + [1,2,3] + end + end.new + end + + after(:each) do + Spec::Matchers.unregister_description_generated(@callback) + end +end diff --git a/vendor/gems/rspec/spec/spec/matchers/eql_spec.rb b/vendor/gems/rspec/spec/spec/matchers/eql_spec.rb new file mode 100644 index 000000000..3f265d700 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/matchers/eql_spec.rb @@ -0,0 +1,28 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Matchers + describe Eql do + it "should match when actual.eql?(expected)" do + Eql.new(1).matches?(1).should be_true + end + it "should not match when !actual.eql?(expected)" do + Eql.new(1).matches?(2).should be_false + end + it "should describe itself" do + matcher = Eql.new(1) + matcher.description.should == "eql 1" + end + it "should provide message, expected and actual on #failure_message" do + matcher = Eql.new("1") + matcher.matches?(1) + matcher.failure_message.should == ["expected \"1\", got 1 (using .eql?)", "1", 1] + end + it "should provide message, expected and actual on #negative_failure_message" do + matcher = Eql.new(1) + matcher.matches?(1) + matcher.negative_failure_message.should == ["expected 1 not to equal 1 (using .eql?)", 1, 1] + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/matchers/equal_spec.rb b/vendor/gems/rspec/spec/spec/matchers/equal_spec.rb new file mode 100644 index 000000000..7667bdc38 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/matchers/equal_spec.rb @@ -0,0 +1,28 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Matchers + describe Equal do + it "should match when actual.equal?(expected)" do + Equal.new(1).matches?(1).should be_true + end + it "should not match when !actual.equal?(expected)" do + Equal.new("1").matches?("1").should be_false + end + it "should describe itself" do + matcher = Equal.new(1) + matcher.description.should == "equal 1" + end + it "should provide message, expected and actual on #failure_message" do + matcher = Equal.new("1") + matcher.matches?(1) + matcher.failure_message.should == ["expected \"1\", got 1 (using .equal?)", "1", 1] + end + it "should provide message, expected and actual on #negative_failure_message" do + matcher = Equal.new(1) + matcher.matches?(1) + matcher.negative_failure_message.should == ["expected 1 not to equal 1 (using .equal?)", 1, 1] + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/matchers/exist_spec.rb b/vendor/gems/rspec/spec/spec/matchers/exist_spec.rb new file mode 100644 index 000000000..fcbdd9556 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/matchers/exist_spec.rb @@ -0,0 +1,48 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +# NOTE - this was initially handled by an explicit matcher, but is now +# handled by a default set of predicate_matchers. + +class Substance + def initialize exists, description + @exists = exists + @description = description + end + def exist? + @exists + end + def inspect + @description + end +end + +describe "should exist" do + before(:each) do + @real = Substance.new true, 'something real' + @imaginary = Substance.new false, 'something imaginary' + end + + it "should pass if target exists" do + @real.should exist + end + + it "should fail if target does not exist" do + lambda { @imaginary.should exist }. + should fail + end +end + +describe "should_not exist" do + before(:each) do + @real = Substance.new true, 'something real' + @imaginary = Substance.new false, 'something imaginary' + end + it "should pass if target doesn't exist" do + @imaginary.should_not exist + end + it "should fail if target does exist" do + lambda { @real.should_not exist }. + should fail + end +end + diff --git a/vendor/gems/rspec/spec/spec/matchers/handler_spec.rb b/vendor/gems/rspec/spec/spec/matchers/handler_spec.rb new file mode 100644 index 000000000..9f04c6bed --- /dev/null +++ b/vendor/gems/rspec/spec/spec/matchers/handler_spec.rb @@ -0,0 +1,88 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module ExampleExpectations + + class ArbitraryMatcher + def initialize(*args, &block) + if args.last.is_a? Hash + @expected = args.last[:expected] + end + if block_given? + @expected = block.call + end + @block = block + end + + def matches?(target) + @target = target + return @expected == target + end + + def with(new_value) + @expected = new_value + self + end + + def failure_message + "expected #{@expected}, got #{@target}" + end + + def negative_failure_message + "expected not #{@expected}, got #{@target}" + end + end + + class PositiveOnlyMatcher < ArbitraryMatcher + undef negative_failure_message + end + + def arbitrary_matcher(*args, &block) + ArbitraryMatcher.new(*args, &block) + end + + def positive_only_matcher(*args, &block) + PositiveOnlyMatcher.new(*args, &block) + end + +end + +module Spec + module Expectations + describe ExpectationMatcherHandler, ".handle_matcher" do + it "should ask the matcher if it matches" do + matcher = mock("matcher") + actual = Object.new + matcher.should_receive(:matches?).with(actual).and_return(true) + ExpectationMatcherHandler.handle_matcher(actual, matcher) + end + end + + describe ExpectationMatcherHandler do + include ExampleExpectations + + it "should handle submitted args" do + 5.should arbitrary_matcher(:expected => 5) + 5.should arbitrary_matcher(:expected => "wrong").with(5) + lambda { 5.should arbitrary_matcher(:expected => 4) }.should fail_with("expected 4, got 5") + lambda { 5.should arbitrary_matcher(:expected => 5).with(4) }.should fail_with("expected 4, got 5") + 5.should_not arbitrary_matcher(:expected => 4) + 5.should_not arbitrary_matcher(:expected => 5).with(4) + lambda { 5.should_not arbitrary_matcher(:expected => 5) }.should fail_with("expected not 5, got 5") + lambda { 5.should_not arbitrary_matcher(:expected => 4).with(5) }.should fail_with("expected not 5, got 5") + end + + it "should handle the submitted block" do + 5.should arbitrary_matcher { 5 } + 5.should arbitrary_matcher(:expected => 4) { 5 } + 5.should arbitrary_matcher(:expected => 4).with(5) { 3 } + end + + it "should explain when matcher does not support should_not" do + lambda { + 5.should_not positive_only_matcher(:expected => 5) + }.should fail_with(/Matcher does not support should_not.\n/) + end + + end + end +end diff --git a/vendor/gems/rspec/spec/spec/matchers/has_spec.rb b/vendor/gems/rspec/spec/spec/matchers/has_spec.rb new file mode 100644 index 000000000..47f048ebf --- /dev/null +++ b/vendor/gems/rspec/spec/spec/matchers/has_spec.rb @@ -0,0 +1,37 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +describe "should have_sym(*args)" do + it "should pass if #has_sym?(*args) returns true" do + {:a => "A"}.should have_key(:a) + end + + it "should fail if #has_sym?(*args) returns false" do + lambda { + {:b => "B"}.should have_key(:a) + }.should fail_with("expected #has_key?(:a) to return true, got false") + end + + it "should fail if target does not respond to #has_sym?" do + lambda { + Object.new.should have_key(:a) + }.should raise_error(NoMethodError) + end +end + +describe "should_not have_sym(*args)" do + it "should pass if #has_sym?(*args) returns false" do + {:a => "A"}.should_not have_key(:b) + end + + it "should fail if #has_sym?(*args) returns true" do + lambda { + {:a => "A"}.should_not have_key(:a) + }.should fail_with("expected #has_key?(:a) to return false, got true") + end + + it "should fail if target does not respond to #has_sym?" do + lambda { + Object.new.should have_key(:a) + }.should raise_error(NoMethodError) + end +end diff --git a/vendor/gems/rspec/spec/spec/matchers/have_spec.rb b/vendor/gems/rspec/spec/spec/matchers/have_spec.rb new file mode 100644 index 000000000..84a75d98e --- /dev/null +++ b/vendor/gems/rspec/spec/spec/matchers/have_spec.rb @@ -0,0 +1,272 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module HaveSpecHelper + def create_collection_owner_with(n) + owner = Spec::Expectations::Helper::CollectionOwner.new + (1..n).each do |n| + owner.add_to_collection_with_length_method(n) + owner.add_to_collection_with_size_method(n) + end + owner + end +end + +describe "should have(n).items" do + include HaveSpecHelper + + it "should pass if target has a collection of items with n members" do + owner = create_collection_owner_with(3) + owner.should have(3).items_in_collection_with_length_method + owner.should have(3).items_in_collection_with_size_method + end + + it "should convert :no to 0" do + owner = create_collection_owner_with(0) + owner.should have(:no).items_in_collection_with_length_method + owner.should have(:no).items_in_collection_with_size_method + end + + it "should fail if target has a collection of items with < n members" do + owner = create_collection_owner_with(3) + lambda { + owner.should have(4).items_in_collection_with_length_method + }.should fail_with("expected 4 items_in_collection_with_length_method, got 3") + lambda { + owner.should have(4).items_in_collection_with_size_method + }.should fail_with("expected 4 items_in_collection_with_size_method, got 3") + end + + it "should fail if target has a collection of items with > n members" do + owner = create_collection_owner_with(3) + lambda { + owner.should have(2).items_in_collection_with_length_method + }.should fail_with("expected 2 items_in_collection_with_length_method, got 3") + lambda { + owner.should have(2).items_in_collection_with_size_method + }.should fail_with("expected 2 items_in_collection_with_size_method, got 3") + end +end + +describe "should have(n).items where result responds to items but returns something other than a collection" do + it "should provide a meaningful error" do + owner = Class.new do + def items + Object.new + end + end.new + lambda do + owner.should have(3).items + end.should raise_error("expected items to be a collection but it does not respond to #length or #size") + end +end + +describe "should_not have(n).items" do + include HaveSpecHelper + + it "should pass if target has a collection of items with < n members" do + owner = create_collection_owner_with(3) + owner.should_not have(4).items_in_collection_with_length_method + owner.should_not have(4).items_in_collection_with_size_method + end + + it "should pass if target has a collection of items with > n members" do + owner = create_collection_owner_with(3) + owner.should_not have(2).items_in_collection_with_length_method + owner.should_not have(2).items_in_collection_with_size_method + end + + it "should fail if target has a collection of items with n members" do + owner = create_collection_owner_with(3) + lambda { + owner.should_not have(3).items_in_collection_with_length_method + }.should fail_with("expected target not to have 3 items_in_collection_with_length_method, got 3") + lambda { + owner.should_not have(3).items_in_collection_with_size_method + }.should fail_with("expected target not to have 3 items_in_collection_with_size_method, got 3") + end +end + +describe "should have_exactly(n).items" do + include HaveSpecHelper + + it "should pass if target has a collection of items with n members" do + owner = create_collection_owner_with(3) + owner.should have_exactly(3).items_in_collection_with_length_method + owner.should have_exactly(3).items_in_collection_with_size_method + end + + it "should convert :no to 0" do + owner = create_collection_owner_with(0) + owner.should have_exactly(:no).items_in_collection_with_length_method + owner.should have_exactly(:no).items_in_collection_with_size_method + end + + it "should fail if target has a collection of items with < n members" do + owner = create_collection_owner_with(3) + lambda { + owner.should have_exactly(4).items_in_collection_with_length_method + }.should fail_with("expected 4 items_in_collection_with_length_method, got 3") + lambda { + owner.should have_exactly(4).items_in_collection_with_size_method + }.should fail_with("expected 4 items_in_collection_with_size_method, got 3") + end + + it "should fail if target has a collection of items with > n members" do + owner = create_collection_owner_with(3) + lambda { + owner.should have_exactly(2).items_in_collection_with_length_method + }.should fail_with("expected 2 items_in_collection_with_length_method, got 3") + lambda { + owner.should have_exactly(2).items_in_collection_with_size_method + }.should fail_with("expected 2 items_in_collection_with_size_method, got 3") + end +end + +describe "should have_at_least(n).items" do + include HaveSpecHelper + + it "should pass if target has a collection of items with n members" do + owner = create_collection_owner_with(3) + owner.should have_at_least(3).items_in_collection_with_length_method + owner.should have_at_least(3).items_in_collection_with_size_method + end + + it "should pass if target has a collection of items with > n members" do + owner = create_collection_owner_with(3) + owner.should have_at_least(2).items_in_collection_with_length_method + owner.should have_at_least(2).items_in_collection_with_size_method + end + + it "should fail if target has a collection of items with < n members" do + owner = create_collection_owner_with(3) + lambda { + owner.should have_at_least(4).items_in_collection_with_length_method + }.should fail_with("expected at least 4 items_in_collection_with_length_method, got 3") + lambda { + owner.should have_at_least(4).items_in_collection_with_size_method + }.should fail_with("expected at least 4 items_in_collection_with_size_method, got 3") + end + + it "should provide educational negative failure messages" do + #given + owner = create_collection_owner_with(3) + length_matcher = have_at_least(3).items_in_collection_with_length_method + size_matcher = have_at_least(3).items_in_collection_with_size_method + + #when + length_matcher.matches?(owner) + size_matcher.matches?(owner) + + #then + length_matcher.negative_failure_message.should == <<-EOF +Isn't life confusing enough? +Instead of having to figure out the meaning of this: + should_not have_at_least(3).items_in_collection_with_length_method +We recommend that you use this instead: + should have_at_most(2).items_in_collection_with_length_method +EOF + + size_matcher.negative_failure_message.should == <<-EOF +Isn't life confusing enough? +Instead of having to figure out the meaning of this: + should_not have_at_least(3).items_in_collection_with_size_method +We recommend that you use this instead: + should have_at_most(2).items_in_collection_with_size_method +EOF + end +end + +describe "should have_at_most(n).items" do + include HaveSpecHelper + + it "should pass if target has a collection of items with n members" do + owner = create_collection_owner_with(3) + owner.should have_at_most(3).items_in_collection_with_length_method + owner.should have_at_most(3).items_in_collection_with_size_method + end + + it "should fail if target has a collection of items with > n members" do + owner = create_collection_owner_with(3) + lambda { + owner.should have_at_most(2).items_in_collection_with_length_method + }.should fail_with("expected at most 2 items_in_collection_with_length_method, got 3") + lambda { + owner.should have_at_most(2).items_in_collection_with_size_method + }.should fail_with("expected at most 2 items_in_collection_with_size_method, got 3") + end + + it "should pass if target has a collection of items with < n members" do + owner = create_collection_owner_with(3) + owner.should have_at_most(4).items_in_collection_with_length_method + owner.should have_at_most(4).items_in_collection_with_size_method + end + + it "should provide educational negative failure messages" do + #given + owner = create_collection_owner_with(3) + length_matcher = have_at_most(3).items_in_collection_with_length_method + size_matcher = have_at_most(3).items_in_collection_with_size_method + + #when + length_matcher.matches?(owner) + size_matcher.matches?(owner) + + #then + length_matcher.negative_failure_message.should == <<-EOF +Isn't life confusing enough? +Instead of having to figure out the meaning of this: + should_not have_at_most(3).items_in_collection_with_length_method +We recommend that you use this instead: + should have_at_least(4).items_in_collection_with_length_method +EOF + + size_matcher.negative_failure_message.should == <<-EOF +Isn't life confusing enough? +Instead of having to figure out the meaning of this: + should_not have_at_most(3).items_in_collection_with_size_method +We recommend that you use this instead: + should have_at_least(4).items_in_collection_with_size_method +EOF + end +end + +describe "have(n).items(args, block)" do + it "should pass args to target" do + target = mock("target") + target.should_receive(:items).with("arg1","arg2").and_return([1,2,3]) + target.should have(3).items("arg1","arg2") + end + + it "should pass block to target" do + target = mock("target") + block = lambda { 5 } + target.should_receive(:items).with("arg1","arg2", block).and_return([1,2,3]) + target.should have(3).items("arg1","arg2", block) + end +end + +describe "have(n).items where target IS a collection" do + it "should reference the number of items IN the collection" do + [1,2,3].should have(3).items + end + + it "should reference the number of items IN the collection" do + lambda { [1,2,3].should have(7).items }.should fail_with("expected 7 items, got 3") + end +end + +describe "have(n).characters where target IS a String" do + it "should pass if the length is correct" do + "this string".should have(11).characters + end + + it "should fail if the length is incorrect" do + lambda { "this string".should have(12).characters }.should fail_with("expected 12 characters, got 11") + end +end + +describe "have(n).things on an object which is not a collection nor contains one" do + it "should fail" do + lambda { Object.new.should have(2).things }.should raise_error(NoMethodError, /undefined method `things' for #<Object:/) + end +end diff --git a/vendor/gems/rspec/spec/spec/matchers/include_spec.rb b/vendor/gems/rspec/spec/spec/matchers/include_spec.rb new file mode 100644 index 000000000..f1057f3fd --- /dev/null +++ b/vendor/gems/rspec/spec/spec/matchers/include_spec.rb @@ -0,0 +1,45 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +describe "should include(expected)" do + it "should pass if target includes expected" do + [1,2,3].should include(3) + "abc".should include("a") + end + + it "should fail if target does not include expected" do + lambda { + [1,2,3].should include(4) + }.should fail_with("expected [1, 2, 3] to include 4") + lambda { + "abc".should include("d") + }.should fail_with("expected \"abc\" to include \"d\"") + end +end + +describe "should include(with, multiple, args)" do + it "should pass if target includes all items" do + [1,2,3].should include(1,2,3) + end + + it "should fail if target does not include any one of the items" do + lambda { + [1,2,3].should include(1,2,4) + }.should fail_with("expected [1, 2, 3] to include 1, 2 and 4") + end +end + +describe "should_not include(expected)" do + it "should pass if target does not include expected" do + [1,2,3].should_not include(4) + "abc".should_not include("d") + end + + it "should fail if target includes expected" do + lambda { + [1,2,3].should_not include(3) + }.should fail_with("expected [1, 2, 3] not to include 3") + lambda { + "abc".should_not include("c") + }.should fail_with("expected \"abc\" not to include \"c\"") + end +end diff --git a/vendor/gems/rspec/spec/spec/matchers/match_spec.rb b/vendor/gems/rspec/spec/spec/matchers/match_spec.rb new file mode 100644 index 000000000..b8aa06b07 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/matchers/match_spec.rb @@ -0,0 +1,37 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +describe "should match(expected)" do + it "should pass when target (String) matches expected (Regexp)" do + "string".should match(/tri/) + end + + it "should fail when target (String) matches expected (Regexp)" do + lambda { + "string".should match(/rings/) + }.should fail + end + + it "should provide message, expected and actual on failure" do + matcher = match(/rings/) + matcher.matches?("string") + matcher.failure_message.should == ["expected \"string\" to match /rings/", /rings/, "string"] + end +end + +describe "should_not match(expected)" do + it "should pass when target (String) matches expected (Regexp)" do + "string".should_not match(/rings/) + end + + it "should fail when target (String) matches expected (Regexp)" do + lambda { + "string".should_not match(/tri/) + }.should fail + end + + it "should provide message, expected and actual on failure" do + matcher = match(/tri/) + matcher.matches?("string") + matcher.negative_failure_message.should == ["expected \"string\" not to match /tri/", /tri/, "string"] + end +end diff --git a/vendor/gems/rspec/spec/spec/matchers/matcher_methods_spec.rb b/vendor/gems/rspec/spec/spec/matchers/matcher_methods_spec.rb new file mode 100644 index 000000000..80cc9855a --- /dev/null +++ b/vendor/gems/rspec/spec/spec/matchers/matcher_methods_spec.rb @@ -0,0 +1,78 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Matchers + context %Q{The Spec::Matchers module gets included in the execution context of every spec. +This module should provide the following methods, each of which returns a Matcher object.} do + it "be_true" do + be_true.should be_an_instance_of(Be) + end + it "be_false" do + be_false.should be_an_instance_of(Be) + end + it "be_nil" do + be_nil.should be_an_instance_of(Be) + end + it "be_arbitrary_predicate" do + be_arbitrary_predicate.should be_an_instance_of(Be) + end + it "be_close" do + be_close(1,2).should be_an_instance_of(BeClose) + end + it "change" do + change("target", :message).should be_an_instance_of(Change) + end + it "eql" do + eql(:expected).should be_an_instance_of(Eql) + end + it "equal" do + equal(:expected).should be_an_instance_of(Equal) + end + it "have" do + have(0).should be_an_instance_of(Have) + end + it "have_exactly" do + have_exactly(0).should be_an_instance_of(Have) + end + it "have_at_least" do + have_at_least(0).should be_an_instance_of(Have) + end + it "have_at_most" do + have_at_most(0).should be_an_instance_of(Have) + end + it "include" do + include(:value).should be_an_instance_of(Include) + end + it "match" do + match(:value).should be_an_instance_of(Match) + end + it "raise_error" do + raise_error.should be_an_instance_of(RaiseError) + raise_error(NoMethodError).should be_an_instance_of(RaiseError) + raise_error(NoMethodError, "message").should be_an_instance_of(RaiseError) + end + it "satisfy" do + satisfy{}.should be_an_instance_of(Satisfy) + end + it "throw_symbol" do + throw_symbol.should be_an_instance_of(ThrowSymbol) + throw_symbol(:sym).should be_an_instance_of(ThrowSymbol) + end + it "respond_to" do + respond_to(:sym).should be_an_instance_of(RespondTo) + end + end + + describe "Spec::Matchers#method_missing" do + it "should convert be_xyz to Be(:be_xyz)" do + Be.should_receive(:new).with(:be_whatever) + be_whatever + end + + it "should convert have_xyz to Has(:have_xyz)" do + Has.should_receive(:new).with(:have_whatever) + have_whatever + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/matchers/mock_constraint_matchers_spec.rb b/vendor/gems/rspec/spec/spec/matchers/mock_constraint_matchers_spec.rb new file mode 100644 index 000000000..bde48686a --- /dev/null +++ b/vendor/gems/rspec/spec/spec/matchers/mock_constraint_matchers_spec.rb @@ -0,0 +1,24 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +describe "The anything() mock argument constraint matcher" do + specify { anything.should == Object.new } + specify { anything.should == Class } + specify { anything.should == 1 } + specify { anything.should == "a string" } + specify { anything.should == :a_symbol } +end + +describe "The boolean() mock argument constraint matcher" do + specify { boolean.should == true } + specify { boolean.should == false } + specify { boolean.should_not == Object.new } + specify { boolean.should_not == Class } + specify { boolean.should_not == 1 } + specify { boolean.should_not == "a string" } + specify { boolean.should_not == :a_symbol } +end + +describe "The an_instance_of() mock argument constraint matcher" do + # NOTE - this is implemented as a predicate_matcher - see behaviour.rb + specify { an_instance_of(String).should == "string" } +end diff --git a/vendor/gems/rspec/spec/spec/matchers/operator_matcher_spec.rb b/vendor/gems/rspec/spec/spec/matchers/operator_matcher_spec.rb new file mode 100644 index 000000000..eaadc8fc8 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/matchers/operator_matcher_spec.rb @@ -0,0 +1,158 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +require 'spec/expectations/differs/default' + +describe "should ==" do + + it "should delegate message to target" do + subject = "apple" + subject.should_receive(:==).with("apple").and_return(true) + subject.should == "apple" + end + + it "should fail when target.==(actual) returns false" do + subject = "apple" + Spec::Expectations.should_receive(:fail_with).with(%[expected: "orange",\n got: "apple" (using ==)], "orange", "apple") + subject.should == "orange" + end + +end + +describe "should_not ==" do + + it "should delegate message to target" do + subject = "orange" + subject.should_receive(:==).with("apple").and_return(false) + subject.should_not == "apple" + end + + it "should fail when target.==(actual) returns false" do + subject = "apple" + Spec::Expectations.should_receive(:fail_with).with(%[expected not: == "apple",\n got: "apple"], "apple", "apple") + subject.should_not == "apple" + end + +end + +describe "should ===" do + + it "should delegate message to target" do + subject = "apple" + subject.should_receive(:===).with("apple").and_return(true) + subject.should === "apple" + end + + it "should fail when target.===(actual) returns false" do + subject = "apple" + subject.should_receive(:===).with("orange").and_return(false) + Spec::Expectations.should_receive(:fail_with).with(%[expected: "orange",\n got: "apple" (using ===)], "orange", "apple") + subject.should === "orange" + end + +end + +describe "should_not ===" do + + it "should delegate message to target" do + subject = "orange" + subject.should_receive(:===).with("apple").and_return(false) + subject.should_not === "apple" + end + + it "should fail when target.===(actual) returns false" do + subject = "apple" + subject.should_receive(:===).with("apple").and_return(true) + Spec::Expectations.should_receive(:fail_with).with(%[expected not: === "apple",\n got: "apple"], "apple", "apple") + subject.should_not === "apple" + end + +end + +describe "should =~" do + + it "should delegate message to target" do + subject = "foo" + subject.should_receive(:=~).with(/oo/).and_return(true) + subject.should =~ /oo/ + end + + it "should fail when target.=~(actual) returns false" do + subject = "fu" + subject.should_receive(:=~).with(/oo/).and_return(false) + Spec::Expectations.should_receive(:fail_with).with(%[expected: /oo/,\n got: "fu" (using =~)], /oo/, "fu") + subject.should =~ /oo/ + end + +end + +describe "should_not =~" do + + it "should delegate message to target" do + subject = "fu" + subject.should_receive(:=~).with(/oo/).and_return(false) + subject.should_not =~ /oo/ + end + + it "should fail when target.=~(actual) returns false" do + subject = "foo" + subject.should_receive(:=~).with(/oo/).and_return(true) + Spec::Expectations.should_receive(:fail_with).with(%[expected not: =~ /oo/,\n got: "foo"], /oo/, "foo") + subject.should_not =~ /oo/ + end + +end + +describe "should >" do + + it "should pass if > passes" do + 4.should > 3 + end + + it "should fail if > fails" do + Spec::Expectations.should_receive(:fail_with).with(%[expected: > 5,\n got: 4], 5, 4) + 4.should > 5 + end + +end + +describe "should >=" do + + it "should pass if >= passes" do + 4.should > 3 + 4.should >= 4 + end + + it "should fail if > fails" do + Spec::Expectations.should_receive(:fail_with).with(%[expected: >= 5,\n got: 4], 5, 4) + 4.should >= 5 + end + +end + +describe "should <" do + + it "should pass if < passes" do + 4.should < 5 + end + + it "should fail if > fails" do + Spec::Expectations.should_receive(:fail_with).with(%[expected: < 3,\n got: 4], 3, 4) + 4.should < 3 + end + +end + +describe "should <=" do + + it "should pass if <= passes" do + 4.should <= 5 + 4.should <= 4 + end + + it "should fail if > fails" do + Spec::Expectations.should_receive(:fail_with).with(%[expected: <= 3,\n got: 4], 3, 4) + 4.should <= 3 + end + +end + diff --git a/vendor/gems/rspec/spec/spec/matchers/raise_error_spec.rb b/vendor/gems/rspec/spec/spec/matchers/raise_error_spec.rb new file mode 100644 index 000000000..f33fba903 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/matchers/raise_error_spec.rb @@ -0,0 +1,185 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +describe "should raise_error" do + it "should pass if anything is raised" do + lambda {raise}.should raise_error + end + + it "should fail if nothing is raised" do + lambda { + lambda {}.should raise_error + }.should fail_with("expected Exception but nothing was raised") + end +end + +describe "should_not raise_error" do + it "should pass if nothing is raised" do + lambda {}.should_not raise_error + end + + it "should fail if anything is raised" do + lambda { + lambda {raise}.should_not raise_error + }.should fail_with("expected no Exception, got RuntimeError") + end +end + +describe "should raise_error(message)" do + it "should pass if RuntimeError is raised with the right message" do + lambda {raise 'blah'}.should raise_error('blah') + end + it "should pass if any other error is raised with the right message" do + lambda {raise NameError.new('blah')}.should raise_error('blah') + end + it "should fail if RuntimeError error is raised with the wrong message" do + lambda do + lambda {raise 'blarg'}.should raise_error('blah') + end.should fail_with("expected Exception with \"blah\", got #<RuntimeError: blarg>") + end + it "should fail if any other error is raised with the wrong message" do + lambda do + lambda {raise NameError.new('blarg')}.should raise_error('blah') + end.should fail_with("expected Exception with \"blah\", got #<NameError: blarg>") + end +end + +describe "should_not raise_error(message)" do + it "should pass if RuntimeError error is raised with the different message" do + lambda {raise 'blarg'}.should_not raise_error('blah') + end + it "should pass if any other error is raised with the wrong message" do + lambda {raise NameError.new('blarg')}.should_not raise_error('blah') + end + it "should fail if RuntimeError is raised with message" do + lambda do + lambda {raise 'blah'}.should_not raise_error('blah') + end.should fail_with(%Q|expected no Exception with "blah", got #<RuntimeError: blah>|) + end + it "should fail if any other error is raised with message" do + lambda do + lambda {raise NameError.new('blah')}.should_not raise_error('blah') + end.should fail_with(%Q|expected no Exception with "blah", got #<NameError: blah>|) + end +end + +describe "should raise_error(NamedError)" do + it "should pass if named error is raised" do + lambda { non_existent_method }.should raise_error(NameError) + end + + it "should fail if nothing is raised" do + lambda { + lambda { }.should raise_error(NameError) + }.should fail_with("expected NameError but nothing was raised") + end + + it "should fail if another error is raised" do + lambda { + lambda { raise }.should raise_error(NameError) + }.should fail_with("expected NameError, got RuntimeError") + end +end + +describe "should_not raise_error(NamedError)" do + it "should pass if nothing is raised" do + lambda { }.should_not raise_error(NameError) + end + + it "should pass if another error is raised" do + lambda { raise }.should_not raise_error(NameError) + end + + it "should fail if named error is raised" do + lambda { + lambda { non_existent_method }.should_not raise_error(NameError) + }.should fail_with(/expected no NameError, got #<NameError: undefined/) + end +end + +describe "should raise_error(NamedError, error_message) with String" do + it "should pass if named error is raised with same message" do + lambda { raise "example message" }.should raise_error(RuntimeError, "example message") + end + + it "should fail if nothing is raised" do + lambda { + lambda {}.should raise_error(RuntimeError, "example message") + }.should fail_with("expected RuntimeError with \"example message\" but nothing was raised") + end + + it "should fail if incorrect error is raised" do + lambda { + lambda { raise }.should raise_error(NameError, "example message") + }.should fail_with("expected NameError with \"example message\", got RuntimeError") + end + + it "should fail if correct error is raised with incorrect message" do + lambda { + lambda { raise RuntimeError.new("not the example message") }.should raise_error(RuntimeError, "example message") + }.should fail_with(/expected RuntimeError with \"example message\", got #<RuntimeError: not the example message/) + end +end + +describe "should_not raise_error(NamedError, error_message) with String" do + it "should pass if nothing is raised" do + lambda {}.should_not raise_error(RuntimeError, "example message") + end + + it "should pass if a different error is raised" do + lambda { raise }.should_not raise_error(NameError, "example message") + end + + it "should pass if same error is raised with different message" do + lambda { raise RuntimeError.new("not the example message") }.should_not raise_error(RuntimeError, "example message") + end + + it "should fail if named error is raised with same message" do + lambda { + lambda { raise "example message" }.should_not raise_error(RuntimeError, "example message") + }.should fail_with("expected no RuntimeError with \"example message\", got #<RuntimeError: example message>") + end +end + +describe "should raise_error(NamedError, error_message) with Regexp" do + it "should pass if named error is raised with matching message" do + lambda { raise "example message" }.should raise_error(RuntimeError, /ample mess/) + end + + it "should fail if nothing is raised" do + lambda { + lambda {}.should raise_error(RuntimeError, /ample mess/) + }.should fail_with("expected RuntimeError with message matching /ample mess/ but nothing was raised") + end + + it "should fail if incorrect error is raised" do + lambda { + lambda { raise }.should raise_error(NameError, /ample mess/) + }.should fail_with("expected NameError with message matching /ample mess/, got RuntimeError") + end + + it "should fail if correct error is raised with incorrect message" do + lambda { + lambda { raise RuntimeError.new("not the example message") }.should raise_error(RuntimeError, /less than ample mess/) + }.should fail_with("expected RuntimeError with message matching /less than ample mess/, got #<RuntimeError: not the example message>") + end +end + +describe "should_not raise_error(NamedError, error_message) with Regexp" do + it "should pass if nothing is raised" do + lambda {}.should_not raise_error(RuntimeError, /ample mess/) + end + + it "should pass if a different error is raised" do + lambda { raise }.should_not raise_error(NameError, /ample mess/) + end + + it "should pass if same error is raised with non-matching message" do + lambda { raise RuntimeError.new("non matching message") }.should_not raise_error(RuntimeError, /ample mess/) + end + + it "should fail if named error is raised with matching message" do + lambda { + lambda { raise "example message" }.should_not raise_error(RuntimeError, /ample mess/) + }.should fail_with("expected no RuntimeError with message matching /ample mess/, got #<RuntimeError: example message>") + end +end diff --git a/vendor/gems/rspec/spec/spec/matchers/respond_to_spec.rb b/vendor/gems/rspec/spec/spec/matchers/respond_to_spec.rb new file mode 100644 index 000000000..2cdbbcd63 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/matchers/respond_to_spec.rb @@ -0,0 +1,54 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +describe "should respond_to(:sym)" do + + it "should pass if target responds to :sym" do + Object.new.should respond_to(:methods) + end + + it "should fail target does not respond to :sym" do + lambda { + Object.new.should respond_to(:some_method) + }.should fail_with("expected target to respond to :some_method") + end + +end + +describe "should respond_to(message1, message2)" do + + it "should pass if target responds to both messages" do + Object.new.should respond_to('methods', 'inspect') + end + + it "should fail target does not respond to first message" do + lambda { + Object.new.should respond_to('method_one', 'inspect') + }.should fail_with('expected target to respond to "method_one"') + end + + it "should fail target does not respond to second message" do + lambda { + Object.new.should respond_to('inspect', 'method_one') + }.should fail_with('expected target to respond to "method_one"') + end + + it "should fail target does not respond to either message" do + lambda { + Object.new.should respond_to('method_one', 'method_two') + }.should fail_with('expected target to respond to "method_one", "method_two"') + end +end + +describe "should_not respond_to(:sym)" do + + it "should pass if target does not respond to :sym" do + Object.new.should_not respond_to(:some_method) + end + + it "should fail target responds to :sym" do + lambda { + Object.new.should_not respond_to(:methods) + }.should fail_with("expected target not to respond to :methods") + end + +end diff --git a/vendor/gems/rspec/spec/spec/matchers/satisfy_spec.rb b/vendor/gems/rspec/spec/spec/matchers/satisfy_spec.rb new file mode 100644 index 000000000..7e8d6f972 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/matchers/satisfy_spec.rb @@ -0,0 +1,36 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +describe "should satisfy { block }" do + it "should pass if block returns true" do + true.should satisfy { |val| val } + true.should satisfy do |val| + val + end + end + + it "should fail if block returns false" do + lambda { + false.should satisfy { |val| val } + }.should fail_with("expected false to satisfy block") + lambda do + false.should satisfy do |val| + val + end + end.should fail_with("expected false to satisfy block") + end +end + +describe "should_not satisfy { block }" do + it "should pass if block returns false" do + false.should_not satisfy { |val| val } + false.should_not satisfy do |val| + val + end + end + + it "should fail if block returns true" do + lambda { + true.should_not satisfy { |val| val } + }.should fail_with("expected true not to satisfy block") + end +end diff --git a/vendor/gems/rspec/spec/spec/matchers/throw_symbol_spec.rb b/vendor/gems/rspec/spec/spec/matchers/throw_symbol_spec.rb new file mode 100644 index 000000000..1548ec6f0 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/matchers/throw_symbol_spec.rb @@ -0,0 +1,51 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Matchers + describe ThrowSymbol, "(constructed with no Symbol)" do + before(:each) { @matcher = ThrowSymbol.new } + + it "should match if any Symbol is thrown" do + @matcher.matches?(lambda{ throw :sym }).should be_true + end + it "should not match if no Symbol is thrown" do + @matcher.matches?(lambda{ }).should be_false + end + it "should provide a failure message" do + @matcher.matches?(lambda{}) + @matcher.failure_message.should == "expected a Symbol but nothing was thrown" + end + it "should provide a negative failure message" do + @matcher.matches?(lambda{ throw :sym}) + @matcher.negative_failure_message.should == "expected no Symbol, got :sym" + end + end + + describe ThrowSymbol, "(constructed with a Symbol)" do + before(:each) { @matcher = ThrowSymbol.new(:sym) } + + it "should match if correct Symbol is thrown" do + @matcher.matches?(lambda{ throw :sym }).should be_true + end + it "should not match no Symbol is thrown" do + @matcher.matches?(lambda{ }).should be_false + end + it "should not match if correct Symbol is thrown" do + @matcher.matches?(lambda{ throw :other_sym }).should be_false + @matcher.failure_message.should == "expected :sym, got :other_sym" + end + it "should provide a failure message when no Symbol is thrown" do + @matcher.matches?(lambda{}) + @matcher.failure_message.should == "expected :sym but nothing was thrown" + end + it "should provide a failure message when wrong Symbol is thrown" do + @matcher.matches?(lambda{ throw :other_sym }) + @matcher.failure_message.should == "expected :sym, got :other_sym" + end + it "should provide a negative failure message" do + @matcher.matches?(lambda{ throw :sym }) + @matcher.negative_failure_message.should == "expected :sym not to be thrown" + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/any_number_of_times_spec.rb b/vendor/gems/rspec/spec/spec/mocks/any_number_of_times_spec.rb new file mode 100644 index 000000000..3f50dcfc5 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/any_number_of_times_spec.rb @@ -0,0 +1,29 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Mocks + + describe "AnyNumberOfTimes" do + before(:each) do + @mock = Mock.new("test mock") + end + + it "should pass if any number of times method is called many times" do + @mock.should_receive(:random_call).any_number_of_times + (1..10).each do + @mock.random_call + end + end + + it "should pass if any number of times method is called once" do + @mock.should_receive(:random_call).any_number_of_times + @mock.random_call + end + + it "should pass if any number of times method is not called" do + @mock.should_receive(:random_call).any_number_of_times + end + end + + end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/argument_expectation_spec.rb b/vendor/gems/rspec/spec/spec/mocks/argument_expectation_spec.rb new file mode 100644 index 000000000..2bebbdd4f --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/argument_expectation_spec.rb @@ -0,0 +1,23 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Mocks + describe ArgumentExpectation do + it "should consider an object that responds to #matches? and #description to be a matcher" do + argument_expecatation = Spec::Mocks::ArgumentExpectation.new([]) + obj = mock("matcher") + obj.should_receive(:respond_to?).with(:matches?).and_return(true) + obj.should_receive(:respond_to?).with(:description).and_return(true) + argument_expecatation.is_matcher?(obj).should be_true + end + + it "should NOT consider an object that only responds to #matches? to be a matcher" do + argument_expecatation = Spec::Mocks::ArgumentExpectation.new([]) + obj = mock("matcher") + obj.should_receive(:respond_to?).with(:matches?).and_return(true) + obj.should_receive(:respond_to?).with(:description).and_return(false) + argument_expecatation.is_matcher?(obj).should be_false + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/at_least_spec.rb b/vendor/gems/rspec/spec/spec/mocks/at_least_spec.rb new file mode 100644 index 000000000..01b133dc3 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/at_least_spec.rb @@ -0,0 +1,97 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Mocks + describe "at_least" do + before(:each) do + @mock = Mock.new("test mock") + end + + it "should fail if method is never called" do + @mock.should_receive(:random_call).at_least(4).times + lambda do + @mock.rspec_verify + end.should raise_error(MockExpectationError) + end + + it "should fail when called less than n times" do + @mock.should_receive(:random_call).at_least(4).times + @mock.random_call + @mock.random_call + @mock.random_call + lambda do + @mock.rspec_verify + end.should raise_error(MockExpectationError) + end + + it "should fail when at least once method is never called" do + @mock.should_receive(:random_call).at_least(:once) + lambda do + @mock.rspec_verify + end.should raise_error(MockExpectationError) + end + + it "should fail when at least twice method is called once" do + @mock.should_receive(:random_call).at_least(:twice) + @mock.random_call + lambda do + @mock.rspec_verify + end.should raise_error(MockExpectationError) + end + + it "should fail when at least twice method is never called" do + @mock.should_receive(:random_call).at_least(:twice) + lambda do + @mock.rspec_verify + end.should raise_error(MockExpectationError) + end + + it "should pass when at least n times method is called exactly n times" do + @mock.should_receive(:random_call).at_least(4).times + @mock.random_call + @mock.random_call + @mock.random_call + @mock.random_call + @mock.rspec_verify + end + + it "should pass when at least n times method is called n plus 1 times" do + @mock.should_receive(:random_call).at_least(4).times + @mock.random_call + @mock.random_call + @mock.random_call + @mock.random_call + @mock.random_call + @mock.rspec_verify + end + + it "should pass when at least once method is called once" do + @mock.should_receive(:random_call).at_least(:once) + @mock.random_call + @mock.rspec_verify + end + + it "should pass when at least once method is called twice" do + @mock.should_receive(:random_call).at_least(:once) + @mock.random_call + @mock.random_call + @mock.rspec_verify + end + + it "should pass when at least twice method is called three times" do + @mock.should_receive(:random_call).at_least(:twice) + @mock.random_call + @mock.random_call + @mock.random_call + @mock.rspec_verify + end + + it "should pass when at least twice method is called twice" do + @mock.should_receive(:random_call).at_least(:twice) + @mock.random_call + @mock.random_call + @mock.rspec_verify + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/at_most_spec.rb b/vendor/gems/rspec/spec/spec/mocks/at_most_spec.rb new file mode 100644 index 000000000..f3c5e2150 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/at_most_spec.rb @@ -0,0 +1,93 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Mocks + describe "at_most" do + before(:each) do + @mock = Mock.new("test mock") + end + + it "should fail when at most n times method is called n plus 1 times" do + @mock.should_receive(:random_call).at_most(4).times + @mock.random_call + @mock.random_call + @mock.random_call + @mock.random_call + @mock.random_call + lambda do + @mock.rspec_verify + end.should raise_error(MockExpectationError) + end + + it "should fail when at most once method is called twice" do + @mock.should_receive(:random_call).at_most(:once) + @mock.random_call + @mock.random_call + lambda do + @mock.rspec_verify + end.should raise_error(MockExpectationError) + end + + it "should fail when at most twice method is called three times" do + @mock.should_receive(:random_call).at_most(:twice) + @mock.random_call + @mock.random_call + @mock.random_call + lambda do + @mock.rspec_verify + end.should raise_error(MockExpectationError) + end + + it "should pass when at most n times method is called exactly n times" do + @mock.should_receive(:random_call).at_most(4).times + @mock.random_call + @mock.random_call + @mock.random_call + @mock.random_call + @mock.rspec_verify + end + + it "should pass when at most n times method is called less than n times" do + @mock.should_receive(:random_call).at_most(4).times + @mock.random_call + @mock.random_call + @mock.random_call + @mock.rspec_verify + end + + it "should pass when at most n times method is never called" do + @mock.should_receive(:random_call).at_most(4).times + @mock.rspec_verify + end + + it "should pass when at most once method is called once" do + @mock.should_receive(:random_call).at_most(:once) + @mock.random_call + @mock.rspec_verify + end + + it "should pass when at most once method is never called" do + @mock.should_receive(:random_call).at_most(:once) + @mock.rspec_verify + end + + it "should pass when at most twice method is called once" do + @mock.should_receive(:random_call).at_most(:twice) + @mock.random_call + @mock.rspec_verify + end + + it "should pass when at most twice method is called twice" do + @mock.should_receive(:random_call).at_most(:twice) + @mock.random_call + @mock.random_call + @mock.rspec_verify + end + + it "should pass when at most twice method is never called" do + @mock.should_receive(:random_call).at_most(:twice) + @mock.rspec_verify + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/bug_report_10260_spec.rb b/vendor/gems/rspec/spec/spec/mocks/bug_report_10260_spec.rb new file mode 100644 index 000000000..2f7b5803d --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/bug_report_10260_spec.rb @@ -0,0 +1,8 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +describe "An RSpec Mock" do + it "should hide internals in its inspect representation" do + m = mock('cup') + m.inspect.should =~ /#<Spec::Mocks::Mock:0x[a-f0-9.]+ @name="cup">/ + end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/bug_report_11545_spec.rb b/vendor/gems/rspec/spec/spec/mocks/bug_report_11545_spec.rb new file mode 100644 index 000000000..8a334afa5 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/bug_report_11545_spec.rb @@ -0,0 +1,31 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +class LiarLiarPantsOnFire + def respond_to?(sym) + true + end + + def self.respond_to?(sym) + true + end +end + +describe 'should_receive' do + before(:each) do + @liar = LiarLiarPantsOnFire.new + end + + it "should work when object lies about responding to a method" do + @liar.should_receive(:something) + @liar.something + end + + it 'should work when class lies about responding to a method' do + LiarLiarPantsOnFire.should_receive(:something) + LiarLiarPantsOnFire.something + end + + it 'should cleanup after itself' do + LiarLiarPantsOnFire.metaclass.instance_methods.should_not include("something") + end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/bug_report_7611_spec.rb b/vendor/gems/rspec/spec/spec/mocks/bug_report_7611_spec.rb new file mode 100644 index 000000000..6c9705bcc --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/bug_report_7611_spec.rb @@ -0,0 +1,19 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Bug7611 + class Foo + end + + class Bar < Foo + end + + describe "A Partial Mock" do + it "should respect subclasses" do + Foo.stub!(:new).and_return(Object.new) + end + + it "should" do + Bar.new.class.should == Bar + end + end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/bug_report_7805_spec.rb b/vendor/gems/rspec/spec/spec/mocks/bug_report_7805_spec.rb new file mode 100644 index 000000000..f7edfac17 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/bug_report_7805_spec.rb @@ -0,0 +1,22 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Bug7805 + #This is really a duplicate of 8302 + + describe "Stubs should correctly restore module methods" do + it "1 - stub the open method" do + File.stub!(:open).and_return("something") + File.open.should == "something" + end + it "2 - use File.open to create example.txt" do + filename = "#{File.dirname(__FILE__)}/example-#{Time.new.to_i}.txt" + File.exist?(filename).should be_false + file = File.open(filename,'w') + file.close + File.exist?(filename).should be_true + File.delete(filename) + File.exist?(filename).should be_false + end + end + +end diff --git a/vendor/gems/rspec/spec/spec/mocks/bug_report_8165_spec.rb b/vendor/gems/rspec/spec/spec/mocks/bug_report_8165_spec.rb new file mode 100644 index 000000000..785546dca --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/bug_report_8165_spec.rb @@ -0,0 +1,31 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +describe "An object where respond_to? is true and does not have method" do + # When should_receive(:sym) is sent to any object, the Proxy sends + # respond_to?(:sym) to that object to see if the method should be proxied. + # + # If respond_to? itself is proxied, then when the Proxy sends respond_to? + # to the object, the proxy is invoked and responds yes (if so set in the spec). + # When the object does NOT actually respond to :sym, an exception is thrown + # when trying to proxy it. + # + # The fix was to keep track of whether :respond_to? had been proxied and, if + # so, call the munged copy of :respond_to? on the object. + + it "should not raise an exception" do + obj = Object.new + obj.should_receive(:respond_to?).with(:foobar).and_return(true) + obj.should_receive(:foobar).and_return(:baz) + obj.respond_to?(:foobar).should be_true + obj.foobar.should == :baz + end + + it "should not raise an exception" do + obj = mock("obj") + obj.should_receive(:respond_to?).with(:foobar).and_return(true) + obj.should_receive(:foobar).and_return(:baz) + obj.respond_to?(:foobar).should be_true + obj.foobar.should == :baz + end + +end diff --git a/vendor/gems/rspec/spec/spec/mocks/bug_report_8302_spec.rb b/vendor/gems/rspec/spec/spec/mocks/bug_report_8302_spec.rb new file mode 100644 index 000000000..a41df43d8 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/bug_report_8302_spec.rb @@ -0,0 +1,26 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Bug8302 + class Foo + def Foo.class_method(arg) + end + + def instance_bar(arg) + end + end + + describe "Bug report 8302:" do + it "class method is not restored correctly when proxied" do + Foo.should_not_receive(:class_method).with(Array.new) + Foo.rspec_verify + Foo.class_method(Array.new) + end + + it "instance method is not restored correctly when proxied" do + foo = Foo.new + foo.should_not_receive(:instance_bar).with(Array.new) + foo.rspec_verify + foo.instance_bar(Array.new) + end + end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/failing_mock_argument_constraints_spec.rb b/vendor/gems/rspec/spec/spec/mocks/failing_mock_argument_constraints_spec.rb new file mode 100644 index 000000000..f3c396283 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/failing_mock_argument_constraints_spec.rb @@ -0,0 +1,114 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Mocks + describe "failing MockArgumentConstraints" do + before(:each) do + @mock = mock("test mock") + @reporter = Mock.new("reporter", :null_object => true) + end + + after(:each) do + @mock.rspec_reset + end + + it "should reject non boolean" do + @mock.should_receive(:random_call).with(boolean()) + lambda do + @mock.random_call("false") + end.should raise_error(MockExpectationError) + end + + it "should reject non numeric" do + @mock.should_receive(:random_call).with(an_instance_of(Numeric)) + lambda do + @mock.random_call("1") + end.should raise_error(MockExpectationError) + end + + it "should reject non string" do + @mock.should_receive(:random_call).with(an_instance_of(String)) + lambda do + @mock.random_call(123) + end.should raise_error(MockExpectationError) + end + + it "should reject goose when expecting a duck" do + @mock.should_receive(:random_call).with(duck_type(:abs, :div)) + lambda { @mock.random_call("I don't respond to :abs or :div") }.should raise_error(MockExpectationError) + end + + it "should fail if regexp does not match submitted string" do + @mock.should_receive(:random_call).with(/bcd/) + lambda { @mock.random_call("abc") }.should raise_error(MockExpectationError) + end + + it "should fail if regexp does not match submitted regexp" do + @mock.should_receive(:random_call).with(/bcd/) + lambda { @mock.random_call(/bcde/) }.should raise_error(MockExpectationError) + end + + it "should fail for a hash w/ wrong values" do + @mock.should_receive(:random_call).with(:a => "b", :c => "d") + lambda do + @mock.random_call(:a => "b", :c => "e") + end.should raise_error(MockExpectationError, /Mock 'test mock' expected :random_call with \(\{(:a=>\"b\", :c=>\"d\"|:c=>\"d\", :a=>\"b\")\}\) but received it with \(\{(:a=>\"b\", :c=>\"e\"|:c=>\"e\", :a=>\"b\")\}\)/) + end + + it "should fail for a hash w/ wrong keys" do + @mock.should_receive(:random_call).with(:a => "b", :c => "d") + lambda do + @mock.random_call("a" => "b", "c" => "d") + end.should raise_error(MockExpectationError, /Mock 'test mock' expected :random_call with \(\{(:a=>\"b\", :c=>\"d\"|:c=>\"d\", :a=>\"b\")\}\) but received it with \(\{(\"a\"=>\"b\", \"c\"=>\"d\"|\"c\"=>\"d\", \"a\"=>\"b\")\}\)/) + end + + it "should match against a Matcher" do + lambda do + @mock.should_receive(:msg).with(equal(3)) + @mock.msg(37) + end.should raise_error(MockExpectationError, "Mock 'test mock' expected :msg with (equal 3) but received it with (37)") + end + + it "should fail no_args with one arg" do + lambda do + @mock.should_receive(:msg).with(no_args) + @mock.msg(37) + end.should raise_error(MockExpectationError, "Mock 'test mock' expected :msg with (no args) but received it with (37)") + end + end + + describe "failing deprecated MockArgumentConstraints" do + before(:each) do + @mock = mock("test mock") + @reporter = Mock.new("reporter", :null_object => true) + end + + after(:each) do + @mock.rspec_reset + end + + it "should reject non boolean" do + @mock.should_receive(:random_call).with(:boolean) + lambda do + @mock.random_call("false") + end.should raise_error(MockExpectationError) + end + + it "should reject non numeric" do + @mock.should_receive(:random_call).with(:numeric) + lambda do + @mock.random_call("1") + end.should raise_error(MockExpectationError) + end + + it "should reject non string" do + @mock.should_receive(:random_call).with(:string) + lambda do + @mock.random_call(123) + end.should raise_error(MockExpectationError) + end + + + end + end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/mock_ordering_spec.rb b/vendor/gems/rspec/spec/spec/mocks/mock_ordering_spec.rb new file mode 100644 index 000000000..919da2970 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/mock_ordering_spec.rb @@ -0,0 +1,84 @@ +require File.dirname(__FILE__) + '/../../spec_helper' + +module Spec + module Mocks + + describe "Mock ordering" do + + before do + @mock = mock("test mock") + end + + after do + @mock.rspec_reset + end + + it "should pass two calls in order" do + @mock.should_receive(:one).ordered + @mock.should_receive(:two).ordered + @mock.one + @mock.two + @mock.rspec_verify + end + + it "should pass three calls in order" do + @mock.should_receive(:one).ordered + @mock.should_receive(:two).ordered + @mock.should_receive(:three).ordered + @mock.one + @mock.two + @mock.three + @mock.rspec_verify + end + + it "should fail if second call comes first" do + @mock.should_receive(:one).ordered + @mock.should_receive(:two).ordered + lambda do + @mock.two + end.should raise_error(MockExpectationError, "Mock 'test mock' received :two out of order") + end + + it "should fail if third call comes first" do + @mock.should_receive(:one).ordered + @mock.should_receive(:two).ordered + @mock.should_receive(:three).ordered + @mock.one + lambda do + @mock.three + end.should raise_error(MockExpectationError, "Mock 'test mock' received :three out of order") + end + + it "should fail if third call comes second" do + @mock.should_receive(:one).ordered + @mock.should_receive(:two).ordered + @mock.should_receive(:three).ordered + @mock.one + lambda do + @mock.three + end.should raise_error(MockExpectationError, "Mock 'test mock' received :three out of order") + end + + it "should ignore order of non ordered calls" do + @mock.should_receive(:ignored_0) + @mock.should_receive(:ordered_1).ordered + @mock.should_receive(:ignored_1) + @mock.should_receive(:ordered_2).ordered + @mock.should_receive(:ignored_2) + @mock.should_receive(:ignored_3) + @mock.should_receive(:ordered_3).ordered + @mock.should_receive(:ignored_4) + @mock.ignored_3 + @mock.ordered_1 + @mock.ignored_0 + @mock.ordered_2 + @mock.ignored_4 + @mock.ignored_2 + @mock.ordered_3 + @mock.ignored_1 + @mock.rspec_verify + end + + end + end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/mock_space_spec.rb b/vendor/gems/rspec/spec/spec/mocks/mock_space_spec.rb new file mode 100644 index 000000000..23ffd01bc --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/mock_space_spec.rb @@ -0,0 +1,54 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' +require 'spec/mocks' + +module Spec + module Mocks + describe Space do + before :each do + @space = Space.new + klazz = Class.new do + def rspec_verify + @verified = true + end + def verified? + @verified + end + def rspec_reset + @reset = true + end + def reset? + @reset + end + end + @m1 = klazz.new + @m2 = klazz.new + end + it "should verify all mocks within" do + @space.add(@m1) + @space.add(@m2) + @space.verify_all + @m1.should be_verified + @m2.should be_verified + end + it "should reset all mocks within" do + @space.add(m1 = mock("mock1")) + @space.add(m2 = mock("mock2")) + m1.should_receive(:rspec_reset) + m2.should_receive(:rspec_reset) + @space.reset_all + end + it "should clear internal mocks on reset_all" do + @space.add(m = mock("mock")) + @space.reset_all + @space.instance_eval { mocks.empty? }.should be_true + end + it "should only add an instance once" do + @space.add(m1 = mock("mock1")) + @space.add(m1) + m1.should_receive(:rspec_verify) + @space.verify_all + end + end + end +end + diff --git a/vendor/gems/rspec/spec/spec/mocks/mock_spec.rb b/vendor/gems/rspec/spec/spec/mocks/mock_spec.rb new file mode 100644 index 000000000..bfe36ed57 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/mock_spec.rb @@ -0,0 +1,377 @@ +require File.dirname(__FILE__) + '/../../spec_helper' + +module Spec + module Mocks + describe "a Mock expectation" do + + before do + @mock = mock("test mock") + end + + after do + @mock.rspec_reset + end + + it "should report line number of expectation of unreceived message" do + @mock.should_receive(:wont_happen).with("x", 3) + #NOTE - this test is quite ticklish because it specifies that + #the above statement appears on line 12 of this file. + + begin + @mock.rspec_verify + violated + rescue MockExpectationError => e + e.backtrace[0].should match(/mock_spec\.rb:16/) + end + + end + + it "should pass when not receiving message specified as not to be received" do + @mock.should_not_receive(:not_expected) + @mock.rspec_verify + end + + it "should pass when receiving message specified as not to be received with different args" do + @mock.should_not_receive(:message).with("unwanted text") + @mock.should_receive(:message).with("other text") + @mock.message "other text" + @mock.rspec_verify + end + + it "should fail when receiving message specified as not to be received" do + @mock.should_not_receive(:not_expected) + @mock.not_expected + begin + @mock.rspec_verify + violated + rescue MockExpectationError => e + e.message.should == "Mock 'test mock' expected :not_expected with (any args) 0 times, but received it once" + end + end + + it "should fail when receiving message specified as not to be received with args" do + @mock.should_not_receive(:not_expected).with("unexpected text") + @mock.not_expected("unexpected text") + begin + @mock.rspec_verify + violated + rescue MockExpectationError => e + e.message.should == "Mock 'test mock' expected :not_expected with (\"unexpected text\") 0 times, but received it once" + end + end + + it "should pass when receiving message specified as not to be received with wrong args" do + @mock.should_not_receive(:not_expected).with("unexpected text") + @mock.not_expected "really unexpected text" + @mock.rspec_verify + end + + it "should allow block to calculate return values" do + @mock.should_receive(:something).with("a","b","c").and_return { |a,b,c| c+b+a } + @mock.something("a","b","c").should == "cba" + @mock.rspec_verify + end + + it "should allow parameter as return value" do + @mock.should_receive(:something).with("a","b","c").and_return("booh") + @mock.something("a","b","c").should == "booh" + @mock.rspec_verify + end + + it "should return nil if no return value set" do + @mock.should_receive(:something).with("a","b","c") + @mock.something("a","b","c").should be_nil + @mock.rspec_verify + end + + it "should raise exception if args dont match when method called" do + @mock.should_receive(:something).with("a","b","c").and_return("booh") + begin + @mock.something("a","d","c") + violated + rescue MockExpectationError => e + e.message.should == "Mock 'test mock' expected :something with (\"a\", \"b\", \"c\") but received it with (\"a\", \"d\", \"c\")" + end + end + + it "should fail if unexpected method called" do + begin + @mock.something("a","b","c") + violated + rescue MockExpectationError => e + e.message.should == "Mock 'test mock' received unexpected message :something with (\"a\", \"b\", \"c\")" + end + end + + it "should use block for expectation if provided" do + @mock.should_receive(:something) do | a, b | + a.should == "a" + b.should == "b" + "booh" + end + @mock.something("a", "b").should == "booh" + @mock.rspec_verify + end + + it "should fail if expectation block fails" do + @mock.should_receive(:something) {| bool | bool.should be_true} + begin + @mock.something false + rescue MockExpectationError => e + e.message.should match(/Mock 'test mock' received :something but passed block failed with: expected true, got false/) + end + end + + it "should fail when method defined as never is received" do + @mock.should_receive(:not_expected).never + begin + @mock.not_expected + rescue MockExpectationError => e + e.message.should == "Mock 'test mock' expected :not_expected 0 times, but received it 1 times" + end + end + + it "should raise when told to" do + @mock.should_receive(:something).and_raise(RuntimeError) + lambda do + @mock.something + end.should raise_error(RuntimeError) + end + + it "should raise passed an Exception instance" do + error = RuntimeError.new("error message") + @mock.should_receive(:something).and_raise(error) + begin + @mock.something + rescue RuntimeError => e + e.message.should eql("error message") + end + end + + it "should raise RuntimeError with passed message" do + @mock.should_receive(:something).and_raise("error message") + begin + @mock.something + rescue RuntimeError => e + e.message.should eql("error message") + end + end + + it "should not raise when told to if args dont match" do + @mock.should_receive(:something).with(2).and_raise(RuntimeError) + lambda do + @mock.something 1 + end.should raise_error(MockExpectationError) + end + + it "should throw when told to" do + @mock.should_receive(:something).and_throw(:blech) + lambda do + @mock.something + end.should throw_symbol(:blech) + end + + it "should raise when explicit return and block constrained" do + lambda do + @mock.should_receive(:fruit) do |colour| + :strawberry + end.and_return :apple + end.should raise_error(AmbiguousReturnError) + end + + it "should ignore args on any args" do + @mock.should_receive(:something).at_least(:once).with(any_args) + @mock.something + @mock.something 1 + @mock.something "a", 2 + @mock.something [], {}, "joe", 7 + @mock.rspec_verify + end + + it "should fail on no args if any args received" do + @mock.should_receive(:something).with(no_args()) + begin + @mock.something 1 + rescue MockExpectationError => e + e.message.should == "Mock 'test mock' expected :something with (no args) but received it with (1)" + end + end + + it "should fail when args are expected but none are received" do + @mock.should_receive(:something).with(1) + begin + @mock.something + rescue MockExpectationError => e + e.message.should == "Mock 'test mock' expected :something with (1) but received it with (no args)" + end + end + + it "should yield 0 args to blocks that take a variable number of arguments" do + @mock.should_receive(:yield_back).with(no_args()).once.and_yield + a = nil + @mock.yield_back {|*a|} + a.should == [] + @mock.rspec_verify + end + + it "should yield one arg to blocks that take a variable number of arguments" do + @mock.should_receive(:yield_back).with(no_args()).once.and_yield(99) + a = nil + @mock.yield_back {|*a|} + a.should == [99] + @mock.rspec_verify + end + + it "should yield many args to blocks that take a variable number of arguments" do + @mock.should_receive(:yield_back).with(no_args()).once.and_yield(99, 27, "go") + a = nil + @mock.yield_back {|*a|} + a.should == [99, 27, "go"] + @mock.rspec_verify + end + + it "should yield single value" do + @mock.should_receive(:yield_back).with(no_args()).once.and_yield(99) + a = nil + @mock.yield_back {|a|} + a.should == 99 + @mock.rspec_verify + end + + it "should yield two values" do + @mock.should_receive(:yield_back).with(no_args()).once.and_yield('wha', 'zup') + a, b = nil + @mock.yield_back {|a,b|} + a.should == 'wha' + b.should == 'zup' + @mock.rspec_verify + end + + it "should fail when calling yielding method with wrong arity" do + @mock.should_receive(:yield_back).with(no_args()).once.and_yield('wha', 'zup') + begin + @mock.yield_back {|a|} + rescue MockExpectationError => e + e.message.should == "Mock 'test mock' yielded |\"wha\", \"zup\"| to block with arity of 1" + end + end + + it "should fail when calling yielding method without block" do + @mock.should_receive(:yield_back).with(no_args()).once.and_yield('wha', 'zup') + begin + @mock.yield_back + rescue MockExpectationError => e + e.message.should == "Mock 'test mock' asked to yield |\"wha\", \"zup\"| but no block was passed" + end + end + + it "should be able to mock send" do + @mock.should_receive(:send).with(any_args) + @mock.send 'hi' + @mock.rspec_verify + end + + it "should be able to raise from method calling yielding mock" do + @mock.should_receive(:yield_me).and_yield 44 + + lambda do + @mock.yield_me do |x| + raise "Bang" + end + end.should raise_error(StandardError) + + @mock.rspec_verify + end + + # TODO - this is failing, but not if you run the file w/ --reverse - weird!!!!!! + # specify "should clear expectations after verify" do + # @mock.should_receive(:foobar) + # @mock.foobar + # @mock.rspec_verify + # begin + # @mock.foobar + # rescue MockExpectationError => e + # e.message.should == "Mock 'test mock' received unexpected message :foobar with (no args)" + # end + # end + + it "should restore objects to their original state on rspec_reset" do + mock = mock("this is a mock") + mock.should_receive(:blah) + mock.rspec_reset + mock.rspec_verify #should throw if reset didn't work + end + + end + + describe "a mock message receiving a block" do + before(:each) do + @mock = mock("mock") + @calls = 0 + end + + def add_call + @calls = @calls + 1 + end + + it "should call the block after #should_receive" do + @mock.should_receive(:foo) { add_call } + + @mock.foo + + @calls.should == 1 + end + + it "should call the block after #once" do + @mock.should_receive(:foo).once { add_call } + + @mock.foo + + @calls.should == 1 + end + + it "should call the block after #twice" do + @mock.should_receive(:foo).twice { add_call } + + @mock.foo + @mock.foo + + @calls.should == 2 + end + + it "should call the block after #times" do + @mock.should_receive(:foo).exactly(10).times { add_call } + + (1..10).each { @mock.foo } + + @calls.should == 10 + end + + it "should call the block after #any_number_of_times" do + @mock.should_receive(:foo).any_number_of_times { add_call } + + (1..7).each { @mock.foo } + + @calls.should == 7 + end + + it "should call the block after #with" do + @mock.should_receive(:foo).with(:arg) { add_call } + + @mock.foo(:arg) + + @calls.should == 1 + end + + it "should call the block after #ordered" do + @mock.should_receive(:foo).ordered { add_call } + @mock.should_receive(:bar).ordered { add_call } + + @mock.foo + @mock.bar + + @calls.should == 2 + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/multiple_return_value_spec.rb b/vendor/gems/rspec/spec/spec/mocks/multiple_return_value_spec.rb new file mode 100644 index 000000000..6e082abba --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/multiple_return_value_spec.rb @@ -0,0 +1,113 @@ +require File.dirname(__FILE__) + '/../../spec_helper' + +module Spec + module Mocks + describe "a Mock expectation with multiple return values and no specified count" do + before(:each) do + @mock = Mock.new("mock") + @return_values = ["1",2,Object.new] + @mock.should_receive(:message).and_return(@return_values[0],@return_values[1],@return_values[2]) + end + + it "should return values in order to consecutive calls" do + @mock.message.should == @return_values[0] + @mock.message.should == @return_values[1] + @mock.message.should == @return_values[2] + @mock.rspec_verify + end + + it "should complain when there are too few calls" do + third = Object.new + @mock.message.should == @return_values[0] + @mock.message.should == @return_values[1] + lambda { @mock.rspec_verify }.should raise_error(MockExpectationError, "Mock 'mock' expected :message with (any args) 3 times, but received it twice") + end + + it "should complain when there are too many calls" do + third = Object.new + @mock.message.should == @return_values[0] + @mock.message.should == @return_values[1] + @mock.message.should == @return_values[2] + @mock.message.should == @return_values[2] + lambda { @mock.rspec_verify }.should raise_error(MockExpectationError, "Mock 'mock' expected :message with (any args) 3 times, but received it 4 times") + end + end + + describe "a Mock expectation with multiple return values with a specified count equal to the number of values" do + before(:each) do + @mock = Mock.new("mock") + @return_values = ["1",2,Object.new] + @mock.should_receive(:message).exactly(3).times.and_return(@return_values[0],@return_values[1],@return_values[2]) + end + + it "should return values in order to consecutive calls" do + @mock.message.should == @return_values[0] + @mock.message.should == @return_values[1] + @mock.message.should == @return_values[2] + @mock.rspec_verify + end + + it "should complain when there are too few calls" do + third = Object.new + @mock.message.should == @return_values[0] + @mock.message.should == @return_values[1] + lambda { @mock.rspec_verify }.should raise_error(MockExpectationError, "Mock 'mock' expected :message with (any args) 3 times, but received it twice") + end + + it "should complain when there are too many calls" do + third = Object.new + @mock.message.should == @return_values[0] + @mock.message.should == @return_values[1] + @mock.message.should == @return_values[2] + @mock.message.should == @return_values[2] + lambda { @mock.rspec_verify }.should raise_error(MockExpectationError, "Mock 'mock' expected :message with (any args) 3 times, but received it 4 times") + end + end + + describe "a Mock expectation with multiple return values specifying at_least less than the number of values" do + before(:each) do + @mock = Mock.new("mock") + @mock.should_receive(:message).at_least(:twice).with(:no_args).and_return(11, 22) + end + + it "should use last return value for subsequent calls" do + @mock.message.should equal(11) + @mock.message.should equal(22) + @mock.message.should equal(22) + @mock.rspec_verify + end + + it "should fail when called less than the specified number" do + @mock.message.should equal(11) + lambda { @mock.rspec_verify }.should raise_error(MockExpectationError, "Mock 'mock' expected :message with (no args) twice, but received it once") + end + end + describe "a Mock expectation with multiple return values with a specified count larger than the number of values" do + before(:each) do + @mock = Mock.new("mock") + @mock.should_receive(:message).exactly(3).times.and_return(11, 22) + end + + it "should use last return value for subsequent calls" do + @mock.message.should equal(11) + @mock.message.should equal(22) + @mock.message.should equal(22) + @mock.rspec_verify + end + + it "should fail when called less than the specified number" do + @mock.message.should equal(11) + lambda { @mock.rspec_verify }.should raise_error(MockExpectationError, "Mock 'mock' expected :message with (any args) 3 times, but received it once") + end + + it "should fail when called greater than the specified number" do + @mock.message.should equal(11) + @mock.message.should equal(22) + @mock.message.should equal(22) + @mock.message.should equal(22) + lambda { @mock.rspec_verify }.should raise_error(MockExpectationError, "Mock 'mock' expected :message with (any args) 3 times, but received it 4 times") + end + end + end +end + diff --git a/vendor/gems/rspec/spec/spec/mocks/null_object_mock_spec.rb b/vendor/gems/rspec/spec/spec/mocks/null_object_mock_spec.rb new file mode 100644 index 000000000..57e8ca31c --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/null_object_mock_spec.rb @@ -0,0 +1,40 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Mocks + describe "a mock acting as a NullObject" do + before(:each) do + @mock = Mock.new("null_object", :null_object => true) + end + + it "should allow explicit expectation" do + @mock.should_receive(:something) + @mock.something + end + + it "should fail verification when explicit exception not met" do + lambda do + @mock.should_receive(:something) + @mock.rspec_verify + end.should raise_error(MockExpectationError) + end + + it "should ignore unexpected methods" do + @mock.random_call("a", "d", "c") + @mock.rspec_verify + end + + it "should expected message with different args first" do + @mock.should_receive(:message).with(:expected_arg) + @mock.message(:unexpected_arg) + @mock.message(:expected_arg) + end + + it "should expected message with different args second" do + @mock.should_receive(:message).with(:expected_arg) + @mock.message(:expected_arg) + @mock.message(:unexpected_arg) + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/once_counts_spec.rb b/vendor/gems/rspec/spec/spec/mocks/once_counts_spec.rb new file mode 100644 index 000000000..2c15d5c2e --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/once_counts_spec.rb @@ -0,0 +1,53 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Mocks + describe "OnceCounts" do + before(:each) do + @mock = mock("test mock") + end + + it "once should fail when called once with wrong args" do + @mock.should_receive(:random_call).once.with("a", "b", "c") + lambda do + @mock.random_call("d", "e", "f") + end.should raise_error(MockExpectationError) + @mock.rspec_reset + end + + it "once should fail when called twice" do + @mock.should_receive(:random_call).once + @mock.random_call + @mock.random_call + lambda do + @mock.rspec_verify + end.should raise_error(MockExpectationError) + end + + it "once should fail when not called" do + @mock.should_receive(:random_call).once + lambda do + @mock.rspec_verify + end.should raise_error(MockExpectationError) + end + + it "once should pass when called once" do + @mock.should_receive(:random_call).once + @mock.random_call + @mock.rspec_verify + end + + it "once should pass when called once with specified args" do + @mock.should_receive(:random_call).once.with("a", "b", "c") + @mock.random_call("a", "b", "c") + @mock.rspec_verify + end + + it "once should pass when called once with unspecified args" do + @mock.should_receive(:random_call).once + @mock.random_call("a", "b", "c") + @mock.rspec_verify + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/options_hash_spec.rb b/vendor/gems/rspec/spec/spec/mocks/options_hash_spec.rb new file mode 100644 index 000000000..a1ec9ddf4 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/options_hash_spec.rb @@ -0,0 +1,33 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Mocks + describe "calling :should_receive with an options hash" do + it "should report the file and line submitted with :expected_from" do + spec = Spec::DSL::Example.new "spec" do + mock = Spec::Mocks::Mock.new("a mock") + mock.should_receive(:message, :expected_from => "/path/to/blah.ext:37") + mock.rspec_verify + end + reporter = mock("reporter", :null_object => true) + reporter.should_receive(:example_finished) do |spec, error| + error.backtrace.detect {|line| line =~ /\/path\/to\/blah.ext:37/}.should_not be_nil + end + spec.run(reporter, nil, nil, nil, Object.new) + end + + it "should use the message supplied with :message" do + spec = Spec::DSL::Example.new "spec" do + mock = Spec::Mocks::Mock.new("a mock") + mock.should_receive(:message, :message => "recebi nada") + mock.rspec_verify + end + reporter = mock("reporter", :null_object => true) + reporter.should_receive(:example_finished) do |spec, error| + error.message.should == "recebi nada" + end + spec.run(reporter, nil, nil, nil, Object.new) + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/partial_mock_spec.rb b/vendor/gems/rspec/spec/spec/mocks/partial_mock_spec.rb new file mode 100644 index 000000000..c45b9054c --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/partial_mock_spec.rb @@ -0,0 +1,84 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Mocks + describe "using a Partial Mock," do + before(:each) do + @object = Object.new + end + + it "should name the class in the failure message" do + @object.should_receive(:foo) + lambda do + @object.rspec_verify + end.should raise_error(Spec::Mocks::MockExpectationError, /Object/) + end + + it "should not conflict with @options in the object" do + @object.instance_eval { @options = Object.new } + @object.should_receive(:blah) + @object.blah + end + + it "should_not_receive should mock out the method" do + @object.should_not_receive(:fuhbar) + @object.fuhbar + lambda do + @object.rspec_verify + end.should raise_error(Spec::Mocks::MockExpectationError) + end + + it "should_not_receive should return a negative message expectation" do + @object.should_not_receive(:foobar).should be_kind_of(NegativeMessageExpectation) + end + + it "should_receive should mock out the method" do + @object.should_receive(:foobar).with(:test_param).and_return(1) + @object.foobar(:test_param).should equal(1) + end + + it "should_receive should handle a hash" do + @object.should_receive(:foobar).with(:key => "value").and_return(1) + @object.foobar(:key => "value").should equal(1) + end + + it "should_receive should handle an inner hash" do + hash = {:a => {:key => "value"}} + @object.should_receive(:foobar).with(:key => "value").and_return(1) + @object.foobar(hash[:a]).should equal(1) + end + + it "should_receive should return a message expectation" do + @object.should_receive(:foobar).should be_kind_of(MessageExpectation) + @object.foobar + end + + it "should_receive should verify method was called" do + @object.should_receive(:foobar).with(:test_param).and_return(1) + lambda do + @object.rspec_verify + end.should raise_error(Spec::Mocks::MockExpectationError) + end + + it "should_receive should also take a String argument" do + @object.should_receive('foobar') + @object.foobar + end + + it "should_not_receive should also take a String argument" do + @object.should_not_receive('foobar') + @object.foobar + lambda do + @object.rspec_verify + end.should raise_error(Spec::Mocks::MockExpectationError) + end + + it "should use report nil in the error message" do + @this_will_resolve_to_nil.should_receive(:foobar) + lambda do + @this_will_resolve_to_nil.rspec_verify + end.should raise_error(Spec::Mocks::MockExpectationError, /NilClass.*expected :foobar with/) + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/partial_mock_using_mocks_directly_spec.rb b/vendor/gems/rspec/spec/spec/mocks/partial_mock_using_mocks_directly_spec.rb new file mode 100644 index 000000000..c857d8380 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/partial_mock_using_mocks_directly_spec.rb @@ -0,0 +1,66 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec +module Mocks +describe "PartialMockUsingMocksDirectly" do + before(:each) do + + klass=Class.new + klass.class_eval do + def existing_method + :original_value + end + end + @obj = klass.new + + end + + # See http://rubyforge.org/tracker/index.php?func=detail&aid=10263&group_id=797&atid=3149 + # specify "should clear expectations on verify" do + # @obj.should_receive(:msg) + # @obj.msg + # @obj.rspec_verify + # lambda do + # @obj.msg + # end.should raise_error(NoMethodError) + # + # end + it "should fail when expected message is not received" do + @obj.should_receive(:msg) + lambda do + @obj.rspec_verify + end.should raise_error(MockExpectationError) + + end + it "should fail when message is received with incorrect args" do + @obj.should_receive(:msg).with(:correct_arg) + lambda do + @obj.msg(:incorrect_arg) + end.should raise_error(MockExpectationError) + @obj.msg(:correct_arg) + + end + it "should pass when expected message is received" do + @obj.should_receive(:msg) + @obj.msg + @obj.rspec_verify + + end + it "should pass when message is received with correct args" do + @obj.should_receive(:msg).with(:correct_arg) + @obj.msg(:correct_arg) + @obj.rspec_verify + + end + it "should revert to original method if existed" do + @obj.existing_method.should equal(:original_value) + @obj.should_receive(:existing_method).and_return(:mock_value) + @obj.existing_method.should equal(:mock_value) + @obj.rspec_verify + @obj.existing_method.should equal(:original_value) + + end + +end +end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/passing_mock_argument_constraints_spec.rb b/vendor/gems/rspec/spec/spec/mocks/passing_mock_argument_constraints_spec.rb new file mode 100644 index 000000000..2d631bde5 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/passing_mock_argument_constraints_spec.rb @@ -0,0 +1,148 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Mocks + describe "mock argument constraints", :shared => true do + before(:each) do + @mock = Mock.new("test mock") + end + + after(:each) do + @mock.rspec_verify + end + end + + describe Methods, "handling argument constraints with DEPRECATED symbols" do + it_should_behave_like "mock argument constraints" + + it "should accept true as boolean" do + @mock.should_receive(:random_call).with(:boolean) + @mock.random_call(true) + end + + it "should accept false as boolean" do + @mock.should_receive(:random_call).with(:boolean) + @mock.random_call(false) + end + + it "should accept fixnum as numeric" do + @mock.should_receive(:random_call).with(:numeric) + @mock.random_call(1) + end + + it "should accept float as numeric" do + @mock.should_receive(:random_call).with(:numeric) + @mock.random_call(1.5) + end + + it "should accept string as anything" do + @mock.should_receive(:random_call).with("a", :anything, "c") + @mock.random_call("a", "whatever", "c") + end + + it "should match string" do + @mock.should_receive(:random_call).with(:string) + @mock.random_call("a string") + end + + it "should match no args against any_args" do + @mock.should_receive(:random_call).with(:any_args) + @mock.random_call("a string") + end + end + + describe Methods, "handling argument constraints" do + it_should_behave_like "mock argument constraints" + + it "should accept true as boolean()" do + @mock.should_receive(:random_call).with(boolean()) + @mock.random_call(true) + end + + it "should accept false as boolean()" do + @mock.should_receive(:random_call).with(boolean()) + @mock.random_call(false) + end + + it "should accept fixnum as an_instance_of(Numeric)" do + @mock.should_receive(:random_call).with(an_instance_of(Numeric)) + @mock.random_call(1) + end + + it "should accept float as an_instance_of(Numeric)" do + @mock.should_receive(:random_call).with(an_instance_of(Numeric)) + @mock.random_call(1.5) + end + + it "should accept string as anything()" do + @mock.should_receive(:random_call).with("a", anything(), "c") + @mock.random_call("a", "whatever", "c") + end + + it "should match duck type with one method" do + @mock.should_receive(:random_call).with(duck_type(:length)) + @mock.random_call([]) + end + + it "should match duck type with two methods" do + @mock.should_receive(:random_call).with(duck_type(:abs, :div)) + @mock.random_call(1) + end + + it "should match no args against any_args()" do + @mock.should_receive(:random_call).with(any_args) + @mock.random_call() + end + + it "should match one arg against any_args()" do + @mock.should_receive(:random_call).with(any_args) + @mock.random_call("a string") + end + + it "should match no args against no_args()" do + @mock.should_receive(:random_call).with(no_args) + @mock.random_call() + end + end + + describe Methods, "handling non-constraint arguments" do + + it "should match non special symbol (can be removed when deprecated symbols are removed)" do + @mock.should_receive(:random_call).with(:some_symbol) + @mock.random_call(:some_symbol) + end + + it "should match string against regexp" do + @mock.should_receive(:random_call).with(/bcd/) + @mock.random_call("abcde") + end + + it "should match regexp against regexp" do + @mock.should_receive(:random_call).with(/bcd/) + @mock.random_call(/bcd/) + end + + it "should match against a hash submitted and received by value" do + @mock.should_receive(:random_call).with(:a => "a", :b => "b") + @mock.random_call(:a => "a", :b => "b") + end + + it "should match against a hash submitted by reference and received by value" do + opts = {:a => "a", :b => "b"} + @mock.should_receive(:random_call).with(opts) + @mock.random_call(:a => "a", :b => "b") + end + + it "should match against a hash submitted by value and received by reference" do + opts = {:a => "a", :b => "b"} + @mock.should_receive(:random_call).with(:a => "a", :b => "b") + @mock.random_call(opts) + end + + it "should match against a Matcher" do + @mock.should_receive(:msg).with(equal(37)) + @mock.msg(37) + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/precise_counts_spec.rb b/vendor/gems/rspec/spec/spec/mocks/precise_counts_spec.rb new file mode 100644 index 000000000..ba3898943 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/precise_counts_spec.rb @@ -0,0 +1,52 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Mocks + describe "PreciseCounts" do + before(:each) do + @mock = mock("test mock") + end + + it "should fail when exactly n times method is called less than n times" do + @mock.should_receive(:random_call).exactly(3).times + @mock.random_call + @mock.random_call + lambda do + @mock.rspec_verify + end.should raise_error(MockExpectationError) + end + + it "should fail when exactly n times method is never called" do + @mock.should_receive(:random_call).exactly(3).times + lambda do + @mock.rspec_verify + end.should raise_error(MockExpectationError) + end + + it "should pass if exactly n times method is called exactly n times" do + @mock.should_receive(:random_call).exactly(3).times + @mock.random_call + @mock.random_call + @mock.random_call + @mock.rspec_verify + end + + it "should pass multiple calls with different args and counts" do + @mock.should_receive(:random_call).twice.with(1) + @mock.should_receive(:random_call).once.with(2) + @mock.random_call(1) + @mock.random_call(2) + @mock.random_call(1) + @mock.rspec_verify + end + + it "should pass mutiple calls with different args" do + @mock.should_receive(:random_call).once.with(1) + @mock.should_receive(:random_call).once.with(2) + @mock.random_call(1) + @mock.random_call(2) + @mock.rspec_verify + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/record_messages_spec.rb b/vendor/gems/rspec/spec/spec/mocks/record_messages_spec.rb new file mode 100644 index 000000000..ec247726d --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/record_messages_spec.rb @@ -0,0 +1,26 @@ +require File.dirname(__FILE__) + '/../../spec_helper' + +module Spec + module Mocks + describe "a mock" do + before(:each) do + @mock = mock("mock", :null_object => true) + end + it "should answer false for received_message? when no messages received" do + @mock.received_message?(:message).should be_false + end + it "should answer true for received_message? when message received" do + @mock.message + @mock.received_message?(:message).should be_true + end + it "should answer true for received_message? when message received with correct args" do + @mock.message 1,2,3 + @mock.received_message?(:message, 1,2,3).should be_true + end + it "should answer false for received_message? when message received with incorrect args" do + @mock.message 1,2,3 + @mock.received_message?(:message, 1,2).should be_false + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/stub_spec.rb b/vendor/gems/rspec/spec/spec/mocks/stub_spec.rb new file mode 100644 index 000000000..dc6fff89b --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/stub_spec.rb @@ -0,0 +1,159 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Mocks + describe "A method stub" do + before(:each) do + @class = Class.new do + def self.existing_class_method + :original_value + end + + def existing_instance_method + :original_value + end + end + @obj = @class.new + end + + it "should allow for a mock expectation to temporarily replace a method stub on a mock" do + mock = Spec::Mocks::Mock.new("a mock") + mock.stub!(:msg).and_return(:stub_value) + mock.should_receive(:msg).with(:arg).and_return(:mock_value) + mock.msg(:arg).should equal(:mock_value) + mock.msg.should equal(:stub_value) + mock.msg.should equal(:stub_value) + mock.rspec_verify + end + + it "should allow for a mock expectation to temporarily replace a method stub on a non-mock" do + @obj.stub!(:msg).and_return(:stub_value) + @obj.should_receive(:msg).with(:arg).and_return(:mock_value) + @obj.msg(:arg).should equal(:mock_value) + @obj.msg.should equal(:stub_value) + @obj.msg.should equal(:stub_value) + @obj.rspec_verify + end + + it "should ignore when expected message is not received" do + @obj.stub!(:msg) + lambda do + @obj.rspec_verify + end.should_not raise_error + end + + it "should clear itself on rspec_verify" do + @obj.stub!(:this_should_go).and_return(:blah) + @obj.this_should_go.should == :blah + @obj.rspec_verify + lambda do + @obj.this_should_go + end.should raise_error + end + + it "should ignore when expected message is received" do + @obj.stub!(:msg) + @obj.msg + @obj.rspec_verify + end + + it "should ignore when message is received with args" do + @obj.stub!(:msg) + @obj.msg(:an_arg) + @obj.rspec_verify + end + + it "should not support with" do + lambda do + Spec::Mocks::Mock.new("a mock").stub!(:msg).with(:arg) + end.should raise_error(NoMethodError) + end + + it "should return expected value when expected message is received" do + @obj.stub!(:msg).and_return(:return_value) + @obj.msg.should equal(:return_value) + @obj.rspec_verify + end + + it "should return values in order to consecutive calls" do + return_values = ["1",2,Object.new] + @obj.stub!(:msg).and_return(return_values[0],return_values[1],return_values[2]) + @obj.msg.should == return_values[0] + @obj.msg.should == return_values[1] + @obj.msg.should == return_values[2] + end + + it "should keep returning last value in consecutive calls" do + return_values = ["1",2,Object.new] + @obj.stub!(:msg).and_return(return_values[0],return_values[1],return_values[2]) + @obj.msg.should == return_values[0] + @obj.msg.should == return_values[1] + @obj.msg.should == return_values[2] + @obj.msg.should == return_values[2] + @obj.msg.should == return_values[2] + end + + it "should revert to original instance method if existed" do + @obj.existing_instance_method.should equal(:original_value) + @obj.stub!(:existing_instance_method).and_return(:mock_value) + @obj.existing_instance_method.should equal(:mock_value) + @obj.rspec_verify + # TODO JRUBY: This causes JRuby to fail with: + # NativeException in 'Stub should revert to original instance method if existed' + # java.lang.ArrayIndexOutOfBoundsException: 0 + # org.jruby.internal.runtime.methods.IterateCallable.internalCall(IterateCallable.java:63) + # org.jruby.internal.runtime.methods.AbstractCallable.call(AbstractCallable.java:64) + # org.jruby.runtime.ThreadContext.yieldInternal(ThreadContext.java:574) + # org.jruby.runtime.ThreadContext.yieldSpecificBlock(ThreadContext.java:549) + # org.jruby.runtime.Block.call(Block.java:158) + # org.jruby.RubyProc.call(RubyProc.java:118) + # org.jruby.internal.runtime.methods.ProcMethod.internalCall(ProcMethod.java:69) + # org.jruby.internal.runtime.methods.AbstractMethod.call(AbstractMethod.java:58) + # org.jruby.RubyObject.callMethod(RubyObject.java:379) + # org.jruby.RubyObject.callMethod(RubyObject.java:331) + # org.jruby.evaluator.EvaluationState.evalInternal(EvaluationState.java:472) + # org.jruby.evaluator.EvaluationState.evalInternal(EvaluationState.java:462) + # org.jruby.evaluator.EvaluationState.evalInternal(EvaluationState.java:390) + # org.jruby.evaluator.EvaluationState.eval(EvaluationState.java:133) + @obj.existing_instance_method.should equal(:original_value) + end + + it "should revert to original class method if existed" do + @class.existing_class_method.should equal(:original_value) + @class.stub!(:existing_class_method).and_return(:mock_value) + @class.existing_class_method.should equal(:mock_value) + @class.rspec_verify + @class.existing_class_method.should equal(:original_value) + end + + it "should clear itself on rspec_verify" do + @obj.stub!(:this_should_go).and_return(:blah) + @obj.this_should_go.should == :blah + @obj.rspec_verify + lambda do + @obj.this_should_go + end.should raise_error + end + + it "should support yielding" do + @obj.stub!(:method_that_yields).and_yield(:yielded_value) + current_value = :value_before + @obj.method_that_yields {|val| current_value = val} + current_value.should == :yielded_value + @obj.rspec_verify + end + + it "should throw when told to" do + @mock.stub!(:something).and_throw(:blech) + lambda do + @mock.something + end.should throw_symbol(:blech) + end + + it "should support overriding w/ a new stub" do + @stub.stub!(:existing_instance_method).and_return(:updated_stub_value) + @stub.existing_instance_method.should == :updated_stub_value + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/mocks/twice_counts_spec.rb b/vendor/gems/rspec/spec/spec/mocks/twice_counts_spec.rb new file mode 100644 index 000000000..d07e45736 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/mocks/twice_counts_spec.rb @@ -0,0 +1,67 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Mocks + describe "TwiceCounts" do + before(:each) do + @mock = mock("test mock") + end + + it "twice should fail when call count is higher than expected" do + @mock.should_receive(:random_call).twice + @mock.random_call + @mock.random_call + @mock.random_call + lambda do + @mock.rspec_verify + end.should raise_error(MockExpectationError) + end + + it "twice should fail when call count is lower than expected" do + @mock.should_receive(:random_call).twice + @mock.random_call + lambda do + @mock.rspec_verify + end.should raise_error(MockExpectationError) + end + + it "twice should fail when called twice with wrong args on the first call" do + @mock.should_receive(:random_call).twice.with("1", 1) + lambda do + @mock.random_call(1, "1") + end.should raise_error(MockExpectationError) + @mock.rspec_reset + end + + it "twice should fail when called twice with wrong args on the second call" do + @mock.should_receive(:random_call).twice.with("1", 1) + @mock.random_call("1", 1) + lambda do + @mock.random_call(1, "1") + end.should raise_error(MockExpectationError) + @mock.rspec_reset + end + + it "twice should pass when called twice" do + @mock.should_receive(:random_call).twice + @mock.random_call + @mock.random_call + @mock.rspec_verify + end + + it "twice should pass when called twice with specified args" do + @mock.should_receive(:random_call).twice.with("1", 1) + @mock.random_call("1", 1) + @mock.random_call("1", 1) + @mock.rspec_verify + end + + it "twice should pass when called twice with unspecified args" do + @mock.should_receive(:random_call).twice + @mock.random_call("1") + @mock.random_call(1) + @mock.rspec_verify + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/package/bin_spec_spec.rb b/vendor/gems/rspec/spec/spec/package/bin_spec_spec.rb new file mode 100644 index 000000000..6eac5e8cb --- /dev/null +++ b/vendor/gems/rspec/spec/spec/package/bin_spec_spec.rb @@ -0,0 +1,12 @@ +require "#{File.dirname(__FILE__)}/../../spec_helper" + +describe "The bin/spec script" do + it "should have no warnings" do + spec_path = "#{File.dirname(__FILE__)}/../../../bin/spec" + output = nil + IO.popen("ruby -w #{spec_path} --help 2>&1") do |io| + output = io.read + end + output.should_not =~ /warning/n + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/behaviour_runner_spec.rb b/vendor/gems/rspec/spec/spec/runner/behaviour_runner_spec.rb new file mode 100644 index 000000000..ff4890633 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/behaviour_runner_spec.rb @@ -0,0 +1,229 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Runner + describe BehaviourRunner, "#add_behaviour affecting passed in behaviour" do + before do + @err = StringIO.new('') + @out = StringIO.new('') + @options = Options.new(@err,@out) + @runner = BehaviourRunner.new(@options) + class << @runner + attr_reader :behaviours + end + + @behaviour = ::Spec::DSL::Behaviour.new("A Behaviour") do + it "runs 1" do + end + it "runs 2" do + end + end + end + + it "removes examples not selected from Behaviour when options.examples is set" do + @options.examples << "A Behaviour runs 1" + + @behaviour.number_of_examples.should == 2 + + @runner.add_behaviour @behaviour + @behaviour.number_of_examples.should == 1 + @behaviour.examples.first.send(:description).should == "runs 1" + end + + it "keeps all examples when options.examples is nil" do + @options.examples = nil + @behaviour.number_of_examples.should == 2 + + @runner.add_behaviour @behaviour + @behaviour.number_of_examples.should == 2 + @behaviour.examples.collect {|example| example.send(:description) }.should == ['runs 1', 'runs 2'] + end + + it "keeps all examples when options.examples is empty" do + @options.examples = [] + @behaviour.number_of_examples.should == 2 + + @runner.add_behaviour @behaviour + @behaviour.number_of_examples.should == 2 + @behaviour.examples.collect {|example| example.send(:description) }.should == ['runs 1', 'runs 2'] + end + end + + describe BehaviourRunner, "#add_behaviour affecting behaviours" do + before do + @err = StringIO.new('') + @out = StringIO.new('') + @options = Options.new(@err,@out) + @runner = BehaviourRunner.new(@options) + class << @runner + attr_reader :behaviours + end + end + + it "adds behaviour when behaviour has examples and is not shared" do + @behaviour = ::Spec::DSL::Behaviour.new("A Behaviour") do + it "uses this behaviour" do + end + end + + @behaviour.should_not be_shared + @behaviour.number_of_examples.should be > 0 + @runner.add_behaviour @behaviour + + @runner.behaviours.length.should == 1 + end + + it "does not add the behaviour when number_of_examples is 0" do + @behaviour = ::Spec::DSL::Behaviour.new("A Behaviour") do + end + @behaviour.number_of_examples.should == 0 + @runner.add_behaviour @behaviour + + @runner.behaviours.should be_empty + end + + it "does not add the behaviour when behaviour is shared" do + @behaviour = ::Spec::DSL::Behaviour.new("A Behaviour", :shared => true) do + it "does not use this behaviour" do + end + end + @behaviour.should be_shared + @runner.add_behaviour @behaviour + + @runner.behaviours.should be_empty + end + end + + describe BehaviourRunner do + before do + @err = StringIO.new('') + @out = StringIO.new('') + @options = Options.new(@err,@out) + end + + it "should only run behaviours with at least one example" do + desired_behaviour = mock("desired behaviour") + desired_behaviour.should_receive(:run) + desired_behaviour.should_receive(:retain_examples_matching!) + desired_behaviour.should_receive(:number_of_examples).twice.and_return(1) + desired_behaviour.should_receive(:shared?).and_return(false) + desired_behaviour.should_receive(:set_sequence_numbers).with(0, anything) + + other_behaviour = mock("other behaviour") + other_behaviour.should_receive(:run).never + other_behaviour.should_receive(:retain_examples_matching!) + other_behaviour.should_receive(:number_of_examples).and_return(0) + + reporter = mock("reporter") + @options.reporter = reporter + @options.examples = ["desired behaviour legal spec"] + + runner = Spec::Runner::BehaviourRunner.new(@options) + runner.add_behaviour(desired_behaviour) + runner.add_behaviour(other_behaviour) + reporter.should_receive(:start) + reporter.should_receive(:end) + reporter.should_receive(:dump) + runner.run([], false) + end + + it "should dump even if Interrupt exception is occurred" do + behaviour = Spec::DSL::Behaviour.new("behaviour") do + it "no error" do + end + + it "should interrupt" do + raise Interrupt + end + end + + reporter = mock("reporter") + reporter.should_receive(:start) + reporter.should_receive(:add_behaviour) + reporter.should_receive(:example_started).twice + reporter.should_receive(:example_finished).twice + reporter.should_receive(:rspec_verify) + reporter.should_receive(:rspec_reset) + reporter.should_receive(:end) + reporter.should_receive(:dump) + + @options.reporter = reporter + runner = Spec::Runner::BehaviourRunner.new(@options) + runner.add_behaviour(behaviour) + runner.run([], false) + end + + it "should heckle when options have heckle_runner" do + behaviour = mock("behaviour", :null_object => true) + behaviour.should_receive(:number_of_examples).twice.and_return(1) + behaviour.should_receive(:run).and_return(0) + behaviour.should_receive(:shared?).and_return(false) + + reporter = mock("reporter") + reporter.should_receive(:start).with(1) + reporter.should_receive(:end) + reporter.should_receive(:dump).and_return(0) + + heckle_runner = mock("heckle_runner") + heckle_runner.should_receive(:heckle_with) + + @options.reporter = reporter + @options.heckle_runner = heckle_runner + + runner = Spec::Runner::BehaviourRunner.new(@options) + runner.add_behaviour(behaviour) + runner.run([], false) + end + + it "should run examples backwards if options.reverse is true" do + @options.reverse = true + + reporter = mock("reporter") + reporter.should_receive(:start).with(3) + reporter.should_receive(:end) + reporter.should_receive(:dump).and_return(0) + @options.reporter = reporter + + runner = Spec::Runner::BehaviourRunner.new(@options) + b1 = mock("b1") + b1.should_receive(:number_of_examples).twice.and_return(1) + b1.should_receive(:shared?).and_return(false) + b1.should_receive(:set_sequence_numbers).with(12, true).and_return(18) + + b2 = mock("b2") + b2.should_receive(:number_of_examples).twice.and_return(2) + b2.should_receive(:shared?).and_return(false) + b2.should_receive(:set_sequence_numbers).with(0, true).and_return(12) + b2.should_receive(:run) do + b1.should_receive(:run) + end + + runner.add_behaviour(b1) + runner.add_behaviour(b2) + + runner.run([], false) + end + + it "should yield global configuration" do + Spec::Runner.configure do |config| + config.should equal(Spec::Runner.configuration) + end + end + + it "should pass its Description to the reporter" do + behaviour = Spec::DSL::Behaviour.new("behaviour") do + it "should" do + end + end + + reporter = mock("reporter", :null_object => true) + reporter.should_receive(:add_behaviour).with(an_instance_of(Spec::DSL::Description)) + + @options.reporter = reporter + runner = Spec::Runner::BehaviourRunner.new(@options) + runner.add_behaviour(behaviour) + runner.run([], false) + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/command_line_spec.rb b/vendor/gems/rspec/spec/spec/runner/command_line_spec.rb new file mode 100644 index 000000000..d78626399 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/command_line_spec.rb @@ -0,0 +1,33 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +describe "CommandLine" do + it "should run directory" do + file = File.dirname(__FILE__) + '/../../../examples' + err = StringIO.new + out = StringIO.new + Spec::Runner::CommandLine.run([file], err, out, false, true) + + out.rewind + out.read.should =~ /78 examples, 0 failures, 3 pending/n + end + + it "should run file" do + file = File.dirname(__FILE__) + '/../../../failing_examples/predicate_example.rb' + err = StringIO.new + out = StringIO.new + Spec::Runner::CommandLine.run([file], err, out, false, true) + + out.rewind + out.read.should =~ /2 examples, 1 failure/n + end + + it "should raise when file does not exist" do + file = File.dirname(__FILE__) + '/doesntexist' + err = StringIO.new + out = StringIO.new + + lambda { + Spec::Runner::CommandLine.run([file], err, out, false, true) + }.should raise_error + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/context_matching_spec.rb b/vendor/gems/rspec/spec/spec/runner/context_matching_spec.rb new file mode 100644 index 000000000..ad8017b64 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/context_matching_spec.rb @@ -0,0 +1,27 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module DSL + describe Behaviour do + + before(:each) do + @formatter = Spec::Mocks::Mock.new("formatter") + @behaviour = Behaviour.new("behaviour") {} + end + + it "should retain examples that don't match" do + @behaviour.it("example1") {} + @behaviour.it("example2") {} + @behaviour.retain_examples_matching!(["behaviour"]) + @behaviour.number_of_examples.should == 2 + end + + it "should remove examples that match" do + @behaviour.it("example1") {} + @behaviour.it("example2") {} + @behaviour.retain_examples_matching!(["behaviour example1"]) + @behaviour.number_of_examples.should == 1 + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/drb_command_line_spec.rb b/vendor/gems/rspec/spec/spec/runner/drb_command_line_spec.rb new file mode 100644 index 000000000..d2d68499d --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/drb_command_line_spec.rb @@ -0,0 +1,84 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Runner + describe DrbCommandLine, "without running local server" do + + unless Config::CONFIG['ruby_install_name'] == 'jruby' + it "should print error when there is no running local server" do + err = StringIO.new + out = StringIO.new + DrbCommandLine.run(['--version'], err, out, false) + + err.rewind + err.read.should =~ /No server is running/ + end + end + end + + describe DrbCommandLine, "with local server" do + + unless Config::CONFIG['ruby_install_name'] == 'jruby' + before(:all) do + DRb.start_service("druby://localhost:8989", Spec::Runner::CommandLine) + $drb_example_file_counter = 0 + end + + before(:each) do + create_dummy_spec_file + $drb_example_file_counter = $drb_example_file_counter + 1 + end + + after(:each) do + File.delete(@dummy_spec_filename) + end + + after(:all) do + DRb.stop_service + end + + it "should run against local server" do + out = run_spec_via_druby(['--version']) + out.should =~ /RSpec/n + end + + it "should output green colorized text when running with --colour option" do + out = run_spec_via_druby(["--colour", @dummy_spec_filename]) + out.should =~ /\e\[32m/n + end + + it "should output red colorized text when running with -c option" do + out = run_spec_via_druby(["-c", @dummy_spec_filename]) + out.should =~ /\e\[31m/n + end + + def create_dummy_spec_file + @dummy_spec_filename = File.expand_path(File.dirname(__FILE__)) + "/_dummy_spec#{$drb_example_file_counter}.rb" + File.open(@dummy_spec_filename, 'w') do |f| + f.write %{ + describe "DUMMY CONTEXT for 'DrbCommandLine with -c option'" do + it "should be output with green bar" do + true.should be_true + end + + it "should be output with red bar" do + violated("I want to see a red bar!") + end + end + } + end + end + + def run_spec_via_druby(args) + err, out = StringIO.new, StringIO.new + out.instance_eval do + def tty?; true end + end + Spec::Runner::DrbCommandLine.run(args, err, out, false, true) + out.rewind; out.read + end + end + + end + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/execution_context_spec.rb b/vendor/gems/rspec/spec/spec/runner/execution_context_spec.rb new file mode 100644 index 000000000..82e7447c1 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/execution_context_spec.rb @@ -0,0 +1,31 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +describe "ExecutionContext" do + + it "should provide duck_type()" do + dt = duck_type(:length) + dt.should be_an_instance_of(Spec::Mocks::DuckTypeArgConstraint) + dt.matches?([]).should be_true + end + + it "should violate when violated()" do + lambda do + violated + end.should raise_error(Spec::Expectations::ExpectationNotMetError) + end + + it "should provide mock()" do + mock("thing").should be_an_instance_of(Spec::Mocks::Mock) + end + + it "should provide stub()" do + thing_stub = stub("thing").should be_an_instance_of(Spec::Mocks::Mock) + end + + it "should add method stubs to stub()" do + thing_stub = stub("thing", :a => "A", :b => "B") + thing_stub.a.should == "A" + thing_stub.b.should == "B" + end + +end diff --git a/vendor/gems/rspec/spec/spec/runner/extensions/bug_report_10577_spec.rb b/vendor/gems/rspec/spec/spec/runner/extensions/bug_report_10577_spec.rb new file mode 100644 index 000000000..c4da69f4d --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/extensions/bug_report_10577_spec.rb @@ -0,0 +1,35 @@ +require File.dirname(__FILE__) + '/../../../spec_helper.rb' +require 'delegate' + +module Bug10577 + class OCI8 + def describe(name) + "Hello, #{name}" + end + + def something(name) + "Something, #{name}" + end + end + + class OCI8AutoRecover < DelegateClass(OCI8) + def initialize + @connection = OCI8.new + super(@connection) + end + end + + class OCI8AutoRecover + def describe(name) + @connection.describe(name) + end + end + + describe Kernel do + it "should not mask a delegate class' describe method" do + bugger = OCI8AutoRecover.new + bugger.describe('aslak').should == "Hello, aslak" + bugger.something('aslak').should == "Something, aslak" + end + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/extensions/kernel_spec.rb b/vendor/gems/rspec/spec/spec/runner/extensions/kernel_spec.rb new file mode 100644 index 000000000..6b253a06a --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/extensions/kernel_spec.rb @@ -0,0 +1,36 @@ +require File.dirname(__FILE__) + '/../../../spec_helper.rb' + +describe Kernel, "when extended by rspec" do + it "should respond to :describe" do + Object.new.should respond_to(:describe) + Object.new.should respond_to(:context) + end +end + +describe Kernel, " when creating behaviours with describe" do + + it "should fail when no block given" do + lambda { describe "foo" }.should raise_error(ArgumentError) + end + + it "should fail when no description given" do + lambda { describe do; end }.should raise_error(ArgumentError) + end +end + +describe Kernel, "#respond_to" do + before(:each) do + @kernel_impersonator = Class.new do + include Kernel + end.new + end + + it "should return a Spec::Matchers::RespondTo" do + @kernel_impersonator.respond_to.should be_an_instance_of(Spec::Matchers::RespondTo) + end + + it "should pass the submitted names to the RespondTo instance" do + Spec::Matchers::RespondTo.should_receive(:new).with(:a,'b','c?') + @kernel_impersonator.respond_to(:a,'b','c?') + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/failing_behaviours_formatter_spec.rb b/vendor/gems/rspec/spec/spec/runner/formatter/failing_behaviours_formatter_spec.rb new file mode 100644 index 000000000..de3246c54 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/formatter/failing_behaviours_formatter_spec.rb @@ -0,0 +1,40 @@ +require File.dirname(__FILE__) + '/../../../spec_helper.rb' + +module Spec + module Runner + module Formatter + describe "FailingBehavioursFormatter" do + before(:each) do + @io = StringIO.new + @formatter = FailingBehavioursFormatter.new(@io) + end + + def description(s) + Spec::DSL::Description.new(s) + end + + it "should add example name for each failure" do + @formatter.add_behaviour(description("b 1")) + @formatter.example_failed("e 1", nil, Reporter::Failure.new(nil, RuntimeError.new)) + @formatter.add_behaviour(description("b 2")) + @formatter.example_failed("e 2", nil, Reporter::Failure.new(nil, RuntimeError.new)) + @formatter.example_failed("e 3", nil, Reporter::Failure.new(nil, RuntimeError.new)) + @io.string.should eql(<<-EOF +b 1 +b 2 +EOF +) + end + + it "should remove druby url, which is used by Spec::Distributed" do + @formatter.add_behaviour("something something (druby://99.99.99.99:99)") + @formatter.example_failed("e 1", nil, Reporter::Failure.new(nil, RuntimeError.new)) + @io.string.should eql(<<-EOF +something something +EOF +) + end + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/failing_examples_formatter_spec.rb b/vendor/gems/rspec/spec/spec/runner/formatter/failing_examples_formatter_spec.rb new file mode 100644 index 000000000..396e4b16e --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/formatter/failing_examples_formatter_spec.rb @@ -0,0 +1,28 @@ +require File.dirname(__FILE__) + '/../../../spec_helper.rb' + +module Spec + module Runner + module Formatter + describe "FailingExamplesFormatter" do + before(:each) do + @io = StringIO.new + @formatter = FailingExamplesFormatter.new(@io) + end + + it "should add example name for each failure" do + @formatter.add_behaviour("b 1") + @formatter.example_failed(DSL::Example.new("e 1"), nil, Reporter::Failure.new(nil, RuntimeError.new)) + @formatter.add_behaviour("b 2") + @formatter.example_failed(DSL::Example.new("e 2"), nil, Reporter::Failure.new(nil, RuntimeError.new)) + @formatter.example_failed(DSL::Example.new("e 3"), nil, Reporter::Failure.new(nil, RuntimeError.new)) + @io.string.should eql(<<-EOF +b 1 e 1 +b 2 e 2 +b 2 e 3 +EOF +) + end + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/html_formatter_spec.rb b/vendor/gems/rspec/spec/spec/runner/formatter/html_formatter_spec.rb new file mode 100644 index 000000000..fad3aed1a --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/formatter/html_formatter_spec.rb @@ -0,0 +1,56 @@ +require File.dirname(__FILE__) + '/../../../spec_helper.rb' + +describe "HtmlFormatter" do + ['--diff', '--dry-run'].each do |opt| + it "should produce HTML identical to the one we designed manually with #{opt}" do + root = File.expand_path(File.dirname(__FILE__) + '/../../../..') + suffix = PLATFORM == 'java' ? '-jruby' : '' + expected_file = File.dirname(__FILE__) + "/html_formatted-#{VERSION}#{suffix}.html" + raise "There is no HTML file with expected content for this platform: #{expected_file}" unless File.file?(expected_file) + expected_html = File.read(expected_file) + raise "There should be no absolute paths in html_formatted.html!!" if (expected_html =~ /\/Users/n || expected_html =~ /\/home/n) + + Dir.chdir(root) do + args = ['failing_examples/mocking_example.rb', 'failing_examples/diffing_spec.rb', 'examples/stubbing_example.rb', 'examples/pending_example.rb', '--format', 'html', opt] + err = StringIO.new + out = StringIO.new + Spec::Runner::CommandLine.run( + args, + err, + out, + false + ) + + seconds = /\d+\.\d+ seconds/ + html = out.string.gsub seconds, 'x seconds' + expected_html.gsub! seconds, 'x seconds' + + if opt == '--diff' + # Uncomment this line temporarily in order to overwrite the expected with actual. + # Use with care!!! + # File.open(expected_file, 'w') {|io| io.write(html)} + + doc = Hpricot(html) + backtraces = doc.search("div.backtrace").collect {|e| e.at("/pre").inner_html} + doc.search("div.backtrace").remove + + expected_doc = Hpricot(expected_html) + expected_backtraces = expected_doc.search("div.backtrace").collect {|e| e.at("/pre").inner_html} + expected_doc.search("div.backtrace").remove + + doc.inner_html.should == expected_doc.inner_html + + expected_backtraces.each_with_index do |expected_line, i| + expected_path, expected_line_number, expected_suffix = expected_line.split(':') + actual_path, actual_line_number, actual_suffix = backtraces[i].split(':') + File.expand_path(actual_path).should == File.expand_path(expected_path) + actual_line_number.should == expected_line_number + end + else + html.should =~ /This was a dry-run/m + end + end + end + end + +end diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/progress_bar_formatter_dry_run_spec.rb b/vendor/gems/rspec/spec/spec/runner/formatter/progress_bar_formatter_dry_run_spec.rb new file mode 100644 index 000000000..170fc441a --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/formatter/progress_bar_formatter_dry_run_spec.rb @@ -0,0 +1,20 @@ +require File.dirname(__FILE__) + '/../../../spec_helper.rb' + +module Spec + module Runner + module Formatter + describe ProgressBarFormatter, "dry run" do + before(:each) do + @io = StringIO.new + @formatter = ProgressBarFormatter.new(@io) + @formatter.dry_run = true + end + + it "should not produce summary on dry run" do + @formatter.dump_summary(3, 2, 1, 0) + @io.string.should eql("") + end + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/progress_bar_formatter_failure_dump_spec.rb b/vendor/gems/rspec/spec/spec/runner/formatter/progress_bar_formatter_failure_dump_spec.rb new file mode 100644 index 000000000..04e3d9785 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/formatter/progress_bar_formatter_failure_dump_spec.rb @@ -0,0 +1,36 @@ +require File.dirname(__FILE__) + '/../../../spec_helper.rb' + +module Spec + module Runner + module Formatter + describe "ProgressBarFormatter failure dump with NoisyBacktraceTweaker" do + before(:each) do + @io = StringIO.new + @reporter = Reporter.new([ProgressBarFormatter.new(@io)], NoisyBacktraceTweaker.new) + @reporter.add_behaviour(Spec::DSL::Description.new("context")) + end + + it "should end with line break" do + error=Spec::Expectations::ExpectationNotMetError.new("message") + set_backtrace(error) + @reporter.example_finished("spec", error, "spec") + @reporter.dump + @io.string.should match(/\n\z/) + end + + it "should include context and spec name in backtrace if error in spec" do + error=RuntimeError.new("message") + set_backtrace(error) + @reporter.example_finished("spec", error, "spec") + @reporter.dump + @io.string.should match(/RuntimeError in 'context spec'/) + end + + def set_backtrace(error) + error.set_backtrace(["/a/b/c/d/e.rb:34:in `whatever'"]) + end + + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/progress_bar_formatter_spec.rb b/vendor/gems/rspec/spec/spec/runner/formatter/progress_bar_formatter_spec.rb new file mode 100644 index 000000000..50fc12689 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/formatter/progress_bar_formatter_spec.rb @@ -0,0 +1,111 @@ +require File.dirname(__FILE__) + '/../../../spec_helper.rb' + +module Spec + module Runner + module Formatter + describe ProgressBarFormatter do + before(:each) do + @io = StringIO.new + @formatter = ProgressBarFormatter.new(@io) + end + + it "should produce line break on start dump" do + @formatter.start_dump + @io.string.should eql("\n") + end + + it "should produce standard summary without pending when pending has a 0 count" do + @formatter.dump_summary(3, 2, 1, 0) + @io.string.should eql("\nFinished in 3 seconds\n\n2 examples, 1 failure\n") + end + + it "should produce standard summary" do + @formatter.example_pending("behaviour", "example", "message") + @io.rewind + @formatter.dump_summary(3, 2, 1, 1) + @io.string.should eql(%Q| +Finished in 3 seconds + +2 examples, 1 failure, 1 pending + +Pending: +behaviour example (message) +|) + end + + it "should push green dot for passing spec" do + @io.should_receive(:tty?).and_return(true) + @formatter.colour = true + @formatter.example_passed("spec") + @io.string.should == "\e[32m.\e[0m" + end + + it "should push red F for failure spec" do + @io.should_receive(:tty?).and_return(true) + @formatter.colour = true + @formatter.example_failed("spec", 98, Reporter::Failure.new("c s", Spec::Expectations::ExpectationNotMetError.new)) + @io.string.should eql("\e[31mF\e[0m") + end + + it "should push magenta F for error spec" do + @io.should_receive(:tty?).and_return(true) + @formatter.colour = true + @formatter.example_failed("spec", 98, Reporter::Failure.new("c s", RuntimeError.new)) + @io.string.should eql("\e[35mF\e[0m") + end + + it "should push blue F for fixed pending spec" do + @io.should_receive(:tty?).and_return(true) + @formatter.colour = true + @formatter.example_failed("spec", 98, Reporter::Failure.new("c s", Spec::DSL::PendingFixedError.new)) + @io.string.should eql("\e[34mF\e[0m") + end + + it "should push nothing on start" do + @formatter.start(4) + @io.string.should eql("") + end + + it "should ensure two ':' in the first backtrace" do + backtrace = ["/tmp/x.rb:1", "/tmp/x.rb:2", "/tmp/x.rb:3"] + @formatter.format_backtrace(backtrace).should eql(<<-EOE.rstrip) +/tmp/x.rb:1: +/tmp/x.rb:2: +/tmp/x.rb:3: +EOE + + backtrace = ["/tmp/x.rb:1: message", "/tmp/x.rb:2", "/tmp/x.rb:3"] + @formatter.format_backtrace(backtrace).should eql(<<-EOE.rstrip) +/tmp/x.rb:1: message +/tmp/x.rb:2: +/tmp/x.rb:3: +EOE + end + + it "should dump pending" do + @formatter.example_pending("behaviour", "example", "message") + @formatter.dump_pending + @io.string.should =~ /Pending\:\nbehaviour example \(message\)\n/ + end + end + + describe "ProgressBarFormatter outputting to custom out" do + before(:each) do + @out = mock("out") + @out.stub!(:puts) + @formatter = ProgressBarFormatter.new(@out) + @formatter.class.send :public, :output_to_tty? + end + + after(:each) do + @formatter.class.send :protected, :output_to_tty? + end + + it "should not throw NoMethodError on output_to_tty?" do + @out.should_receive(:tty?).and_raise(NoMethodError) + @formatter.output_to_tty?.should be_false + end + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/rdoc_formatter_dry_run_spec.rb b/vendor/gems/rspec/spec/spec/runner/formatter/rdoc_formatter_dry_run_spec.rb new file mode 100644 index 000000000..c864162ed --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/formatter/rdoc_formatter_dry_run_spec.rb @@ -0,0 +1,19 @@ +require File.dirname(__FILE__) + '/../../../spec_helper.rb' + +module Spec +module Runner +module Formatter +describe "RdocFormatterDryRun" do + before(:each) do + @io = StringIO.new + @formatter = RdocFormatter.new(@io) + @formatter.dry_run = true + end + it "should not produce summary on dry run" do + @formatter.dump_summary(3, 2, 1, 0) + @io.string.should == "" + end +end +end +end +end diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/rdoc_formatter_spec.rb b/vendor/gems/rspec/spec/spec/runner/formatter/rdoc_formatter_spec.rb new file mode 100644 index 000000000..728a515f1 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/formatter/rdoc_formatter_spec.rb @@ -0,0 +1,46 @@ +require File.dirname(__FILE__) + '/../../../spec_helper.rb' + +module Spec + module Runner + module Formatter + describe "RdocFormatter" do + before(:each) do + @io = StringIO.new + @formatter = RdocFormatter.new(@io) + @formatter.dry_run = true + end + + it "should produce no summary" do + @formatter.dump_summary(nil, nil, nil, nil) + @io.string.should be_empty + end + + it "should produce nothing on start dump" do + @formatter.start_dump + @io.string.should be_empty + end + + it "should push out context" do + @formatter.add_behaviour(Spec::DSL::Description.new("context")) + @io.string.should eql("# context\n") + end + + it "should push out failed spec" do + @formatter.example_failed(DSL::Example.new("spec"), 98, nil) + @io.string.should eql("# * spec [98 - FAILED]\n") + end + + it "should push out spec" do + @formatter.example_passed(DSL::Example.new("spec")) + @io.string.should eql("# * spec\n") + end + + it "should push out not pending example" do + @formatter.example_pending("behaviour", "example", "reason") + @io.string.should eql("# * behaviour example [PENDING: reason]\n") + end + + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/snippet_extractor_spec.rb b/vendor/gems/rspec/spec/spec/runner/formatter/snippet_extractor_spec.rb new file mode 100644 index 000000000..dce5c2ff2 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/formatter/snippet_extractor_spec.rb @@ -0,0 +1,11 @@ +require File.dirname(__FILE__) + '/../../../spec_helper.rb' + +describe Spec::Runner::Formatter::SnippetExtractor do + it "should fall back on a default message when it doesn't understand a line" do + Spec::Runner::Formatter::SnippetExtractor.new.snippet_for("blech").should == ["# Couldn't get snippet for blech", 1] + end + + it "should fall back on a default message when it doesn't find the file" do + Spec::Runner::Formatter::SnippetExtractor.new.lines_around("blech", 8).should == "# Couldn't get snippet for blech" + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/specdoc_formatter_dry_run_spec.rb b/vendor/gems/rspec/spec/spec/runner/formatter/specdoc_formatter_dry_run_spec.rb new file mode 100644 index 000000000..c86899cb1 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/formatter/specdoc_formatter_dry_run_spec.rb @@ -0,0 +1,21 @@ +require File.dirname(__FILE__) + '/../../../spec_helper.rb' + +module Spec +module Runner +module Formatter +describe "SpecdocFormatterDryRun" do + before(:each) do + @io = StringIO.new + @formatter = SpecdocFormatter.new(@io) + @formatter.dry_run = true + end + it "should not produce summary on dry run" do + @formatter.dump_summary(3, 2, 1, 0) + @io.string.should eql("") + + end + +end +end +end +end diff --git a/vendor/gems/rspec/spec/spec/runner/formatter/specdoc_formatter_spec.rb b/vendor/gems/rspec/spec/spec/runner/formatter/specdoc_formatter_spec.rb new file mode 100644 index 000000000..14f436036 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/formatter/specdoc_formatter_spec.rb @@ -0,0 +1,62 @@ +require File.dirname(__FILE__) + '/../../../spec_helper.rb' + +module Spec + module Runner + module Formatter + describe "SpecdocFormatter" do + before(:each) do + @io = StringIO.new + @formatter = SpecdocFormatter.new(@io) + end + + it "should produce standard summary without pending when pending has a 0 count" do + @formatter.dump_summary(3, 2, 1, 0) + @io.string.should eql("\nFinished in 3 seconds\n\n2 examples, 1 failure\n") + end + + it "should produce standard summary" do + @formatter.dump_summary(3, 2, 1, 4) + @io.string.should eql("\nFinished in 3 seconds\n\n2 examples, 1 failure, 4 pending\n") + end + + it "should push context name" do + @formatter.add_behaviour(Spec::DSL::Description.new("context")) + @io.string.should eql("\ncontext\n") + end + + it "should push failing spec name and failure number" do + @formatter.example_failed(DSL::Example.new("spec"), 98, Reporter::Failure.new("c s", RuntimeError.new)) + @io.string.should eql("- spec (ERROR - 98)\n") + end + + it "should push nothing on start" do + @formatter.start(5) + @io.string.should eql("") + end + + it "should push nothing on start dump" do + @formatter.start_dump + @io.string.should eql("") + end + + it "should push passing spec name" do + @formatter.example_passed(DSL::Example.new("spec")) + @io.string.should eql("- spec\n") + end + + it "should push pending example name and message" do + @formatter.example_pending('behaviour', 'example','reason') + @io.string.should eql("- example (PENDING: reason)\n") + end + + it "should dump pending" do + @formatter.example_pending('behaviour', 'example','reason') + @io.rewind + @formatter.dump_pending + @io.string.should =~ /Pending\:\nbehaviour example \(reason\)\n/ + end + + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/heckle_runner_spec.rb b/vendor/gems/rspec/spec/spec/runner/heckle_runner_spec.rb new file mode 100644 index 000000000..1f5d11759 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/heckle_runner_spec.rb @@ -0,0 +1,63 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' +unless [/mswin/, /java/].detect{|p| p =~ RUBY_PLATFORM} + require 'spec/runner/heckle_runner' + + module Foo + class Bar + def one; end + def two; end + end + + class Zap + def three; end + def four; end + end + end + + describe "HeckleRunner" do + before(:each) do + @heckle = mock("heckle", :null_object => true) + @behaviour_runner = mock("behaviour_runner") + @heckle_class = mock("heckle_class") + end + + it "should heckle all methods in all classes in a module" do + @heckle_class.should_receive(:new).with("Foo::Bar", "one", behaviour_runner).and_return(@heckle) + @heckle_class.should_receive(:new).with("Foo::Bar", "two", behaviour_runner).and_return(@heckle) + @heckle_class.should_receive(:new).with("Foo::Zap", "three", behaviour_runner).and_return(@heckle) + @heckle_class.should_receive(:new).with("Foo::Zap", "four", behaviour_runner).and_return(@heckle) + + heckle_runner = Spec::Runner::HeckleRunner.new("Foo", @heckle_class) + heckle_runner.heckle_with(behaviour_runner) + end + + it "should heckle all methods in a class" do + @heckle_class.should_receive(:new).with("Foo::Bar", "one", behaviour_runner).and_return(@heckle) + @heckle_class.should_receive(:new).with("Foo::Bar", "two", behaviour_runner).and_return(@heckle) + + heckle_runner = Spec::Runner::HeckleRunner.new("Foo::Bar", @heckle_class) + heckle_runner.heckle_with(behaviour_runner) + end + + it "should fail heckling when the class is not found" do + lambda do + heckle_runner = Spec::Runner::HeckleRunner.new("Foo::Bob", @heckle_class) + heckle_runner.heckle_with(behaviour_runner) + end.should raise_error(StandardError, "Heckling failed - \"Foo::Bob\" is not a known class or module") + end + + it "should heckle specific method in a class (with #)" do + @heckle_class.should_receive(:new).with("Foo::Bar", "two", behaviour_runner).and_return(@heckle) + + heckle_runner = Spec::Runner::HeckleRunner.new("Foo::Bar#two", @heckle_class) + heckle_runner.heckle_with(behaviour_runner) + end + + it "should heckle specific method in a class (with .)" do + @heckle_class.should_receive(:new).with("Foo::Bar", "two", behaviour_runner).and_return(@heckle) + + heckle_runner = Spec::Runner::HeckleRunner.new("Foo::Bar.two", @heckle_class) + heckle_runner.heckle_with(behaviour_runner) + end + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/heckler_spec.rb b/vendor/gems/rspec/spec/spec/runner/heckler_spec.rb new file mode 100644 index 000000000..31d33ab5e --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/heckler_spec.rb @@ -0,0 +1,14 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' +unless [/mswin/, /java/].detect{|p| p =~ RUBY_PLATFORM} + require 'spec/runner/heckle_runner' + + describe "Heckler" do + it "should run behaviour_runner on tests_pass?" do + behaviour_runner = mock("behaviour_runner") + behaviour_runner.should_receive(:run).with([], false) + heckler = Spec::Runner::Heckler.new('Array', 'push', behaviour_runner) + + heckler.tests_pass? + end + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/noisy_backtrace_tweaker_spec.rb b/vendor/gems/rspec/spec/spec/runner/noisy_backtrace_tweaker_spec.rb new file mode 100644 index 000000000..522d346d9 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/noisy_backtrace_tweaker_spec.rb @@ -0,0 +1,45 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Runner + describe "NoisyBacktraceTweaker" do + before(:each) do + @error = RuntimeError.new + @tweaker = NoisyBacktraceTweaker.new + end + + it "should leave anything in lib spec dir" do + ["expectations", "mocks", "runner", "stubs"].each do |child| + @error.set_backtrace(["/lib/spec/#{child}/anything.rb"]) + @tweaker.tweak_backtrace(@error, "spec name") + @error.backtrace.should_not be_empty + end + end + + it "should leave anything in spec dir" do + @error.set_backtrace(["/lib/spec/expectations/anything.rb"]) + @tweaker.tweak_backtrace(@error, "spec name") + @error.backtrace.should_not be_empty + end + + it "should leave bin spec" do + @error.set_backtrace(["bin/spec:"]) + @tweaker.tweak_backtrace(@error, "spec name") + @error.backtrace.should_not be_empty + end + + it "should not barf on nil backtrace" do + lambda do + @tweaker.tweak_backtrace(@error, "spec name") + end.should_not raise_error + end + + it "should clean up double slashes" do + @error.set_backtrace(["/a//b/c//d.rb"]) + @tweaker.tweak_backtrace(@error, "spec name") + @error.backtrace.should include("/a/b/c/d.rb") + end + + end + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/object_ext_spec.rb b/vendor/gems/rspec/spec/spec/runner/object_ext_spec.rb new file mode 100644 index 000000000..0d8348bb2 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/object_ext_spec.rb @@ -0,0 +1,11 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Runner + describe "ObjectExt" do + it "should add copy_instance_variables_from to object" do + Object.new.should respond_to(:copy_instance_variables_from) + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/option_parser_spec.rb b/vendor/gems/rspec/spec/spec/runner/option_parser_spec.rb new file mode 100644 index 000000000..95e1f75a3 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/option_parser_spec.rb @@ -0,0 +1,349 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +describe "OptionParser" do + before(:each) do + @out = StringIO.new + @err = StringIO.new + @parser = Spec::Runner::OptionParser.new + end + + def parse(args) + @parser.parse(args, @err, @out, true) + end + + def behaviour_runner(args) + @parser.create_behaviour_runner(args, @err, @out, true) + end + + it "should accept dry run option" do + options = parse(["--dry-run"]) + options.dry_run.should be_true + end + + it "should eval and use custom formatter when none of the builtins" do + options = parse(["--format", "Custom::Formatter"]) + options.formatters[0].class.should be(Custom::Formatter) + end + + it "should support formatters with relative and absolute paths, even on windows" do + options = parse([ + "--format", "Custom::Formatter:C:\\foo\\bar", + "--format", "Custom::Formatter:foo/bar", + "--format", "Custom::Formatter:foo\\bar", + "--format", "Custom::Formatter:/foo/bar" + ]) + options.formatters[0].where.should eql("C:\\foo\\bar") + options.formatters[1].where.should eql("foo/bar") + options.formatters[2].where.should eql("foo\\bar") + options.formatters[3].where.should eql("/foo/bar") + end + + it "should not be verbose by default" do + options = parse([]) + options.verbose.should be_nil + end + + it "should not use colour by default" do + options = parse([]) + options.colour.should == false + end + + it "should print help to stdout" do + options = parse(["--help"]) + @out.rewind + @out.read.should match(/Usage: spec \(FILE\|DIRECTORY\|GLOB\)\+ \[options\]/m) + end + + it "should print instructions about how to require missing formatter" do + lambda { options = parse(["--format", "Custom::MissingFormatter"]) }.should raise_error(NameError) + @err.string.should match(/Couldn't find formatter class Custom::MissingFormatter/n) + end + + it "should print usage to err if no dir specified" do + options = parse([]) + @err.string.should match(/Usage: spec/) + end + + it "should print version to stdout" do + options = parse(["--version"]) + @out.rewind + @out.read.should match(/RSpec-\d+\.\d+\.\d+.*\(r\d+\) - BDD for Ruby\nhttp:\/\/rspec.rubyforge.org\/\n/n) + end + + it "should require file when require specified" do + lambda do + parse(["--require", "whatever"]) + end.should raise_error(LoadError) + end + + it "should support c option" do + options = parse(["-c"]) + options.colour.should be_true + end + + it "should support queens colour option" do + options = parse(["--colour"]) + options.colour.should be_true + end + + it "should support us color option" do + options = parse(["--color"]) + options.colour.should be_true + end + + it "should support single example with -e option" do + options = parse(["-e", "something or other"]) + options.examples.should eql(["something or other"]) + end + + it "should support single example with -s option (will be removed when autotest supports -e)" do + options = parse(["-s", "something or other"]) + options.examples.should eql(["something or other"]) + end + + it "should support single example with --example option" do + options = parse(["--example", "something or other"]) + options.examples.should eql(["something or other"]) + end + + it "should read several example names from file if --example is given an existing file name" do + options = parse(["--example", File.dirname(__FILE__) + '/examples.txt']) + options.examples.should eql([ + "Sir, if you were my husband, I would poison your drink.", + "Madam, if you were my wife, I would drink it."]) + end + + it "should read no examples if given an empty file" do + options = parse(["--example", File.dirname(__FILE__) + '/empty_file.txt']) + options.examples.should eql([]) + end + + it "should use html formatter when format is h" do + options = parse(["--format", "h"]) + options.formatters[0].class.should equal(Spec::Runner::Formatter::HtmlFormatter) + end + + it "should use html formatter when format is html" do + options = parse(["--format", "html"]) + options.formatters[0].class.should equal(Spec::Runner::Formatter::HtmlFormatter) + end + + it "should use html formatter with explicit output when format is html:test.html" do + FileUtils.rm 'test.html' if File.exist?('test.html') + options = parse(["--format", "html:test.html"]) + File.should be_exist('test.html') + options.formatters[0].class.should equal(Spec::Runner::Formatter::HtmlFormatter) + options.formatters[0].close + FileUtils.rm 'test.html' + end + + it "should use noisy backtrace tweaker with b option" do + options = parse(["-b"]) + options.backtrace_tweaker.should be_instance_of(Spec::Runner::NoisyBacktraceTweaker) + end + + it "should use noisy backtrace tweaker with backtrace option" do + options = parse(["--backtrace"]) + options.backtrace_tweaker.should be_instance_of(Spec::Runner::NoisyBacktraceTweaker) + end + + it "should use quiet backtrace tweaker by default" do + options = parse([]) + options.backtrace_tweaker.should be_instance_of(Spec::Runner::QuietBacktraceTweaker) + end + + it "should use progress bar formatter by default" do + options = parse([]) + options.formatters[0].class.should equal(Spec::Runner::Formatter::ProgressBarFormatter) + end + + it "should use rdoc formatter when format is r" do + options = parse(["--format", "r"]) + options.formatters[0].class.should equal(Spec::Runner::Formatter::RdocFormatter) + end + + it "should use rdoc formatter when format is rdoc" do + options = parse(["--format", "rdoc"]) + options.formatters[0].class.should equal(Spec::Runner::Formatter::RdocFormatter) + end + + it "should use specdoc formatter when format is s" do + options = parse(["--format", "s"]) + options.formatters[0].class.should equal(Spec::Runner::Formatter::SpecdocFormatter) + end + + it "should use specdoc formatter when format is specdoc" do + options = parse(["--format", "specdoc"]) + options.formatters[0].class.should equal(Spec::Runner::Formatter::SpecdocFormatter) + end + + it "should support diff option when format is not specified" do + options = parse(["--diff"]) + options.diff_format.should == :unified + end + + it "should use unified diff format option when format is unified" do + options = parse(["--diff", "unified"]) + options.diff_format.should == :unified + options.differ_class.should equal(Spec::Expectations::Differs::Default) + end + + it "should use context diff format option when format is context" do + options = parse(["--diff", "context"]) + options.diff_format.should == :context + options.differ_class.should == Spec::Expectations::Differs::Default + end + + it "should use custom diff format option when format is a custom format" do + options = parse(["--diff", "Custom::Formatter"]) + options.diff_format.should == :custom + options.differ_class.should == Custom::Formatter + end + + it "should print instructions about how to fix missing differ" do + lambda { parse(["--diff", "Custom::MissingFormatter"]) }.should raise_error(NameError) + @err.string.should match(/Couldn't find differ class Custom::MissingFormatter/n) + end + + it "should support --line to identify spec" do + spec_parser = mock("spec_parser") + @parser.instance_variable_set('@spec_parser', spec_parser) + + file_factory = mock("File") + file_factory.should_receive(:file?).and_return(true) + file_factory.should_receive(:open).and_return("fake_io") + @parser.instance_variable_set('@file_factory', file_factory) + + spec_parser.should_receive(:spec_name_for).with("fake_io", 169).and_return("some spec") + + options = parse(["some file", "--line", "169"]) + options.examples.should eql(["some spec"]) + File.rspec_verify + end + + it "should fail with error message if file is dir along with --line" do + spec_parser = mock("spec_parser") + @parser.instance_variable_set('@spec_parser', spec_parser) + + file_factory = mock("File") + file_factory.should_receive(:file?).and_return(false) + file_factory.should_receive(:directory?).and_return(true) + @parser.instance_variable_set('@file_factory', file_factory) + + options = parse(["some file", "--line", "169"]) + @err.string.should match(/You must specify one file, not a directory when using the --line option/n) + end + + it "should fail with error message if file is dir along with --line" do + spec_parser = mock("spec_parser") + @parser.instance_variable_set('@spec_parser', spec_parser) + + file_factory = mock("File") + file_factory.should_receive(:file?).and_return(false) + file_factory.should_receive(:directory?).and_return(false) + @parser.instance_variable_set('@file_factory', file_factory) + + options = parse(["some file", "--line", "169"]) + @err.string.should match(/some file does not exist/n) + end + + it "should fail with error message if more than one files are specified along with --line" do + spec_parser = mock("spec_parser") + @parser.instance_variable_set('@spec_parser', spec_parser) + + options = parse(["some file", "some other file", "--line", "169"]) + @err.string.should match(/Only one file can be specified when using the --line option/n) + end + + it "should fail with error message if --example and --line are used simultaneously" do + spec_parser = mock("spec_parser") + @parser.instance_variable_set('@spec_parser', spec_parser) + + options = parse(["some file", "--example", "some example", "--line", "169"]) + @err.string.should match(/You cannot use both --line and --example/n) + end + + if [/mswin/, /java/].detect{|p| p =~ RUBY_PLATFORM} + it "should barf when --heckle is specified (and platform is windows)" do + lambda do + options = parse(["--heckle", "Spec"]) + end.should raise_error(StandardError, "Heckle not supported on Windows") + end + else + it "should heckle when --heckle is specified (and platform is not windows)" do + options = parse(["--heckle", "Spec"]) + options.heckle_runner.should be_instance_of(Spec::Runner::HeckleRunner) + end + end + + it "should read options from file when --options is specified" do + Spec::Runner::CommandLine.should_receive(:run).with(["--diff", "--colour"], @err, @out, true, true) + options = parse(["--options", File.dirname(__FILE__) + "/spec.opts"]) + end + + it "should append options from file when --options is specified" do + Spec::Runner::CommandLine.should_receive(:run).with(["some/spec.rb", "--diff", "--colour"], @err, @out, true, true) + options = parse(["some/spec.rb", "--options", File.dirname(__FILE__) + "/spec.opts"]) + end + + it "should read spaced and multi-line options from file when --options is specified" do + Spec::Runner::CommandLine.should_receive(:run).with(["--diff", "--colour", "--format", "s"], @err, @out, true, true) + options = parse(["--options", File.dirname(__FILE__) + "/spec_spaced.opts"]) + end + + it "should save config to file when --generate-options is specified" do + FileUtils.rm 'test.spec.opts' if File.exist?('test.spec.opts') + options = parse(["--colour", "--generate-options", "test.spec.opts", "--diff"]) + IO.read('test.spec.opts').should == "--colour\n--diff\n" + FileUtils.rm 'test.spec.opts' + end + + it "should call DrbCommandLine when --drb is specified" do + Spec::Runner::DrbCommandLine.should_receive(:run).with(["some/spec.rb", "--diff", "--colour"], @err, @out, true, true) + options = parse(["some/spec.rb", "--diff", "--drb", "--colour"]) + end + + it "should not return an Options object when --drb is specified" do + Spec::Runner::DrbCommandLine.stub!(:run) + parse(["some/spec.rb", "--drb"]).should be_nil + end + + it "should reverse spec order when --reverse is specified" do + options = parse(["some/spec.rb", "--reverse"]) + end + + it "should set an mtime comparator when --loadby mtime" do + behaviour_runner = behaviour_runner(["--loadby", 'mtime']) + Dir.chdir(File.dirname(__FILE__)) do + FileUtils.touch "most_recent_spec.rb" + all_files = ['command_line_spec.rb', 'most_recent_spec.rb'] + sorted_files = behaviour_runner.sort_paths(all_files) + sorted_files.should == ["most_recent_spec.rb", "command_line_spec.rb"] + FileUtils.rm "most_recent_spec.rb" + end + end + + it "should use the standard runner by default" do + options = parse([]) + options.create_behaviour_runner.class.should equal(Spec::Runner::BehaviourRunner) + end + + it "should use a custom runner when given" do + options = parse(["--runner", "Custom::BehaviourRunner"]) + options.create_behaviour_runner.class.should equal(Custom::BehaviourRunner) + end + + it "should use a custom runner with extra options" do + options = parse(["--runner", "Custom::BehaviourRunner:something"]) + options.create_behaviour_runner.class.should equal(Custom::BehaviourRunner) + end + + it "should return the correct default behaviour runner" do + @parser.create_behaviour_runner([], @err, @out, true).should be_instance_of(Spec::Runner::BehaviourRunner) + end + + it "should return the correct default behaviour runner" do + @parser.create_behaviour_runner(["--runner", "Custom::BehaviourRunner"], @err, @out, true).should be_instance_of(Custom::BehaviourRunner) + end + +end diff --git a/vendor/gems/rspec/spec/spec/runner/options_spec.rb b/vendor/gems/rspec/spec/spec/runner/options_spec.rb new file mode 100644 index 000000000..609d8d95c --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/options_spec.rb @@ -0,0 +1,175 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Runner + describe Options do + before do + @err = StringIO.new('') + @out = StringIO.new('') + @options = Options.new(@err, @out) + end + + it "instantiates empty arrays" do + @options.examples.should == [] + @options.formatters.should == [] + end + + it "defaults to QuietBacktraceTweaker" do + @options.backtrace_tweaker.class.should == QuietBacktraceTweaker + end + + it "defaults to no dry_run" do + @options.dry_run.should == false + end + + it "parse_diff sets context_lines" do + @options.parse_diff nil + @options.context_lines.should == 3 + end + + it "defaults diff to unified" do + @options.parse_diff nil + @options.diff_format.should == :unified + end + + it "should use unified diff format option when format is unified" do + @options.parse_diff 'unified' + @options.diff_format.should == :unified + @options.differ_class.should equal(Spec::Expectations::Differs::Default) + end + + it "should use context diff format option when format is context" do + @options.parse_diff 'context' + @options.diff_format.should == :context + @options.differ_class.should == Spec::Expectations::Differs::Default + end + + it "should use custom diff format option when format is a custom format" do + @options.parse_diff "Custom::Formatter" + @options.diff_format.should == :custom + @options.differ_class.should == Custom::Formatter + end + + it "should print instructions about how to fix missing differ" do + lambda { @options.parse_diff "Custom::MissingDiffer" }.should raise_error(NameError) + @err.string.should match(/Couldn't find differ class Custom::MissingDiffer/n) + end + + it "should print instructions about how to fix bad formatter" do + lambda do + @options.parse_format "Custom::BadFormatter" + end.should raise_error(NameError, /undefined local variable or method `bad_method'/) + end + + it "parse_example sets single example when argument not a file" do + example = "something or other" + File.file?(example).should == false + @options.parse_example example + @options.examples.should eql(["something or other"]) + end + + it "parse_example sets examples to contents of file" do + example = "#{File.dirname(__FILE__)}/examples.txt" + File.should_receive(:file?).with(example).and_return(true) + file = StringIO.new("Sir, if you were my husband, I would poison your drink.\nMadam, if you were my wife, I would drink it.") + File.should_receive(:open).with(example).and_return(file) + + @options.parse_example example + @options.examples.should eql([ + "Sir, if you were my husband, I would poison your drink.", + "Madam, if you were my wife, I would drink it." + ]) + end + end + + describe Options, "splitting class names and args" do + before do + @err = StringIO.new('') + @out = StringIO.new('') + @options = Options.new(@err, @out) + end + + it "should split class names with args" do + @options.split_at_colon('Foo').should == ['Foo', nil] + @options.split_at_colon('Foo:arg').should == ['Foo', 'arg'] + @options.split_at_colon('Foo::Bar::Zap:arg').should == ['Foo::Bar::Zap', 'arg'] + @options.split_at_colon('Foo:arg1,arg2').should == ['Foo', 'arg1,arg2'] + @options.split_at_colon('Foo::Bar::Zap:arg1,arg2').should == ['Foo::Bar::Zap', 'arg1,arg2'] + @options.split_at_colon('Foo::Bar::Zap:drb://foo,drb://bar').should == ['Foo::Bar::Zap', 'drb://foo,drb://bar'] + end + + it "should raise error when splitting something starting with a number" do + lambda { @options.split_at_colon('') }.should raise_error("Couldn't parse \"\"") + end + + it "should raise error when not class name" do + lambda do + @options.load_class('foo', 'fruit', '--food') + end.should raise_error('"foo" is not a valid class name') + end + end + + describe Options, "receiving create_behaviour_runner" do + before do + @err = StringIO.new + @out = StringIO.new + @options = Options.new(@err, @out) + end + + it "should fail when custom runner not found" do + @options.runner_arg = "Whatever" + lambda { @options.create_behaviour_runner }.should raise_error(NameError) + @err.string.should match(/Couldn't find behaviour runner class/) + end + + it "should fail when custom runner not valid class name" do + @options.runner_arg = "whatever" + lambda { @options.create_behaviour_runner }.should raise_error('"whatever" is not a valid class name') + @err.string.should match(/"whatever" is not a valid class name/) + end + + it "returns nil when generate is true" do + @options.generate = true + @options.create_behaviour_runner.should == nil + end + + it "returns a BehaviourRunner by default" do + runner = @options.create_behaviour_runner + runner.class.should == BehaviourRunner + end + + it "does not set Expectations differ when differ_class is not set" do + @options.differ_class = nil + Spec::Expectations.should_not_receive(:differ=) + @options.create_behaviour_runner + end + + it "sets Expectations differ when differ_class is set" do + @options.differ_class = Spec::Expectations::Differs::Default + Spec::Expectations.should_receive(:differ=).with(anything()).and_return do |arg| + arg.class.should == Spec::Expectations::Differs::Default + end + @options.configure + end + + it "creates a Reporter" do + formatter = ::Spec::Runner::Formatter::BaseFormatter.new(:somewhere) + @options.formatters << formatter + reporter = Reporter.new(@formatters, @backtrace_tweaker) + Reporter.should_receive(:new).with(@options.formatters, @options.backtrace_tweaker).and_return(reporter) + @options.configure + @options.reporter.should === reporter + end + + it "sets colour and dry_run on the formatters" do + @options.colour = true + @options.dry_run = true + formatter = ::Spec::Runner::Formatter::BaseTextFormatter.new(:somewhere) + formatter.should_receive(:colour=).with(true) + formatter.should_receive(:dry_run=).with(true) + @options.formatters << formatter + @options.configure + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/quiet_backtrace_tweaker_spec.rb b/vendor/gems/rspec/spec/spec/runner/quiet_backtrace_tweaker_spec.rb new file mode 100644 index 000000000..2578dbe6d --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/quiet_backtrace_tweaker_spec.rb @@ -0,0 +1,56 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Runner + describe "QuietBacktraceTweaker" do + before(:each) do + @error = RuntimeError.new + @tweaker = QuietBacktraceTweaker.new + end + + it "should not barf on nil backtrace" do + lambda do + @tweaker.tweak_backtrace(@error, "spec name") + end.should_not raise_error + end + + it "should remove anything from textmate ruby bundle" do + @error.set_backtrace(["/Applications/TextMate.app/Contents/SharedSupport/Bundles/Ruby.tmbundle/Support/tmruby.rb:147"]) + @tweaker.tweak_backtrace(@error, "spec name") + @error.backtrace.should be_empty + end + + it "should remove anything in lib spec dir" do + ["expectations", "mocks", "runner"].each do |child| + element="/lib/spec/#{child}/anything.rb" + @error.set_backtrace([element]) + @tweaker.tweak_backtrace(@error, "spec name") + unless (@error.backtrace.empty?) + raise("Should have tweaked away '#{element}'") + end + end + end + + it "should remove mock_frameworks/rspec" do + element = "mock_frameworks/rspec" + @error.set_backtrace([element]) + @tweaker.tweak_backtrace(@error, "spec name") + unless (@error.backtrace.empty?) + raise("Should have tweaked away '#{element}'") + end + end + + it "should remove bin spec" do + @error.set_backtrace(["bin/spec:"]) + @tweaker.tweak_backtrace(@error, "spec name") + @error.backtrace.should be_empty + end + + it "should clean up double slashes" do + @error.set_backtrace(["/a//b/c//d.rb"]) + @tweaker.tweak_backtrace(@error, "spec name") + @error.backtrace.should include("/a/b/c/d.rb") + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/reporter_spec.rb b/vendor/gems/rspec/spec/spec/runner/reporter_spec.rb new file mode 100644 index 000000000..574625ce8 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/reporter_spec.rb @@ -0,0 +1,205 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +module Spec + module Runner + + module ReporterSpecHelper + def setup + @io = StringIO.new + @backtrace_tweaker = stub("backtrace tweaker", :tweak_backtrace => nil) + @formatter = mock("formatter") + @reporter = Reporter.new([@formatter], @backtrace_tweaker) + end + + def failure + Mocks::DuckTypeArgConstraint.new(:header, :exception) + end + + def description(s) + Spec::DSL::Description.new(s) + end + end + + describe Reporter do + include ReporterSpecHelper + before(:each) {setup} + + it "should tell formatter when behaviour is added" do + @formatter.should_receive(:add_behaviour).with(description("behaviour")) + @reporter.add_behaviour(description("behaviour")) + end + + it "should handle multiple behaviours with same name" do + @formatter.should_receive(:add_behaviour).exactly(3).times + @formatter.should_receive(:example_started).exactly(3).times + @formatter.should_receive(:example_passed).exactly(3).times + @formatter.should_receive(:start_dump) + @formatter.should_receive(:close).with(no_args) + @formatter.should_receive(:dump_summary).with(anything(), 3, 0, 0) + @reporter.add_behaviour(description("behaviour")) + @reporter.example_started("spec 1") + @reporter.example_finished("spec 1") + @reporter.add_behaviour(description("behaviour")) + @reporter.example_started("spec 2") + @reporter.example_finished("spec 2") + @reporter.add_behaviour(description("behaviour")) + @reporter.example_started("spec 3") + @reporter.example_finished("spec 3") + @reporter.dump + end + + it "should handle multiple examples with the same name" do + error=RuntimeError.new + @formatter.should_receive(:add_behaviour).exactly(2).times + @formatter.should_receive(:example_passed).with("example").exactly(2).times + @formatter.should_receive(:example_failed).with("example", 1, failure) + @formatter.should_receive(:example_failed).with("example", 2, failure) + @formatter.should_receive(:dump_failure).exactly(2).times + @formatter.should_receive(:start_dump) + @formatter.should_receive(:close).with(no_args) + @formatter.should_receive(:dump_summary).with(anything(), 4, 2, 0) + @backtrace_tweaker.should_receive(:tweak_backtrace).twice + @reporter.add_behaviour(description("behaviour")) + @reporter.example_finished("example") + @reporter.example_finished("example", error) + @reporter.add_behaviour(description("behaviour")) + @reporter.example_finished("example") + @reporter.example_finished("example", error) + @reporter.dump + end + + it "should push stats to formatter even with no data" do + @formatter.should_receive(:start_dump) + @formatter.should_receive(:dump_summary).with(anything(), 0, 0, 0) + @formatter.should_receive(:close).with(no_args) + @reporter.dump + end + + it "should push time to formatter" do + @formatter.should_receive(:start).with(5) + @formatter.should_receive(:start_dump) + @formatter.should_receive(:close).with(no_args) + @formatter.should_receive(:dump_summary) do |time, a, b| + time.to_s.should match(/[0-9].[0-9|e|-]+/) + end + @reporter.start(5) + @reporter.end + @reporter.dump + end + end + + describe Reporter, "reporting one passing example" do + include ReporterSpecHelper + before(:each) {setup} + + it "should tell formatter example passed" do + @formatter.should_receive(:example_passed) + @reporter.example_finished("example") + end + + it "should not delegate to backtrace tweaker" do + @formatter.should_receive(:example_passed) + @backtrace_tweaker.should_not_receive(:tweak_backtrace) + @reporter.example_finished("example") + end + + it "should account for passing example in stats" do + @formatter.should_receive(:example_passed) + @formatter.should_receive(:start_dump) + @formatter.should_receive(:dump_summary).with(anything(), 1, 0, 0) + @formatter.should_receive(:close).with(no_args) + @reporter.example_finished("example") + @reporter.dump + end + end + + describe Reporter, "reporting one failing example" do + include ReporterSpecHelper + before(:each) {setup} + + it "should tell formatter that example failed" do + @formatter.should_receive(:example_failed) + @reporter.example_finished("example", RuntimeError.new) + end + + it "should delegate to backtrace tweaker" do + @formatter.should_receive(:example_failed) + @backtrace_tweaker.should_receive(:tweak_backtrace) + @reporter.example_finished("spec", RuntimeError.new) + end + + it "should account for failing example in stats" do + @formatter.should_receive(:add_behaviour) + @formatter.should_receive(:example_failed).with("example", 1, failure) + @formatter.should_receive(:start_dump) + @formatter.should_receive(:dump_failure).with(1, anything()) + @formatter.should_receive(:dump_summary).with(anything(), 1, 1, 0) + @formatter.should_receive(:close).with(no_args) + @reporter.add_behaviour(description("behaviour")) + @reporter.example_finished("example", RuntimeError.new) + @reporter.dump + end + + end + + describe Reporter, "reporting one pending example (Not Yet Implemented)" do + include ReporterSpecHelper + before(:each) {setup} + + it "should tell formatter example is pending" do + @formatter.should_receive(:example_pending).with(description("behaviour"), "example", "Not Yet Implemented") + @formatter.should_receive(:add_behaviour).with(description("behaviour")) + @reporter.add_behaviour(description('behaviour')) + @reporter.example_finished("example", nil, nil, true) + end + + it "should account for pending example in stats" do + @formatter.should_receive(:example_pending).with(description("behaviour"), "example", "Not Yet Implemented") + @formatter.should_receive(:start_dump) + @formatter.should_receive(:dump_summary).with(anything(), 1, 0, 1) + @formatter.should_receive(:add_behaviour).with(description("behaviour")) + @formatter.should_receive(:close).with(no_args) + @reporter.add_behaviour(description('behaviour')) + @reporter.example_finished("example", nil, nil, true) + @reporter.dump + end + end + + describe Reporter, "reporting one pending example (ExamplePendingError)" do + include ReporterSpecHelper + before(:each) {setup} + + it "should tell formatter example is pending" do + @formatter.should_receive(:example_pending).with(description("behaviour"), "example", "reason") + @formatter.should_receive(:add_behaviour).with(description("behaviour")) + @reporter.add_behaviour(description('behaviour')) + @reporter.example_finished("example", Spec::DSL::ExamplePendingError.new("reason"), nil, false) + end + + it "should account for pending example in stats" do + @formatter.should_receive(:example_pending).with(description("behaviour"), "example", "reason") + @formatter.should_receive(:start_dump) + @formatter.should_receive(:dump_summary).with(anything(), 1, 0, 1) + @formatter.should_receive(:close).with(no_args) + @formatter.should_receive(:add_behaviour).with(description("behaviour")) + @reporter.add_behaviour(description('behaviour')) + @reporter.example_finished("example", Spec::DSL::ExamplePendingError.new("reason"), nil, false) + @reporter.dump + end + end + + describe Reporter, "reporting one pending example (PendingFixedError)" do + include ReporterSpecHelper + before(:each) {setup} + + it "should tell formatter pending example is fixed" do + @formatter.should_receive(:example_failed) do |name, counter, failure| + failure.header.should == "'behaviour example' FIXED" + end + @formatter.should_receive(:add_behaviour).with(description("behaviour")) + @reporter.add_behaviour(description('behaviour')) + @reporter.example_finished("example", Spec::DSL::PendingFixedError.new("reason"), nil, false) + end + end + end +end diff --git a/vendor/gems/rspec/spec/spec/runner/spec_parser_spec.rb b/vendor/gems/rspec/spec/spec/runner/spec_parser_spec.rb new file mode 100644 index 000000000..6fb83dc35 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/runner/spec_parser_spec.rb @@ -0,0 +1,93 @@ +require File.dirname(__FILE__) + '/../../spec_helper.rb' + +describe "c" do + + it "1" do + end + + it "2" do + end + +end + +describe "d" do + + it "3" do + end + + it "4" do + end + +end + +class SpecParserSubject +end + +describe SpecParserSubject do + + it "5" do + end + +end + +describe SpecParserSubject, "described" do + + it "6" do + end + +end + +describe "SpecParser" do + before(:each) do + @p = Spec::Runner::SpecParser.new + end + + it "should find spec name for 'specify' at same line" do + @p.spec_name_for(File.open(__FILE__), 5).should == "c 1" + end + + it "should find spec name for 'specify' at end of spec line" do + @p.spec_name_for(File.open(__FILE__), 6).should == "c 1" + end + + it "should find context for 'context' above all specs" do + @p.spec_name_for(File.open(__FILE__), 4).should == "c" + end + + it "should find spec name for 'it' at same line" do + @p.spec_name_for(File.open(__FILE__), 15).should == "d 3" + end + + it "should find spec name for 'it' at end of spec line" do + @p.spec_name_for(File.open(__FILE__), 16).should == "d 3" + end + + it "should find context for 'describe' above all specs" do + @p.spec_name_for(File.open(__FILE__), 14).should == "d" + end + + it "should find nearest example name between examples" do + @p.spec_name_for(File.open(__FILE__), 7).should == "c 1" + end + + it "should find nothing outside a context" do + @p.spec_name_for(File.open(__FILE__), 2).should be_nil + end + + it "should find context name for type" do + @p.spec_name_for(File.open(__FILE__), 26).should == "SpecParserSubject" + end + + it "should find context and spec name for type" do + @p.spec_name_for(File.open(__FILE__), 28).should == "SpecParserSubject 5" + end + + it "should find context and description for type" do + @p.spec_name_for(File.open(__FILE__), 33).should == "SpecParserSubject described" + end + + it "should find context and description and example for type" do + @p.spec_name_for(File.open(__FILE__), 36).should == "SpecParserSubject described 6" + end + +end diff --git a/vendor/gems/rspec/spec/spec/spec_classes.rb b/vendor/gems/rspec/spec/spec/spec_classes.rb new file mode 100644 index 000000000..89eee72c4 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/spec_classes.rb @@ -0,0 +1,119 @@ +# This file contains various classes used by the specs. +module Spec + module Expectations + class Person + attr_reader :name + def initialize name + @name = name + end + def == other + return @name == other.name + end + end + + class ClassWithMultiWordPredicate + def multi_word_predicate? + true + end + end + + module Helper + class CollectionWithSizeMethod + def initialize; @list = []; end + def size; @list.size; end + def push(item); @list.push(item); end + end + + class CollectionWithLengthMethod + def initialize; @list = []; end + def length; @list.size; end + def push(item); @list.push(item); end + end + + class CollectionOwner + attr_reader :items_in_collection_with_size_method, :items_in_collection_with_length_method + + def initialize + @items_in_collection_with_size_method = CollectionWithSizeMethod.new + @items_in_collection_with_length_method = CollectionWithLengthMethod.new + end + + def add_to_collection_with_size_method(item) + @items_in_collection_with_size_method.push(item) + end + + def add_to_collection_with_length_method(item) + @items_in_collection_with_length_method.push(item) + end + + def items_for(arg) + return [1, 2, 3] if arg == 'a' + [1] + end + + end + + class HandCodedMock + include Spec::Matchers + def initialize(return_val) + @return_val = return_val + @funny_called = false + end + + def funny? + @funny_called = true + @return_val + end + + def hungry?(a, b, c) + a.should equal(1) + b.should equal(2) + c.should equal(3) + @funny_called = true + @return_val + end + + def exists? + @return_val + end + + def multi_word_predicate? + @return_val + end + + def rspec_verify + @funny_called.should be_true + end + end + class ClassWithUnqueriedPredicate + attr_accessor :foo + def initialize(foo) + @foo = foo + end + end + end + end +end + +module Custom + class Formatter < Spec::Runner::Formatter::BaseTextFormatter + attr_reader :where + + def initialize(where) + @where = where + end + end + + class BadFormatter < Spec::Runner::Formatter::BaseTextFormatter + attr_reader :where + + def initialize(where) + bad_method + end + end + + class BehaviourRunner + def initialize(options, arg=nil); end + end +end + diff --git a/vendor/gems/rspec/spec/spec/translator_spec.rb b/vendor/gems/rspec/spec/spec/translator_spec.rb new file mode 100644 index 000000000..e11983a42 --- /dev/null +++ b/vendor/gems/rspec/spec/spec/translator_spec.rb @@ -0,0 +1,264 @@ +require File.dirname(__FILE__) + '/../spec_helper.rb' + +describe "Translator" do + before do + @t = Spec::Translator.new + end + + it "should translate files" do + from = File.dirname(__FILE__) + '/..' + to = File.dirname(__FILE__) + '/../../translated_specs' + @t.translate_dir(from, to) + end + + it "should translate context_setup do" do + @t.translate_line( + "context_setup do\n" + ).should eql( + "before(:all) do\n" + ) + end + + it "should translate context_setup {foo}" do + @t.translate_line( + "context_setup {foo}\n" + ).should eql( + "before(:all) {foo}\n" + ) + end + + it "should translate context ' to describe '" do + @t.translate_line( + "context 'Translator' do\n" + ).should eql( + "describe 'Translator' do\n" + ) + end + + it 'should translate context " to describe "' do + @t.translate_line( + 'context "Translator"' + ).should eql( + 'describe "Translator"' + ) + end + + it 'should translate spaces then context " to describe "' do + @t.translate_line( + ' context "Translator"' + ).should eql( + ' describe "Translator"' + ) + end + + it "should not translate context=foo" do + @t.translate_line(' context=foo').should eql(' context=foo') + end + + it "should not translate context = foo" do + @t.translate_line(' context = foo').should eql(' context = foo') + end + + it "should not translate context = foo" do + @t.translate_line(' context = foo').should eql(' context = foo') + end + + it "should translate should_be_close" do + @t.translate_line('5.0.should_be_close(5.0, 0.5)').should eql('5.0.should be_close(5.0, 0.5)') + end + + it "should translate should_not_raise" do + @t.translate_line('lambda { self.call }.should_not_raise').should eql('lambda { self.call }.should_not raise_error') + end + + it "should translate should_throw" do + @t.translate_line('lambda { self.call }.should_throw').should eql('lambda { self.call }.should throw_symbol') + end + + it "should not translate 0.9 should_not" do + @t.translate_line('@target.should_not @matcher').should eql('@target.should_not @matcher') + end + + it "should leave should_not_receive" do + @t.translate_line('@mock.should_not_receive(:not_expected).with("unexpected text")').should eql('@mock.should_not_receive(:not_expected).with("unexpected text")') + end + + it "should leave should_receive" do + @t.translate_line('@mock.should_receive(:not_expected).with("unexpected text")').should eql('@mock.should_receive(:not_expected).with("unexpected text")') + end + + it "should translate multi word predicates" do + @t.translate_line('foo.should_multi_word_predicate').should eql('foo.should be_multi_word_predicate') + end + + it "should translate multi word predicates prefixed with be" do + @t.translate_line('foo.should_be_multi_word_predicate').should eql('foo.should be_multi_word_predicate') + end + + it "should translate be(expected) to equal(expected)" do + @t.translate_line('foo.should_be :cool').should eql('foo.should equal :cool') + end + + it "should translate instance_of" do + @t.translate_line('5.should_be_an_instance_of(Integer)').should eql('5.should be_an_instance_of(Integer)') + end + + it "should translate should_be <" do + @t.translate_line('3.should_be < 4').should eql('3.should be < 4') + end + + it "should translate should_be <=" do + @t.translate_line('3.should_be <= 4').should eql('3.should be <= 4') + end + + it "should translate should_be >=" do + @t.translate_line('4.should_be >= 3').should eql('4.should be >= 3') + end + + it "should translate should_be >" do + @t.translate_line('4.should_be > 3').should eql('4.should be > 3') + end + + it "should translate should_be_happy" do + @t.translate_line("4.should_be_happy").should eql("4.should be_happy") + end + + it "should translate custom method taking regexp with parenthesis" do + @t.translate_line("@browser.should_contain_text(/Sn.rrunger og annet rusk/)").should eql("@browser.should be_contain_text(/Sn.rrunger og annet rusk/)") + end + + it "should translate custom method taking regexp without parenthesis" do + @t.translate_line("@browser.should_contain_text /Sn.rrunger og annet rusk/\n").should eql("@browser.should be_contain_text(/Sn.rrunger og annet rusk/)\n") + end + + it "should translate should_not_be_nil" do + @t.translate_line("foo.should_not_be_nil\n").should eql("foo.should_not be_nil\n") + end + + it "should translate kind of" do + @t.translate_line('@object.should_be_kind_of(MessageExpectation)').should( + eql('@object.should be_kind_of(MessageExpectation)')) + end + + it "should translate should_be_true" do + @t.translate_line("foo.should_be_true\n").should eql("foo.should be_true\n") + end + + # [#9674] spec_translate incorrectly handling shoud_match, when regexp in a var, in a block + # http://rubyforge.org/tracker/?func=detail&atid=3149&aid=9674&group_id=797 + it "should translate should_match on a regexp, in a var, in a block" do + @t.translate_line("collection.each { |c| c.should_match a_regexp_in_a_var }\n").should eql("collection.each { |c| c.should match(a_regexp_in_a_var) }\n") + @t.translate_line("collection.each{|c| c.should_match a_regexp_in_a_var}\n").should eql("collection.each{|c| c.should match(a_regexp_in_a_var) }\n") + end + + # From Rubinius specs + it "should translate close_to without parens" do + @t.translate_line("end.should_be_close 3.14159_26535_89793_23846, TOLERANCE\n").should eql("end.should be_close(3.14159_26535_89793_23846, TOLERANCE)\n") + end + + # [#9882] 0.9 Beta 1 - translator bugs + # http://rubyforge.org/tracker/index.php?func=detail&aid=9882&group_id=797&atid=3149 + it "should support symbol arguments" do + @t.translate_line( + "lambda { sequence.parse('bar') }.should_throw :ZeroWidthParseSuccess\n" + ).should eql( + "lambda { sequence.parse('bar') }.should throw_symbol(:ZeroWidthParseSuccess)\n" + ) + end + + # [#9882] 0.9 Beta 1 - translator bugs + # http://rubyforge.org/tracker/index.php?func=detail&aid=9882&group_id=797&atid=3149 + it "should support instance var arguments" do + @t.translate_line( + "a.should_eql @local" + ).should eql( + "a.should eql(@local)" + ) + end + + # [#9882] 0.9 Beta 1 - translator bugs + # http://rubyforge.org/tracker/index.php?func=detail&aid=9882&group_id=797&atid=3149 + it "should support lambdas as expecteds" do + @t.translate_line( + "@parslet.should_not_eql lambda { nil }.to_parseable" + ).should eql( + "@parslet.should_not eql(lambda { nil }.to_parseable)" + ) + end + + # [#9882] 0.9 Beta 1 - translator bugs + # http://rubyforge.org/tracker/index.php?func=detail&aid=9882&group_id=797&atid=3149 + it "should support fully qualified names" do + @t.translate_line( + "results.should_be_kind_of SimpleASTLanguage::Identifier" + ).should eql( + "results.should be_kind_of(SimpleASTLanguage::Identifier)" + ) + end + + # [#9882] 0.9 Beta 1 - translator bugs + # http://rubyforge.org/tracker/index.php?func=detail&aid=9882&group_id=797&atid=3149 + # it "should leave whitespace between expression and comments" do + # @t.translate_line( + # "lambda { @instance.foo = foo }.should_raise NoMethodError # no writer defined" + # ).should eql( + # "lambda { @instance.foo = foo }.should raise_error(NoMethodError) # no writer defined" + # ) + # end + + it "should translate redirects" do + @t.translate_line( + "controller.should_redirect_to 'http://not_existing_domain_for_novalis.test.host/404.html'" + ).should eql( + "controller.should redirect_to('http://not_existing_domain_for_novalis.test.host/404.html')" + ) + end + + it "should translate :any_args" do + @t.translate_line( + "mock.should_receive(:foo).with(:any_args)" + ).should eql( + "mock.should_receive(:foo).with(any_args)" + ) + end + + it "should translate :anything" do + @t.translate_line( + "mock.should_receive(:foo).with(:anything)" + ).should eql( + "mock.should_receive(:foo).with(anything)" + ) + end + + it "should translate :boolean" do + @t.translate_line( + "mock.should_receive(:foo).with(:boolean)" + ).should eql( + "mock.should_receive(:foo).with(boolean)" + ) + end + + it "should translate :no_args" do + @t.translate_line( + "mock.should_receive(:foo).with(:no_args)" + ).should eql( + "mock.should_receive(:foo).with(no_args)" + ) + end + + it "should translate :numeric" do + @t.translate_line( + "mock.should_receive(:foo).with(:numeric)" + ).should eql( + "mock.should_receive(:foo).with(an_instance_of(Numeric))" + ) + end + + it "should translate :string" do + @t.translate_line( + "mock.should_receive(:foo).with(:string)" + ).should eql( + "mock.should_receive(:foo).with(an_instance_of(String))" + ) + end +end diff --git a/vendor/gems/rspec/spec/spec_helper.rb b/vendor/gems/rspec/spec/spec_helper.rb new file mode 100644 index 000000000..a7a4a82db --- /dev/null +++ b/vendor/gems/rspec/spec/spec_helper.rb @@ -0,0 +1,46 @@ +require 'stringio' +require 'rbconfig' + +dir = File.dirname(__FILE__) +lib_path = File.expand_path("#{dir}/../lib") +$LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path) +$_spec_spec = true # Prevents Kernel.exit in various places + +require 'spec' +require 'spec/mocks' +require 'hpricot' # Needed to compare generated with wanted HTML +spec_classes_path = File.expand_path("#{dir}/../spec/spec/spec_classes") +require spec_classes_path unless $LOAD_PATH.include?(spec_classes_path) + +module Spec + module Matchers + def fail + raise_error(Spec::Expectations::ExpectationNotMetError) + end + + def fail_with(message) + raise_error(Spec::Expectations::ExpectationNotMetError, message) + end + + class Pass + def matches?(proc, &block) + begin + proc.call + true + rescue Exception => @error + false + end + end + + def failure_message + @error.message + "\n" + @error.backtrace.join("\n") + end + end + + def pass + Pass.new + end + end +end + +class NonStandardError < Exception; end |